From 34a2453dbc9757fadffb5249761849b9d87d35d8 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 16 Oct 2018 09:20:08 -0400 Subject: [PATCH 001/475] typos, fix for empty string --- .../iq/dataverse/DataverseServiceBean.java | 10 ++-- .../edu/harvard/iq/dataverse/api/Admin.java | 16 ++++--- .../command/impl/CreateDataverseCommand.java | 46 ++++++++++--------- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java index 6da6eb13a19..1447318a52c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java @@ -649,7 +649,7 @@ public List findAllDataverseDatasetChildren(Long dvId) { } } - public JsonObjectBuilder addRoleAssignementsToChildren(Dataverse owner, ArrayList rolesToInherit, + public JsonObjectBuilder addRoleAssignmentsToChildren(Dataverse owner, ArrayList rolesToInherit, boolean inheritAllRoles) { /* * This query recursively finds all Dataverses that are inside/children of the @@ -778,9 +778,9 @@ public JsonObjectBuilder addRoleAssignementsToChildren(Dataverse owner, ArrayLis * handled. Add this to the log and the API return message. */ logger.info(Json.createObjectBuilder().add("Dataverses Updated", dataverseIds) - .add("Updated Dataverse Aliases", dataverseAliases).add("Admins added", usedNames) - .add("Admins not added", unusedNames).build().toString()); - return Json.createObjectBuilder().add("Dataverses Updated", dataverseAliases).add("Admins added", usedNames) - .add("Admins not added", unusedNames); + .add("Updated Dataverse Aliases", dataverseAliases).add("Assignments added for", usedNames) + .add("Assignments not added for", unusedNames).build().toString()); + return Json.createObjectBuilder().add("Dataverses Updated", dataverseAliases).add("Assignments added for", usedNames) + .add("Assignments not added for", unusedNames); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index e2ce08de20a..3b430463378 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -1301,15 +1301,17 @@ public Response addRoleAssignementsToChildren(@PathParam("alias") String alias) } boolean inheritAllRoles = false; String rolesString = settingsSvc.getValueForKey(SettingsServiceBean.Key.InheritParentRoleAssignments, ""); - ArrayList rolesToInherit = new ArrayList(Arrays.asList(rolesString.split("\\s*,\\s*"))); - if (!rolesToInherit.isEmpty()) { - if (rolesToInherit.contains("*")) { - inheritAllRoles = true; + if (rolesString.length() > 0) { + ArrayList rolesToInherit = new ArrayList(Arrays.asList(rolesString.split("\\s*,\\s*"))); + if (!rolesToInherit.isEmpty()) { + if (rolesToInherit.contains("*")) { + inheritAllRoles = true; + } + + return ok(dataverseSvc.addRoleAssignmentsToChildren(owner, rolesToInherit, inheritAllRoles)); } - - return ok(dataverseSvc.addRoleAssignementsToChildren(owner, rolesToInherit, inheritAllRoles)); } return error(Response.Status.BAD_REQUEST, - "InheritParentRoleAssignements does not list any roles on this instance"); + "InheritParentRoleAssignments does not list any roles on this instance"); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommand.java index a1bc3ff54fe..7bcf645ff91 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommand.java @@ -107,30 +107,32 @@ public Dataverse execute(CommandContext ctxt) throws CommandException { boolean inheritAllRoles = false; String rolesString = ctxt.settings().getValueForKey(SettingsServiceBean.Key.InheritParentRoleAssignments, ""); ArrayList rolesToInherit = new ArrayList(Arrays.asList(rolesString.split("\\s*,\\s*"))); - if (!rolesToInherit.isEmpty()) { - if (rolesToInherit.contains("*")) { - inheritAllRoles = true; - } + if (rolesString.length() > 0) { + if (!rolesToInherit.isEmpty()) { + if (rolesToInherit.contains("*")) { + inheritAllRoles = true; + } - List assignedRoles = ctxt.roles().directRoleAssignments(owner); - for (RoleAssignment role : assignedRoles) { - // If all roles are to be inherited, or this role is in the list, and, in both - // cases, this is not an admin role for the current user which was just created - // above... - if ((inheritAllRoles || rolesToInherit.contains(role.getRole().getAlias())) - && !(role.getAssigneeIdentifier().equals(getRequest().getUser().getIdentifier()) - && role.getRole().equals(adminRole))) { - String identifier = role.getAssigneeIdentifier(); - if (identifier.startsWith(AuthenticatedUser.IDENTIFIER_PREFIX)) { - identifier = identifier.substring(AuthenticatedUser.IDENTIFIER_PREFIX.length()); - ctxt.roles().save(new RoleAssignment(role.getRole(), - ctxt.authentication().getAuthenticatedUser(identifier), managedDv, privateUrlToken)); - } else if (identifier.startsWith(Group.IDENTIFIER_PREFIX)) { - identifier = identifier.substring(Group.IDENTIFIER_PREFIX.length()); - Group roleGroup = ctxt.groups().getGroup(identifier); - if (roleGroup!=null) { + List assignedRoles = ctxt.roles().directRoleAssignments(owner); + for (RoleAssignment role : assignedRoles) { + // If all roles are to be inherited, or this role is in the list, and, in both + // cases, this is not an admin role for the current user which was just created + // above... + if ((inheritAllRoles || rolesToInherit.contains(role.getRole().getAlias())) + && !(role.getAssigneeIdentifier().equals(getRequest().getUser().getIdentifier()) + && role.getRole().equals(adminRole))) { + String identifier = role.getAssigneeIdentifier(); + if (identifier.startsWith(AuthenticatedUser.IDENTIFIER_PREFIX)) { + identifier = identifier.substring(AuthenticatedUser.IDENTIFIER_PREFIX.length()); ctxt.roles().save(new RoleAssignment(role.getRole(), - roleGroup, managedDv, privateUrlToken)); + ctxt.authentication().getAuthenticatedUser(identifier), managedDv, privateUrlToken)); + } else if (identifier.startsWith(Group.IDENTIFIER_PREFIX)) { + identifier = identifier.substring(Group.IDENTIFIER_PREFIX.length()); + Group roleGroup = ctxt.groups().getGroup(identifier); + if (roleGroup != null) { + ctxt.roles().save(new RoleAssignment(role.getRole(), + roleGroup, managedDv, privateUrlToken)); + } } } } From e353ccc5555d457e3be9d5d7a01b5334fd23cc5a Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 16 Oct 2018 12:42:06 -0400 Subject: [PATCH 002/475] use String return value the JsonObjectBuilders were getting cleared in the build().toString() used to generate the log message, so the returned value was mostly empty... --- .../edu/harvard/iq/dataverse/DataverseServiceBean.java | 10 +++++----- src/main/java/edu/harvard/iq/dataverse/api/Admin.java | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java index 1447318a52c..d53caf989ad 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java @@ -649,7 +649,7 @@ public List findAllDataverseDatasetChildren(Long dvId) { } } - public JsonObjectBuilder addRoleAssignmentsToChildren(Dataverse owner, ArrayList rolesToInherit, + public String addRoleAssignmentsToChildren(Dataverse owner, ArrayList rolesToInherit, boolean inheritAllRoles) { /* * This query recursively finds all Dataverses that are inside/children of the @@ -777,10 +777,10 @@ public JsonObjectBuilder addRoleAssignmentsToChildren(Dataverse owner, ArrayList * entities that had an admin role on the specified dataverse which were not * handled. Add this to the log and the API return message. */ - logger.info(Json.createObjectBuilder().add("Dataverses Updated", dataverseIds) + String result = Json.createObjectBuilder().add("Dataverses Updated", dataverseIds) .add("Updated Dataverse Aliases", dataverseAliases).add("Assignments added for", usedNames) - .add("Assignments not added for", unusedNames).build().toString()); - return Json.createObjectBuilder().add("Dataverses Updated", dataverseAliases).add("Assignments added for", usedNames) - .add("Assignments not added for", unusedNames); + .add("Assignments not added for", unusedNames).build().toString(); + logger.info(result); + return (result); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 3b430463378..2d15439b6ce 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -1307,7 +1307,6 @@ public Response addRoleAssignementsToChildren(@PathParam("alias") String alias) if (rolesToInherit.contains("*")) { inheritAllRoles = true; } - return ok(dataverseSvc.addRoleAssignmentsToChildren(owner, rolesToInherit, inheritAllRoles)); } } From 7a0f302300c3f3ab5e757dcefe84fb090dd73bc3 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 16 Oct 2018 15:29:51 -0400 Subject: [PATCH 003/475] filter custom roles --- .../iq/dataverse/DataverseServiceBean.java | 5 ++- .../command/impl/CreateDataverseCommand.java | 35 ++++++++++--------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java index d53caf989ad..ac564e2915c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java @@ -699,7 +699,10 @@ public String addRoleAssignmentsToChildren(Dataverse owner, ArrayList ro List inheritableRAsOnOwner = new ArrayList(); for (RoleAssignment role : allRAsOnOwner) { if (inheritAllRoles || rolesToInherit.contains(role.getRole().getAlias())) { - inheritableRAsOnOwner.add(role); + //Only supporting built-in/non-dataverse-specific custom roles. Custom roles all have an owner. + if(role.getRole().getOwner()==null) { + inheritableRAsOnOwner.add(role); + } } } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommand.java index 7bcf645ff91..7a352590aac 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommand.java @@ -115,23 +115,26 @@ public Dataverse execute(CommandContext ctxt) throws CommandException { List assignedRoles = ctxt.roles().directRoleAssignments(owner); for (RoleAssignment role : assignedRoles) { - // If all roles are to be inherited, or this role is in the list, and, in both - // cases, this is not an admin role for the current user which was just created - // above... - if ((inheritAllRoles || rolesToInherit.contains(role.getRole().getAlias())) - && !(role.getAssigneeIdentifier().equals(getRequest().getUser().getIdentifier()) - && role.getRole().equals(adminRole))) { - String identifier = role.getAssigneeIdentifier(); - if (identifier.startsWith(AuthenticatedUser.IDENTIFIER_PREFIX)) { - identifier = identifier.substring(AuthenticatedUser.IDENTIFIER_PREFIX.length()); - ctxt.roles().save(new RoleAssignment(role.getRole(), - ctxt.authentication().getAuthenticatedUser(identifier), managedDv, privateUrlToken)); - } else if (identifier.startsWith(Group.IDENTIFIER_PREFIX)) { - identifier = identifier.substring(Group.IDENTIFIER_PREFIX.length()); - Group roleGroup = ctxt.groups().getGroup(identifier); - if (roleGroup != null) { + //Only supporting built-in/non-dataverse-specific custom roles. Custom roles all have an owner. + if (role.getRole().getOwner() == null) { + // And... If all roles are to be inherited, or this role is in the list, and, in both + // cases, this is not an admin role for the current user which was just created + // above... + if ((inheritAllRoles || rolesToInherit.contains(role.getRole().getAlias())) + && !(role.getAssigneeIdentifier().equals(getRequest().getUser().getIdentifier()) + && role.getRole().equals(adminRole))) { + String identifier = role.getAssigneeIdentifier(); + if (identifier.startsWith(AuthenticatedUser.IDENTIFIER_PREFIX)) { + identifier = identifier.substring(AuthenticatedUser.IDENTIFIER_PREFIX.length()); ctxt.roles().save(new RoleAssignment(role.getRole(), - roleGroup, managedDv, privateUrlToken)); + ctxt.authentication().getAuthenticatedUser(identifier), managedDv, privateUrlToken)); + } else if (identifier.startsWith(Group.IDENTIFIER_PREFIX)) { + identifier = identifier.substring(Group.IDENTIFIER_PREFIX.length()); + Group roleGroup = ctxt.groups().getGroup(identifier); + if (roleGroup != null) { + ctxt.roles().save(new RoleAssignment(role.getRole(), + roleGroup, managedDv, privateUrlToken)); + } } } } From 2910168fe6fbdb6ce0b88d0416f98466568ecfb7 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Mon, 12 Nov 2018 12:53:44 -0500 Subject: [PATCH 004/475] Don't open input stream when not needed. --- .../edu/harvard/iq/dataverse/api/Access.java | 14 +++--- .../dataaccess/ImageThumbConverter.java | 4 +- .../iq/dataverse/dataaccess/S3AccessIO.java | 43 +++++++++++++------ .../iq/dataverse/dataaccess/StorageIO.java | 4 +- .../dataverse/dataaccess/StorageIOTest.java | 4 +- 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Access.java b/src/main/java/edu/harvard/iq/dataverse/api/Access.java index 02f6f427027..019c9009f14 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Access.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Access.java @@ -651,15 +651,14 @@ public InputStream fileCardImage(@PathParam("fileId") Long fileId, @Context UriI || "application/zipped-shapefile".equalsIgnoreCase(df.getContentType())) { thumbnailDataAccess = ImageThumbConverter.getImageThumbnailAsInputStream(dataAccess, 48); + if (thumbnailDataAccess != null && thumbnailDataAccess.getInputStream() != null) { + return thumbnailDataAccess.getInputStream(); + } } } } catch (IOException ioEx) { return null; } - - if (thumbnailDataAccess != null && thumbnailDataAccess.getInputStream() != null) { - return thumbnailDataAccess.getInputStream(); - } return null; } @@ -695,6 +694,9 @@ public InputStream dsCardImage(@PathParam("versionId") Long versionId, @Context dataAccess.open(); thumbnailDataAccess = ImageThumbConverter.getImageThumbnailAsInputStream(dataAccess, 48); } + if (thumbnailDataAccess != null && thumbnailDataAccess.getInputStream() != null) { + return thumbnailDataAccess.getInputStream(); + } } catch (IOException ioEx) { thumbnailDataAccess = null; } @@ -711,10 +713,6 @@ public InputStream dsCardImage(@PathParam("versionId") Long versionId, @Context } }*/ - if (thumbnailDataAccess != null && thumbnailDataAccess.getInputStream() != null) { - return thumbnailDataAccess.getInputStream(); - } - } return null; diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/ImageThumbConverter.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/ImageThumbConverter.java index a18af48cdd0..41860fb0c3e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/ImageThumbConverter.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/ImageThumbConverter.java @@ -271,12 +271,12 @@ private static boolean generateImageThumbnail(StorageIO storageIO, int try { storageIO.open(); + return generateImageThumbnailFromInputStream(storageIO, size, storageIO.getInputStream()); } catch (IOException ioex) { logger.warning("caught IOException trying to open an input stream for " + storageIO.getDataFile().getStorageIdentifier() + ioex); return false; } - - return generateImageThumbnailFromInputStream(storageIO, size, storageIO.getInputStream()); + } /* diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index 530f7ee4a17..bbae7468286 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -12,6 +12,7 @@ import com.amazonaws.services.s3.model.DeleteObjectsRequest; import com.amazonaws.services.s3.model.DeleteObjectsRequest.KeyVersion; import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; +import com.amazonaws.services.s3.model.GetObjectMetadataRequest; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ListObjectsRequest; import com.amazonaws.services.s3.model.ObjectListing; @@ -123,22 +124,13 @@ public void open(DataAccessOption... options) throws IOException { if (isReadAccess) { key = getMainFileKey(); - S3Object s3object = null; + ObjectMetadata objectMetadata = null; try { - s3object = s3.getObject(new GetObjectRequest(bucketName, key)); + objectMetadata = s3.getObjectMetadata(bucketName, key); } catch (SdkClientException sce) { throw new IOException("Cannot get S3 object " + key + " ("+sce.getMessage()+")"); } - InputStream in = s3object.getObjectContent(); - - if (in == null) { - throw new IOException("Cannot get InputStream for S3 Object" + key); - } - - this.setInputStream(in); - - setChannel(Channels.newChannel(in)); - this.setSize(s3object.getObjectMetadata().getContentLength()); + this.setSize(objectMetadata.getContentLength()); if (dataFile.getContentType() != null && dataFile.getContentType().equals("text/tab-separated-values") @@ -181,6 +173,33 @@ public void open(DataAccessOption... options) throws IOException { } } + @Override + public InputStream getInputStream() throws IOException { + if(super.getInputStream()==null) { + try { + setInputStream(s3.getObject(new GetObjectRequest(bucketName, key)).getObjectContent()); + } catch (SdkClientException sce) { + throw new IOException("Cannot get S3 object " + key + " ("+sce.getMessage()+")"); + } + } + + if (super.getInputStream() == null) { + throw new IOException("Cannot get InputStream for S3 Object" + key); + } + + setChannel(Channels.newChannel(super.getInputStream())); + + return super.getInputStream(); + } + + public Channel getChannel() throws IOException { + if(super.getChannel()==null) { + getInputStream(); + } + return channel; + } + + // StorageIO method for copying a local Path (for ex., a temp file), into this DataAccess location: @Override public void savePath(Path fileSystemPath) throws IOException { diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/StorageIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/StorageIO.java index fda93b3f557..99eb36d44b0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/StorageIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/StorageIO.java @@ -227,7 +227,7 @@ public boolean canWrite() { // getters: - public Channel getChannel() { + public Channel getChannel() throws IOException { return channel; } @@ -276,7 +276,7 @@ public long getSize() { return size; } - public InputStream getInputStream() { + public InputStream getInputStream() throws IOException { return in; } diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/StorageIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/StorageIOTest.java index 70dbc11db29..f85b59053f9 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/StorageIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/StorageIOTest.java @@ -32,7 +32,7 @@ public class StorageIOTest { StorageIO instance = new FileAccessIO<>(); @Test - public void testGetChannel() throws FileNotFoundException { + public void testGetChannel() throws IOException { assertEquals(null, instance.getChannel()); Channel c = new RandomAccessFile("src/main/java/Bundle.properties", "r").getChannel(); instance.setChannel(c); @@ -104,7 +104,7 @@ public void testSize() { } @Test - public void testInputStream() { + public void testInputStream() throws IOException { assertEquals(null, instance.getInputStream()); InputStream is = new ByteArrayInputStream("Test".getBytes()); instance.setInputStream(is); From 7ed30fb11e419c051c003749820208e895bcc5ba Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 13 Nov 2018 10:12:24 -0500 Subject: [PATCH 005/475] simplify --- .../iq/dataverse/dataaccess/ImageThumbConverter.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/ImageThumbConverter.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/ImageThumbConverter.java index 41860fb0c3e..f273d215a3e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/ImageThumbConverter.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/ImageThumbConverter.java @@ -146,12 +146,11 @@ public static InputStreamIO getImageThumbnailAsInputStream(StorageIO s try { storageIO.open(); - Channel cachedThumbnailChannel = storageIO.openAuxChannel(THUMBNAIL_SUFFIX + size); - if (cachedThumbnailChannel == null) { - logger.warning("Null channel for aux object " + THUMBNAIL_SUFFIX + size); + cachedThumbnailInputStream = storageIO.getAuxFileAsInputStream(THUMBNAIL_SUFFIX + size); + if (cachedThumbnailInputStream == null) { + logger.warning("Null stream for aux object " + THUMBNAIL_SUFFIX + size); return null; } - cachedThumbnailInputStream = Channels.newInputStream((ReadableByteChannel) cachedThumbnailChannel); int cachedThumbnailSize = (int) storageIO.getAuxObjectSize(THUMBNAIL_SUFFIX + size); InputStreamIO inputStreamIO = new InputStreamIO(cachedThumbnailInputStream, cachedThumbnailSize); From 08a0e7e37d497bc7facbfd06d4e424e05c29fba4 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 13 Nov 2018 12:42:57 -0500 Subject: [PATCH 006/475] add @Override --- .../java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index bbae7468286..0bdcdfd6be4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -192,6 +192,7 @@ public InputStream getInputStream() throws IOException { return super.getInputStream(); } + @Override public Channel getChannel() throws IOException { if(super.getChannel()==null) { getInputStream(); From e5fed4aeaaffc20dc256004dda504d918bd6447a Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 13 Nov 2018 17:37:14 -0500 Subject: [PATCH 007/475] override getReadChannel as well --- .../edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index 0bdcdfd6be4..616085fcf08 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -35,6 +35,7 @@ import java.net.URLEncoder; import java.nio.channels.Channel; import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.file.Path; import java.nio.file.Paths; @@ -199,8 +200,14 @@ public Channel getChannel() throws IOException { } return channel; } - + @Override + public ReadableByteChannel getReadChannel() throws IOException { + //Make sure StorageIO.channel variable exists + getChannel(); + return super.getReadChannel(); + } + // StorageIO method for copying a local Path (for ex., a temp file), into this DataAccess location: @Override public void savePath(Path fileSystemPath) throws IOException { From 6ea25243eafd0f76659490edad354f9e5f249376 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Fri, 21 Dec 2018 10:07:36 -0500 Subject: [PATCH 008/475] TDL image and release name changes --- pom.xml | 2 +- .../resources/images/favicondataverse.png | Bin 1184 -> 7165 bytes src/main/webapp/resources/images/tdl.png | Bin 0 -> 14054 bytes 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/main/webapp/resources/images/tdl.png diff --git a/pom.xml b/pom.xml index 1692c190922..1368d2c23a4 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ --> edu.harvard.iq dataverse - 4.10 + 4.10-tdl war dataverse diff --git a/src/main/webapp/resources/images/favicondataverse.png b/src/main/webapp/resources/images/favicondataverse.png index dd1d8b3fb7e8395ec73a63cb4652de24bf17311a..1b6d61ad1b4c2929ac8b7d985d25f6d740fc25b8 100644 GIT binary patch literal 7165 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 diff --git a/src/main/webapp/resources/images/tdl.png b/src/main/webapp/resources/images/tdl.png new file mode 100644 index 0000000000000000000000000000000000000000..6de3ed12cb36db431e2144ea8e06279263b34322 GIT binary patch literal 14054 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 ZpMtBThx_qz@U&onjHIGOm6-9T{{==`;wb Date: Fri, 21 Dec 2018 10:15:24 -0500 Subject: [PATCH 009/475] text changes --- src/main/java/Bundle.properties | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/Bundle.properties b/src/main/java/Bundle.properties index d857d6d8026..7035b657e91 100644 --- a/src/main/java/Bundle.properties +++ b/src/main/java/Bundle.properties @@ -115,7 +115,7 @@ contact.header=Contact {0} contact.dataverse.header=Email Dataverse Contact contact.dataset.header=Email Dataset Contact contact.to=To -contact.support=Support +contact.support=TDL Dataverse Support contact.from=From contact.from.required=User email is required. contact.from.invalid=Email is invalid. @@ -260,10 +260,10 @@ login.System=Login System login.forgot.text=Forgot your password? login.builtin=Dataverse Account login.institution=Institutional Account -login.institution.blurb=Log in or sign up with your institutional account — learn more. +login.institution.blurb=Log in or sign up with your institutional account — learn more. If you are not affiliated with a TDR member institution (see dropdown menu), please use the Google Login option. login.institution.support.beforeLink=Leaving your institution? Please contact login.institution.support.afterLink=for assistance. -login.builtin.credential.usernameOrEmail=Username/Email +login.builtin.credential.usernameOrEmail=Admin ID login.builtin.credential.password=Password login.builtin.invalidUsernameEmailOrPassword=The username, email address, or password you entered is invalid. Need assistance accessing your account? login.echo.credential.name=Name @@ -274,16 +274,16 @@ login.error=Error validating the username, email address, or password. Please tr user.error.cannotChangePassword=Sorry, your password cannot be changed. Please contact your system administrator. user.error.wrongPassword=Sorry, wrong password. login.button=Log In with {0} -login.button.orcid=Create or Connect your ORCID +login.button.orcid=Google Login - No TDR affiliation # authentication providers auth.providers.title=Other options auth.providers.tip=You can convert a Dataverse account to use one of the options above. Learn more. -auth.providers.title.builtin=Username/Email +auth.providers.title.builtin=Admin ID auth.providers.title.shib=Your Institution auth.providers.title.orcid=ORCID auth.providers.title.google=Google auth.providers.title.github=GitHub -auth.providers.blurb=Log in or sign up with your {0} account — learn more. Having trouble? Please contact {3} for assistance. +auth.providers.blurb=Log in or sign up with your Google account — learn more. If you are not affiliated with a TDR member institution, please use the Google Login option. Having trouble? Please contact {3} for assistance. auth.providers.persistentUserIdName.orcid=ORCID iD auth.providers.persistentUserIdName.github=ID auth.providers.persistentUserIdTooltip.orcid=ORCID provides a persistent digital identifier that distinguishes you from other researchers. @@ -322,7 +322,7 @@ shib.welcomeExistingUserMessageDefaultInstitution=your institution shib.dataverseUsername=Dataverse Username shib.currentDataversePassword=Current Dataverse Password shib.accountInformation=Account Information -shib.offerToCreateNewAccount=This information is provided by your institution and will be used to create your Dataverse account. +shib.offerToCreateNewAccount=Contact your TDR liaison to get help and training. Published content cannot be easily deleted. shib.passwordRejected=Validation Error - Your account can only be converted if you provide the correct password for your existing account. # oauth2/firstLogin.xhtml From 799892906c8256a96c247bfa89c46db9df0dfc38 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Wed, 26 Dec 2018 15:27:50 -0500 Subject: [PATCH 010/475] TDRDV-46 --- src/main/java/edu/harvard/iq/dataverse/DataversePage.java | 3 +++ src/main/webapp/dataverse.xhtml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java index 0bd67f0f24e..f95908df058 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java @@ -46,6 +46,8 @@ import javax.faces.model.SelectItem; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; +import org.primefaces.PrimeFaces; +import org.primefaces.context.RequestContext; import org.primefaces.event.TransferEvent; /** @@ -506,6 +508,7 @@ public void updateInclude(Long mdbId, long dsftId) { } } } + PrimeFaces.current().scrollTo("dsft"+dsftId); } public List resetSelectItems(DatasetFieldType typeIn) { diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index b287d151122..33f1a378cca 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -264,7 +264,7 @@ - +
Date: Thu, 27 Dec 2018 17:02:59 -0500 Subject: [PATCH 011/475] TDRDV-46 use javascript to scroll within panel after update --- .../java/edu/harvard/iq/dataverse/DataversePage.java | 2 +- src/main/webapp/dataverse.xhtml | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java index f95908df058..e7493e936c5 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java @@ -508,7 +508,7 @@ public void updateInclude(Long mdbId, long dsftId) { } } } - PrimeFaces.current().scrollTo("dsft"+dsftId); + PrimeFaces.current().executeScript("scrollAfterUpdate();"); } public List resetSelectItems(DatasetFieldType typeIn) { diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index 33f1a378cca..16268969756 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -264,10 +264,10 @@ - +
@@ -743,6 +743,9 @@ diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index f26218913f3..4b3a9c5ee81 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -1,3 +1,40 @@ +var fileList = []; +var observer2=null; + +function setupDirectUpload() { + +var fileInput=document.getElementById('datasetForm:fileUpload_input'); +fileInput.addEventListener('change', function(event) { +fileList=[]; +for(var i=0;i Date: Fri, 6 Dec 2019 10:28:12 -0500 Subject: [PATCH 054/475] toggle auto upload based on directupload property --- .../java/edu/harvard/iq/dataverse/EditDatafilesPage.java | 5 +++++ src/main/webapp/editFilesFragment.xhtml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 44dab4fc3cd..e50f566e028 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -9,6 +9,7 @@ import edu.harvard.iq.dataverse.datasetutility.AddReplaceFileHelper; import edu.harvard.iq.dataverse.datasetutility.FileReplaceException; import edu.harvard.iq.dataverse.datasetutility.FileReplacePageHelper; +import edu.harvard.iq.dataverse.dataaccess.DataAccess; import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter; import edu.harvard.iq.dataverse.datacapturemodule.DataCaptureModuleUtil; import edu.harvard.iq.dataverse.datacapturemodule.ScriptRequestResponse; @@ -350,6 +351,10 @@ public boolean doesSessionUserHaveDataSetPermission(Permission permissionToCheck return hasPermission; } + public boolean directUploadEnabled() { + return Boolean.getBoolean(System.getProperty("dataverse.file." + DataAccess.getStorageDriverId(this.dataset.getDataverseContext()) + ".upload-redirect", "false")); + } + public void reset() { // ? } diff --git a/src/main/webapp/editFilesFragment.xhtml b/src/main/webapp/editFilesFragment.xhtml index 315abe117ce..030726cff2d 100644 --- a/src/main/webapp/editFilesFragment.xhtml +++ b/src/main/webapp/editFilesFragment.xhtml @@ -124,7 +124,7 @@ Date: Mon, 9 Dec 2019 13:23:50 -0500 Subject: [PATCH 055/475] implement proxying --- .../harvard/iq/dataverse/api/Datasets.java | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index c88ed4ca981..ce039521e8a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -1450,21 +1450,10 @@ public Response getUploadUrl(@PathParam("id") String idSupplied) { return error(Response.Status.FORBIDDEN, "You are not permitted to upload files to this dataset."); } - String driverId = DataAccess.getStorageDriverId(dataset.getDataverseContext()); - boolean directEnabled = Boolean.getBoolean(System.getProperty("dataverse.files." + driverId + ".upload-redirect", "false")); - if(!directEnabled) { - return error(Response.Status.NOT_FOUND, "Direct upload not supported for files in this dataset."); - } - String bucket = System.getProperty("dataverse.files." + driverId + ".bucket-name") + "/"; - String sid = bucket+ dataset.getAuthorityForFileStorage() + "/" + dataset.getIdentifierForFileStorage() + "/" + FileUtil.generateStorageIdentifier(); - S3AccessIO s3io = new S3AccessIO(sid, driverId); - String url = null; - try { - url = s3io.generateTemporaryS3UploadUrl(); - } catch (IOException e) { - logger.warning("Identifier Collision"); - e.printStackTrace(); - } + String url = FileUtil.getDirectUploadUrl(dataset); + if(url==null) { + return error(Response.Status.NOT_FOUND,"Direct upload not supported for files in this dataset: " + dataset.getId()); + } return ok(url); } catch (WrappedResponse wr) { return wr.getResponse(); From 9c01f28d997748dc9d577959aa4c76488541ae7a Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 9 Dec 2019 13:25:25 -0500 Subject: [PATCH 056/475] implement proxy --- .../harvard/iq/dataverse/util/FileUtil.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index cbad62329e8..ade2040b44c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -24,11 +24,13 @@ import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.DataFile.ChecksumType; import edu.harvard.iq.dataverse.DataFileServiceBean; +import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.FileMetadata; import edu.harvard.iq.dataverse.TermsOfUseAndAccess; import edu.harvard.iq.dataverse.dataaccess.DataAccess; import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter; +import edu.harvard.iq.dataverse.dataaccess.S3AccessIO; import edu.harvard.iq.dataverse.dataset.DatasetThumbnail; import edu.harvard.iq.dataverse.datasetutility.FileExceedsMaxSizeException; import static edu.harvard.iq.dataverse.datasetutility.FileSizeChecker.bytesToHumanReadable; @@ -1666,5 +1668,33 @@ public static DatasetThumbnail getThumbnail(DataFile file) { public static boolean isPackageFile(DataFile dataFile) { return DataFileServiceBean.MIME_TYPE_PACKAGE_FILE.equalsIgnoreCase(dataFile.getContentType()); } + + public static String getDirectUploadUrl(Dataset dataset) { + String driverId = DataAccess.getStorageDriverId(dataset.getDataverseContext()); + boolean directEnabled = Boolean.getBoolean("dataverse.files." + driverId + ".upload-redirect"); + //Should only be requested when it is allowed, but we'll log a warning otherwise + if(!directEnabled) { + logger.warning("Direct upload not supported for files in this dataset: " + dataset.getId()); + return null; + } + String bucket = System.getProperty("dataverse.files." + driverId + ".bucket-name") + "/"; + String sid = bucket+ dataset.getAuthorityForFileStorage() + "/" + dataset.getIdentifierForFileStorage() + "/" + FileUtil.generateStorageIdentifier(); + S3AccessIO s3io = new S3AccessIO(sid, driverId); + String url = null; + try { + url = s3io.generateTemporaryS3UploadUrl(); + } catch (IOException e) { + logger.warning("Identifier Collision"); + e.printStackTrace(); + } + String endpoint = System.getProperty("dataverse.files." + driverId + ".custom-endpoint-url"); + + String proxy = System.getProperty("dataverse.files." + driverId + ".proxy-url" + + ""); + if(proxy!=null) { + url.replace(endpoint, proxy); + } + return url; + } } From 0fe9918afa18ab4cd39e7d4822546d27d48a9100 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 9 Dec 2019 13:27:54 -0500 Subject: [PATCH 057/475] further updates to direct upload files --- .../iq/dataverse/EditDatafilesPage.java | 10 +- .../iq/dataverse/dataaccess/DataAccess.java | 7 ++ src/main/webapp/editFilesFragment.xhtml | 6 +- src/main/webapp/resources/js/fileupload.js | 110 +++++++++++++----- 4 files changed, 101 insertions(+), 32 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index e50f566e028..9638cda4ba8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -11,6 +11,7 @@ import edu.harvard.iq.dataverse.datasetutility.FileReplacePageHelper; import edu.harvard.iq.dataverse.dataaccess.DataAccess; import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter; +import edu.harvard.iq.dataverse.dataaccess.S3AccessIO; import edu.harvard.iq.dataverse.datacapturemodule.DataCaptureModuleUtil; import edu.harvard.iq.dataverse.datacapturemodule.ScriptRequestResponse; import edu.harvard.iq.dataverse.dataset.DatasetThumbnail; @@ -84,6 +85,8 @@ import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; +import javax.ws.rs.core.Response; + import org.apache.commons.lang.StringUtils; import org.primefaces.PrimeFaces; //import org.primefaces.context.RequestContext; @@ -352,7 +355,9 @@ public boolean doesSessionUserHaveDataSetPermission(Permission permissionToCheck } public boolean directUploadEnabled() { - return Boolean.getBoolean(System.getProperty("dataverse.file." + DataAccess.getStorageDriverId(this.dataset.getDataverseContext()) + ".upload-redirect", "false")); + logger.info(this.dataset.getDataverseContext().getAlias() + " " + this.dataset.getDataverseContext().getAffiliation() + " " + DataAccess.getStorageDriverId(this.dataset.getDataverseContext())); + logger.info("denabled: " + DataAccess.getStorageDriverId(this.dataset.getDataverseContext()) + " " + Boolean.getBoolean("dataverse.files." + DataAccess.getStorageDriverId(this.dataset.getDataverseContext()) + ".upload-redirect")); + return Boolean.getBoolean("dataverse.files." + DataAccess.getStorageDriverId(this.dataset.getDataverseContext()) + ".upload-redirect"); } public void reset() { @@ -1722,6 +1727,9 @@ public String getRsyncScriptFilename() { return rsyncScriptFilename; } + public void requestDirectUploadUrl() { + PrimeFaces.current().executeScript("uploadFileDirectly('" + FileUtil.getDirectUploadUrl(dataset) + "')"); + } public void uploadFinished() { // This method is triggered from the page, by the @@ -124,7 +125,7 @@ + diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index 4b3a9c5ee81..febf7c59a57 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -1,39 +1,91 @@ var fileList = []; var observer2=null; +var datasetId=null; -function setupDirectUpload() { - -var fileInput=document.getElementById('datasetForm:fileUpload_input'); -fileInput.addEventListener('change', function(event) { -fileList=[]; -for(var i=0;i')); + $.ajax({ + url: url, + type: 'POST', + data: data, + cache: false, + processData: false, + success: reportUpload, + xhr: function() { + var myXhr = $.ajaxSettings.xhr(); + if(myXhr.upload) { + myXhr.upload.addEventListener('progress', function(e) { + if(e.lengthComputable) { + $('progress').attr({ + value:e.loaded, + max:e.total + }) + } + }) + } + } + }); + //perform post - check cors issues + //trigger gui swap/server file add + //handle cancel buttons? + } - } - }); - }; - if(observer2 !=null) { - observer2.disconnect(); - } - observer2 = new MutationObserver(callback); - observer2.observe(fileInput.parentElement,config); +function reportUpload(data){ + console.log('Done ' + data ); } function removeErrors() { From 518e2d27a95a0e943f75b2739a8ed4e0f9723e60 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 13 Dec 2019 17:43:01 -0500 Subject: [PATCH 058/475] add driver to upload url response --- src/main/java/edu/harvard/iq/dataverse/api/Datasets.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index ce039521e8a..bdde4aa21c9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -1454,7 +1454,9 @@ public Response getUploadUrl(@PathParam("id") String idSupplied) { if(url==null) { return error(Response.Status.NOT_FOUND,"Direct upload not supported for files in this dataset: " + dataset.getId()); } - return ok(url); + String driverId = DataAccess.getStorageDriverId(dataset.getDataverseContext()); + String response = "{\"url\":\"" + url + "\",\"driverId\":\"" + driverId + "\"}"; + return ok(response); } catch (WrappedResponse wr) { return wr.getResponse(); } From 076c75a3335c7543d1459bed3dafd08c647fe899 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 13 Dec 2019 17:43:34 -0500 Subject: [PATCH 059/475] fix proxy url replacement --- .../java/edu/harvard/iq/dataverse/util/FileUtil.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index ade2040b44c..1a799ebd786 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -1688,12 +1688,13 @@ public static String getDirectUploadUrl(Dataset dataset) { e.printStackTrace(); } String endpoint = System.getProperty("dataverse.files." + driverId + ".custom-endpoint-url"); - - String proxy = System.getProperty("dataverse.files." + driverId + ".proxy-url" - + ""); + logger.info("endpoint: " + endpoint); + String proxy = System.getProperty("dataverse.files." + driverId + ".proxy-url"); + logger.info("proxy: " + proxy); if(proxy!=null) { - url.replace(endpoint, proxy); + url = url.replace(endpoint, proxy); } + logger.info("url: " + url); return url; } From 2f7102d3e1046baff5f99efc08b52a5d3c3d6b65 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 10:01:16 -0500 Subject: [PATCH 060/475] single file, no hash upload via GUI minimally working --- .../iq/dataverse/EditDatafilesPage.java | 174 +++++++++++++++++- .../harvard/iq/dataverse/api/Datasets.java | 21 ++- .../iq/dataverse/dataaccess/DataAccess.java | 18 +- .../iq/dataverse/dataaccess/S3AccessIO.java | 80 ++++---- .../datasetutility/AddReplaceFileHelper.java | 3 +- .../datasetutility/FileReplacePageHelper.java | 7 +- .../dataverse/ingest/IngestServiceBean.java | 14 +- .../harvard/iq/dataverse/util/FileUtil.java | 62 ++++--- src/main/webapp/editFilesFragment.xhtml | 1 + src/main/webapp/resources/js/fileupload.js | 54 ++++-- 10 files changed, 329 insertions(+), 105 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 9638cda4ba8..d26d0a33112 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -2,6 +2,7 @@ import edu.harvard.iq.dataverse.provenance.ProvPopupFragmentBean; import edu.harvard.iq.dataverse.api.AbstractApiBean; +import edu.harvard.iq.dataverse.api.AbstractApiBean.WrappedResponse; import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean; import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; @@ -10,8 +11,10 @@ import edu.harvard.iq.dataverse.datasetutility.FileReplaceException; import edu.harvard.iq.dataverse.datasetutility.FileReplacePageHelper; import edu.harvard.iq.dataverse.dataaccess.DataAccess; +import edu.harvard.iq.dataverse.dataaccess.DataAccessOption; import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter; import edu.harvard.iq.dataverse.dataaccess.S3AccessIO; +import edu.harvard.iq.dataverse.dataaccess.StorageIO; import edu.harvard.iq.dataverse.datacapturemodule.DataCaptureModuleUtil; import edu.harvard.iq.dataverse.datacapturemodule.ScriptRequestResponse; import edu.harvard.iq.dataverse.dataset.DatasetThumbnail; @@ -1728,7 +1731,21 @@ public String getRsyncScriptFilename() { } public void requestDirectUploadUrl() { - PrimeFaces.current().executeScript("uploadFileDirectly('" + FileUtil.getDirectUploadUrl(dataset) + "')"); + S3AccessIO s3io = FileUtil.getS3AccessForDirectUpload(dataset); + if(s3io == null) { + FacesContext.getCurrentInstance().addMessage(uploadComponentId, new FacesMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("dataset.file.uploadWarning"), "Direct upload not supported for this dataset")); + } + String url = null; + String storageIdentifier = null; + try { + url = s3io.generateTemporaryS3UploadUrl(); + storageIdentifier = FileUtil.getStorageIdentifierFromLocation(s3io.getStorageLocation()); + } catch (IOException io) { + logger.warning(io.getMessage()); + FacesContext.getCurrentInstance().addMessage(uploadComponentId, new FacesMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("dataset.file.uploadWarning"), "Issue in connecting to S3 store for direct upload")); + } + + PrimeFaces.current().executeScript("uploadFileDirectly('" + url + "','" + storageIdentifier + "')"); } public void uploadFinished() { @@ -1758,6 +1775,7 @@ public void uploadFinished() { for (DataFile dataFile : uploadedFiles) { fileMetadatas.add(dataFile.getFileMetadata()); newFiles.add(dataFile); + logger.info("Added " + dataFile.getFileMetadata().getLabel()); } @@ -1821,7 +1839,7 @@ private void handleReplaceFileUpload(FacesEvent event, InputStream inputStream, uploadComponentId = event.getComponent().getClientId(); - if (fileReplacePageHelper.handleNativeFileUpload(inputStream, + if (fileReplacePageHelper.handleNativeFileUpload(inputStream,null, fileName, contentType )){ @@ -1879,6 +1897,32 @@ the uploadFinished() method, triggered next, after the upload event // new FacesMessage(FacesMessage.SEVERITY_ERROR, "upload failure", uploadWarningMessage)); } } + + private void handleReplaceFileUpload(String fullStorageLocation, + String fileName, + String contentType){ + + fileReplacePageHelper.resetReplaceFileHelper(); + + saveEnabled = false; + + if (fileReplacePageHelper.handleNativeFileUpload(null, fullStorageLocation, + fileName, + contentType + )){ + saveEnabled = true; + + /** + * If the file content type changed, let the user know + */ + if (fileReplacePageHelper.hasContentTypeWarning()){ + //Add warning to popup instead of page for Content Type Difference + setWarningMessageForPopUp(fileReplacePageHelper.getContentTypeWarning()); + } + } else { + uploadWarningMessage = fileReplacePageHelper.getErrorMessages(); + } + } private String uploadWarningMessage = null; private String uploadSuccessMessage = null; @@ -1967,6 +2011,129 @@ public void handleFileUpload(FileUploadEvent event) throws IOException { } } + /** + * Using information from the DropBox choose, ingest the chosen files + * https://www.dropbox.com/developers/dropins/chooser/js + * + * @param event + */ + public void handleExternalUpload() { + Map paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); + + this.uploadComponentId = paramMap.get("uploadComponentId"); + String fullStorageIdentifier = paramMap.get("fullStorageIdentifier"); + String fileName = paramMap.get("fileName"); + String contentType = paramMap.get("contentType"); + String checksumType = paramMap.get("checksumType"); + String checksumValue = paramMap.get("checksumValue"); + + logger.info("UCI" + uploadComponentId); + logger.info("FSI" + fullStorageIdentifier); + logger.info("FN" + fileName); + logger.info("CT" + contentType); + logger.info("CST" + checksumType); + logger.info("CDV" + checksumValue); + int lastColon = fullStorageIdentifier.lastIndexOf(':'); + String storageLocation= fullStorageIdentifier.substring(0,lastColon) + "/" + dataset.getAuthorityForFileStorage() + "/" + dataset.getIdentifierForFileStorage() + "/" + fullStorageIdentifier.substring(lastColon+1); + logger.info("SL " + storageLocation); + if (!uploadInProgress) { + uploadInProgress = true; + } + logger.fine("handleExternalUpload"); + + StorageIO sio; + String localWarningMessage = null; + try { + sio = DataAccess.getDirectStorageIO(storageLocation); + + //Populate metadata + sio.open(DataAccessOption.READ_ACCESS); + //get file size + long fileSize = sio.getSize(); + logger.info("FS " + fileSize); + + /* ---------------------------- + Check file size + - Max size NOT specified in db: default is unlimited + - Max size specified in db: check too make sure file is within limits + // ---------------------------- */ + if ((!this.isUnlimitedUploadFileSize()) && (fileSize > this.getMaxFileUploadSizeInBytes())) { + String warningMessage = "Uploaded file \"" + fileName + "\" exceeded the limit of " + fileSize + " bytes and was not uploaded."; + sio.delete(); + //msg(warningMessage); + //FacesContext.getCurrentInstance().addMessage(event.getComponent().getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, "upload failure", warningMessage)); + if (localWarningMessage == null) { + localWarningMessage = warningMessage; + } else { + localWarningMessage = localWarningMessage.concat("; " + warningMessage); + } + } else { + // ----------------------------------------------------------- + // Is this a FileReplaceOperation? If so, then diverge! + // ----------------------------------------------------------- + if (this.isFileReplaceOperation()){ + this.handleReplaceFileUpload(storageLocation, fileName, FileUtil.MIME_TYPE_UNDETERMINED_DEFAULT); + this.setFileMetadataSelectedForTagsPopup(fileReplacePageHelper.getNewFileMetadatasBeforeSave().get(0)); + return; + } + // ----------------------------------------------------------- + List datafiles = new ArrayList<>(); + + // ----------------------------------------------------------- + // Send it through the ingest service + // ----------------------------------------------------------- + try { + + // Note: A single uploaded file may produce multiple datafiles - + // for example, multiple files can be extracted from an uncompressed + // zip file. + //datafiles = ingestService.createDataFiles(workingVersion, dropBoxStream, fileName, "application/octet-stream"); + if(contentType==null) { + contentType = "application/octet-stream"; + } + if(DataFile.ChecksumType.fromString(checksumType) != DataFile.ChecksumType.MD5 ) { + String warningMessage = "Non-MD5 checksums not yet supported in external uploads"; + if (localWarningMessage == null) { + localWarningMessage = warningMessage; + } else { + localWarningMessage = localWarningMessage.concat("; " + warningMessage); + } + + } + datafiles = FileUtil.createDataFiles(workingVersion, null, fileName, contentType, storageLocation, checksumValue, systemConfig); + logger.info("Created " + datafiles.size() + " files."); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Error during ingest of file {0}", new Object[]{fileName}); + } + + if (datafiles == null){ + logger.log(Level.SEVERE, "Failed to create DataFile for file {0}", new Object[]{fileName}); + }else{ + // ----------------------------------------------------------- + // Check if there are duplicate files or ingest warnings + // ----------------------------------------------------------- + uploadWarningMessage = processUploadedFileList(datafiles); + logger.info("Warning message during upload: " + uploadWarningMessage); + } + if(!uploadInProgress) { + logger.warning("Upload in progress cancelled"); + for (DataFile newFile : datafiles) { + deleteTempFile(newFile); + } + } + } + } catch (IOException e) { + logger.log(Level.SEVERE, "Failed to create DataFile for file {0}: {1}", new Object[]{fileName, e.getMessage()}); + } + if (localWarningMessage != null) { + if (uploadWarningMessage == null) { + uploadWarningMessage = localWarningMessage; + } else { + uploadWarningMessage = localWarningMessage.concat("; " + uploadWarningMessage); + } + } + } + /** * After uploading via the site or Dropbox, * check the list of DataFile objects @@ -1980,7 +2147,7 @@ public void handleFileUpload(FileUploadEvent event) throws IOException { private boolean uploadInProgress = false; private String processUploadedFileList(List dFileList) { - + logger.info("Processing list of " + dFileList.size() + " files."); if (dFileList == null) { return null; } @@ -2042,6 +2209,7 @@ private String processUploadedFileList(List dFileList) { dataFile.setPreviewImageAvailable(true); } uploadedFiles.add(dataFile); + logger.info("Added file to list: " + dataFile.getFileMetadata().getLabel()); // We are NOT adding the fileMetadata to the list that is being used // to render the page; we'll do that once we know that all the individual uploads // in this batch (as in, a bunch of drag-and-dropped files) have finished. diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index bdde4aa21c9..322c9922a3f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -1449,13 +1449,24 @@ public Response getUploadUrl(@PathParam("id") String idSupplied) { if (!canUpdateDataset) { return error(Response.Status.FORBIDDEN, "You are not permitted to upload files to this dataset."); } - - String url = FileUtil.getDirectUploadUrl(dataset); - if(url==null) { + S3AccessIO s3io = FileUtil.getS3AccessForDirectUpload(dataset); + if(s3io == null) { return error(Response.Status.NOT_FOUND,"Direct upload not supported for files in this dataset: " + dataset.getId()); } - String driverId = DataAccess.getStorageDriverId(dataset.getDataverseContext()); - String response = "{\"url\":\"" + url + "\",\"driverId\":\"" + driverId + "\"}"; + String url = null; + String storageIdentifier = null; + try { + url = s3io.generateTemporaryS3UploadUrl(); + storageIdentifier = FileUtil.getStorageIdentifierFromLocation(s3io.getStorageLocation()); + } catch (IOException io) { + logger.warning(io.getMessage()); + throw new WrappedResponse(io, error( Response.Status.INTERNAL_SERVER_ERROR, "Could not create process direct upload request")); + } + + + JsonObjectBuilder response = Json.createObjectBuilder() + .add("url", url) + .add("storageIdentifier", storageIdentifier ); return ok(response); } catch (WrappedResponse wr) { return wr.getResponse(); diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index db24fa94382..9c77cdf6293 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -91,24 +91,24 @@ public static StorageIO getStorageIO(T dvObject, DataAcc // Experimental extension of the StorageIO system allowing direct access to // stored physical files that may not be associated with any DvObjects - public static StorageIO getDirectStorageIO(String storageLocation) throws IOException { - String[] response = getDriverIdAndStorageId(storageLocation); + public static StorageIO getDirectStorageIO(String fullStorageLocation) throws IOException { + String[] response = getDriverIdAndStorageLocation(fullStorageLocation); String storageDriverId = response[0]; - String storageIdentifier=response[1]; + String storageLocation=response[1]; String storageType = getDriverType(storageDriverId); switch(storageType) { case "file": - return new FileAccessIO<>(storageIdentifier, storageDriverId); + return new FileAccessIO<>(storageLocation, storageDriverId); case "s3": - return new S3AccessIO<>(storageIdentifier, storageDriverId); + return new S3AccessIO<>(storageLocation, storageDriverId); case "swift": - return new SwiftAccessIO<>(storageIdentifier, storageDriverId); + return new SwiftAccessIO<>(storageLocation, storageDriverId); default: throw new IOException("getDirectStorageIO: Unsupported storage method."); } } - public static String[] getDriverIdAndStorageId(String storageLocation) { + public static String[] getDriverIdAndStorageLocation(String storageLocation) { //default if no prefix String storageIdentifier=storageLocation; int separatorIndex = storageLocation.indexOf("://"); @@ -120,6 +120,10 @@ public static String[] getDriverIdAndStorageId(String storageLocation) { return new String[]{storageDriverId, storageIdentifier}; } + public static String getStorarageIdFromLocation(String location) { + return location.substring(location.lastIndexOf('/')+1); + } + public static String getDriverType(String driverId) { return System.getProperty("dataverse.files." + driverId + ".type", "file"); } diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index d0949e821c8..13c8a8a1e17 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -1,6 +1,7 @@ package edu.harvard.iq.dataverse.dataaccess; import com.amazonaws.AmazonClientException; +import com.amazonaws.AmazonServiceException; import com.amazonaws.HttpMethod; import com.amazonaws.SdkClientException; import com.amazonaws.auth.profile.ProfileCredentialsProvider; @@ -101,11 +102,12 @@ public S3AccessIO(T dvObject, DataAccessRequest req, String driverId) { } - public S3AccessIO(String storageLocation, String driverId) { + public S3AccessIO(String storageLocation, String driverId) throws IOException { this(null, null, driverId); // TODO: validate the storage location supplied bucketName = storageLocation.substring(0,storageLocation.indexOf('/')); key = storageLocation.substring(storageLocation.indexOf('/')+1); + } public S3AccessIO(T dvObject, DataAccessRequest req, @NotNull AmazonS3 s3client, String driverId) { @@ -126,7 +128,7 @@ public S3AccessIO(T dvObject, DataAccessRequest req, @NotNull AmazonS3 s3client, private String s3profile = "default"; private String bucketName = null; - private String key; + private String key = null; @Override public void open(DataAccessOption... options) throws IOException { @@ -212,7 +214,18 @@ public void open(DataAccessOption... options) throws IOException { } else if (dvObject instanceof Dataverse) { throw new IOException("Data Access: Storage driver does not support dvObject type Dataverse yet"); } else { + //Direct access, e.g. for external upload - no associated DVobject yet, but we want to be abel to get the size + if(key!=null) { + ObjectMetadata objectMetadata = null; + try { + objectMetadata = s3.getObjectMetadata(bucketName, key); + } catch (SdkClientException sce) { + throw new IOException("Cannot get S3 object " + key + " ("+sce.getMessage()+")"); + } + this.setSize(objectMetadata.getContentLength()); + }else { throw new IOException("Data Access: Invalid DvObject type"); + } } } @@ -773,7 +786,7 @@ public String generateTemporaryS3Url() throws IOException { key = getMainFileKey(); java.util.Date expiration = new java.util.Date(); long msec = expiration.getTime(); - msec += 1000 * getUrlExpirationMinutes(); + msec += 60 * 1000 * getUrlExpirationMinutes(); expiration.setTime(msec); GeneratePresignedUrlRequest generatePresignedUrlRequest = @@ -821,40 +834,37 @@ public String generateTemporaryS3Url() throws IOException { } public String generateTemporaryS3UploadUrl() throws IOException { - //Questions: - // Q. how long should the download url work? - // A. 1 hour by default seems like an OK number. Making it configurable seems like a good idea too. -- L.A. - if (s3 == null) { - throw new IOException("ERROR: s3 not initialised. "); - } - //ToDO: Check for existing file given storage ID (could check bucket and/or DV Datafile - if(true) { - key = getMainFileKey(); - java.util.Date expiration = new java.util.Date(); - long msec = expiration.getTime(); - msec += 1000 * getUrlExpirationMinutes(); - expiration.setTime(msec); - - GeneratePresignedUrlRequest generatePresignedUrlRequest = - new GeneratePresignedUrlRequest(bucketName, key).withMethod(HttpMethod.PUT).withExpiration(expiration); - URL s; - try { - s = s3.generatePresignedUrl(generatePresignedUrlRequest); - } catch (SdkClientException sce) { - //throw new IOException("SdkClientException generating temporary S3 url for "+key+" ("+sce.getMessage()+")"); - s = null; - } + key = getMainFileKey(); + java.util.Date expiration = new java.util.Date(); + long msec = expiration.getTime(); + msec += 60 * 1000 * getUrlExpirationMinutes(); + expiration.setTime(msec); - if (s != null) { - return s.toString(); - } - - //throw new IOException("Failed to generate temporary S3 url for "+key); - return null; - } else { - throw new IOException("Data Access: GenerateTemporaryS3UploadUrl: StorageIdentifier already in use!"); - } + GeneratePresignedUrlRequest generatePresignedUrlRequest = + new GeneratePresignedUrlRequest(bucketName, key).withMethod(HttpMethod.PUT).withExpiration(expiration); + URL presignedUrl; + try { + presignedUrl = s3.generatePresignedUrl(generatePresignedUrlRequest); + } catch (SdkClientException sce) { + //throw new IOException("SdkClientException generating temporary S3 url for "+key+" ("+sce.getMessage()+")"); + presignedUrl = null; + } + String urlString = null; + if (presignedUrl != null) { + String endpoint = System.getProperty("dataverse.files." + driverId + ".custom-endpoint-url"); + logger.info("endpoint: " + endpoint); + String proxy = System.getProperty("dataverse.files." + driverId + ".proxy-url"); + logger.info("proxy: " + proxy); + if(proxy!=null) { + urlString = presignedUrl.toString().replace(endpoint, proxy); + } else { + urlString = presignedUrl.toString(); + } + } + + //throw new IOException("Failed to generate temporary S3 url for "+key); + return urlString; } int getUrlExpirationMinutes() { diff --git a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java index 700b04ab0d9..ea5b5ed3d5e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java +++ b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java @@ -442,6 +442,7 @@ public boolean runReplaceFromUI_Phase1(Long oldFileId, String newFileName, String newFileContentType, InputStream newFileInputStream, + String fullStorageId, OptionalFileParams optionalFileParams){ @@ -463,7 +464,7 @@ public boolean runReplaceFromUI_Phase1(Long oldFileId, return this.runAddReplacePhase1(fileToReplace.getOwner(), newFileName, newFileContentType, - null, + fullStorageId, newFileInputStream, optionalFileParams); diff --git a/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileReplacePageHelper.java b/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileReplacePageHelper.java index e6d7c1e5ebe..94f247e6419 100644 --- a/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileReplacePageHelper.java +++ b/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileReplacePageHelper.java @@ -96,14 +96,14 @@ public boolean resetReplaceFileHelper(){ * Handle native file replace * @param event */ - public boolean handleNativeFileUpload(InputStream inputStream, String fileName, String fileContentType) { + public boolean handleNativeFileUpload(InputStream inputStream, String fullStorageId, String fileName, String fileContentType) { phase1Success = false; // Preliminary sanity check // - if (inputStream == null){ - throw new NullPointerException("inputStream cannot be null"); + if ((inputStream == null)&&(fullStorageId==null)){ + throw new NullPointerException("inputStream and storageId cannot both be null"); } if (fileName == null){ throw new NullPointerException("fileName cannot be null"); @@ -118,6 +118,7 @@ public boolean handleNativeFileUpload(InputStream inputStream, String fileName, fileName, fileContentType, inputStream, + fullStorageId, null ); diff --git a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java index c9f0eed779c..83ba0cdb88b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java @@ -176,22 +176,22 @@ public List saveAndAddFilesToDataset(DatasetVersion version, List dataAccess = null; try { - logger.fine("Attempting to create a new storageIO object for " + storageId); - dataAccess = DataAccess.createNewStorageIO(dataFile, storageId); + logger.fine("Attempting to create a new storageIO object for " + storageLocation); + dataAccess = DataAccess.createNewStorageIO(dataFile, storageLocation); logger.fine("Successfully created a new storageIO object."); /* @@ -252,7 +252,7 @@ public List saveAndAddFilesToDataset(DatasetVersion version, List generatedTempFiles = listGeneratedTempFiles(Paths.get(FileUtil.getFilesTempDirectory()), - storageId); + storageLocation); if (generatedTempFiles != null) { for (Path generated : generatedTempFiles) { if (savedSuccess) { // no need to try to save this aux file permanently, if we've failed to diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index 1a799ebd786..7318f082d04 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -82,6 +82,8 @@ import static edu.harvard.iq.dataverse.datasetutility.FileSizeChecker.bytesToHumanReadable; import org.apache.commons.io.FilenameUtils; +import com.amazonaws.AmazonServiceException; + /** * a 4.0 implementation of the DVN FileUtil; @@ -1669,33 +1671,39 @@ public static boolean isPackageFile(DataFile dataFile) { return DataFileServiceBean.MIME_TYPE_PACKAGE_FILE.equalsIgnoreCase(dataFile.getContentType()); } - public static String getDirectUploadUrl(Dataset dataset) { - String driverId = DataAccess.getStorageDriverId(dataset.getDataverseContext()); - boolean directEnabled = Boolean.getBoolean("dataverse.files." + driverId + ".upload-redirect"); - //Should only be requested when it is allowed, but we'll log a warning otherwise - if(!directEnabled) { - logger.warning("Direct upload not supported for files in this dataset: " + dataset.getId()); - return null; - } - String bucket = System.getProperty("dataverse.files." + driverId + ".bucket-name") + "/"; - String sid = bucket+ dataset.getAuthorityForFileStorage() + "/" + dataset.getIdentifierForFileStorage() + "/" + FileUtil.generateStorageIdentifier(); - S3AccessIO s3io = new S3AccessIO(sid, driverId); - String url = null; - try { - url = s3io.generateTemporaryS3UploadUrl(); - } catch (IOException e) { - logger.warning("Identifier Collision"); - e.printStackTrace(); - } - String endpoint = System.getProperty("dataverse.files." + driverId + ".custom-endpoint-url"); - logger.info("endpoint: " + endpoint); - String proxy = System.getProperty("dataverse.files." + driverId + ".proxy-url"); - logger.info("proxy: " + proxy); - if(proxy!=null) { - url = url.replace(endpoint, proxy); - } - logger.info("url: " + url); - return url; + public static S3AccessIO getS3AccessForDirectUpload(Dataset dataset) { + String driverId = DataAccess.getStorageDriverId(dataset.getDataverseContext()); + boolean directEnabled = Boolean.getBoolean("dataverse.files." + driverId + ".upload-redirect"); + //Should only be requested when it is allowed, but we'll log a warning otherwise + if(!directEnabled) { + logger.warning("Direct upload not supported for files in this dataset: " + dataset.getId()); + return null; + } + S3AccessIO s3io = null; + String bucket = System.getProperty("dataverse.files." + driverId + ".bucket-name") + "/"; + String sid = null; + int i=0; + while (s3io==null && i<5) { + sid = bucket+ dataset.getAuthorityForFileStorage() + "/" + dataset.getIdentifierForFileStorage() + "/" + FileUtil.generateStorageIdentifier(); + try { + s3io = new S3AccessIO(sid, driverId); + if(s3io.exists()) { + s3io=null; + i=i+1; + } + + } catch (Exception e) { + i=i+1; + } + + } + return s3io; + } + + public static String getStorageIdentifierFromLocation(String location) { + int driverEnd = location.indexOf("://") + 3; + int bucketEnd = driverEnd + location.substring(driverEnd).indexOf("/"); + return location.substring(0,bucketEnd) + ":" + location.substring(location.lastIndexOf("/") + 1); } } diff --git a/src/main/webapp/editFilesFragment.xhtml b/src/main/webapp/editFilesFragment.xhtml index db17829ae4e..900ef90e9ed 100644 --- a/src/main/webapp/editFilesFragment.xhtml +++ b/src/main/webapp/editFilesFragment.xhtml @@ -520,6 +520,7 @@ + diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index febf7c59a57..c6e1b18148b 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -11,7 +11,7 @@ function setupDirectUpload(enabled, theDatasetId) { fileInput.addEventListener('change', function(event) { fileList=[]; for(var i=0;i')); + $('.ui-fileupload-progress').append($('')); $.ajax({ url: url, - type: 'POST', + type: 'PUT', data: data, cache: false, processData: false, - success: reportUpload, + success: function () { + reportUpload(storageId, fileList[0]) + }, + error: function(jqXHR, textStatus, errorThrown) { + console.log('Failure: ' + jqXHR.status); + console.log('Failure: ' + errorThrown); + }, xhr: function() { var myXhr = $.ajaxSettings.xhr(); if(myXhr.upload) { @@ -72,22 +78,34 @@ function uploadFileDirectly(url) { $('progress').attr({ value:e.loaded, max:e.total - }) + }); } - }) + }); } + return myXhr; } }); - //perform post - check cors issues + console.log('after ajax'); +//perform post - check cors issues //trigger gui swap/server file add //handle cancel buttons? - + } -function reportUpload(data){ - console.log('Done ' + data ); +function reportUpload(storageId, file){ + + //storageId is not the location - has a : separator and no path elements from dataset + + //(String uploadComponentId, String fullStorageIdentifier, String fileName, String contentType, String checksumType, String checksumValue) + handleExternalUpload([{name:'uploadComponentId', value:'datasetForm:fileUpload'}, {name:'fullStorageIdentifier', value:storageId}, {name:'fileName', value:file.name}, {name:'contentType', value:file.type}, {name:'checksumType', value:'MD5'}, {name:'checksumValue', value:0}]); + console.log('Done ' + storageId + " " + file.name ); + $('.ui-fileupload-files').html(""); + fileList=[]; + uploadFinished(document.getElementById('datasetForm:fileUpload_input')); + } + function removeErrors() { var errors = document.getElementsByClassName("ui-fileupload-error"); for(i=errors.length-1; i >=0; i--) { @@ -136,6 +154,8 @@ function uploadFinished(fileupload) { observer.disconnect(); observer=null; } + } else { + console.log('Still ' + fileupload.files.length + ' files' ); } } From d8de35fb687d34bb0021465b7dfbae2dd19c5c2c Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 12:10:24 -0500 Subject: [PATCH 061/475] send ID without dataset path --- src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index d26d0a33112..fae88a20c07 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -2100,7 +2100,7 @@ public void handleExternalUpload() { } } - datafiles = FileUtil.createDataFiles(workingVersion, null, fileName, contentType, storageLocation, checksumValue, systemConfig); + datafiles = FileUtil.createDataFiles(workingVersion, null, fileName, contentType, fullStorageIdentifier, checksumValue, systemConfig); logger.info("Created " + datafiles.size() + " files."); } catch (IOException ex) { logger.log(Level.SEVERE, "Error during ingest of file {0}", new Object[]{fileName}); From c1db7a5615e5f508086b00b4add75aae7d3b9430 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 12:13:23 -0500 Subject: [PATCH 062/475] add md5 --- src/main/webapp/editFilesFragment.xhtml | 2 + src/main/webapp/resources/js/fileupload.js | 78 +++++++++++++++++++--- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/main/webapp/editFilesFragment.xhtml b/src/main/webapp/editFilesFragment.xhtml index 900ef90e9ed..8e255df9368 100644 --- a/src/main/webapp/editFilesFragment.xhtml +++ b/src/main/webapp/editFilesFragment.xhtml @@ -12,6 +12,8 @@ xmlns:iqbs="http://xmlns.jcp.org/jsf/composite/iqbs"> + +
    diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index c6e1b18148b..fc769d9b4a4 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -94,15 +94,19 @@ function uploadFileDirectly(url, storageId) { function reportUpload(storageId, file){ - //storageId is not the location - has a : separator and no path elements from dataset - - //(String uploadComponentId, String fullStorageIdentifier, String fileName, String contentType, String checksumType, String checksumValue) - handleExternalUpload([{name:'uploadComponentId', value:'datasetForm:fileUpload'}, {name:'fullStorageIdentifier', value:storageId}, {name:'fileName', value:file.name}, {name:'contentType', value:file.type}, {name:'checksumType', value:'MD5'}, {name:'checksumValue', value:0}]); - console.log('Done ' + storageId + " " + file.name ); - $('.ui-fileupload-files').html(""); - fileList=[]; - uploadFinished(document.getElementById('datasetForm:fileUpload_input')); + getMD5( + file, + prog => console.log("Progress: " + prog) + ).then( + md5 => { + //storageId is not the location - has a : separator and no path elements from dataset + //(String uploadComponentId, String fullStorageIdentifier, String fileName, String contentType, String checksumType, String checksumValue) + handleExternalUpload([{name:'uploadComponentId', value:'datasetForm:fileUpload'}, {name:'fullStorageIdentifier', value:storageId}, {name:'fileName', value:file.name}, {name:'contentType', value:file.type}, {name:'checksumType', value:'MD5'}, {name:'checksumValue', value:d5}]); + console.log('Done ' + storageId + " " + file.name ); + }, + err => console.error(err) + ); } @@ -207,3 +211,61 @@ function uploadFailure(fileUpload) { } } } + +//MD5 Hashing functions + +function readChunked(file, chunkCallback, endCallback) { + var fileSize = file.size; + var chunkSize = 4 * 1024 * 1024; // 4MB + var offset = 0; + + var reader = new FileReader(); + reader.onload = function() { + if (reader.error) { + endCallback(reader.error || {}); + return; + } + offset += reader.result.length; + // callback for handling read chunk + // TODO: handle errors + chunkCallback(reader.result, offset, fileSize); + if (offset >= fileSize) { + endCallback(null); + return; + } + readNext(); + }; + + reader.onerror = function(err) { + endCallback(err || {}); + }; + + function readNext() { + var fileSlice = file.slice(offset, offset + chunkSize); + reader.readAsBinaryString(fileSlice); + } + readNext(); +} + +function getMD5(blob, cbProgress) { + return new Promise((resolve, reject) => { + var md5 = CryptoJS.algo.MD5.create(); + readChunked(blob, (chunk, offs, total) => { + md5.update(CryptoJS.enc.Latin1.parse(chunk)); + if (cbProgress) { + cbProgress(offs / total); + } + }, err => { + if (err) { + reject(err); + } else { + // TODO: Handle errors + var hash = md5.finalize(); + var hashHex = hash.toString(CryptoJS.enc.Hex); + resolve(hashHex); + } + }); + }); +} + + From 707709f7fcb76b312a57e0c41874c0f4605bc01e Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 12:13:55 -0500 Subject: [PATCH 063/475] bug: switch to calling uploadFinished at oncomplete --- src/main/webapp/editFilesFragment.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/editFilesFragment.xhtml b/src/main/webapp/editFilesFragment.xhtml index 8e255df9368..32739aef301 100644 --- a/src/main/webapp/editFilesFragment.xhtml +++ b/src/main/webapp/editFilesFragment.xhtml @@ -522,7 +522,7 @@ - + From 25c1739d1e6c25f8a96d8071446b391c4122f621 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 13:54:31 -0500 Subject: [PATCH 064/475] fix exist test for direct access --- .../java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index 13c8a8a1e17..7fe8fe505f0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -691,6 +691,9 @@ public boolean exists() { String destinationKey = null; if (dvObject instanceof DataFile) { destinationKey = key; + } else if((dvObject==null) && (key !=null)) { + //direct access + destinationKey = key; } else { logger.warning("Trying to check if a path exists is only supported for a data file."); } From dd1cca07f63e231d3c782a78a12de06b32464e60 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 13:54:51 -0500 Subject: [PATCH 065/475] debug constraint violations --- src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index fae88a20c07..ca2b112c3d9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -1230,7 +1230,7 @@ public String save() { Command cmd; try { cmd = new UpdateDatasetVersionCommand(dataset, dvRequestService.getDataverseRequest(), filesToBeDeleted, clone); - ((UpdateDatasetVersionCommand) cmd).setValidateLenient(true); + ((UpdateDatasetVersionCommand) cmd).setValidateLenient(false); dataset = commandEngine.submit(cmd); } catch (EJBException ex) { From a02980bf10151cda15283168be367f995a8bc288 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 13:55:25 -0500 Subject: [PATCH 066/475] typo, clear file list after upload complete --- src/main/webapp/resources/js/fileupload.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index fc769d9b4a4..3107c704ff5 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -101,8 +101,11 @@ function reportUpload(storageId, file){ md5 => { //storageId is not the location - has a : separator and no path elements from dataset + $('.ui-fileupload-files').html(""); + fileList=[]; + //(String uploadComponentId, String fullStorageIdentifier, String fileName, String contentType, String checksumType, String checksumValue) - handleExternalUpload([{name:'uploadComponentId', value:'datasetForm:fileUpload'}, {name:'fullStorageIdentifier', value:storageId}, {name:'fileName', value:file.name}, {name:'contentType', value:file.type}, {name:'checksumType', value:'MD5'}, {name:'checksumValue', value:d5}]); + handleExternalUpload([{name:'uploadComponentId', value:'datasetForm:fileUpload'}, {name:'fullStorageIdentifier', value:storageId}, {name:'fileName', value:file.name}, {name:'contentType', value:file.type}, {name:'checksumType', value:'MD5'}, {name:'checksumValue', value:md5}]); console.log('Done ' + storageId + " " + file.name ); }, err => console.error(err) @@ -163,6 +166,19 @@ function uploadFinished(fileupload) { } } +function directUploadFinished() { + if (fileList.length === 0) { + $('button[id$="AllUploadsFinished"]').trigger('click'); + //stop observer when we're done + if(observer !=null) { + observer.disconnect(); + observer=null; + } + } else { + console.log('Still ' + fileupload.files.length + ' files' ); + } +} + function uploadFailure(fileUpload) { // This handles HTTP errors (non-20x reponses) such as 0 (no connection at all), 413 (Request too large), // and 504 (Gateway timeout) where the upload call to the server fails (the server doesn't receive the request) From cafcfeeffe4d8537331e27b83d897cb5b47730c3 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 14:23:30 -0500 Subject: [PATCH 067/475] use new method --- src/main/webapp/editFilesFragment.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/editFilesFragment.xhtml b/src/main/webapp/editFilesFragment.xhtml index 32739aef301..ac4fd701744 100644 --- a/src/main/webapp/editFilesFragment.xhtml +++ b/src/main/webapp/editFilesFragment.xhtml @@ -522,7 +522,7 @@ - + From 8859e1dbfda1ba88ba07c00d45af4f3f4c9d764b Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 16:33:23 -0500 Subject: [PATCH 068/475] catch empty contentType not just null --- src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index ca2b112c3d9..f3af6e86f66 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -2088,7 +2088,7 @@ public void handleExternalUpload() { // for example, multiple files can be extracted from an uncompressed // zip file. //datafiles = ingestService.createDataFiles(workingVersion, dropBoxStream, fileName, "application/octet-stream"); - if(contentType==null) { + if(StringUtils.isEmpty(contentType)) { contentType = "application/octet-stream"; } if(DataFile.ChecksumType.fromString(checksumType) != DataFile.ChecksumType.MD5 ) { From 25da677a62a9d4678495d3e392309d41a4beb9d6 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 16:33:57 -0500 Subject: [PATCH 069/475] List any constraint violations --- .../command/impl/UpdateDatasetVersionCommand.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetVersionCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetVersionCommand.java index 0bcf11d371d..fefa8707c8b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetVersionCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/UpdateDatasetVersionCommand.java @@ -15,6 +15,9 @@ import java.util.concurrent.Future; import java.util.logging.Level; import java.util.logging.Logger; + +import javax.validation.ConstraintViolationException; + import org.apache.solr.client.solrj.SolrServerException; /** @@ -119,7 +122,13 @@ public Dataset execute(CommandContext ctxt) throws CommandException { if (editVersion.getId() == null || editVersion.getId() == 0L) { ctxt.em().persist(editVersion); } else { - ctxt.em().merge(editVersion); + try { + ctxt.em().merge(editVersion); + } catch (ConstraintViolationException e) { + logger.log(Level.SEVERE,"Exception: "); + e.getConstraintViolations().forEach(err->logger.log(Level.SEVERE,err.toString())); + throw e; + } } for (DataFile dataFile : theDataset.getFiles()) { From e07b2df7f617ecadd92aa83bb3b976c3e941fc0a Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 2 Jan 2020 16:35:34 -0500 Subject: [PATCH 070/475] try adding multifile support, fix repeat uploads --- src/main/webapp/resources/js/fileupload.js | 42 ++++++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index 3107c704ff5..c3b177ee627 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -37,7 +37,7 @@ function setupDirectUpload(enabled, theDatasetId) { observer2.disconnect(); } observer2 = new MutationObserver(callback); - observer2.observe(fileInput.parentElement,config); + observer2.observe(document.getElementById('datasetForm:fileUpload'),config); } //else ? } @@ -48,6 +48,13 @@ function queueFileForDirectUpload(file, datasetId) { //check for dupes //check size requestDirectUploadUrl(); + var files = $('.ui-fileupload-files .ui-fileupload-row'); + //Add an id attribute to each entry so we can later match errors with the right entry + for(var i=0;i< files.length;i++) { + if(files[i].children[1].nodeValue == file.name) { + files[i].setAttribute('upid', 'pending'); + } + } console.log('URL Requested'); } @@ -55,7 +62,22 @@ function queueFileForDirectUpload(file, datasetId) { function uploadFileDirectly(url, storageId) { console.log("Retrieved " + url + ' for ' + storageId); var data = new FormData(); - data.append('file',fileList[0]); + //Pick a pending file + var files = $('.ui-fileupload-files .ui-fileupload-row'); + var index = -1; + for(var i=0;i< files.length;i++) { + if(files[i].getAttribute('upid') == 'pending') { + files[i].setAttribute('upid', storageId); + for(var j=0;j')); $.ajax({ url: url, @@ -64,7 +86,7 @@ function uploadFileDirectly(url, storageId) { cache: false, processData: false, success: function () { - reportUpload(storageId, fileList[0]) + reportUpload(storageId, fileList[index]) }, error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); @@ -100,9 +122,15 @@ function reportUpload(storageId, file){ ).then( md5 => { //storageId is not the location - has a : separator and no path elements from dataset - - $('.ui-fileupload-files').html(""); - fileList=[]; + var index = -1; + for(var j=0;j Date: Thu, 2 Jan 2020 17:12:28 -0500 Subject: [PATCH 071/475] just pop for multifile --- src/main/webapp/resources/js/fileupload.js | 37 +++------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index c3b177ee627..aca70f7e4cc 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -48,13 +48,7 @@ function queueFileForDirectUpload(file, datasetId) { //check for dupes //check size requestDirectUploadUrl(); - var files = $('.ui-fileupload-files .ui-fileupload-row'); - //Add an id attribute to each entry so we can later match errors with the right entry - for(var i=0;i< files.length;i++) { - if(files[i].children[1].nodeValue == file.name) { - files[i].setAttribute('upid', 'pending'); - } - } + console.log('URL Requested'); } @@ -63,21 +57,8 @@ function uploadFileDirectly(url, storageId) { console.log("Retrieved " + url + ' for ' + storageId); var data = new FormData(); //Pick a pending file - var files = $('.ui-fileupload-files .ui-fileupload-row'); - var index = -1; - for(var i=0;i< files.length;i++) { - if(files[i].getAttribute('upid') == 'pending') { - files[i].setAttribute('upid', storageId); - for(var j=0;j')); $.ajax({ url: url, @@ -86,7 +67,7 @@ function uploadFileDirectly(url, storageId) { cache: false, processData: false, success: function () { - reportUpload(storageId, fileList[index]) + reportUpload(storageId, file) }, error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); @@ -122,16 +103,6 @@ function reportUpload(storageId, file){ ).then( md5 => { //storageId is not the location - has a : separator and no path elements from dataset - var index = -1; - for(var j=0;j Date: Fri, 3 Jan 2020 14:24:29 -0500 Subject: [PATCH 072/475] control store via dataverse.storagedriver param manageable by superuser only --- .../edu/harvard/iq/dataverse/Dataverse.java | 10 +++ .../harvard/iq/dataverse/DataversePage.java | 11 ++++ .../iq/dataverse/EditDatafilesPage.java | 6 +- .../harvard/iq/dataverse/api/Datasets.java | 2 +- .../iq/dataverse/dataaccess/DataAccess.java | 61 ++++++++++++++----- .../impl/AbstractCreateDatasetCommand.java | 2 +- .../harvard/iq/dataverse/util/FileUtil.java | 4 +- src/main/java/propertyFiles/Bundle.properties | 2 + .../migration/V4.19.0.1__tbd_multistore.sql | 2 + src/main/webapp/dataverse.xhtml | 13 ++++ 10 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 src/main/resources/db/migration/V4.19.0.1__tbd_multistore.sql diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java index 024281b0b96..02dd1fa09a9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java @@ -147,6 +147,8 @@ public String getIndexableCategoryName() { } private String affiliation; + + private String storageDriver; // Note: We can't have "Remove" here, as there are role assignments that refer // to this role. So, adding it would mean violating a forign key contstraint. @@ -756,4 +758,12 @@ public boolean isAncestorOf( DvObject other ) { } return false; } + + public String getStorageDriverId() { + return storageDriver; + } + + public void setStorageDriverId(String storageDriver) { + this.storageDriver = storageDriver; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java index eca97e52402..a1f21c07888 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java @@ -4,6 +4,7 @@ import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.authorization.users.User; +import edu.harvard.iq.dataverse.dataaccess.DataAccess; import edu.harvard.iq.dataverse.dataverse.DataverseUtil; import edu.harvard.iq.dataverse.engine.command.Command; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; @@ -39,6 +40,8 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.faces.component.UIComponent; @@ -1182,4 +1185,12 @@ public List completeHostDataverseMenuList(String query) { return null; } } + + public Set> getStorageDriverOptions() { + return DataAccess.getStorageDriverLabels(); + } + + public String getCurrentStorageDriverLabel() { + return DataAccess.getStorageDriverLabelFor(dataverse.getStorageDriverId()); + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index f3af6e86f66..2a0c9efc786 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -358,9 +358,9 @@ public boolean doesSessionUserHaveDataSetPermission(Permission permissionToCheck } public boolean directUploadEnabled() { - logger.info(this.dataset.getDataverseContext().getAlias() + " " + this.dataset.getDataverseContext().getAffiliation() + " " + DataAccess.getStorageDriverId(this.dataset.getDataverseContext())); - logger.info("denabled: " + DataAccess.getStorageDriverId(this.dataset.getDataverseContext()) + " " + Boolean.getBoolean("dataverse.files." + DataAccess.getStorageDriverId(this.dataset.getDataverseContext()) + ".upload-redirect")); - return Boolean.getBoolean("dataverse.files." + DataAccess.getStorageDriverId(this.dataset.getDataverseContext()) + ".upload-redirect"); + logger.info(this.dataset.getDataverseContext().getAlias() + " " + this.dataset.getDataverseContext().getAffiliation() + " " + this.dataset.getDataverseContext().getStorageDriverId()); + logger.info("denabled: " + this.dataset.getDataverseContext().getStorageDriverId() + " " + Boolean.getBoolean("dataverse.files." + this.dataset.getDataverseContext().getStorageDriverId() + ".upload-redirect")); + return Boolean.getBoolean("dataverse.files." + this.dataset.getDataverseContext().getStorageDriverId() + ".upload-redirect"); } public void reset() { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index 322c9922a3f..bc15b04ab31 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -1301,7 +1301,7 @@ public Response receiveChecksumValidationResults(@PathParam("identifier") String if ("validation passed".equals(statusMessageFromDcm)) { logger.log(Level.INFO, "Checksum Validation passed for DCM."); - String storageDriver = DataAccess.getStorageDriverId(dataset.getDataverseContext()); + String storageDriver = dataset.getDataverseContext().getStorageDriverId(); String uploadFolder = jsonFromDcm.getString("uploadFolder"); int totalSize = jsonFromDcm.getInt("totalSize"); String storageDriverType = System.getProperty("dataverse.file." + storageDriver + ".type"); diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index 9c77cdf6293..6773cb7e357 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -22,9 +22,14 @@ import edu.harvard.iq.dataverse.Dataverse; import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.util.StringUtil; + import java.io.IOException; import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; import java.util.Properties; +import java.util.Set; /** * * @author Leonid Andreev @@ -132,7 +137,7 @@ public static String getDriverType(String driverId) { // for saving new, not yet saved datafiles. public static StorageIO createNewStorageIO(T dvObject, String storageTag) throws IOException { - return createNewStorageIO(dvObject, storageTag, getStorageDriverId(dvObject.getDataverseContext())); + return createNewStorageIO(dvObject, storageTag, dvObject.getDataverseContext().getStorageDriverId()); } public static StorageIO createNewStorageIO(T dvObject, String storageTag, String storageDriverId) throws IOException { @@ -170,25 +175,51 @@ public static StorageIO createNewStorageIO(T dvObject, S static HashMap drivers = null; - public static String getStorageDriverId(Dataverse dataverse) { + public static String getStorageDriverId(String driverLabel) { if (drivers==null) { - drivers = new HashMap(); - Properties p = System.getProperties(); - for(String property: p.stringPropertyNames()) { - if(property.startsWith("dataverse.files.") && property.endsWith(".affiliation")) { - String driverId = property.substring(16); - driverId=driverId.substring(0,driverId.indexOf('.')); - logger.info("Found Storage Driver: " + driverId + " for " + p.get(property).toString()); - drivers.put(p.get(property).toString(), driverId); - } - - } + populateDrivers(); } - if(drivers.containsKey(dataverse.getAffiliation())) { - return drivers.get(dataverse.getAffiliation()); + if(StringUtil.nonEmpty(driverLabel) && drivers.containsKey(driverLabel)) { + return drivers.get(driverLabel); } return DEFAULT_STORAGE_DRIVER_IDENTIFIER; + } + public static Set> getStorageDriverLabels() { + if (drivers==null) { + populateDrivers(); + } + return drivers.entrySet(); } + private static void populateDrivers() { + drivers = new HashMap(); + Properties p = System.getProperties(); + for(String property: p.stringPropertyNames()) { + if(property.startsWith("dataverse.files.") && property.endsWith(".label")) { + String driverId = property.substring(16); // "dataverse.files.".length + driverId=driverId.substring(0,driverId.indexOf('.')); + logger.info("Found Storage Driver: " + driverId + " for " + p.get(property).toString()); + drivers.put(p.get(property).toString(), driverId); + } + + } + } + + public static String getStorageDriverLabelFor(String storageDriverId) { + String label = "<>"; + if (drivers==null) { + populateDrivers(); + } + if(drivers.containsValue(storageDriverId)) { + for(String key: drivers.keySet()) { + if(drivers.get(key).equals(storageDriverId)) { + label = key; + break; + } + + } + } + return label; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java index 864bb700e0e..971c005a902 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java @@ -96,7 +96,7 @@ public Dataset execute(CommandContext ctxt) throws CommandException { theDataset.setAuthority(ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound)); } if (theDataset.getStorageIdentifier() == null) { - String driverId = DataAccess.getStorageDriverId(theDataset.getDataverseContext()); + String driverId = theDataset.getDataverseContext().getStorageDriverId(); theDataset.setStorageIdentifier(driverId + "://" + theDataset.getGlobalId().asString()); } if (theDataset.getIdentifier()==null) { diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index 7318f082d04..b108acfdba8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -1338,7 +1338,7 @@ public static String getFilesTempDirectory() { } public static void generateS3PackageStorageIdentifier(DataFile dataFile) { - String driverId = DataAccess.getStorageDriverId(dataFile.getDataverseContext()); + String driverId = dataFile.getDataverseContext().getStorageDriverId(); String bucketName = System.getProperty("dataverse.files." + driverId + ".bucket-name"); String storageId = driverId + "://" + bucketName + ":" + dataFile.getFileMetadata().getLabel(); @@ -1672,7 +1672,7 @@ public static boolean isPackageFile(DataFile dataFile) { } public static S3AccessIO getS3AccessForDirectUpload(Dataset dataset) { - String driverId = DataAccess.getStorageDriverId(dataset.getDataverseContext()); + String driverId = dataset.getDataverseContext().getStorageDriverId(); boolean directEnabled = Boolean.getBoolean("dataverse.files." + driverId + ".upload-redirect"); //Should only be requested when it is allowed, but we'll log a warning otherwise if(!directEnabled) { diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 1e864c7879a..24f1cb18dc6 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -35,6 +35,7 @@ name=Name institution=Institution position=Position affiliation=Affiliation +storage=Storage Driver createDataverse=Create Dataverse remove=Remove done=Done @@ -688,6 +689,7 @@ dataverse.host.tip=Changing the host dataverse will clear any fields you may hav dataverse.host.autocomplete.nomatches=No matches dataverse.identifier.title=Short name used for the URL of this dataverse. dataverse.affiliation.title=The organization with which this dataverse is affiliated. +dataverse.storage.title=A storage service to be used for datasets in this dataverse. dataverse.category=Category dataverse.category.title=The type that most closely reflects this dataverse. dataverse.type.selectTab.top=Select one... diff --git a/src/main/resources/db/migration/V4.19.0.1__tbd_multistore.sql b/src/main/resources/db/migration/V4.19.0.1__tbd_multistore.sql new file mode 100644 index 00000000000..273de02fef7 --- /dev/null +++ b/src/main/resources/db/migration/V4.19.0.1__tbd_multistore.sql @@ -0,0 +1,2 @@ +ALTER TABLE dataverse +ADD COLUMN IF NOT EXISTS storagedriver TEXT; diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index b9df65bfc69..e553c3563a5 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -138,6 +138,19 @@
+
+ + #{bundle.storage} + + +
+ + + + +
+
From 0911571a3912d64548c8470633f570c09f0871a5 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 6 Jan 2020 12:58:38 -0500 Subject: [PATCH 073/475] fix temporary(which is also final) file delete for direct upload --- .../iq/dataverse/EditDatafilesPage.java | 79 ++++++++++--------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 2a0c9efc786..13290b10724 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -967,42 +967,49 @@ public void deleteFiles() { } private void deleteTempFile(DataFile dataFile) { - // Before we remove the file from the list and forget about - // it: - // The physical uploaded file is still sitting in the temporary - // directory. If it were saved, it would be moved into its - // permanent location. But since the user chose not to save it, - // we have to delete the temp file too. - // - // Eventually, we will likely add a dedicated mechanism - // for managing temp files, similar to (or part of) the storage - // access framework, that would allow us to handle specialized - // configurations - highly sensitive/private data, that - // has to be kept encrypted even in temp files, and such. - // But for now, we just delete the file directly on the - // local filesystem: - - try { - List generatedTempFiles = ingestService.listGeneratedTempFiles( - Paths.get(FileUtil.getFilesTempDirectory()), dataFile.getStorageIdentifier()); - if (generatedTempFiles != null) { - for (Path generated : generatedTempFiles) { - logger.fine("(Deleting generated thumbnail file " + generated.toString() + ")"); - try { - Files.delete(generated); - } catch (IOException ioex) { - logger.warning("Failed to delete generated file " + generated.toString()); - } - } - } - Files.delete(Paths.get(FileUtil.getFilesTempDirectory() + "/" + dataFile.getStorageIdentifier())); - } catch (IOException ioEx) { - // safe to ignore - it's just a temp file. - logger.warning("Failed to delete temporary file " + FileUtil.getFilesTempDirectory() + "/" - + dataFile.getStorageIdentifier()); - } - } - + // Before we remove the file from the list and forget about + // it: + // The physical uploaded file is still sitting in the temporary + // directory. If it were saved, it would be moved into its + // permanent location. But since the user chose not to save it, + // we have to delete the temp file too. + // + // Eventually, we will likely add a dedicated mechanism + // for managing temp files, similar to (or part of) the storage + // access framework, that would allow us to handle specialized + // configurations - highly sensitive/private data, that + // has to be kept encrypted even in temp files, and such. + // But for now, we just delete the file directly on the + // local filesystem: + + try { + List generatedTempFiles = ingestService.listGeneratedTempFiles( + Paths.get(FileUtil.getFilesTempDirectory()), dataFile.getStorageIdentifier()); + if (generatedTempFiles != null) { + for (Path generated : generatedTempFiles) { + logger.fine("(Deleting generated thumbnail file " + generated.toString() + ")"); + try { + Files.delete(generated); + } catch (IOException ioex) { + logger.warning("Failed to delete generated file " + generated.toString()); + } + } + } + String si = dataFile.getStorageIdentifier(); + if (si.contains("://")) { + //Direct upload files will already have a store id in their storageidentifier + DataAccess.getStorageIO(dataFile).delete(); + } else { + //Temp files sent to this method have no prefix, not even "tmp://" + Files.delete(Paths.get(FileUtil.getFilesTempDirectory() + "/" + dataFile.getStorageIdentifier())); + } + } catch (IOException ioEx) { + // safe to ignore - it's just a temp file. + logger.warning("Failed to delete temporary file " + FileUtil.getFilesTempDirectory() + "/" + + dataFile.getStorageIdentifier()); + } + } + private void removeFileMetadataFromList(List fmds, FileMetadata fmToDelete) { Iterator fmit = fmds.iterator(); while (fmit.hasNext()) { From 150d52ece76ca07c605c96475f05022937711273 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 6 Jan 2020 12:58:50 -0500 Subject: [PATCH 074/475] progress bar styling --- src/main/webapp/resources/css/structure.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/webapp/resources/css/structure.css b/src/main/webapp/resources/css/structure.css index 819681c5c7b..07c82639787 100644 --- a/src/main/webapp/resources/css/structure.css +++ b/src/main/webapp/resources/css/structure.css @@ -997,3 +997,12 @@ span.ui-autocomplete input.ui-autocomplete-input {width:100%;} #citation-banner {width:100%; height:45px; position: absolute; z-index: 999999; border-radius: 0; border-width: 0 0 1px 0;} #citation-banner a.close, #citation-banner a.close span.glyphicon {line-height:.2;} #citation-forward {position: absolute; top:45px; height: calc(100% - 65px); border:0; background:url(/resources/images/ajax-loading.gif) no-repeat 50% 50%;} + +/*Direct upload progress bar*/ +progress::-webkit-progress-bar { + background-color:white; +} + +progress::-webkit-progress-value { + background-color:#0e90d2; +} From 92dbb2e002379cc91304b41013966f6230c5bb5d Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 6 Jan 2020 12:59:13 -0500 Subject: [PATCH 075/475] remove drag/drop message once file(s) are selected in direct upload --- src/main/webapp/resources/js/fileupload.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index aca70f7e4cc..675244d25ff 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -42,6 +42,7 @@ function setupDirectUpload(enabled, theDatasetId) { } function queueFileForDirectUpload(file, datasetId) { + if(fileList.length === 0) {uploadWidgetDropRemoveMsg();} fileList.push(file); //calc md5 @@ -59,7 +60,8 @@ function uploadFileDirectly(url, storageId) { //Pick a pending file var file = fileList.pop(); data.append('file',file); - $('.ui-fileupload-progress').append($('')); + $('.ui-fileupload-progress').html(''); + $('.ui-fileupload-progress').append($('')).attr('class', 'ui-progressbar ui-widget ui-widget-content ui-corner-all'); $.ajax({ url: url, type: 'PUT', @@ -78,9 +80,10 @@ function uploadFileDirectly(url, storageId) { if(myXhr.upload) { myXhr.upload.addEventListener('progress', function(e) { if(e.lengthComputable) { + var doublelength = 2 * e.total; $('progress').attr({ value:e.loaded, - max:e.total + max:doublelength }); } }); @@ -99,7 +102,14 @@ function reportUpload(storageId, file){ getMD5( file, - prog => console.log("Progress: " + prog) + prog => {console.log("Progress: " + prog); + + var current = 1 + prog; + $('progress').attr({ + value:current, + max:2 + }); + } ).then( md5 => { //storageId is not the location - has a : separator and no path elements from dataset @@ -231,7 +241,7 @@ function uploadFailure(fileUpload) { function readChunked(file, chunkCallback, endCallback) { var fileSize = file.size; - var chunkSize = 4 * 1024 * 1024; // 4MB + var chunkSize = 64 * 1024 * 1024; // 64MB var offset = 0; var reader = new FileReader(); From 216a7def0d685c6a24aca0d5bd641ab2069d0caf Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 6 Jan 2020 13:15:31 -0500 Subject: [PATCH 076/475] bugfix apply styles to progress element to make it appear --- src/main/webapp/resources/js/fileupload.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index 675244d25ff..fa084bb12a0 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -61,7 +61,7 @@ function uploadFileDirectly(url, storageId) { var file = fileList.pop(); data.append('file',file); $('.ui-fileupload-progress').html(''); - $('.ui-fileupload-progress').append($('')).attr('class', 'ui-progressbar ui-widget ui-widget-content ui-corner-all'); + $('.ui-fileupload-progress').append($('').attr('class', 'ui-progressbar ui-widget ui-widget-content ui-corner-all')); $.ajax({ url: url, type: 'PUT', From 6f56da2453638a5b2ec6a5cf1f3d7766bb81fca4 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 6 Jan 2020 13:34:23 -0500 Subject: [PATCH 077/475] bugfix for failing s3 delete --- .../edu/harvard/iq/dataverse/EditDatafilesPage.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 13290b10724..a478ccfc64a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -998,15 +998,22 @@ private void deleteTempFile(DataFile dataFile) { String si = dataFile.getStorageIdentifier(); if (si.contains("://")) { //Direct upload files will already have a store id in their storageidentifier - DataAccess.getStorageIO(dataFile).delete(); + StorageIO sio = DataAccess.getStorageIO(dataFile); + sio.open(DataAccessOption.WRITE_ACCESS); //populates the key/location needed to do a delete() + sio.delete(); } else { //Temp files sent to this method have no prefix, not even "tmp://" Files.delete(Paths.get(FileUtil.getFilesTempDirectory() + "/" + dataFile.getStorageIdentifier())); } } catch (IOException ioEx) { // safe to ignore - it's just a temp file. - logger.warning("Failed to delete temporary file " + FileUtil.getFilesTempDirectory() + "/" - + dataFile.getStorageIdentifier()); + logger.warning(ioEx.getMessage()); + if(dataFile.getStorageIdentifier().contains("://")) { + logger.warning("Failed to delete temporary file " + dataFile.getStorageIdentifier()); + } else { + logger.warning("Failed to delete temporary file " + FileUtil.getFilesTempDirectory() + "/" + + dataFile.getStorageIdentifier()); + } } } From 1895611db61f302065f6ef67982fea44686ebe76 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 6 Jan 2020 13:54:00 -0500 Subject: [PATCH 078/475] bugfix - temporarily set datafile owner for location calculation --- .../java/edu/harvard/iq/dataverse/EditDatafilesPage.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index a478ccfc64a..49f8d070d27 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -998,9 +998,16 @@ private void deleteTempFile(DataFile dataFile) { String si = dataFile.getStorageIdentifier(); if (si.contains("://")) { //Direct upload files will already have a store id in their storageidentifier + //but they need to be associated with a dataset for the overall storagelocation to be calculated + //so we temporarily set the owner + if(dataFile.getOwner()!=null) { + logger.warning("Datafile owner was not null as expected"); + } + dataFile.setOwner(dataset); StorageIO sio = DataAccess.getStorageIO(dataFile); sio.open(DataAccessOption.WRITE_ACCESS); //populates the key/location needed to do a delete() sio.delete(); + dataFile.setOwner(null); } else { //Temp files sent to this method have no prefix, not even "tmp://" Files.delete(Paths.get(FileUtil.getFilesTempDirectory() + "/" + dataFile.getStorageIdentifier())); From ca6b4d426bacac2cc1320a6136db2ca156744909 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 6 Jan 2020 14:15:48 -0500 Subject: [PATCH 079/475] bugfix: use direct storage for delete --- .../java/edu/harvard/iq/dataverse/EditDatafilesPage.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 49f8d070d27..4000975dbb2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -1004,9 +1004,10 @@ private void deleteTempFile(DataFile dataFile) { logger.warning("Datafile owner was not null as expected"); } dataFile.setOwner(dataset); - StorageIO sio = DataAccess.getStorageIO(dataFile); - sio.open(DataAccessOption.WRITE_ACCESS); //populates the key/location needed to do a delete() - sio.delete(); + //Use one StorageIO to get the storageLocation and then create a direct storage storageIO class to perform the delete + // (since delete is forbidden except for direct storage) + String sl = DataAccess.getStorageIO(dataFile).getStorageLocation(); + DataAccess.getDirectStorageIO(sl).delete(); dataFile.setOwner(null); } else { //Temp files sent to this method have no prefix, not even "tmp://" From cc0833035208d6c03de18a00b936d5fd35dc8d8b Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 4 Dec 2019 18:02:24 -0500 Subject: [PATCH 080/475] multistore implementation (built on direct upload) Conflicts: pom.xml src/main/java/edu/harvard/iq/dataverse/api/Datasets.java src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java --- pom.xml | 4 + .../iq/dataverse/DataFileServiceBean.java | 3 +- .../harvard/iq/dataverse/api/Datasets.java | 10 +- .../iq/dataverse/dataaccess/DataAccess.java | 119 +++-- .../iq/dataverse/dataaccess/FileAccessIO.java | 73 +-- .../iq/dataverse/dataaccess/S3AccessIO.java | 113 +++-- .../iq/dataverse/dataaccess/StorageIO.java | 13 +- .../dataverse/dataaccess/SwiftAccessIO.java | 81 +-- .../impl/AbstractCreateDatasetCommand.java | 11 +- .../dataverse/ingest/IngestServiceBean.java | 462 ++++++++++-------- .../harvard/iq/dataverse/util/FileUtil.java | 8 +- .../dataaccess/FileAccessIOTest.java | 8 +- .../dataverse/dataaccess/S3AccessIOTest.java | 4 +- .../dataverse/dataaccess/StorageIOTest.java | 5 +- .../dataaccess/SwiftAccessIOTest.java | 5 +- 15 files changed, 527 insertions(+), 392 deletions(-) diff --git a/pom.xml b/pom.xml index 481f0418c3c..06f3d26a650 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,11 @@ --> edu.harvard.iq dataverse +<<<<<<< IQSS/6485 4.18.1 +======= + 4.18.1-tdl-dev-ms +>>>>>>> 08f6849 multistore implementation (built on direct upload) war dataverse diff --git a/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java index a35bfb0df15..54a88c27d91 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java @@ -1565,7 +1565,8 @@ public void finalizeFileDelete(Long dataFileId, String storageLocation) throws I throw new IOException("Attempted to permanently delete a physical file still associated with an existing DvObject " + "(id: " + dataFileId + ", location: " + storageLocation); } - StorageIO directStorageAccess = DataAccess.getDirectStorageIO(storageLocation); + logger.info("deleting: " + storageLocation); + StorageIO directStorageAccess = DataAccess.getDirectStorageIO(storageLocation); directStorageAccess.delete(); } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index 7fa85473d1a..f7f31077864 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -78,6 +78,8 @@ import edu.harvard.iq.dataverse.S3PackageImporter; import static edu.harvard.iq.dataverse.api.AbstractApiBean.error; import edu.harvard.iq.dataverse.batch.util.LoggingUtil; +import edu.harvard.iq.dataverse.dataaccess.DataAccess; +import edu.harvard.iq.dataverse.dataaccess.S3AccessIO; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.UnforcedCommandException; import edu.harvard.iq.dataverse.engine.command.impl.UpdateDvObjectPIDMetadataCommand; @@ -92,6 +94,7 @@ import edu.harvard.iq.dataverse.util.ArchiverUtil; import edu.harvard.iq.dataverse.util.BundleUtil; import edu.harvard.iq.dataverse.util.EjbUtil; +import edu.harvard.iq.dataverse.util.FileUtil; import edu.harvard.iq.dataverse.util.SystemConfig; import edu.harvard.iq.dataverse.util.json.JsonParseException; import edu.harvard.iq.dataverse.search.IndexServiceBean; @@ -1297,11 +1300,12 @@ public Response receiveChecksumValidationResults(@PathParam("identifier") String if ("validation passed".equals(statusMessageFromDcm)) { logger.log(Level.INFO, "Checksum Validation passed for DCM."); - String storageDriver = (System.getProperty("dataverse.files.storage-driver-id") != null) ? System.getProperty("dataverse.files.storage-driver-id") : "file"; + String storageDriver = DataAccess.getStorageDriverId(dataset.getDataverseContext()); String uploadFolder = jsonFromDcm.getString("uploadFolder"); int totalSize = jsonFromDcm.getInt("totalSize"); + String storageDriverType = System.getProperty("dataverse.file." + storageDriver + ".type"); - if (storageDriver.equals("file")) { + if (storageDriverType.equals("file")) { logger.log(Level.INFO, "File storage driver used for (dataset id={0})", dataset.getId()); ImportMode importMode = ImportMode.MERGE; @@ -1317,7 +1321,7 @@ public Response receiveChecksumValidationResults(@PathParam("identifier") String String message = wr.getMessage(); return error(Response.Status.INTERNAL_SERVER_ERROR, "Uploaded files have passed checksum validation but something went wrong while attempting to put the files into Dataverse. Message was '" + message + "'."); } - } else if(storageDriver.equals("s3")) { + } else if(storageDriverType.equals("s3")) { logger.log(Level.INFO, "S3 storage driver used for DCM (dataset id={0})", dataset.getId()); try { diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index acb9336b5c6..de8be99152c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -20,8 +20,11 @@ package edu.harvard.iq.dataverse.dataaccess; +import edu.harvard.iq.dataverse.Dataverse; import edu.harvard.iq.dataverse.DvObject; import java.io.IOException; +import java.util.HashMap; +import java.util.Properties; /** * * @author Leonid Andreev @@ -51,16 +54,22 @@ public static StorageIO getStorageIO(T dvObject, DataAcc || dvObject.getStorageIdentifier().isEmpty()) { throw new IOException("getDataAccessObject: null or invalid datafile."); } - - if (dvObject.getStorageIdentifier().startsWith("file://") - || (!dvObject.getStorageIdentifier().matches("^[a-z][a-z0-9]*://.*"))) { - return new FileAccessIO<>(dvObject, req); - } else if (dvObject.getStorageIdentifier().startsWith("swift://")){ - return new SwiftAccessIO<>(dvObject, req); - } else if (dvObject.getStorageIdentifier().startsWith("s3://")){ - return new S3AccessIO<>(dvObject, req); - } else if (dvObject.getStorageIdentifier().startsWith("tmp://")) { - throw new IOException("DataAccess IO attempted on a temporary file that hasn't been permanently saved yet."); + String storageIdentifier = dvObject.getStorageIdentifier(); + int separatorIndex = storageIdentifier.indexOf("://"); + String storageDriverId = "file"; //default + if(separatorIndex>0) { + storageDriverId = storageIdentifier.substring(0,separatorIndex); + } + String storageType = getDriverType(storageDriverId); + switch(storageType) { + case "file": + return new FileAccessIO<>(dvObject, req, storageDriverId); + case "s3": + return new S3AccessIO<>(dvObject, req, storageDriverId); + case "swift": + return new SwiftAccessIO<>(dvObject, req, storageDriverId); + case "tmp": + throw new IOException("DataAccess IO attempted on a temporary file that hasn't been permanently saved yet."); } // TODO: @@ -76,26 +85,47 @@ public static StorageIO getStorageIO(T dvObject, DataAcc // Experimental extension of the StorageIO system allowing direct access to // stored physical files that may not be associated with any DvObjects - public static StorageIO getDirectStorageIO(String storageLocation) throws IOException { - if (storageLocation.startsWith("file://")) { - return new FileAccessIO(storageLocation.substring(7)); - } else if (storageLocation.startsWith("swift://")){ - return new SwiftAccessIO<>(storageLocation.substring(8)); - } else if (storageLocation.startsWith("s3://")){ - return new S3AccessIO<>(storageLocation.substring(5)); + public static StorageIO getDirectStorageIO(String storageLocation) throws IOException { + String[] response = getDriverIdAndStorageId(storageLocation); + String storageDriverId = response[0]; + String storageIdentifier=response[1]; + String storageType = getDriverType(storageDriverId); + switch(storageType) { + case "file": + return new FileAccessIO<>(storageIdentifier, storageDriverId); + case "s3": + return new S3AccessIO<>(storageIdentifier, storageDriverId); + case "swift": + return new SwiftAccessIO<>(storageIdentifier, storageDriverId); + default: + throw new IOException("getDirectStorageIO: Unsupported storage method."); } - - throw new IOException("getDirectStorageIO: Unsupported storage method."); + } + + public static String[] getDriverIdAndStorageId(String storageLocation) { + //default if no prefix + String storageIdentifier=storageLocation; + int separatorIndex = storageLocation.indexOf("://"); + String storageDriverId = "file"; //default + if(separatorIndex>0) { + storageDriverId = storageLocation.substring(0,separatorIndex); + storageIdentifier = storageLocation.substring(separatorIndex + 3); + } + return new String[]{storageDriverId, storageIdentifier}; + } + + public static String getDriverType(String driverId) { + return System.getProperty("dataverse.files." + driverId + ".type", "file"); } // createDataAccessObject() methods create a *new*, empty DataAccess objects, // for saving new, not yet saved datafiles. public static StorageIO createNewStorageIO(T dvObject, String storageTag) throws IOException { - return createNewStorageIO(dvObject, storageTag, DEFAULT_STORAGE_DRIVER_IDENTIFIER); + return createNewStorageIO(dvObject, storageTag, getStorageDriverId(dvObject.getDataverseContext())); } - public static StorageIO createNewStorageIO(T dvObject, String storageTag, String driverIdentifier) throws IOException { + public static StorageIO createNewStorageIO(T dvObject, String storageTag, String storageDriverId) throws IOException { if (dvObject == null || storageTag == null || storageTag.isEmpty()) { @@ -106,23 +136,48 @@ public static StorageIO createNewStorageIO(T dvObject, S dvObject.setStorageIdentifier(storageTag); - if (driverIdentifier == null) { - driverIdentifier = "file"; + if (storageDriverId == null) { + storageDriverId = "file"; } - - if (driverIdentifier.equals("file")) { - storageIO = new FileAccessIO<>(dvObject, null); - } else if (driverIdentifier.equals("swift")) { - storageIO = new SwiftAccessIO<>(dvObject, null); - } else if (driverIdentifier.equals("s3")) { - storageIO = new S3AccessIO<>(dvObject, null); - } else { - throw new IOException("createDataAccessObject: Unsupported storage method " + driverIdentifier); + String storageType = getDriverType(storageDriverId); + switch(storageType) { + case "file": + storageIO = new FileAccessIO<>(dvObject, null, storageDriverId); + break; + case "swift": + storageIO = new SwiftAccessIO<>(dvObject, null, storageDriverId); + break; + case "s3": + storageIO = new S3AccessIO<>(dvObject, null, storageDriverId); + break; + default: + throw new IOException("createDataAccessObject: Unsupported storage method " + storageDriverId); } storageIO.open(DataAccessOption.WRITE_ACCESS); return storageIO; } + static HashMap drivers = null; + + public static String getStorageDriverId(Dataverse dataverse) { + if (drivers==null) { + drivers = new HashMap(); + Properties p = System.getProperties(); + for(String property: p.stringPropertyNames()) { + if(property.startsWith("dataverse.files.") && property.endsWith(".affiliation")) { + String driverId = property.substring(16); + driverId=driverId.substring(0,driverId.indexOf('.')); + drivers.put(p.get(property).toString(), driverId); + } + + } + } + if(drivers.containsKey(dataverse.getAffiliation())) { + return drivers.get(dataverse.getAffiliation()); + } + return DEFAULT_STORAGE_DRIVER_IDENTIFIER; + + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java index 3afab58c1ce..6284e7fd51e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java @@ -49,25 +49,23 @@ public class FileAccessIO extends StorageIO { - public FileAccessIO () { - this((T)null); - } - - public FileAccessIO(T dvObject) { - this (dvObject, null); - - } + public FileAccessIO() { + //Partially functional StorageIO object - constructor only for testing + super(); + } + + public FileAccessIO(T dvObject, DataAccessRequest req, String driverId ) { - public FileAccessIO(T dvObject, DataAccessRequest req) { - - super(dvObject, req); + super(dvObject, req, driverId); this.setIsLocalFile(true); } // "Direct" File Access IO, opened on a physical file not associated with // a specific DvObject - public FileAccessIO(String storageLocation) { + public FileAccessIO(String storageLocation, String driverId) { + super(storageLocation, driverId); + this.setIsLocalFile(true); physicalPath = Paths.get(storageLocation); } @@ -122,9 +120,10 @@ public void open (DataAccessOption... options) throws IOException { } } else if (isWriteAccess) { // Creates a new directory as needed for a dataset. - if (dataFile.getOwner().getFileSystemDirectory() != null && !Files.exists(dataFile.getOwner().getFileSystemDirectory())) { - Files.createDirectories(dataFile.getOwner().getFileSystemDirectory()); - } + Path datasetPath=Paths.get(getDatasetDirectory()); + if (datasetPath != null && !Files.exists(datasetPath)) { + Files.createDirectories(datasetPath); + } FileOutputStream fout = openLocalFileAsOutputStream(); if (fout == null) { @@ -158,10 +157,11 @@ public void open (DataAccessOption... options) throws IOException { // this.setInputStream(fin); } else if (isWriteAccess) { //this checks whether a directory for a dataset exists - if (dataset.getFileSystemDirectory() != null && !Files.exists(dataset.getFileSystemDirectory())) { - Files.createDirectories(dataset.getFileSystemDirectory()); - } - dataset.setStorageIdentifier("file://"+dataset.getAuthority()+"/"+dataset.getIdentifier()); + Path datasetPath=Paths.get(getDatasetDirectory()); + if (datasetPath != null && !Files.exists(datasetPath)) { + Files.createDirectories(datasetPath); + } + dataset.setStorageIdentifier(this.driverId + "://"+dataset.getAuthority()+"/"+dataset.getIdentifier()); } } else if (dvObject instanceof Dataverse) { @@ -290,7 +290,7 @@ public Path getAuxObjectAsPath(String auxItemTag) throws IOException { } Path auxPath = null; if (dvObject instanceof DataFile) { - auxPath = Paths.get(datasetDirectory, dvObject.getStorageIdentifier() + "." + auxItemTag); + auxPath = Paths.get(datasetDirectory, stripDriverId(dvObject.getStorageIdentifier()) + "." + auxItemTag); } else if (dvObject instanceof Dataset) { auxPath = Paths.get(datasetDirectory, auxItemTag); } else if (dvObject instanceof Dataverse) { @@ -305,7 +305,8 @@ public Path getAuxObjectAsPath(String auxItemTag) throws IOException { return auxPath; } - @Override + + @Override public void backupAsAux(String auxItemTag) throws IOException { Path auxPath = getAuxObjectAsPath(auxItemTag); @@ -369,7 +370,7 @@ public void saveInputStreamAsAux(InputStream inputStream, String auxItemTag) thr } List cachedFileNames = new ArrayList<>(); - String baseName = this.getDataFile().getStorageIdentifier() + "."; + String baseName = stripDriverId(this.getDataFile().getStorageIdentifier()) + "."; for (Path auxPath : cachedFiles) { cachedFileNames.add(auxPath.getFileName().toString().substring(baseName.length())); } @@ -427,7 +428,7 @@ public Path getFileSystemPath() throws IOException { throw new IOException("Data Access: No local storage identifier defined for this datafile."); } - physicalPath = Paths.get(datasetDirectory, dvObject.getStorageIdentifier()); + physicalPath = Paths.get(datasetDirectory, stripDriverId(dvObject.getStorageIdentifier())); return physicalPath; } @@ -533,9 +534,9 @@ private String getDatasetDirectory() throws IOException { Path datasetDirectoryPath=null; if (dvObject instanceof Dataset) { - datasetDirectoryPath = this.getDataset().getFileSystemDirectory(); + datasetDirectoryPath = Paths.get(this.getDataset().getAuthorityForFileStorage(), this.getDataset().getIdentifierForFileStorage()); } else if (dvObject instanceof DataFile) { - datasetDirectoryPath = this.getDataFile().getOwner().getFileSystemDirectory(); + datasetDirectoryPath = Paths.get(this.getDataFile().getOwner().getAuthorityForFileStorage(), this.getDataFile().getOwner().getIdentifierForFileStorage()); } else if (dvObject instanceof Dataverse) { throw new IOException("FileAccessIO: Dataverses are not a supported dvObject"); } @@ -543,7 +544,7 @@ private String getDatasetDirectory() throws IOException { if (datasetDirectoryPath == null) { throw new IOException("Could not determine the filesystem directory of the parent dataset."); } - String datasetDirectory = datasetDirectoryPath.toString(); + String datasetDirectory = Paths.get(getFilesRootDirectory(), datasetDirectoryPath.toString()).toString(); if (dvObject.getStorageIdentifier() == null || dvObject.getStorageIdentifier().isEmpty()) { throw new IOException("Data Access: No local storage identifier defined for this datafile."); @@ -552,6 +553,16 @@ private String getDatasetDirectory() throws IOException { return datasetDirectory; } + + private String getFilesRootDirectory() { + String filesRootDirectory = System.getProperty("dataverse.files." + this.driverId + ".directory"); + + if (filesRootDirectory == null || filesRootDirectory.equals("")) { + filesRootDirectory = "/tmp/files"; + } + return filesRootDirectory; + } + private List listCachedFiles() throws IOException { List auxItems = new ArrayList<>(); @@ -571,7 +582,7 @@ private List listCachedFiles() throws IOException { throw new IOException("Null or invalid DataFile in FileAccessIO object."); } - baseName = this.getDataFile().getStorageIdentifier(); + baseName = stripDriverId(this.getDataFile().getStorageIdentifier()); datasetDirectoryPath = this.getDataFile().getOwner().getFileSystemDirectory(); } @@ -612,5 +623,11 @@ public InputStream getAuxFileAsInputStream(String auxItemTag) throws IOException } return in; } - + private String stripDriverId(String storageIdentifier) { + int separatorIndex = storageIdentifier.indexOf("://"); + if(separatorIndex>0) { + return storageIdentifier.substring(separatorIndex + 3); + } + return storageIdentifier; + } } \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index d2429f6ebe7..5efd612901d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -3,6 +3,7 @@ import com.amazonaws.AmazonClientException; import com.amazonaws.HttpMethod; import com.amazonaws.SdkClientException; +import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; @@ -64,16 +65,9 @@ public class S3AccessIO extends StorageIO { private static final Logger logger = Logger.getLogger("edu.harvard.iq.dataverse.dataaccess.S3AccessIO"); - public S3AccessIO() { - this((T)null); - } - - public S3AccessIO(T dvObject) { - this(dvObject, null); - } - - public S3AccessIO(T dvObject, DataAccessRequest req) { - super(dvObject, req); + public S3AccessIO(T dvObject, DataAccessRequest req, String driverId) { + super(dvObject, req, driverId); + readSettings(); this.setIsLocalFile(false); try { @@ -91,6 +85,7 @@ public S3AccessIO(T dvObject, DataAccessRequest req) { // Boolean is inverted, otherwise setting dataverse.files.s3-chunked-encoding=false would result in leaving Chunked Encoding enabled s3CB.setChunkedEncodingDisabled(!s3chunkedEncoding); + s3CB.setCredentials(new ProfileCredentialsProvider(s3profile)); // let's build the client :-) this.s3 = s3CB.build(); @@ -105,50 +100,32 @@ public S3AccessIO(T dvObject, DataAccessRequest req) { } } - public S3AccessIO(String storageLocation) { - this((T)null); - + + public S3AccessIO(String storageLocation, String driverId) { + this(null, null, driverId); // TODO: validate the storage location supplied bucketName = storageLocation.substring(0,storageLocation.indexOf('/')); key = storageLocation.substring(storageLocation.indexOf('/')+1); } - public S3AccessIO(T dvObject, DataAccessRequest req, @NotNull AmazonS3 s3client) { - super(dvObject, req); + public S3AccessIO(T dvObject, DataAccessRequest req, @NotNull AmazonS3 s3client, String driverId) { + super(dvObject, req, driverId); + readSettings(); this.setIsLocalFile(false); this.s3 = s3client; } - - public static String S3_IDENTIFIER_PREFIX = "s3"; private AmazonS3 s3 = null; private TransferManager tm = null; - /** - * Pass in a URL pointing to your S3 compatible storage. - * For possible values see https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/client/builder/AwsClientBuilder.EndpointConfiguration.html - */ - private String s3CEUrl = System.getProperty("dataverse.files.s3-custom-endpoint-url", ""); - /** - * Pass in a region to use for SigV4 signing of requests. - * Defaults to "dataverse" as it is not relevant for custom S3 implementations. - */ - private String s3CERegion = System.getProperty("dataverse.files.s3-custom-endpoint-region", "dataverse"); - /** - * Pass in a boolean value if path style access should be used within the S3 client. - * Anything but case-insensitive "true" will lead to value of false, which is default value, too. - */ - private boolean s3pathStyleAccess = Boolean.parseBoolean(System.getProperty("dataverse.files.s3-path-style-access", "false")); - /** - * Pass in a boolean value if payload signing should be used within the S3 client. - * Anything but case-insensitive "true" will lead to value of false, which is default value, too. - */ - private boolean s3payloadSigning = Boolean.parseBoolean(System.getProperty("dataverse.files.s3-payload-signing","false")); - /** - * Pass in a boolean value if chunked encoding should not be used within the S3 client. - * Anything but case-insensitive "false" will lead to value of true, which is default value, too. - */ - private boolean s3chunkedEncoding = Boolean.parseBoolean(System.getProperty("dataverse.files.s3-chunked-encoding","true")); - private String bucketName = System.getProperty("dataverse.files.s3-bucket-name"); + //See readSettings() for the source of these values + private String s3CEUrl = null; + private String s3CERegion = null; + private boolean s3pathStyleAccess = false; + private boolean s3payloadSigning = false; + private boolean s3chunkedEncoding = true; + private String s3profile = "default"; + private String bucketName = null; + private String key; @Override @@ -212,11 +189,11 @@ public void open(DataAccessOption... options) throws IOException { } else if (isWriteAccess) { key = dataFile.getOwner().getAuthorityForFileStorage() + "/" + this.getDataFile().getOwner().getIdentifierForFileStorage(); - if (storageIdentifier.startsWith(S3_IDENTIFIER_PREFIX + "://")) { + if (storageIdentifier.startsWith(this.driverId + "://")) { key += "/" + storageIdentifier.substring(storageIdentifier.lastIndexOf(":") + 1); } else { key += "/" + storageIdentifier; - dvObject.setStorageIdentifier(S3_IDENTIFIER_PREFIX + "://" + bucketName + ":" + storageIdentifier); + dvObject.setStorageIdentifier(this.driverId + "://" + bucketName + ":" + storageIdentifier); } } @@ -231,7 +208,7 @@ public void open(DataAccessOption... options) throws IOException { } else if (dvObject instanceof Dataset) { Dataset dataset = this.getDataset(); key = dataset.getAuthorityForFileStorage() + "/" + dataset.getIdentifierForFileStorage(); - dataset.setStorageIdentifier(S3_IDENTIFIER_PREFIX + "://" + key); + dataset.setStorageIdentifier(this.driverId + "://" + key); } else if (dvObject instanceof Dataverse) { throw new IOException("Data Access: Storage driver does not support dvObject type Dataverse yet"); } else { @@ -688,7 +665,7 @@ public String getStorageLocation() throws IOException { throw new IOException("Failed to obtain the S3 key for the file"); } - return S3_IDENTIFIER_PREFIX + "://" + bucketName + "/" + locationKey; + return this.driverId + "://" + bucketName + "/" + locationKey; } @Override @@ -772,8 +749,8 @@ String getMainFileKey() throws IOException { throw new FileNotFoundException("Data Access: No local storage identifier defined for this datafile."); } - if (storageIdentifier.startsWith(S3_IDENTIFIER_PREFIX + "://")) { - bucketName = storageIdentifier.substring((S3_IDENTIFIER_PREFIX + "://").length(), storageIdentifier.lastIndexOf(":")); + if (storageIdentifier.startsWith(this.driverId + "://")) { + bucketName = storageIdentifier.substring((this.driverId + "://").length(), storageIdentifier.lastIndexOf(":")); key = baseKey + "/" + storageIdentifier.substring(storageIdentifier.lastIndexOf(":") + 1); } else { throw new IOException("S3AccessIO: DataFile (storage identifier " + storageIdentifier + ") does not appear to be an S3 object."); @@ -858,4 +835,42 @@ int getUrlExpirationMinutes() { } return 60; } + + private void readSettings() { + /** + * Pass in a URL pointing to your S3 compatible storage. + * For possible values see https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/client/builder/AwsClientBuilder.EndpointConfiguration.html + */ + s3CEUrl = System.getProperty("dataverse.files." + this.driverId + ".custom-endpoint-url", ""); + /** + * Pass in a region to use for SigV4 signing of requests. + * Defaults to "dataverse" as it is not relevant for custom S3 implementations. + */ + s3CERegion = System.getProperty("dataverse.files." + this.driverId + ".custom-endpoint-region", "dataverse"); + /** + * Pass in a boolean value if path style access should be used within the S3 client. + * Anything but case-insensitive "true" will lead to value of false, which is default value, too. + */ + s3pathStyleAccess = Boolean.parseBoolean(System.getProperty("dataverse.files." + this.driverId + ".path-style-access", "false")); + /** + * Pass in a boolean value if payload signing should be used within the S3 client. + * Anything but case-insensitive "true" will lead to value of false, which is default value, too. + */ + s3payloadSigning = Boolean.parseBoolean(System.getProperty("dataverse.files." + this.driverId + ".payload-signing","false")); + /** + * Pass in a boolean value if chunked encoding should not be used within the S3 client. + * Anything but case-insensitive "false" will lead to value of true, which is default value, too. + */ + s3chunkedEncoding = Boolean.parseBoolean(System.getProperty("dataverse.files." + this.driverId + ".chunked-encoding","true")); + /** + * Pass in a string value if this storage driver should use a non-default AWS S3 profile. + * The default is "default" which should work when only one profile exists. + */ + s3profile = System.getProperty("dataverse.files." + this.driverId + ".profile","default"); + + bucketName = System.getProperty("dataverse.files." + this.driverId + ".bucket-name"); + + + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/StorageIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/StorageIO.java index 1043d3f44aa..9e0cf7e11b8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/StorageIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/StorageIO.java @@ -53,17 +53,21 @@ public abstract class StorageIO { public StorageIO() { } - - public StorageIO(T dvObject) { - this(dvObject, null); + + public StorageIO(String storageLocation, String driverId) { + this.driverId=driverId; } - public StorageIO(T dvObject, DataAccessRequest req) { + public StorageIO(T dvObject, DataAccessRequest req, String driverId) { this.dvObject = dvObject; this.req = req; + this.driverId=driverId; if (this.req == null) { this.req = new DataAccessRequest(); } + if (this.driverId == null) { + this.driverId = "file"; + } } @@ -183,6 +187,7 @@ public boolean canWrite() { private OutputStream out; protected Channel channel; protected DvObject dvObject; + protected String driverId; /*private int status;*/ private long size; diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/SwiftAccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/SwiftAccessIO.java index 73ee28e17b9..3bc29cb9836 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/SwiftAccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/SwiftAccessIO.java @@ -48,43 +48,48 @@ public class SwiftAccessIO extends StorageIO { private static final Logger logger = Logger.getLogger("edu.harvard.iq.dataverse.dataaccess.SwiftAccessIO"); - public SwiftAccessIO() { - this((T)null); - } - - public SwiftAccessIO(T dvObject) { - this(dvObject, null); - } - - public SwiftAccessIO(T dvObject, DataAccessRequest req) { - super(dvObject, req); - + public SwiftAccessIO() { + //Partially functional StorageIO object - constructor only for testing + super(); + } + + public SwiftAccessIO(T dvObject, DataAccessRequest req, String driverId) { + super(dvObject, req, driverId); + readSettings(); this.setIsLocalFile(false); } - public SwiftAccessIO(String swiftLocation) { - this((T)null); + public SwiftAccessIO(String swiftLocation, String driverId) { + super(swiftLocation, driverId); + readSettings(); this.swiftLocation = swiftLocation; + this.setIsLocalFile(false); } - private Account account = null; + private void readSettings() { + isPublicContainer = Boolean.parseBoolean(System.getProperty("dataverse.files." + this.driverId + ".isPublicContainer", "true")); + swiftFolderPathSeparator = System.getProperty("dataverse.files." + this.driverId + ".folderPathSeparator", "_"); + swiftDefaultEndpoint = System.getProperty("dataverse.files." + this.driverId + ".defaultEndpoint"); + tempUrlExpires = Integer.parseInt(System.getProperty("dataverse.files." + this.driverId + ".temporaryUrlExpiryTime", "60")); + + } + + private Account account = null; private StoredObject swiftFileObject = null; private Container swiftContainer = null; - private boolean isPublicContainer = Boolean.parseBoolean(System.getProperty("dataverse.files.swift.isPublicContainer", "true")); - private String swiftFolderPathSeparator = System.getProperty("dataverse.files.swift.folderPathSeparator", "_"); - private String swiftDefaultEndpoint = System.getProperty("dataverse.files.swift.defaultEndpoint"); + private boolean isPublicContainer = true; + private String swiftFolderPathSeparator = "_"; + private String swiftDefaultEndpoint = null; //for hash private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1"; //TODO: should this be dynamically generated based on size of file? //Also, this is in seconds - private static int TEMP_URL_EXPIRES = Integer.parseInt(System.getProperty("dataverse.files.swift.temporaryUrlExpiryTime", "60")); + private int tempUrlExpires = 60; private static int LIST_PAGE_LIMIT = 100; - public static String SWIFT_IDENTIFIER_PREFIX = "swift"; - @Override public void open(DataAccessOption... options) throws IOException { DataAccessRequest req = this.getRequest(); @@ -503,7 +508,7 @@ private StoredObject initializeSwiftFileObject(boolean writeAccess, String auxIt if (dvObject instanceof DataFile) { Dataset owner = this.getDataFile().getOwner(); - if (storageIdentifier.startsWith(SWIFT_IDENTIFIER_PREFIX + "://")) { + if (storageIdentifier.startsWith(this.driverId + "://")) { // This is a call on an already existing swift object. String[] swiftStorageTokens = storageIdentifier.substring(8).split(":", 3); @@ -547,17 +552,17 @@ private StoredObject initializeSwiftFileObject(boolean writeAccess, String auxIt //setSwiftContainerName(swiftFolderPath); //swiftFileName = dataFile.getDisplayName(); //Storage Identifier is now updated after the object is uploaded on Swift. - dvObject.setStorageIdentifier(SWIFT_IDENTIFIER_PREFIX + "://" + swiftDefaultEndpoint + ":" + swiftFolderPath + ":" + swiftFileName); + dvObject.setStorageIdentifier(this.driverId + "://" + swiftDefaultEndpoint + ":" + swiftFolderPath + ":" + swiftFileName); } else { throw new IOException("SwiftAccessIO: unknown access mode."); } } else if (dvObject instanceof Dataset) { Dataset dataset = this.getDataset(); - if (storageIdentifier.startsWith(SWIFT_IDENTIFIER_PREFIX + "://")) { + if (storageIdentifier.startsWith(this.driverId + "://")) { // This is a call on an already existing swift object. - //TODO: determine how storage identifer will give us info + //TODO: determine how storage identifier will give us info String[] swiftStorageTokens = storageIdentifier.substring(8).split(":", 3); //number of tokens should be two because there is not main file if (swiftStorageTokens.length != 2) { @@ -596,7 +601,7 @@ private StoredObject initializeSwiftFileObject(boolean writeAccess, String auxIt swiftPseudoFolderPathSeparator + dataset.getIdentifierForFileStorage(); swiftFileName = auxItemTag; - dvObject.setStorageIdentifier(SWIFT_IDENTIFIER_PREFIX + "://" + swiftEndPoint + ":" + swiftFolderPath); + dvObject.setStorageIdentifier(this.driverId + "://" + swiftEndPoint + ":" + swiftFolderPath); } else { throw new IOException("SwiftAccessIO: unknown access mode."); } @@ -623,7 +628,7 @@ private StoredObject initializeSwiftFileObject(boolean writeAccess, String auxIt other swiftContainerName Object Store pseudo-folder can be created, which is not provide by the joss Java swift library as of yet. */ - if (storageIdentifier.startsWith(SWIFT_IDENTIFIER_PREFIX + "://")) { + if (storageIdentifier.startsWith(this.driverId + "://")) { // An existing swift object; the container must already exist as well. this.swiftContainer = account.getContainer(swiftContainerName); } else { @@ -659,9 +664,9 @@ private StoredObject initializeSwiftFileObject(boolean writeAccess, String auxIt setRemoteUrl(getSwiftFileURI(fileObject)); if (!this.isWriteAccess && !this.getDataFile().isIngestInProgress()) { //otherwise this gets called a bunch on upload - setTemporarySwiftUrl(generateTemporarySwiftUrl(swiftEndPoint, swiftContainerName, swiftFileName, TEMP_URL_EXPIRES)); - setTempUrlSignature(generateTempUrlSignature(swiftEndPoint, swiftContainerName, swiftFileName, TEMP_URL_EXPIRES)); - setTempUrlExpiry(generateTempUrlExpiry(TEMP_URL_EXPIRES, System.currentTimeMillis())); + setTemporarySwiftUrl(generateTemporarySwiftUrl(swiftEndPoint, swiftContainerName, swiftFileName, tempUrlExpires)); + setTempUrlSignature(generateTempUrlSignature(swiftEndPoint, swiftContainerName, swiftFileName, tempUrlExpires)); + setTempUrlExpiry(generateTempUrlExpiry(tempUrlExpires, System.currentTimeMillis())); } setSwiftFileName(swiftFileName); @@ -732,12 +737,12 @@ private StoredObject openSwiftAuxFile(boolean writeAccess, String auxItemTag) th } Account authenticateWithSwift(String swiftEndPoint) throws IOException { - String swiftEndPointAuthUrl = System.getProperty("dataverse.files.swift.authUrl." + swiftEndPoint); - String swiftEndPointUsername = System.getProperty("dataverse.files.swift.username." + swiftEndPoint); - String swiftEndPointSecretKey = System.getProperty("dataverse.files.swift.password." + swiftEndPoint); - String swiftEndPointTenantName = System.getProperty("dataverse.files.swift.tenant." + swiftEndPoint); - String swiftEndPointAuthMethod = System.getProperty("dataverse.files.swift.authType." + swiftEndPoint); - String swiftEndPointTenantId = System.getProperty("dataverse.files.swift.tenant." + swiftEndPoint); + String swiftEndPointAuthUrl = System.getProperty("dataverse.files." + this.driverId + ".authUrl." + swiftEndPoint); + String swiftEndPointUsername = System.getProperty("dataverse.files." + this.driverId + ".username." + swiftEndPoint); + String swiftEndPointSecretKey = System.getProperty("dataverse.files." + this.driverId + ".password." + swiftEndPoint); + String swiftEndPointTenantName = System.getProperty("dataverse.files." + this.driverId + ".tenant." + swiftEndPoint); + String swiftEndPointAuthMethod = System.getProperty("dataverse.files." + this.driverId + ".authType." + swiftEndPoint); + String swiftEndPointTenantId = System.getProperty("dataverse.files." + this.driverId + ".tenant." + swiftEndPoint); if (swiftEndPointAuthUrl == null || swiftEndPointUsername == null || swiftEndPointSecretKey == null || "".equals(swiftEndPointAuthUrl) || "".equals(swiftEndPointUsername) || "".equals(swiftEndPointSecretKey)) { @@ -806,9 +811,9 @@ private String getSwiftFileURI(StoredObject fileObject) throws IOException { private String hmac = null; public String generateTempUrlSignature(String swiftEndPoint, String containerName, String objectName, int duration) throws IOException { if (hmac == null || isExpiryExpired(generateTempUrlExpiry(duration, System.currentTimeMillis()), duration, System.currentTimeMillis())) { - String secretKey = System.getProperty("dataverse.files.swift.hashKey." + swiftEndPoint); + String secretKey = System.getProperty("dataverse.files." + this.driverId + ".hashKey." + swiftEndPoint); if (secretKey == null) { - throw new IOException("Please input a hash key under dataverse.files.swift.hashKey." + swiftEndPoint); + throw new IOException("Please input a hash key under dataverse.files." + this.driverId + ".hashKey." + swiftEndPoint); } String path = "/v1/" + containerName + "/" + objectName; Long expires = generateTempUrlExpiry(duration, System.currentTimeMillis()); @@ -833,7 +838,7 @@ public long generateTempUrlExpiry(int duration, long currentTime) { private String temporaryUrl = null; private String generateTemporarySwiftUrl(String swiftEndPoint, String containerName, String objectName, int duration) throws IOException { - String baseUrl = System.getProperty("dataverse.files.swift.endpoint." + swiftEndPoint); + String baseUrl = System.getProperty("dataverse.files." + this.driverId + ".endpoint." + swiftEndPoint); String path = "/v1/" + containerName + "/" + objectName; if (temporaryUrl == null || isExpiryExpired(generateTempUrlExpiry(duration, System.currentTimeMillis()), duration, System.currentTimeMillis())) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java index eb21f70f2cb..864bb700e0e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java @@ -96,15 +96,8 @@ public Dataset execute(CommandContext ctxt) throws CommandException { theDataset.setAuthority(ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound)); } if (theDataset.getStorageIdentifier() == null) { - try { - DataAccess.createNewStorageIO(theDataset, "placeholder"); - } catch (IOException ioex) { - // if setting the storage identifier through createNewStorageIO fails, dataset creation - // does not have to fail. we just set the storage id to a default -SF - String storageDriver = (System.getProperty("dataverse.files.storage-driver-id") != null) ? System.getProperty("dataverse.files.storage-driver-id") : "file"; - theDataset.setStorageIdentifier(storageDriver + "://" + theDataset.getGlobalId().asString()); - logger.log(Level.INFO, "Failed to create StorageIO. StorageIdentifier set to default. Not fatal.({0})", ioex.getMessage()); - } + String driverId = DataAccess.getStorageDriverId(theDataset.getDataverseContext()); + theDataset.setStorageIdentifier(driverId + "://" + theDataset.getGlobalId().asString()); } if (theDataset.getIdentifier()==null) { theDataset.setIdentifier(ctxt.datasets().generateDatasetIdentifier(theDataset, idServiceBean)); diff --git a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java index eb1b2b658d5..710e8d462df 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java @@ -36,10 +36,12 @@ import edu.harvard.iq.dataverse.DatasetFieldCompoundValue; import edu.harvard.iq.dataverse.DatasetLock; import edu.harvard.iq.dataverse.DatasetVersion; +import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.FileMetadata; import edu.harvard.iq.dataverse.MetadataBlock; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.dataaccess.DataAccess; +import edu.harvard.iq.dataverse.dataaccess.DataAccessOption; import edu.harvard.iq.dataverse.dataaccess.StorageIO; import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter; import edu.harvard.iq.dataverse.dataaccess.TabularSubsetGenerator; @@ -151,221 +153,251 @@ public class IngestServiceBean { // DataFileCategory objects, if any were already assigned to the files). // It must be called before we attempt to permanently save the files in // the database by calling the Save command on the dataset and/or version. - public List saveAndAddFilesToDataset(DatasetVersion version, List newFiles) { - List ret = new ArrayList<>(); - - if (newFiles != null && newFiles.size() > 0) { - //ret = new ArrayList<>(); - // final check for duplicate file names; - // we tried to make the file names unique on upload, but then - // the user may have edited them on the "add files" page, and - // renamed FOOBAR-1.txt back to FOOBAR.txt... - - IngestUtil.checkForDuplicateFileNamesFinal(version, newFiles); - - Dataset dataset = version.getDataset(); - - for (DataFile dataFile : newFiles) { - String tempFileLocation = FileUtil.getFilesTempDirectory() + "/" + dataFile.getStorageIdentifier(); - - // Try to save the file in its permanent location: - String storageId = dataFile.getStorageIdentifier().replaceFirst("^tmp://", ""); - - Path tempLocationPath = Paths.get(FileUtil.getFilesTempDirectory() + "/" + storageId); - WritableByteChannel writeChannel = null; - FileChannel readChannel = null; - - boolean unattached = false; - boolean savedSuccess = false; - StorageIO dataAccess = null; - - try { - logger.fine("Attempting to create a new storageIO object for " + storageId); - if (dataFile.getOwner() == null) { - unattached = true; - dataFile.setOwner(dataset); - } - dataAccess = DataAccess.createNewStorageIO(dataFile, storageId); - - logger.fine("Successfully created a new storageIO object."); - /* - This commented-out code demonstrates how to copy bytes - from a local InputStream (or a readChannel) into the - writable byte channel of a Dataverse DataAccessIO object: - */ - - /* - storageIO.open(DataAccessOption.WRITE_ACCESS); - - writeChannel = storageIO.getWriteChannel(); - readChannel = new FileInputStream(tempLocationPath.toFile()).getChannel(); - - long bytesPerIteration = 16 * 1024; // 16K bytes - long start = 0; - while ( start < readChannel.size() ) { - readChannel.transferTo(start, bytesPerIteration, writeChannel); - start += bytesPerIteration; - } - */ - - /* - But it's easier to use this convenience method from the - DataAccessIO: - - (if the underlying storage method for this file is - local filesystem, the DataAccessIO will simply copy - the file using Files.copy, like this: - - Files.copy(tempLocationPath, storageIO.getFileSystemLocation(), StandardCopyOption.REPLACE_EXISTING); - */ - dataAccess.savePath(tempLocationPath); - - // Set filesize in bytes - // - dataFile.setFilesize(dataAccess.getSize()); - savedSuccess = true; - logger.fine("Success: permanently saved file " + dataFile.getFileMetadata().getLabel()); - - } catch (IOException ioex) { - logger.warning("Failed to save the file, storage id " + dataFile.getStorageIdentifier() + " (" + ioex.getMessage() + ")"); - } finally { - if (readChannel != null) { - try { - readChannel.close(); - } catch (IOException e) { - } - } - if (writeChannel != null) { - try { - writeChannel.close(); - } catch (IOException e) { - } - } - } - - // Since we may have already spent some CPU cycles scaling down image thumbnails, - // we may as well save them, by moving these generated images to the permanent - // dataset directory. We should also remember to delete any such files in the - // temp directory: - List generatedTempFiles = listGeneratedTempFiles(Paths.get(FileUtil.getFilesTempDirectory()), storageId); - if (generatedTempFiles != null) { - for (Path generated : generatedTempFiles) { - if (savedSuccess) { // no need to try to save this aux file permanently, if we've failed to save the main file! - logger.fine("(Will also try to permanently save generated thumbnail file " + generated.toString() + ")"); - try { - //Files.copy(generated, Paths.get(dataset.getFileSystemDirectory().toString(), generated.getFileName().toString())); - int i = generated.toString().lastIndexOf("thumb"); - if (i > 1) { - String extensionTag = generated.toString().substring(i); - dataAccess.savePathAsAux(generated, extensionTag); - logger.fine("Saved generated thumbnail as aux object. \"preview available\" status: " + dataFile.isPreviewImageAvailable()); - } else { - logger.warning("Generated thumbnail file name does not match the expected pattern: " + generated.toString()); - } - - } catch (IOException ioex) { - logger.warning("Failed to save generated file " + generated.toString()); - } - } - - // ... but we definitely want to delete it: - try { - Files.delete(generated); - } catch (IOException ioex) { - logger.warning("Failed to delete generated file " + generated.toString()); - } - } - } - - // ... and let's delete the main temp file: - try { - logger.fine("Will attempt to delete the temp file " + tempLocationPath.toString()); - Files.delete(tempLocationPath); - } catch (IOException ex) { - // (non-fatal - it's just a temp file.) - logger.warning("Failed to delete temp file " + tempLocationPath.toString()); - } - - if (unattached) { - dataFile.setOwner(null); - } - // Any necessary post-processing: - //performPostProcessingTasks(dataFile); - - if (savedSuccess) { - // These are all brand new files, so they should all have - // one filemetadata total. -- L.A. - FileMetadata fileMetadata = dataFile.getFileMetadatas().get(0); - String fileName = fileMetadata.getLabel(); - - boolean metadataExtracted = false; - if (FileUtil.canIngestAsTabular(dataFile)) { - /* - * Note that we don't try to ingest the file right away - - * instead we mark it as "scheduled for ingest", then at - * the end of the save process it will be queued for async. - * ingest in the background. In the meantime, the file - * will be ingested as a regular, non-tabular file, and - * appear as such to the user, until the ingest job is - * finished with the Ingest Service. - */ - dataFile.SetIngestScheduled(); - } else if (fileMetadataExtractable(dataFile)) { - - try { - // FITS is the only type supported for metadata - // extraction, as of now. -- L.A. 4.0 - dataFile.setContentType("application/fits"); - metadataExtracted = extractMetadata(tempFileLocation, dataFile, version); - } catch (IOException mex) { - logger.severe("Caught exception trying to extract indexable metadata from file " + fileName + ", " + mex.getMessage()); - } - if (metadataExtracted) { - logger.fine("Successfully extracted indexable metadata from file " + fileName); - } else { - logger.fine("Failed to extract indexable metadata from file " + fileName); - } - } - // temp dbug line - //System.out.println("ADDING FILE: " + fileName + "; for dataset: " + dataset.getGlobalId()); - // Make sure the file is attached to the dataset and to the version, if this - // hasn't been done yet: - if (dataFile.getOwner() == null) { - dataFile.setOwner(dataset); - - version.getFileMetadatas().add(dataFile.getFileMetadata()); - dataFile.getFileMetadata().setDatasetVersion(version); - dataset.getFiles().add(dataFile); - - if (dataFile.getFileMetadata().getCategories() != null) { - ListIterator dfcIt = dataFile.getFileMetadata().getCategories().listIterator(); - - while (dfcIt.hasNext()) { - DataFileCategory dataFileCategory = dfcIt.next(); - - if (dataFileCategory.getDataset() == null) { - DataFileCategory newCategory = dataset.getCategoryByName(dataFileCategory.getName()); - if (newCategory != null) { - newCategory.addFileMetadata(dataFile.getFileMetadata()); - //dataFileCategory = newCategory; - dfcIt.set(newCategory); - } else { - dfcIt.remove(); - } - } - } - } - } - - ret.add(dataFile); - } - } - - logger.fine("Done! Finished saving new files in permanent storage and adding them to the dataset."); - } - - return ret; - } + public List saveAndAddFilesToDataset(DatasetVersion version, List newFiles) { + List ret = new ArrayList<>(); + + if (newFiles != null && newFiles.size() > 0) { + // ret = new ArrayList<>(); + // final check for duplicate file names; + // we tried to make the file names unique on upload, but then + // the user may have edited them on the "add files" page, and + // renamed FOOBAR-1.txt back to FOOBAR.txt... + + IngestUtil.checkForDuplicateFileNamesFinal(version, newFiles); + + Dataset dataset = version.getDataset(); + + for (DataFile dataFile : newFiles) { + boolean unattached = false; + boolean savedSuccess = false; + if (dataFile.getOwner() == null) { + unattached = true; + dataFile.setOwner(dataset); + } + + String[] storageInfo = DataAccess.getDriverIdAndStorageId(dataFile.getStorageIdentifier()); + String driverType = DataAccess.getDriverType(storageInfo[0]); + String storageId = storageInfo[1]; + if (driverType.equals("tmp")|| driverType.contentEquals("file")) { //"file" is the default if no prefix + String tempFileLocation = FileUtil.getFilesTempDirectory() + "/" + storageId; + + // Try to save the file in its permanent location: + Path tempLocationPath = Paths.get(FileUtil.getFilesTempDirectory() + "/" + storageId); + WritableByteChannel writeChannel = null; + FileChannel readChannel = null; + + StorageIO dataAccess = null; + + try { + logger.fine("Attempting to create a new storageIO object for " + storageId); + dataAccess = DataAccess.createNewStorageIO(dataFile, storageId); + + logger.fine("Successfully created a new storageIO object."); + /* + * This commented-out code demonstrates how to copy bytes from a local + * InputStream (or a readChannel) into the writable byte channel of a Dataverse + * DataAccessIO object: + */ + + /* + * storageIO.open(DataAccessOption.WRITE_ACCESS); + * + * writeChannel = storageIO.getWriteChannel(); readChannel = new + * FileInputStream(tempLocationPath.toFile()).getChannel(); + * + * long bytesPerIteration = 16 * 1024; // 16K bytes long start = 0; while ( + * start < readChannel.size() ) { readChannel.transferTo(start, + * bytesPerIteration, writeChannel); start += bytesPerIteration; } + */ + + /* + * But it's easier to use this convenience method from the DataAccessIO: + * + * (if the underlying storage method for this file is local filesystem, the + * DataAccessIO will simply copy the file using Files.copy, like this: + * + * Files.copy(tempLocationPath, storageIO.getFileSystemLocation(), + * StandardCopyOption.REPLACE_EXISTING); + */ + dataAccess.savePath(tempLocationPath); + + // Set filesize in bytes + // + dataFile.setFilesize(dataAccess.getSize()); + savedSuccess = true; + logger.fine("Success: permanently saved file " + dataFile.getFileMetadata().getLabel()); + + } catch (IOException ioex) { + logger.warning("Failed to save the file, storage id " + dataFile.getStorageIdentifier() + " (" + + ioex.getMessage() + ")"); + } finally { + if (readChannel != null) { + try { + readChannel.close(); + } catch (IOException e) { + } + } + if (writeChannel != null) { + try { + writeChannel.close(); + } catch (IOException e) { + } + } + } + + // Since we may have already spent some CPU cycles scaling down image + // thumbnails, + // we may as well save them, by moving these generated images to the permanent + // dataset directory. We should also remember to delete any such files in the + // temp directory: + List generatedTempFiles = listGeneratedTempFiles(Paths.get(FileUtil.getFilesTempDirectory()), + storageId); + if (generatedTempFiles != null) { + for (Path generated : generatedTempFiles) { + if (savedSuccess) { // no need to try to save this aux file permanently, if we've failed to + // save the main file! + logger.fine("(Will also try to permanently save generated thumbnail file " + + generated.toString() + ")"); + try { + // Files.copy(generated, Paths.get(dataset.getFileSystemDirectory().toString(), + // generated.getFileName().toString())); + int i = generated.toString().lastIndexOf("thumb"); + if (i > 1) { + String extensionTag = generated.toString().substring(i); + dataAccess.savePathAsAux(generated, extensionTag); + logger.fine( + "Saved generated thumbnail as aux object. \"preview available\" status: " + + dataFile.isPreviewImageAvailable()); + } else { + logger.warning( + "Generated thumbnail file name does not match the expected pattern: " + + generated.toString()); + } + + } catch (IOException ioex) { + logger.warning("Failed to save generated file " + generated.toString()); + } + } + + // ... but we definitely want to delete it: + try { + Files.delete(generated); + } catch (IOException ioex) { + logger.warning("Failed to delete generated file " + generated.toString()); + } + } + } + + // ... and let's delete the main temp file: + try { + logger.fine("Will attempt to delete the temp file " + tempLocationPath.toString()); + Files.delete(tempLocationPath); + } catch (IOException ex) { + // (non-fatal - it's just a temp file.) + logger.warning("Failed to delete temp file " + tempLocationPath.toString()); + } + + if (unattached) { + dataFile.setOwner(null); + } + // Any necessary post-processing: + // performPostProcessingTasks(dataFile); + + if (savedSuccess) { + // These are all brand new files, so they should all have + // one filemetadata total. -- L.A. + FileMetadata fileMetadata = dataFile.getFileMetadatas().get(0); + String fileName = fileMetadata.getLabel(); + + boolean metadataExtracted = false; + if (FileUtil.canIngestAsTabular(dataFile)) { + /* + * Note that we don't try to ingest the file right away - instead we mark it as + * "scheduled for ingest", then at the end of the save process it will be queued + * for async. ingest in the background. In the meantime, the file will be + * ingested as a regular, non-tabular file, and appear as such to the user, + * until the ingest job is finished with the Ingest Service. + */ + dataFile.SetIngestScheduled(); + } else if (fileMetadataExtractable(dataFile)) { + + try { + // FITS is the only type supported for metadata + // extraction, as of now. -- L.A. 4.0 + dataFile.setContentType("application/fits"); + metadataExtracted = extractMetadata(tempFileLocation, dataFile, version); + } catch (IOException mex) { + logger.severe("Caught exception trying to extract indexable metadata from file " + + fileName + ", " + mex.getMessage()); + } + if (metadataExtracted) { + logger.fine("Successfully extracted indexable metadata from file " + fileName); + } else { + logger.fine("Failed to extract indexable metadata from file " + fileName); + } + } + } + } else { + try { + StorageIO dataAccess = DataAccess.getStorageIO(dataFile); + //Populate metadata + dataAccess.open(DataAccessOption.READ_ACCESS); + //set file size + dataFile.setFilesize(dataAccess.getSize()); + } catch (IOException ioex) { + logger.warning("Failed to get file size, storage id " + dataFile.getStorageIdentifier() + " (" + + ioex.getMessage() + ")"); + } + savedSuccess = true; + logger.info("unattached: " + unattached); + dataFile.setOwner(null); + + } + + logger.fine("Done! Finished saving new files in permanent storage and adding them to the dataset."); + + if (savedSuccess) { + // temp dbug line + // System.out.println("ADDING FILE: " + fileName + "; for dataset: " + + // dataset.getGlobalId()); + // Make sure the file is attached to the dataset and to the version, if this + // hasn't been done yet: + if (dataFile.getOwner() == null) { + dataFile.setOwner(dataset); + + version.getFileMetadatas().add(dataFile.getFileMetadata()); + dataFile.getFileMetadata().setDatasetVersion(version); + dataset.getFiles().add(dataFile); + + if (dataFile.getFileMetadata().getCategories() != null) { + ListIterator dfcIt = dataFile.getFileMetadata().getCategories() + .listIterator(); + + while (dfcIt.hasNext()) { + DataFileCategory dataFileCategory = dfcIt.next(); + + if (dataFileCategory.getDataset() == null) { + DataFileCategory newCategory = dataset + .getCategoryByName(dataFileCategory.getName()); + if (newCategory != null) { + newCategory.addFileMetadata(dataFile.getFileMetadata()); + // dataFileCategory = newCategory; + dfcIt.set(newCategory); + } else { + dfcIt.remove(); + } + } + } + } + } + } + + ret.add(dataFile); + } + } + + return ret; + } public List listGeneratedTempFiles(Path tempDirectory, String baseName) { List generatedFiles = new ArrayList<>(); diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index 45ce6949127..71786001ad9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -27,8 +27,8 @@ import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.FileMetadata; import edu.harvard.iq.dataverse.TermsOfUseAndAccess; +import edu.harvard.iq.dataverse.dataaccess.DataAccess; import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter; -import static edu.harvard.iq.dataverse.dataaccess.S3AccessIO.S3_IDENTIFIER_PREFIX; import edu.harvard.iq.dataverse.dataset.DatasetThumbnail; import edu.harvard.iq.dataverse.datasetutility.FileExceedsMaxSizeException; import static edu.harvard.iq.dataverse.datasetutility.FileSizeChecker.bytesToHumanReadable; @@ -1281,8 +1281,10 @@ public static String getFilesTempDirectory() { } public static void generateS3PackageStorageIdentifier(DataFile dataFile) { - String bucketName = System.getProperty("dataverse.files.s3-bucket-name"); - String storageId = S3_IDENTIFIER_PREFIX + "://" + bucketName + ":" + dataFile.getFileMetadata().getLabel(); + String driverId = DataAccess.getStorageDriverId(dataFile.getDataverseContext()); + + String bucketName = System.getProperty("dataverse.files." + driverId + ".bucket-name"); + String storageId = driverId + "://" + bucketName + ":" + dataFile.getFileMetadata().getLabel(); dataFile.setStorageIdentifier(storageId); } diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIOTest.java index 96c74515c76..e80c82d059b 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIOTest.java @@ -56,10 +56,10 @@ public void setUpClass() throws IOException { dataFile = MocksFactory.makeDataFile(); dataFile.setOwner(dataset); dataFile.setStorageIdentifier("DataFile"); - - datasetAccess = new FileAccessIO<>(dataset); - dataFileAccess = new FileAccessIO<>(dataFile); - dataverseAccess = new FileAccessIO<>(dataverse); + String dummyDriverId = "dummmy"; + datasetAccess = new FileAccessIO<>(dataset,null, dummyDriverId); + dataFileAccess = new FileAccessIO<>(dataFile, null, dummyDriverId); + dataverseAccess = new FileAccessIO<>(dataverse, null, dummyDriverId); File file = new File("/tmp/files/tmp/dataset/Dataset"); file.getParentFile().mkdirs(); diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIOTest.java index 4ce821a5fee..86d129af664 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIOTest.java @@ -43,8 +43,8 @@ public void setup() throws IOException { dataFile.setOwner(dataSet); dataFileId = UtilIT.getRandomIdentifier(); dataFile.setStorageIdentifier("s3://bucket:"+dataFileId); - dataSetAccess = new S3AccessIO<>(dataSet, null, s3client); - dataFileAccess = new S3AccessIO<>(dataFile, null, s3client); + dataSetAccess = new S3AccessIO<>(dataSet, null, s3client, "s3"); + dataFileAccess = new S3AccessIO<>(dataFile, null, s3client, "s3"); } /* diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/StorageIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/StorageIOTest.java index 2700bf3448c..4d2e1072950 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/StorageIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/StorageIOTest.java @@ -77,8 +77,9 @@ public void testGetDvObject() { } catch (ClassCastException ex) { assertEquals(ex.getMessage(), "edu.harvard.iq.dataverse.Dataset cannot be cast to edu.harvard.iq.dataverse.Dataverse"); } - assertEquals(new DataFile(), new FileAccessIO<>(new DataFile()).getDataFile()); - assertEquals(new Dataverse(), new FileAccessIO<>(new Dataverse()).getDataverse()); + String dummyDriverId="dummy"; + assertEquals(new DataFile(), new FileAccessIO<>(new DataFile(), null, dummyDriverId).getDataFile()); + assertEquals(new Dataverse(), new FileAccessIO<>(new Dataverse(), null, dummyDriverId).getDataverse()); } @Test diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/SwiftAccessIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/SwiftAccessIOTest.java index 554242c9311..c1aa6b5fca3 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/SwiftAccessIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/SwiftAccessIOTest.java @@ -39,8 +39,9 @@ public void setUpClass() throws IOException { datafile = MocksFactory.makeDataFile(); dataset = MocksFactory.makeDataset(); datafile.setOwner(dataset); - datasetAccess = new SwiftAccessIO<>(dataset); - datafileAccess = new SwiftAccessIO<>(datafile); + String dummyDriverId="dummy"; + datasetAccess = new SwiftAccessIO<>(dataset, null, dummyDriverId); + datafileAccess = new SwiftAccessIO<>(datafile, null, dummyDriverId); swiftAccess = new SwiftAccessIO(); } From cdbd6f2a0571146b156f34b1defd047a11fef59d Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 7 Jan 2020 09:53:16 -0500 Subject: [PATCH 081/475] merge issue --- pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pom.xml b/pom.xml index 06f3d26a650..481f0418c3c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,11 +7,7 @@ --> edu.harvard.iq dataverse -<<<<<<< IQSS/6485 4.18.1 -======= - 4.18.1-tdl-dev-ms ->>>>>>> 08f6849 multistore implementation (built on direct upload) war dataverse From 9cc034a351761d5994aee931ff102369ff439102 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 7 Jan 2020 10:28:27 -0500 Subject: [PATCH 082/475] dcm - use new option name - assume store with id 's3' Note: DCM doesn't use any of the other S3 options in creating the Amazon client, so it is somewhat hardcoded that was as well. A rewrite might identify a specific s3 store to use, build the amazon client from it's settings and still use the general dcm-s3-bucket-name entry. If DCM should be supported across multiple stores, a dataverse.files..dcm-s3-bucket-name option could be created so that everything is ties to a specific store. --- src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java index f6f46e375ff..054ed61f320 100644 --- a/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java +++ b/src/main/java/edu/harvard/iq/dataverse/S3PackageImporter.java @@ -69,7 +69,7 @@ public void copyFromS3(Dataset dataset, String s3ImportPath) throws IOException String dcmBucketName = System.getProperty("dataverse.files.dcm-s3-bucket-name"); String dcmDatasetKey = s3ImportPath; - String dvBucketName = System.getProperty("dataverse.files.s3-bucket-name"); + String dvBucketName = System.getProperty("dataverse.files.s3.bucket-name"); String dvDatasetKey = getS3DatasetKey(dataset); @@ -137,7 +137,7 @@ public DataFile createPackageDataFile(Dataset dataset, String folderName, long t //This is a brittle calculation, changes of the dcm post_upload script will blow this up String rootPackageName = "package_" + folderName.replace("/", ""); - String dvBucketName = System.getProperty("dataverse.files.s3-bucket-name"); + String dvBucketName = System.getProperty("dataverse.files.s3.bucket-name"); String dvDatasetKey = getS3DatasetKey(dataset); //getting the name of the .sha file via substring, ${packageName}.sha From ae6ecfa0bfe254bc7e16cc84112d5d76a9073091 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 3 Jan 2020 14:24:29 -0500 Subject: [PATCH 083/475] control store via dataverse.storagedriver param manageable by superuser only Conflicts: src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java --- .../edu/harvard/iq/dataverse/Dataverse.java | 10 +++ .../harvard/iq/dataverse/DataversePage.java | 11 +++ .../harvard/iq/dataverse/api/Datasets.java | 2 +- .../iq/dataverse/dataaccess/DataAccess.java | 82 ++++++++++++++----- .../impl/AbstractCreateDatasetCommand.java | 2 +- .../harvard/iq/dataverse/util/FileUtil.java | 10 ++- src/main/java/propertyFiles/Bundle.properties | 2 + .../migration/V4.19.0.1__tbd_multistore.sql | 2 + src/main/webapp/dataverse.xhtml | 13 +++ 9 files changed, 109 insertions(+), 25 deletions(-) create mode 100644 src/main/resources/db/migration/V4.19.0.1__tbd_multistore.sql diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java index 024281b0b96..02dd1fa09a9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java @@ -147,6 +147,8 @@ public String getIndexableCategoryName() { } private String affiliation; + + private String storageDriver; // Note: We can't have "Remove" here, as there are role assignments that refer // to this role. So, adding it would mean violating a forign key contstraint. @@ -756,4 +758,12 @@ public boolean isAncestorOf( DvObject other ) { } return false; } + + public String getStorageDriverId() { + return storageDriver; + } + + public void setStorageDriverId(String storageDriver) { + this.storageDriver = storageDriver; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java index 6dc792aefed..60922f4f849 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java @@ -4,6 +4,7 @@ import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.authorization.users.User; +import edu.harvard.iq.dataverse.dataaccess.DataAccess; import edu.harvard.iq.dataverse.dataverse.DataverseUtil; import edu.harvard.iq.dataverse.engine.command.Command; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; @@ -39,6 +40,8 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.faces.component.UIComponent; @@ -1197,4 +1200,12 @@ public List completeHostDataverseMenuList(String query) { return null; } } + + public Set> getStorageDriverOptions() { + return DataAccess.getStorageDriverLabels(); + } + + public String getCurrentStorageDriverLabel() { + return DataAccess.getStorageDriverLabelFor(dataverse.getStorageDriverId()); + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index f7f31077864..65f3a214fea 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -1300,7 +1300,7 @@ public Response receiveChecksumValidationResults(@PathParam("identifier") String if ("validation passed".equals(statusMessageFromDcm)) { logger.log(Level.INFO, "Checksum Validation passed for DCM."); - String storageDriver = DataAccess.getStorageDriverId(dataset.getDataverseContext()); + String storageDriver = dataset.getDataverseContext().getStorageDriverId(); String uploadFolder = jsonFromDcm.getString("uploadFolder"); int totalSize = jsonFromDcm.getInt("totalSize"); String storageDriverType = System.getProperty("dataverse.file." + storageDriver + ".type"); diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index de8be99152c..d57363975d8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -20,18 +20,25 @@ package edu.harvard.iq.dataverse.dataaccess; -import edu.harvard.iq.dataverse.Dataverse; import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.util.StringUtil; + import java.io.IOException; import java.util.HashMap; import java.util.Properties; +import java.util.logging.Logger; +import java.util.Map.Entry; +import java.util.Set; /** * * @author Leonid Andreev */ + public class DataAccess { + private static final Logger logger = Logger.getLogger(DataAccess.class.getCanonicalName()); + public DataAccess() { }; @@ -85,24 +92,24 @@ public static StorageIO getStorageIO(T dvObject, DataAcc // Experimental extension of the StorageIO system allowing direct access to // stored physical files that may not be associated with any DvObjects - public static StorageIO getDirectStorageIO(String storageLocation) throws IOException { - String[] response = getDriverIdAndStorageId(storageLocation); + public static StorageIO getDirectStorageIO(String fullStorageLocation) throws IOException { + String[] response = getDriverIdAndStorageLocation(fullStorageLocation); String storageDriverId = response[0]; - String storageIdentifier=response[1]; + String storageLocation=response[1]; String storageType = getDriverType(storageDriverId); switch(storageType) { case "file": - return new FileAccessIO<>(storageIdentifier, storageDriverId); + return new FileAccessIO<>(storageLocation, storageDriverId); case "s3": - return new S3AccessIO<>(storageIdentifier, storageDriverId); + return new S3AccessIO<>(storageLocation, storageDriverId); case "swift": - return new SwiftAccessIO<>(storageIdentifier, storageDriverId); + return new SwiftAccessIO<>(storageLocation, storageDriverId); default: throw new IOException("getDirectStorageIO: Unsupported storage method."); } } - public static String[] getDriverIdAndStorageId(String storageLocation) { + public static String[] getDriverIdAndStorageLocation(String storageLocation) { //default if no prefix String storageIdentifier=storageLocation; int separatorIndex = storageLocation.indexOf("://"); @@ -114,6 +121,10 @@ public static String[] getDriverIdAndStorageId(String storageLocation) { return new String[]{storageDriverId, storageIdentifier}; } + public static String getStorarageIdFromLocation(String location) { + return location.substring(location.lastIndexOf('/')+1); + } + public static String getDriverType(String driverId) { return System.getProperty("dataverse.files." + driverId + ".type", "file"); } @@ -122,7 +133,7 @@ public static String getDriverType(String driverId) { // for saving new, not yet saved datafiles. public static StorageIO createNewStorageIO(T dvObject, String storageTag) throws IOException { - return createNewStorageIO(dvObject, storageTag, getStorageDriverId(dvObject.getDataverseContext())); + return createNewStorageIO(dvObject, storageTag, dvObject.getDataverseContext().getStorageDriverId()); } public static StorageIO createNewStorageIO(T dvObject, String storageTag, String storageDriverId) throws IOException { @@ -160,24 +171,51 @@ public static StorageIO createNewStorageIO(T dvObject, S static HashMap drivers = null; - public static String getStorageDriverId(Dataverse dataverse) { + public static String getStorageDriverId(String driverLabel) { if (drivers==null) { - drivers = new HashMap(); - Properties p = System.getProperties(); - for(String property: p.stringPropertyNames()) { - if(property.startsWith("dataverse.files.") && property.endsWith(".affiliation")) { - String driverId = property.substring(16); - driverId=driverId.substring(0,driverId.indexOf('.')); - drivers.put(p.get(property).toString(), driverId); - } - - } + populateDrivers(); } - if(drivers.containsKey(dataverse.getAffiliation())) { - return drivers.get(dataverse.getAffiliation()); + if(StringUtil.nonEmpty(driverLabel) && drivers.containsKey(driverLabel)) { + return drivers.get(driverLabel); } return DEFAULT_STORAGE_DRIVER_IDENTIFIER; + } + + public static Set> getStorageDriverLabels() { + if (drivers==null) { + populateDrivers(); + } + return drivers.entrySet(); + } + + private static void populateDrivers() { + drivers = new HashMap(); + Properties p = System.getProperties(); + for(String property: p.stringPropertyNames()) { + if(property.startsWith("dataverse.files.") && property.endsWith(".label")) { + String driverId = property.substring(16); // "dataverse.files.".length + driverId=driverId.substring(0,driverId.indexOf('.')); + logger.info("Found Storage Driver: " + driverId + " for " + p.get(property).toString()); + drivers.put(p.get(property).toString(), driverId); + } + } } + public static String getStorageDriverLabelFor(String storageDriverId) { + String label = "<>"; + if (drivers==null) { + populateDrivers(); + } + if(drivers.containsValue(storageDriverId)) { + for(String key: drivers.keySet()) { + if(drivers.get(key).equals(storageDriverId)) { + label = key; + break; + } + + } + } + return label; + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java index 864bb700e0e..971c005a902 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java @@ -96,7 +96,7 @@ public Dataset execute(CommandContext ctxt) throws CommandException { theDataset.setAuthority(ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound)); } if (theDataset.getStorageIdentifier() == null) { - String driverId = DataAccess.getStorageDriverId(theDataset.getDataverseContext()); + String driverId = theDataset.getDataverseContext().getStorageDriverId(); theDataset.setStorageIdentifier(driverId + "://" + theDataset.getGlobalId().asString()); } if (theDataset.getIdentifier()==null) { diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index 71786001ad9..2cd8ab69bbf 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -24,11 +24,13 @@ import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.DataFile.ChecksumType; import edu.harvard.iq.dataverse.DataFileServiceBean; +import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.FileMetadata; import edu.harvard.iq.dataverse.TermsOfUseAndAccess; import edu.harvard.iq.dataverse.dataaccess.DataAccess; import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter; +import edu.harvard.iq.dataverse.dataaccess.S3AccessIO; import edu.harvard.iq.dataverse.dataset.DatasetThumbnail; import edu.harvard.iq.dataverse.datasetutility.FileExceedsMaxSizeException; import static edu.harvard.iq.dataverse.datasetutility.FileSizeChecker.bytesToHumanReadable; @@ -80,6 +82,7 @@ import static edu.harvard.iq.dataverse.datasetutility.FileSizeChecker.bytesToHumanReadable; import org.apache.commons.io.FilenameUtils; +import com.amazonaws.AmazonServiceException; /** * a 4.0 implementation of the DVN FileUtil; @@ -1281,7 +1284,7 @@ public static String getFilesTempDirectory() { } public static void generateS3PackageStorageIdentifier(DataFile dataFile) { - String driverId = DataAccess.getStorageDriverId(dataFile.getDataverseContext()); + String driverId = dataFile.getDataverseContext().getStorageDriverId(); String bucketName = System.getProperty("dataverse.files." + driverId + ".bucket-name"); String storageId = driverId + "://" + bucketName + ":" + dataFile.getFileMetadata().getLabel(); @@ -1614,4 +1617,9 @@ public static boolean isPackageFile(DataFile dataFile) { return DataFileServiceBean.MIME_TYPE_PACKAGE_FILE.equalsIgnoreCase(dataFile.getContentType()); } + public static String getStorageIdentifierFromLocation(String location) { + int driverEnd = location.indexOf("://") + 3; + int bucketEnd = driverEnd + location.substring(driverEnd).indexOf("/"); + return location.substring(0,bucketEnd) + ":" + location.substring(location.lastIndexOf("/") + 1); + } } diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index fc88691d9cc..b9a123fd517 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -35,6 +35,7 @@ name=Name institution=Institution position=Position affiliation=Affiliation +storage=Storage Driver createDataverse=Create Dataverse remove=Remove done=Done @@ -691,6 +692,7 @@ dataverse.host.tip=Changing the host dataverse will clear any fields you may hav dataverse.host.autocomplete.nomatches=No matches dataverse.identifier.title=Short name used for the URL of this dataverse. dataverse.affiliation.title=The organization with which this dataverse is affiliated. +dataverse.storage.title=A storage service to be used for datasets in this dataverse. dataverse.category=Category dataverse.category.title=The type that most closely reflects this dataverse. dataverse.type.selectTab.top=Select one... diff --git a/src/main/resources/db/migration/V4.19.0.1__tbd_multistore.sql b/src/main/resources/db/migration/V4.19.0.1__tbd_multistore.sql new file mode 100644 index 00000000000..273de02fef7 --- /dev/null +++ b/src/main/resources/db/migration/V4.19.0.1__tbd_multistore.sql @@ -0,0 +1,2 @@ +ALTER TABLE dataverse +ADD COLUMN IF NOT EXISTS storagedriver TEXT; diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index a9f013fc0a3..855b53ab10e 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -139,6 +139,19 @@
+
+ + #{bundle.storage} + + +
+ + + + +
+
From 79fbd8ce4781ae996c17f0b8e24e1d385bd6a37b Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 7 Jan 2020 11:25:05 -0500 Subject: [PATCH 084/475] redirect and url lifetime store specific --- .../iq/dataverse/api/DownloadInstanceWriter.java | 11 +---------- .../harvard/iq/dataverse/dataaccess/S3AccessIO.java | 12 ++++++++++-- .../edu/harvard/iq/dataverse/util/SystemConfig.java | 2 +- .../iq/dataverse/dataaccess/S3AccessIOTest.java | 6 +++--- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/DownloadInstanceWriter.java b/src/main/java/edu/harvard/iq/dataverse/api/DownloadInstanceWriter.java index 8c480bdcc36..a9b4746299d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/DownloadInstanceWriter.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/DownloadInstanceWriter.java @@ -228,7 +228,7 @@ public void writeTo(DownloadInstance di, Class clazz, Type type, Annotation[] throw new NotFoundException("datafile access error: requested optional service (image scaling, format conversion, etc.) could not be performed on this datafile."); } } else { - if (storageIO instanceof S3AccessIO && !(dataFile.isTabularData()) && isRedirectToS3()) { + if (storageIO instanceof S3AccessIO && !(dataFile.isTabularData()) && ((S3AccessIO) storageIO).downloadRedirectEnabled()) { // definitely close the (still open) S3 input stream, // since we are not going to use it. The S3 documentation // emphasizes that it is very important not to leave these @@ -445,13 +445,4 @@ private long getFileSize(DownloadInstance di, String extraHeader) { } return -1; } - - private boolean isRedirectToS3() { - String optionValue = System.getProperty("dataverse.files.s3-download-redirect"); - if ("true".equalsIgnoreCase(optionValue)) { - return true; - } - return false; - } - } diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index 5efd612901d..8194ab80c58 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -82,7 +82,7 @@ public S3AccessIO(T dvObject, DataAccessRequest req, String driverId) { // Openstack SWIFT S3 implementations require "PayloadSigning" set to true. default = false s3CB.setPayloadSigningEnabled(s3payloadSigning); // Openstack SWIFT S3 implementations require "ChunkedEncoding" set to false. default = true - // Boolean is inverted, otherwise setting dataverse.files.s3-chunked-encoding=false would result in leaving Chunked Encoding enabled + // Boolean is inverted, otherwise setting dataverse.files..chunked-encoding=false would result in leaving Chunked Encoding enabled s3CB.setChunkedEncodingDisabled(!s3chunkedEncoding); s3CB.setCredentials(new ProfileCredentialsProvider(s3profile)); @@ -760,6 +760,14 @@ String getMainFileKey() throws IOException { return key; } + public boolean downloadRedirectEnabled() { + String optionValue = System.getProperty("dataverse.files." + this.driverId + ".download-redirect"); + if ("true".equalsIgnoreCase(optionValue)) { + return true; + } + return false; + } + public String generateTemporaryS3Url() throws IOException { //Questions: // Q. Should this work for private and public? @@ -821,7 +829,7 @@ public String generateTemporaryS3Url() throws IOException { } int getUrlExpirationMinutes() { - String optionValue = System.getProperty("dataverse.files.s3-url-expiration-minutes"); + String optionValue = System.getProperty("dataverse.files." + this.driverId + ".url-expiration-minutes"); if (optionValue != null) { Integer num; try { diff --git a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java index b8836060069..8d0cb276a93 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java @@ -862,7 +862,7 @@ public String toString() { /** * See FileUploadMethods. * - * TODO: Consider if dataverse.files.s3-download-redirect belongs here since + * TODO: Consider if dataverse.files..download-redirect belongs here since * it's a way to bypass Glassfish when downloading. */ public enum FileDownloadMethods { diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIOTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIOTest.java index 86d129af664..f92b44862e2 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIOTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIOTest.java @@ -99,7 +99,7 @@ void keyNullstorageIdNull_getMainFileKey() throws IOException { @Test void default_getUrlExpirationMinutes() { // given - System.clearProperty("dataverse.files.s3-url-expiration-minutes"); + System.clearProperty("dataverse.files.s3.url-expiration-minutes"); // when & then assertEquals(60, dataFileAccess.getUrlExpirationMinutes()); } @@ -107,7 +107,7 @@ void default_getUrlExpirationMinutes() { @Test void validSetting_getUrlExpirationMinutes() { // given - System.setProperty("dataverse.files.s3-url-expiration-minutes", "120"); + System.setProperty("dataverse.files.s3.url-expiration-minutes", "120"); // when & then assertEquals(120, dataFileAccess.getUrlExpirationMinutes()); } @@ -115,7 +115,7 @@ void validSetting_getUrlExpirationMinutes() { @Test void invalidSetting_getUrlExpirationMinutes() { // given - System.setProperty("dataverse.files.s3-url-expiration-minutes", "NaN"); + System.setProperty("dataverse.files.s3.url-expiration-minutes", "NaN"); // when & then assertEquals(60, dataFileAccess.getUrlExpirationMinutes()); } From 6c506ab5c9a602364563c6afaead1fc875c35135 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 7 Jan 2020 11:47:26 -0500 Subject: [PATCH 085/475] limit rsync setup/panel to datasets using 's3' store --- .../edu/harvard/iq/dataverse/EditDatafilesPage.java | 10 +++++++++- src/main/webapp/editFilesFragment.xhtml | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 3c3da259f75..55318bac371 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -571,7 +571,7 @@ public String init() { } saveEnabled = true; - if (mode == FileEditMode.UPLOAD && workingVersion.getFileMetadatas().isEmpty() && settingsWrapper.isRsyncUpload()) { + if (mode == FileEditMode.UPLOAD && workingVersion.getFileMetadatas().isEmpty() && rsyncUploadSupported()) { setUpRsync(); } @@ -2757,6 +2757,14 @@ public void saveAdvancedOptions() { fileMetadataSelectedForIngestOptionsPopup = null; } + public boolean rsyncUploadSupported() { + // ToDo - rsync was written before multiple store support and currently is hardcoded to use the "s3" store. + // When those restrictions are lifted/rsync can be configured per store, this test should check that setting + // instead of testing for the 's3" store. + return settingsWrapper.isRsyncUpload() && dataset.getDataverseContext().getStorageDriverId().equals("s3"); + } + + private void populateFileMetadatas() { fileMetadatas = new ArrayList<>(); if (selectedFileIdsList == null || selectedFileIdsList.isEmpty()) { diff --git a/src/main/webapp/editFilesFragment.xhtml b/src/main/webapp/editFilesFragment.xhtml index b451a43c9fe..811e6c4d55f 100644 --- a/src/main/webapp/editFilesFragment.xhtml +++ b/src/main/webapp/editFilesFragment.xhtml @@ -153,7 +153,7 @@
-
+
)eJCvKIufNenH=}Kg^d)KHf=uN+S($+5@(eAU0v!?9_)9#L^ z3ibq^sGzNd&!FTR#`}PtKC)}}Ry@9-tG?|#0&fV=9VaZ9F97$B)ae_2>W?qj!E3uz zgfD-{9qR5cL?@&hC!9ec>NA-yJ?M1W(24;|koFdV7HrZ;D;(w^|M#&bdmW0lUx6FZ zIx4^$h}PNU^@DtpNr?!{^WO&Ve|W}&Kc|xKvFJEQHANh`;7@tkTa(^_xIB`AH}GBc ziGmBRO1AlIT5UmVmt#nlUQ|M5yn5K8HuNT7O`lwRQA@j2(}XWvB$1mq$IvXDlFAkish5EZ;qQ1Y9_p_RO96a_Do$s{jW1`8iSOz@i!sgf2x1w2yM z(#8rF_zHPsFYt=e*I-PDnw*j-%A%;GN?8+eEM-hMn;1>Vnv%vWEh`eaED6-I^BXgUpN!k6I)W>HDACJ+!DVGZ>w*u$ge1`m|n7OamlZ! zdyH=VZ@tI~s0bKd3U0;72`H{5(zfyp35rQnIulQRqtlylX%1d7(JCt#dA5YB zF?Wd#TBXS<+;|obQXMjM$qnMBZq*q270;_om~jaW{w!`#!5dhp0m?`dDBfTcJ1OJ! zu@nO3iw~#}j5PCrP{mFvc%uu-4lMJj;YO)^l|c34m{N}DlLD%($$Lh03I-qTK?&&` z`MOYxrf{WHI(Y}G`6Q~XVdtdq`Lt@)8<65AD&LqBPjtWkoCCufQf-wS*yb;&AW|>o z>i{RR=;NuEN;gEs(`8tOp2C9+^959@47|mLi6^jB>C)4s95E*v=+tT5rNDk^zfxd< zw4UOPLot1Y`sBSB6`k>Gc(@$XM_Ra4YImL?{CrMDYvxG?RkiVJb$CTucZuPz`R&qY zwE6Awk>bc6r8pbxZMC>4Y`+>}E#^-_5jL}T0g-02cX<&u^Y?;q>)GeHaO=5L`8XS# zbrs`+p`Owa)hL3B5z{C?rML?mew8?Q+^=e4EjHg`;taM=A(3XAcWn_i+xM7o>&@q+ zaO*8P`M8VqAgX%*4sELXppFfy`mhcjs`{voPOAF2j(TNdYBv|9xXF#AD&qCFijHvW z<7!>1`l1fcijm?=VlP82w>aLqx(+(ExT;N;pm6I;x_W|UH_TN;+|Dyg^i`nFa_I>9 z)tEw@%~nzcF>Y5yPq_6%H4pmgxej~Ti0f6mh6tPYvON0gtxijYc(ETEoy;H5CpL4` z-3r`~VgB4JnNlFiA2c=jA05Hnqd|9+Xnv5k*xPybZ+zezF~1|5h44WD-XKt);NYPQNFBX|JOmI*`rXiPeUt8F8v)C` zRqiBkz5e#NTQEWn92?O_`dC|_{SGjZ|6$uhP6foN!xS*U6)-{sJ^zmE6|twF3#n^` zxa^B!KxpZA_r|y!3baSW4}@O%iF!kp3gGu2ea1lB<+i8)#4pYTAAB}T4bSOgc}KZ) zBHFkb3qGla)ek;1bpOueAo+~$x{bWodYR?AqZ<+= zg}`}PNFJCDTU0Ii+ld!Ma2dsYqzUG*^^|CT4ep>?2g#Ke5?PHzxiwwC`b;FWT^F?f z0VB2Ajp*?8$6*@^!}bHTa(nk*D)#^SFRk4NHevByp8SV5aCk1K{3$lT z6(oe`Ew^_bDk__t<#(xo8MAt%B;_jo|2)d6Ly)m8hyXaRm&vh+ux(}-VS#3!^hqd7N zo>uuUcez|MUx~W+cYyj{ZbI65;_lMgp>|&QAp7q6!26!~z$y76(N(y8pAVOA@s@mPsjgc&p-Z~$KGS<9;CrE8LOV9 zt4yzLYYF+DD~hdzG`H=pqinC_FV3eaxi6pgU+1xbU&12@U{WC}V3G0`^6VJT!9f9Z zJ-bdpogiPe-$gOn-$gM;arK;oi1$B*v94>a@~qT3_8;Ig@^Jm_XR74j-gx=CFjtTl z?%5sNnEPVwcn4kjy#yfwnD^6<<}F%7ibGGl>HJP=^W|sG=(~Oq8AUE%!AA+znwe~G zW4`_e?(-jr4>H|%cN+?~lf08V{H0AI0B(IdVr(w`bdUgsKJ5g$lX4IbFf%lnY=hum0v#_SB%11+g1SIX*& zHv#%qh&*-~`D2(1rUvZG;*{{Psvamabu$wP7J|SW$=m+Cn%f9(T`O>UkT?Y&S&)cE z<2%g9cE)*lEHIh{ch6WAK8_do_B)BfEeCHiy&iTFc@&gxqop8^Q8o|YKt(Tcr8EmS z^WfTOCMD?|!c06OEMCGx);BRO9FExyr6hNBc5A!kdgFCn(!4{-ADgL#$r(TE(Q!&? z3kb%?;cjquoGLZu*Od;#pJ@82)NTesrp$QuzX+9*46>KlnJ${7$k>*G**~B!FWcnaS?R;+1AhO@di zJ)3VIq}yW&?yU9{&Kp(Zl6M%do!Cxqz=9_uXY2pb{P#L{jcaCFo-nFw9# zySPzAtX=cB1-kCY9g9#cjTu-xI45*$pwSOykm5s2p6TasBl6Ufwmk5kgwkYRSPi4U z9+HuEaIXud(p6cJ1mvL-`WPLvXb#vLzQ~^UzpHqKqtmx8r?YfUpEs8CTno0@GFGPt z<3gHSf9a;qzK7SyIDkmGoPjq(gn*>W`{$*z%w~99Ouaqn;8`8l492@)G4AOG2kz^y z(z(e(C7JVHmxFw}n1^o{(?dC}rMtJdHfC;Eo4XYz+8@XnCQeu6iB23+4lZ(B(>>(b za>Q?Xkv7dUacW=cfCga@C#=Cc+hZ!u%Q#eR|XE$q7cy5jUBzHA1yil(xN{f zUZWee23{H&MP`08;yZYR8KL%uhEK36X^x939~w_PM}vig^Wxg+x=r>|nBluygaj@= z49kFM$n|e%qR*nSqB}&TqHKsp1W{2|JbE;{@rDjlI3_h_VY%#>oSNALJCn@nObZ)` z`pAAf!7+nh6a?c@TQKd%7hSm>t6cT9`$BchQ;7%%JEh@cwP{qd>1J5PQ=ID+)8`$r zEzM1K@ifi%g&wXt#yXj4rm!?A%zpXKWmPE<&9n#^l**}~WaNdzGrvSJGm9*vXcZCG z48!iyf{YPDASqOmo?5B~8>@J*7gGT00KDqmnsYxXUG0r4VXs6Z>Ec#}@nq z*BnrBhsYpdroE%T7C%l@kNmbVkU#*M@@Qha_X!}>7kcef^ z+Fot;a5k7=bprNVJieTdsg~!*C9oa5>_dX;92$M#b}PDLL*f}PA{$E`yg#r%U2Z;N zJD~8iB)T%Y8hV`Uml{roO^*o83r$YZz}$6vGHxMs3KIO)F{6|J>KG(=sjZk8EW`I_ zXVuok5XhDk!cFGIS@ewN_TZNU-%!CqsnZrU$%V24eRbJ>ro(#>$+bT;V(3y0(YQQF zJihE-{1@g{5lbzNX;zwlbn8^I~9T{8py1cH*S z+Uif-IU)cYrU`v9s>d_rL<>FiO$E4wQrywqAp@F$tsx2H10`!rIUAZ`C~Ubm)|^v-1{(+l_!pG+9+3WW0(q zdEC~)V+8RMl1&N|{<;+q4x|m_UtDqS?x+SyS^m3luQTS8kO}sx5{7lw4zGR+@c4e>0?5BQCL>1bTgPA) zRg0u%Ef+0Er7KP+zKQ3qxA)9wx5fwy(SKtYZ2lMOn(nN=w#_a?Rj&Fh#0h@x_6$-& z%ulM)@30mgCl|qB!FmWYn|aDHUx;=Ht-wv6RZ|gn(A#rA>)7o!710+G%oCgtV440< zR7K?3kUk<6y1NKwu3TRjM$LBt`!aC!Wp`$7auS@&6K$_`_-ZmV%J!zQ7SqHqJdR6J zgs*XmszowYND+$^87Za|+Eq107#@xwOQ_99qwfI%*kEfHp_Zzd*u-WrQVOobm}6th z0B73*Jt!HhUN!kU157T0VHRIo)!ZcI@Jt66ldyk=BM^|$$ateMr{v)gFux|n#e1A$5`iiwpB>i&BmehSlCJtqkDx|{$FXx2 zNqljSq=cR!1jtvUeHl6Op`@rG4qtv*vbLCI>f>-%?5+NHL_5E5>2^YWcaO}~EEmoA zV5q}@KmrRL3i?E72Uq+l6My0Cejx|WqFHe2iHT+Q7DPNdd};9{qy)N$6yaRI97G^U zoD`Vs3MMP8s(rx;@xW;|1X9RGHxj!V4Rmm8fySY2o0r?h=NH{?~2{Ldr zZ=Jap5TZ5Q`AYKq7Y?lb+Jmnw(pQr5?hxaU$)n^e%~>khfmJtnTX6~rnRMQHeFe?* z#=2kfed~XIkAZhQ9|fm%CDcg<5;_dOz?_wYGyj$=ZW=hEVH0)~uWWr(xy;WY7l=sR zCewWhS=}c>2Ig9SCdNs*rFFEIx&8E#9D^huhfb&qvAMfd@l5@A5NarxnYJn%T^SFq z4wHT$k`xkVW?;8MY;LvLb#d9C|+esG9E}6)ZUTPHZvg?o4V!0Uw&vkAu~!& zhp7D-A6+?#$-#ue_;A|92hI1n{+K>2;U{3qk{G!CeW|*YTXeE%a%N^FjIVcHU%;|f zk;~AnAJNn)DQ=A#w)c#;XEM6l8-@ZpQhZ^lgNa*u5mXN!se5W!R?=ygaZ9amvanNf zU5JNL3w2o(cHr;}+JxbO#?u1%>(-EObyZZAjhPvCZBh6dFNs;oxmd%0)0etvR( z1dU_RB6N`sf^!n!_yH6Ny+3q}Z!_o9^~WlvgPM@Oi2F!TcV7`1x{(KeAol`rae6nk z&Pcic@YTkNb4+-2@p|n%ztzO{cK4W##<>Pdh4kJf_EI#pC0Pc@0*CB-o-CMxlApk8 zR`_?rH{dP>0R$EiWdE*_RL>dC5;(T#n4FE6J8~<3cn>PPp;#6atGIxCtVgQ17*UC zdlCWYdsHMhmYLi+X;gm0^Rg};$Gx<%RJF=#IWJY4N}`MW)~*q6twM_FG<3{hK0oZB zMZ?+sj|)!S0gvO9k}r98k@SPWRQ8>)zh?^Gcxwv7+=C#pK+RR`AuU8ps8i4Vs3GVfmn32p_j&CdA?~3YCiqhH;oyB z>P6I&0K;(m<-n&?5k_7**ANZDd(HPej}TY-X3~}8@^l!l{(#{$ObMk)hWJ`UXImAo zTXOIS$zizeAK2Tk-EvgOnYyV^i|`YyGb2t82I(gmLXG*ewWc>9qr}C}-7tUS$5m4r z*c^NCfg_QVFs?MAy7E)209e?|K??HQA&4jVwc{^w8?Jtl zayX5UafQQku>`tkJnYDO@9?{bm01?>R`EKIG2wP!_O+|&L+fI+pDvydFP54n`3djg zk5T@5UOJ@Pk@myHlHEuBCUAspF~UC=^2rc3W9^kB4XGxo96$_bin%?>kM`7qFLR_k zR9W#MtGUzCPGKi>61F@}ljt=Npp{Pr^nS_5h^JQ$%vF%nzCF2DCnK-as@+#1!J8JR z)Dt~XQLKvJj9M<w)A^qpbMq}3b)k;+E$xFHs`)* z3G{CL&`2tjp5!(9h*;+xKXkrvOfUYKL0fJTKU@UJw$yE77*W+6p~47sGRV{69SWVb z<+{U97kKB698$s_u64^r*&6$|R>?Z|F82fxrOhyVomq$!YPoP~DQG=mTteNyHU{{k z$z?b~lVm2Tv|F{h!NSVe#Ab7jy4c5Gn}8{eI?lUuLaxBC>m{fWVMJUngZwLvO76F| zaq8CkOz|(jTLMJYFOQ%5ueA8PzY*?d+yDqX-t(wrvy9q1X**?m@YA^4lX4Ns0#48O zP8X~#C3!lM@RX4IV(1w?=8$?{3rC}(zjII0xeQJg&moh{NkCAyEp;s1PaHB>sfuO7 zCh&o}e zeLW7WVZJLOn643`-7=U<{)=NQ{y!Y^YaHqu$6)huQ9z7AV#8pS%o(bTu|%jJok=iK z42XaedH%&QL%+&8;mXhNpu1QmSF{_d z7jKDY#J?IS)au>7bf5@oWYB7g|t(nFEy0-!@t^VzMM!B@zdCeCFf zEoyw%t*sipqlOi61{z-KQ0{~^^h*!33$<+mso5G$ivl@OOXS>W4y7lpoB^CQi&vOb z-NmG=%q8GY$E*S7!-UW(tQf>#_n!oA5Q_+y|zh1J!_Q`CFH;)I;Nz!-5QNgLB zOOL|vsCH+qi3-X}QBWk9pj_ZpYCNu1cbCtw5P)HQPX=>=l)7B7%(}_Ay z16rJQS{&PHeTHY-5Csp6k&}QR)8>{iR?d>nid6^G=P;5&Mm~}>5-fM64#*4sj<%Z# zepc|SgrxS)8*ZlOj{mw*~i zur-oC#x*=cYQV63c;(wvtDKQ}#hY+fpkR@aC3DK7`m+Iq&DzN8>N=Ro8v-%R_?3d``z( zcC6#{Ez^Sv<;PK!s+Ye&rr}B0*e;uzUs8^QD_qATpdqE47H=m>9}N5VUmyeB<^uN@ z$h1}l-Wa|L)ksbcYbZdV!4~s=$cMtEr#70wUx#Rr_{y@4?8IK}OpM>YHAXC5m;?`> z{T6wN^in9BD0OScA%s!v`-MvvR#$^4E{WscF+*UFA)Uk<<@ z`#90=;%0)swPA`IJmd@>M#q1Y3<-6bOJ)xPbV7%%f5yWJ(wuO3R z$gx+hkx&XX{B9-Ov`K=&PdSp3#RvQ%yJ5__DJW@9I#%f#jI1)D}35<@7FiF;2d!g5sT0|zC3 zleA2)nh)#9hLq0XJqUncI&5dZTahS8TWIrDOYn*L+ z^u67Uvt`FcjPr@ukL6bA48dAv+)@qS|9163P6><5MY!QYnUcOvR%GPmQi3&{Tw%?nfT&15_dB-(DjnM|)%_K(ZIOa?IX zA0{KP#CHg+T>|ZHc$xfpcMd6b)JA0gnukz`1B6o>h@=$;?VRO*V;czdVl}#nP`z|j z0XeEIc0>~^kjj1>i?y`F>HzlmHP2Z0r&6cq0{gUS+oh!UuaZIHmI?h@`bz(+WP*D8 zOm5ZM5dTp!`t;tQgWpO9=8ykBN=7aX@DGs4EnOPOpHQ$ps-9Q42ZX;$Mu6%*ZB4W9{i z^Jntiw~`V5Rx*gqKuP0Eu*%mZ&zMKJmbEG+@?P1DG3yt}f|iX*7)z#9!%N4Mzm>S8 z(?zbpj|42mD8H3V^tX~3rF1ICDV-{Oh8-5VBL0t(A)|s*@=Dz=Y>~fH^2${du&GBZ zaxFnDcoz7!FmM$AD4F1OjtQeB-YRZ^EAM}l3`8?jlF1TiGRhLBBuq1b2}-j;an8Er z5yiKX`L)EG&nEhG%dYMu9a4$(!!`wYHik_v^IXoVS<+U zIe|+GmSjo_mi#FVOEJr2p#sauQPsrAQGjjWsLU~PnC2MxEo5T8g$#3I;)Dk2l_Xap zTGIccl97CcBfTO2Gk&OZq$a(sv~6;)b+jVAt>!y<2z2Bo&8y6-e-Cy9C(WzKnf9R( zLI0{A!SLF7uP4o`_BC`Ubu=seRqibaEbvN&r2I89l>d<(q4XLkQF2d`xIOWQ{;cpL za~y;cP)S4tOG!lpY*9*OO5Za*GF=+1Y&GnRALX6#m+}YfVx`LEsB?5AUxp=WO-8>0{Z zaK5xzdD^6NOQeVNNjZC9xz=#zUjaiSeNxFDSuQs`FFmP(J=i2T>>!O+#-3v#J{%!E zNGWUh79N?H&Rem+C5@+ahg%X?$sTfsL@8_ZRumZ`U8$1Q?_3`_EPbKUm22^r#PAmH z2T5b8eBdrVQGWTKfufu+ZdL4amux6M(r?umLM-A?rZCv3-WimlwAFVFoBWD(t65w2qk>VcMK(Td&t3`DA7;8*6WrM;&u8MKxNSums<4AACm}^XK#aQTHFGGXH zrxY*q*UN0M`qmI)v3+TYwAg+~im=*Ym5n{y2%)U?*|4Il4cNG%tPR<~qO6VB$fB%` z* zswvXqy>UgEaE2E$i8R;OgHk}~{Z#PhrS;(xLPc9N+z=k5&gv}Fy6vano!hP{AZ)8r zUJgIcH6Tbypyb|*VH!+oA9fqEv!@j=v_A+vJSqaG2X>8rF*3E4MUg1v`2{&Un}Ykc zK)wf^HV_T-n?ht?DLH8G54JukND7JyEHW)~IxXmCMdpg`83U|_h}*)_=e?nMyOxo+*@E=Z z;samTEErM^gSx64oOi`SZ*34j0%q{bi9jc9rGt8PLU$mRK$ zyxk5s%=6W4Qa1+XRdwC^HmKZ&Ua;9^Z9nF_R^9R!ZB?V+kBcjYRsBD}tn0o0GQjd| zT#WhS^KdQfpnZ+7FfE)7`k6#oT*&4TjOmMo+v4MD;qk~d2oqHx`1RrA@P`VB? zA$VMqyDDZNUB^|yx$KpDr8AiBTkV*>$D81G?5%^d+0(ZrjVRlWE&UraXnTBFwf%Hi zcKv>wJ0W_UeExbIMz^sKNbW1IAYEc*Zz~w-x0%ttw;Ry_x4xmEy^~{sJ7$OdU>JqF zgVA@lVbPs?h0%hiV`(6!BiiA{NdnA;fQA^!bLk2&f07k|{HDsn_z+G%z}8A*b{|uP z-{F%kN$^Sk4IMK*%_uthZDiE`S0jV`{|_DG;%s3}2lV5wv-$q;2jJi0`z9|11dRLx z931=yR-m2qzwiB9;(tHq|g+4RW)FuFgQ617N1{sURBC%|N;W;MRFht7=AeRA$ z)sx&-kxfF$Ykc!tr2}HCMCY6MvQ3Kl(#<6oW^i?pMRQ8en%9og^O~98`=!@)tKUP6 zTSQqz4`CT)CZ5%p3Dk%>uLgUzEjebnvyfKTPiVF?V&L(_@3nrYGdI)n9FsR=I=yoP z)V(GVt|}aeM~4@vm#2{q&(>$4a4JrZ#81>S+ncj+av0yH*zkqjy24T}*41S+i!DC% ztMk~$N&s4cN!TV_lRJUx@+pNXWDfT-mUX_>o#s}onT@1&k)M@Zj=^G7TSR3A zt#l1!3oB@6=!Yhq9lrY3ufLzml`YI>d@|PAb(k>dv%C5Vp*hmW*47sF7zAM^^Q3MsyIgu=m1In}^|~(Z zI^T=uFz+3hBl=ERK%V|>gDH-lXIz?)E5Vw%K_fsKuq927c(47Z++%bsY69p; z95IwAB@&zB8niZr%~yQNL=%db7{dr;WzzuVP=jqfF&O(;jY!U`IhBnX0UMNNwI~gz z-t4h5vU))R4-My7jtausqJ*#)AD^5F7OV;6ur_TbTLKXR3T3D$DUyV1snUfGh>gcW zxexDdT#cau+MPVum4Lb`z4e813vHDiHDMf_s9)|6p~SWZOm}1;p}c|@jeAS zkZMYHS2xNMNKr?@QZW_HDE&>nZFxFG1ALtE7vR-*beN7aV3>ezII_y>G|4#P2Tm9- z@_fo{?O+@8J8jzZ{v6gNnuMLWG)djMCG;37F^a6@4iQTIy*?#Neax`D_GJ-ru+;cw zPzX(pR&$i&)258XT)Cw!tX~imb50XKL%IGK#uq})%xS=(STtnSbS}blutebs8z;wd zHin&rbN+}U`ZeyoErwQ|#7kfOLTTY;^$I^6W6opj|?` zf967)5sEo`a-bApZ7V5nZjh$hx;@_<9zpeD;W-kdlG{vKhcG>;RnfO?4dAsLnn^9- z|D&5e%W~GtsloudlvC16vsqnJInFVL1jZJDw?mk&BIq6?$qDD?3-L3a(R*1eZr&p~ zY?dI(rr#2Uo#dR)kMa%iqWT0znOS7Bs^X1j$dMlr2UT5iVeLcU+xjiB= zu-M@+B%<;8`n#oZrLzcWRyR&P`be`GS=sE3HVY@C#gyA+n~e)B?MJfJ$z6SqcEA*^ zg;-IeA*PW%cTF4%nhzw(q;1h|oEpS-B(x@maiPpj$@usG6Cj89Z1WZW*zETFDp zFA47C(-V`K`QTYbpQ_b;WyCH}lbo?;7yl_aIc0nF$S6z=j;Vp<>L$W|#Mvvt1CQ|~ z-+YW45b8zN?V#}k15$}MMGq@kyDv+BhADAx}00%KfD)2+tu&F?3Tw3o!sIn`z zIkI%7m%9GR^GF+MF`BK|K)Il^-mvaJf(6?UluZIgW3Qj-ChwCPq_Q0Jnk8Vlm$l{4 zoUC(2*}e{><{by40(JvCTygIBOu%Dkg12z(sG`M7bm`Q2w5SSnfymvdLZpK>0NZ;& zvVc<|t5EXRmI7<#OH+1aD!!8JGIsL;=<%5mU82!_WVw80kjirj%PBU1>$Q5}_R6DX zt~GX3fx7_Mu~QAZ+q9BT3i_do(JhTKQ3WR&jI#^I5!u(j{2wVL5k$ zNipln)gyre1h94Orl!1I)V-4FV=^eS?uO%)o^SQY*_>SAfa&$d`Sn`~nOS8{Z63Kp z!35wj3-?f{(DaS{iBOBv(KjA;U(Mv4`#VjW60pk(+_+G-u{?Bw+EH27j@Hq~Hsz6; zL?jQF_fDRW_7>&IXdhz)u!Uh3<&XqqxKdk^>8(qA@fM*NfCwGEb=4;=Y5Yu67<>WE3+|PQl9X;-kwQ^vVmw{dS3oAseJ83A-Xl_17&! z5v6wk0E(|Z!UlH30hN{{;Jm3?o|YIV&pECFB?^$1lOYq6s+d)~G>qMXgLD7L5wn|s zs&qprtod2bIN3n#6N@ic$6j&Tfo7Rzqv_QjJ=6Mr4!gN)$Htx!2H<&+d5^0<=V36K zJ;9d!3q|^XJzG=3A`vFErjDK9fKt!}8&Zb>aZ8j|!#=@oCO@x*}=LfRe27 zvXxfA8I)}In2u0+2V*uy7Eo#L)z)q#)ph&B?yQvQzOpigSRkWT6qfDwM!b-U-&uKR zw)>B6=uUa=aDDVXP(FiRSi9-IGJGk&LV4l+s3?cr6gqd1Fz$TrNbcOU7kC@O%+B&8 z$eb_xt8MLzS8n3u{dirL0@vGewpD_z3o(;p^`>!YSqQyWm2h11!+^tT<`T_GWA67u zqzu>`kKEWod3@ute9~K9cv@1==KYUXN?rEcMn5{9Aw@oC{7vEVG`eNbLI-5opE^~h zS#^tVGanDR5pwyjKWjWtzYiyTAsdDR+jy@K)lP7Kb0K7~?bd;HxgI^V`~RMyddO-{ z-I-Tbrt-*nxGH9A)8ViedB^lg&`YN}rSguM?>nu01hnR4Ym;+ef?6BT)yvL&y>3trbE*6Q7}6@nq6dgIj#e{aarX{GEL*zI-EL$LO3#9~^(vtoZA+jDTV{(6H_%UDX4~xDJ6j zV?@BT9p7EKTQn_s60g2we&z%rvUQ@@PJk)Iq0+GfQFs`t`m*@u`)(%UyTj2Ji)Nb zjy6}Qy*tKNKGP#zIYDk@+7x?H}wxTaiEtvYCx<* zj9pO=)HVrOK(jbO-twU0Mbz4x|8e~Jm} zM8?T~UraGlkR}@bzZZ@F*6=@d{m-)rTGC--Md`l!)!oa`ZOm1DzKt}3RV9#b$i8FWnqlpUu2NS;l=(+8OSMdT@F{87D$r{;K z-)9><>{!_&Ae=Z}ofa*?^H_18ZacKQyrh1vHtc08N?)2b05`E3AeDbo zz>nKB=pS)T)^UtE`XA^A_y_Pt+NuCyCM@&>L461sK++Q|eG2WU?4(u!2lu%8lG{++ z6gNOQ3BQ3B?*Vp$z2Vd1;Q$&NVAB#W{7X&1(@rR9$Da6wY=5904fZjWT>yBb%#IT0 z#!>L%oxFH+k09ijd1u`L-qLV>f!cb>MV<^n9odH80Ni08rv9oF@rK0tj+&njpNikD z{iWTG<`XjpFSnr7ro#K3Xk(NK{SUP$FCDK`?w)R2l68rDKxe*?i;zI=U252a-#>f0 zOzw={P?#S-4$%I$JssJ9+tYbCn+Vz2x|%pTn>hZvwM$mfal$k~_D!h`p&`bq2oIE$ zj`C+2B3(Dn)PyLYS2vT6PJavysS@urQBpT#OjPZ*AHjGUxRdO57*VkMIFDh}eF6GV z7;)P6aeD}0q6F$X@z`<7IpOFu+neq6{R7m8cn)cLCD7Vs1ebl?hrL}tK~!p%O!Xey zZu#47I=~24nH=&lbEHP0CEB<3!}Gml%|RI$g;f1s?NJt%9& z_bJhGw@{abU6kIA?k(#PMj>k&X3^SLptQdblhw}Le{GY7jhAdORKXa{F{KT_)5x-U z`8>Rxx^7^PWe;T-Ioo!dUW!*$uN4Z6Ry|Q8H40+__97zB!wU!`&kRMO z`=_39UE2x{VrW`D8mRR#$4}vpv|Gzq%sn~QD0&eORoxn zh$6rpp_k)IGDUidn-#s6D*$wBABgQ(P9%>arw4^QH=kh-gd zvxS5a+a=z&6AE?#u_ZvAw1o+ z5E*roUeI6$Mg?-w7QI;BO(>hGfUyJ_GPZa zhNuyp45F=!l)tDR&cE|Vhd=RVcT-jj`T_ktF9IPUUjPIC@k8?a$h zR>aBK!p6YaM9IR_R3J6~w0gUYnKww}fAszkvxTCRQ9UU@v zOd!}TIk0WIAq&;?`-3;Ys-dWQi1`x>aee&a^o2s!3K!F5Vp|k~?N$&KU6Y#1r!*dJginJ zW(F`Y&SHl35RvUj6Bz*=-RpH1+z)`;Erf53z`_dt+04c1bey%8{j~TnNaT;`ik`x= zqgvZ-tN-5Rbx_vL&u;k(t#xx{)5#7y+TeVlqgi>>(WZI1=P+9z8zOYP%u)@N-nas$ z+GUQNX@U$48iXeyJ%CR8oorCsXKv!7l4|r9ABu^7f?%WpXHuqEvnUfYM&(8WbqKT& z@1aGy<}`joQ>&C7qz9*wIBw3lXPJ&?Z|c1s%k)n!3cMA=SZS#_{m6v5=J9P#efznK#IVh@j`Dyb;uGD9x96?oH-Ii>gc6Hdd&v#ln@l6%U z)SkG#IY{4VNmNsKML)3VuO)_mm0B4v7-$p2A3MP@wL`LtM-{D%heJ0SXHwFkY_WU!GhTwya^a1?%!3^}j^$6Pk(j!FN?Y~2HJADV}mUpzX|DI1ROq~Ah8!^f{ zN|Yb`g*|XWBkpH9>?nUhaz?bxuH5~Mjv%|&L5@(#s;K1;&NB&Yhu z#$hYv#W7UV{ij0Zb1R!#`2`5C7%{!@XX+`&KLTow-Uw(43IM62s ziD!6!km(W}wGLB7w3~enx6b2l+AYqh7hNPS;f6YlcOI@5gOejRBQqnq-DuO~w3uCb z1mwwrh}~9%A)7H_dxVNU$24`{Mc?2ehj5Mr3u{*K1&C+FhD>y(JJxk*Um`z+*&;-a zp<(GqH$(fpkKi2Z%h%w;G<(o2fHSYGIFPJ}BC1ou95K}$&b7o9zxqE+pYXhIc%;se zYlm6ZswN-8DxuS`vI)+SX}TmOi-%q?3fg4bOhaB7u3RP!HzCILej&7Mv<#>pShA5! z_DK*<@K9tLH6mq^m%CuW;TPheCWSE4-eC-swkx&bn><6M8YGk~^lN>}ijb0Yy99}6 zMaVHA#b#+1`nFHw7kna2gkbaPKv0#=#<36BWLXFqrPL;bmfg!!PSaDd^V~FZi|yhc zp7u~uFPqoX&^|y9ht2#NrQ@_h3Dh#%gev9`X!X+ZPLI;t{U}xYpdwuoYg?q7(7y=6 zWEwF)?c2XXMq?D%5WiBvKmCYk`ACwHF`koyDp{uriGk=C_a{` z?Ij6d_wTIP_BosFovJW6KnnWH%N-XfQU#uxagQq_bCn z=fMerAl(3M%uWNuIzXsT@!xzHx5oEJXA|*{jV4Yun2zwB z&hADu+WahW604}O1!69zSdpD5NZy;T4ILFsXGDA!bC&e*Y34$eSMuI*cuPlon(TqK zOGl}|pf1{!xy8?#g#?odT}Ss@Qw@LMnr-$XF|#JyCR*vWpdRJR1PsGsLQVs62vt68 z*q*nh`EAQYcFPXJ?md01lt!i#i7v{uyc&*e*?J!?I{HlXeAFuq$PYsLWDwJLq3>XL zUtysuElOCb%$;V*uiCI)U`FNr`v7}snHUFoT7!BVP0)hqoKFc?0z!dC8Gy~L()a7WmBQd-017W?s0p3gUV0FI7|c%NP=J<5xtZ4s;xlhBkW!? z74wK*WFK@FHXF6Y(iujw2#sbLp1EtO4bpRPjlT}^=_C40ni9SKjIR6ISu$w&#+19A zR(1)+F;dwvTycjv_}t^AaiwV#5~-zc4rVEN^l#ce-ld@SE^bE58y8cPgwLfQ5*Mb+ z%Hz5$#85Vtrr9ysW=PW^>`{&|gfVK+SP{f<5q~Egq1Apb(^IJgL;eyzzNS6a%db74 zL$9TONGOHbdf+U{?M$!{`CWm;X94F27CbWxxhe1)P5>VM@Xgp0aj#;zcC5LssA{FMYZxPLtC{b;;H)*Cr*; zSE)39j8ti4uA}26I@}yD2{3=n$*RkVIRB(dd0D<*pRroGg`&k{T~J=&m4l4U;?*F1 zosbVT>NXVxN^6J>W@j?ZWTH+L0YntLG73aK#FCG86cL1EV?!kvMOlX&0fmKG_S}0B zg&I}YP}a7=lqZE^0cICc`)t%vo29Vexgt`tAeTxVa(Q{gY{hF!TVhLF;Rk~7Nj~z^ z$@oV~dKoL_i`>*|WwFw@y`ef&GcW)I8H*Iu&EoxDzjePjYv^Ei5r5hrrbkrS(&y8& zd3!;s!zW{Reda7QZ1Hu~h$;gM;{*oh89iQW7%NqErYHM}H7j~6#WJ}KrdlmU!Y*iY z51s2=dY9>fizI@exvL+DYtp1v!A}S@iBcDPm-?%Y`$+NO)hnva`3gGCNVIY1S>3Kp(dPU5eXKFHnXegWmE99Rr^!vLu? zn+bmsLChhtD84FoGL4GjqDV7CX3VzWDa88DYDvY#Qf-RiJ$|~rJ+mNNLgC$%Uc%bZ zu3sO55n5xS{OH(lsN{C;Smjt{Ezo;9vq4@HvzBJ}Pzbky5zfQh62A7p!r*0lV!v%x zLXGLwMyl#6fV9pUj=jOd87AU!^++L!0Fe+(`;3vraNk~JnAY-WVQG!x+6TRnMpPQK zwaNrX0ggJQqtW+&EBvTS&Nsk-giI?!(kIgJzP5HqO7|AN@PXp@89ct13loAwonE%3D_W3n*ygzyH4tcj)ub)O8lUkN zoIH~NiE#>WwvNo^Jv?x`)!~!8<%ykyspj?0o!_8EVMeB!@Yn*g2j+uUz$vbLtApcf z2taQL1$u#a8(u)?qji@Y!a0)@Il&&89SX6wH)+DQc>q!pp=yAUyIYTi5_6D#@tTg~ ztj|@;lCw$Ks>T863eby8c7W`7+jqc=b(#d$l04hh^F1DOw%@l$%N0&+()IP#E`g*G zOrw*uB7TaW4l4L#bYFR>_MI8{58H=lox?Sgxsw$ERjBZyh|27mV#hnqHrmm;#I zSwKRS^+ZfY=1P6X{6Bu5vR$W4`Ytx{rd{FfzAg-%1)pk{Kfe45pMD!dnF{t2kjz02 zK?|{QEok!Ap43OXI0}6n%mUoG%v@0Pu-wgrhLJG_Na-F3L41u_^`Y)7Cf$7@{OM9u zoB>dXg=`D1zh_|iNaFQGjB1s|ZyNuFSHl0m+8;gX?_)o!0IyOL%cP z5~Zefk2jX3)<|fKDWJAT%P(4iRyZ_Ff@BdTeREu!m2sQ3iRqcj>ZeMYnN`}*jce{+qP}nwr$(CZDYkwR-TPTI2*l7W{&&J#)s9&dO$+=&hkx1ZFS)Y5k&Ov`+i zkhiEkMb7qPTws3btT2_|5sL>1np{V`3jdMnwHaLs-q1U(Al2+y5_iu^etIR9zL4HX zLlkZjV;5y5pz5a*fx%2Sqamsu-2AZh1BrQI;%V#mN`-V+p;l_pCaM1T3}aHSDKA&z z9VO|`F)7WpfCBIoZFZA_;Y-kdNmh3*8m)Nl3lEIDQzHA*rb2TsCaYf+xT}M- z(jeh8xxBd3NHW^c)N6nZ+3R4K1Hd<+xk2y@S#OsoB+GrNbc6dBRgU?9BY+DfdVkA- zdv4FhKBW6vdTlvOJT-WZJ%0x{nXO%tG;PFQ<*$alv`S{>g0xD3%TvC7l-DnrrI(<)m~v%UdZ%H`f) zFf3&Xiro)>2B+5pO5TViY8|9^(+#EDh$;`N-tQ|C*jtur-BWDb0mpj_P`wpf6wecH z*E1(EBe2eel>nutyDSXeulGs!coyT8c%pU5NJ%q^oXznnpoW4Rho6q-y}T=={Sm2b-FbcQ2ta)1iB7cIWz#yP9;|*8%zQ zadAK0+!cJ&goUnuc0HEpMr^_rVo`jK#`aw&+cuB$$Vj_}od6#}Xq5y(eOM;dfxbH; zX{Z>8Dmy?))U{iLG&vle7&Ttb#ytx#aw>}5R9Ww`jlk+ z&!kNUk1&ypH%tUS{1%(%rEG=qshf2(T+w>J!sW*0?-BZ1ap6x9d&z24rp>`(uIcK2%eBl+HLmUBd3?`w< zvGQWR+29u<3Fcj>^1C!T*Sp{YwuCEvEqYdqjO>$U>jB;YvF`6@xI=Ee!NjPJYZ92l zSX`nsfJnIQY-{t}5^24DEx~+nlJZ)Mdv3Dh4p>_@EwJ_=#UxdaGcAxd|B{tSh$n|@ zge%SopKH>^D+BLm$FO&Zo6qQHz>!=0Nqc`1_wXgSg);<5Z{#Z`pch5f?Ompi2HKLZA5BXva@cXar0NsnSp z#D-wukK(gKian8&(rmH>{9N-&7A0aWA_t{|q?jc!MLlm6Y~n@SvP~px3pvDuvXue3 zdl;|K<3)n`D}3-q=u>Da;{y)Ww;y=6elP7j8a`a*JITz)I$;N zNiCwkDMzDF7)}%QD%LTDxGY13$M>SPlE1GQ)m6*xKeYc=*tVOEZoDPaO;5GJ|F1|+tXL(&$om+FSA^17`c$kh1y7Cv8{PK ziDC?5D7>zUG}N&w3XoLb+G_poJ%o%cbMXqMWOk$|lFsyI>?&W+Xnek=SxY?}O zNuisy`qUGqx!;6@gL8>y`rJIhciVC-2y&f7>QED5CASiH>MEMY9Ha2Z-tSF(lb?Xg zV&zNvF}$j*_Tk*)n~T#BZvaDSOP@Z&x77ChCOOLA7jnt;L2nvFP0Va zaW~)GfX0h*JKJz&OVNHL^Y&XLzdpOdtV<(Q{j~dQ|Jr$L#8ryI39e??dQhz#uP=;D z7*K?Hq_qj*HgZKp_K@O4q?H2c9*oulfJIPD-qj)jY7bR z5E9Uf{R`h(JpF<&<4bQ9)OrCCM&aXylE2?KE}o364-}!tx7|}$fC#HWj9z=VBkxJy z!Ic{VD)U-B%=PcQmab?FE#lSmG>hoZ18*#(fEv__d0&kmQ|^UY{3b_T=z zWHepn8D35dIDBshw_b8kjW zz!B*h!o5VwXm4-&A~*W&tlC<)2y5qpExSE9mN}BuZSr_%K?6J+C*i~qRSmQQN75I= z0c-;kIpE*2sJC}C5(3GCM;;&Mke3Fk+alB5qR|MIB?xs+#IatL#kI)3)EMD6j$Xig z1{o^sQEVK?4E0i}o70a;+NTD|x=@$M`?*Kbcw#*0dwKdsT$H%+h$rr~HPd=$ z=AU$wg`39VkS~ER?;m)PY7m};2=5jMec3`qa&i~TAQ=!Sx9=Vw5kiFLeL=wU7n>Z+ zuci_BC>&^+lzX$eIS=>IM3AzNWN9lav&LNPsMa@a(iTGxB&?*wLXq7s-HRkB(FqYu z=7d~c?Yxrf4%*4>MG&kcXz+yEcMoW})Nr~%+$!AA4RE}J_3bPvCS^7_>wV))8n=G` z`Zku~@y<%Ig2&>16h+%DgK1Hpl5*J{_gugG znr?r*eeR?76Ffm^k)Cw{Bdz-u?@3+$vdQ0ME93cAm-_x_`6KBM(Zb|GqC+#-``+tT z>P;0-@|P?aJR(%y9XB|@M_}x#tc z8l91oepjJN%6toj6R$f>&xb`^66ij7BpEkA6T>7N5mo+p;g!@luHq{AkimLXvWiyO zT*>nDySv{Jk}87Y_M1lbJlpxBe6OGt$7TDLmablRAZdsJNk;R_>M$TTT?toVld1Qw z4hCpr*aaFSTA57c>SP?1^{(dj%6Q+CyLJ_Tz(v7j4Rj%&^oPUpE(!c3wr5>{|a?@UltR*m(3ZZkIyuCQt+YW3WKR9t_aOi-=iH4y6*1FPx{{Y%b4 z*0O$FK7jRf(DehzxItI+*2xJ}t7r73UT`9Asj!^yfAjg-J|b=NKMZHpe`PrTiSw3r zbP+NzGB+V+_z&l;FewQv0AD?0m6V>29%DBg6n?uy8J-r7PY_s7S?Hc;9cpa68SxJP zEp)^6KPgLRqts(eY)nf4%BC6;F^)7f` z4pz`s?v-+ltauqKjU>82Ss2Vjko2r7zJ4#db>0|~O@X+&hO3W<1kmq;w+H1x_ zuhXHvxp^Xgru=(clErB)GtVW|wIYb5Gq;BUV!;cL1gw#vSc;w00zJU&eyaL6U{6%g9OC2=Ea{)@+6#CiHl8$S??% zz3v`8T`{6>t_CQwQ^>!m9HKP4YWtrPjQSbl`R63~|MvtL|MvuCfqqU9%m7s2Hb9OT zm)jqF8J)*K8s_(q@gh3xvq^e?x{IhA+J0O53qr0m_Y0tJa)a4#G3MR5MW#h1mQAK> zygEC8CwUTOnH48H8RTa{j7`uheAR&Skf2h!H%F&sKm^IPDA3VQ*qXljb0pf)|z5R@2}K_Ld-tfxmRnf=~PwD0qnTEuLNe6v%h!{0a03&nm(z zHzRQK_{PO7#K~4$+X0x5toM*sEoo@F=K^Ev2G92(jKLk>l)XI`o%2i4H$kmPY&wFw!d4ipzhbXM^8mFEw-MAnC(KwLLCu^FlEl=i zBwmoAJm9%5$qYGEvY70=69{hFr}E{UFx^uimQ)sT^kFlyAZrt3=?>=8D26EN%Z>vy z`1Cp#;3B>FI-UxX3-?_oa&HU@{=D5=a?eP}iM1NO&${@Kxcgu-7l!c5Cjjx#P#$1i zi+~$datoB;z9i&Ips&NCc`a17#ne$nIah`>T5%7?Rh{E?1Qe>~;C40#Ktsc-JvRvc zQd=H1RpYVlz%2aiiR_2w{Wr6+2c^yX{Zswb|HSv7q47`hjsK0Uh^vK>^ZzHbaxzjw z^vKz5cr}-`os?VLp5^#QdlDk?CZGlQimP5Q1*VXvnZ;3k(?NXwcqF8czz)B)x3Vx8 z?T#)#4^jFlo*+bwtXi$J>uQ|kGFx;lRM%W5hKsnfYm#r&2C7Di@ds{)v(Hs?Q=ohI zq@9$S*26-Ozdjsu2&KOqDZqlK?cS5fk$!ze#S@Z5`yS%MmmTU_zOBxU%CaC`2d5DH?C_-;|9#Pz+*`2S{X{eHzebbhAFA#Dji$7P zjfJy`v5bNJe+q9EiJ!t7`3n=oh^E@q0da2ye?3thb_E35-Wp?g04NaxDU4l;sAbqc zUf)zWWW#%sKuj;OvRLu3(ED~+MFT%fdFEBDV&dsh9Dh=^AAGvo+|t^3Ge&k z4a?ub8cLf|eRa1c@Y0yZ#O^pWDmDX4R&zLAx~@WheuEh&B_mA>4CME?O9#;;I#XW( zV_Qkj$jRS%oE9t{&D4&<$QfbK&Tnw@exf<&F}`92AfC}j{eJix6-)$no!uihd)909 zE->$d8YpxK21B%g(;X6 z9h;Mf0ze%gTpd;YpA8R|x1p3$CTzP#OhGCusGIE+P7EC+3#Ef9Q6MFgD8{6;3$nip ziD-AyPMaGqMW~9J%|!C26|+KcSh6O`*D0V~Nt3GyoS3ECM_K!nfgTI&3H^CNe6+tn zQ7Lc1#6-#OUy+6uD$?NZc992C{!Z2U z+EO@+0HY75UwL+0nxZq>r*tI$O{~?`QR#?i%mcAAnva9jMl$!~u+^9BS5JBhd>e2G z(S+0oTmDQR;rdH=-O2T`!k{v8sFSxshANpukQl^&Su3(aqO=7YF5> zm*62sPS!x8Y0o5+GNwpc@*(dK56y@e_gE!!norBfUCDV_)6or-yBl-y-_~>^j>DO5 z{+#hqO5l`HH}j3(ceU0`}WG5F0HTtRNV~Ag7%Ke z>c%pP!?6dj^R&Jm3Z|?y**}Fo4M!3_1tLDSJ{5w0B&*shFn}Vwbu}8Yn{71-W&Xqo`Xq!-`tct{Lb6iL_;6@4b;+c!KAbG{(D zL*FE^Du3wwIN@Uc%SW;|0Z9Jw(GO?~;T?3DlmwB3@`CdPdWp;3Z}Z9078gSF4uE%q z`Rwe`9oH*X7Mc>#$!&=@`7ACFlK1iM@~Omn<{*M$wvM=b%fP$4hwJ#7x5uPb-a}OI zbi+{;7_~*hIt|K4KB+O$eLc~rhFTfi=NGI;q8sHFa~F`d#u2U1Too<519e^Am41Mb zN$7~V-W`COcu%#_-xj_LzA<1lWf+rzV}9}ptqZ)6(C4t=zkN>@S9BWto0E%N<8j4) zJ7(;5Q?@FW{PXzuIF*IX^M8_4l=G|-v>%m<`hQia{8NAL|K2$NbIs(aohxCfAb)Sh zPYbFK2vv+|LZw0qDbLL2;?sS9=cy8EPpAQ z^6F5pN|}ylHt4m5inV1yH-BiA5|Ph2lf4w(sqZA@0JzGnNV$%4@>$TH&w&nPT?5_X z&?v=Ewi%ld`@-zJ$?AI`p{8S zvD$D-5ui#UJsVSE>Z7reC`}>sBvf508#fEtT=k-8az;8Y@vtFWL zYiP6&jd&r{u2=fl9^hjeCES1IXH818T$N4JfBAKE>n--BWR0as^>kEfVi4Lfhx&_%fWU{8fgYjX6O zONJP5DpW=>-mEsKYB;kH+}ewqtO)@W*|tMX=?E)oLi9MZ2sa{DF^6ifgX{7(%wed| zu}bbSSfiSh)#_j~?GC!dV>w7*x`~CN*-Uf0^Ai>|Nifg8jS$5YLH9A~LEd__Nu>pp z9*gdE%Y&D528Zma5Fb`_#c*%5RSB5(G^ib8LQ~|IM+|Fpr`-mE!;-qD^9_Y_I;^;N( zf`z6R)?3smI1_uHaleWp9#FHjTt3F(eV&!dJbc)QsH(+v~&ihSHkwQM~Ii@hawTt>eLLc$17 zy$-H=8GPv+Fo{b;N#@eHMF`5etWvyAuIz8*n`T!z3DSu?eO_4}+MK@!X=DGwkNGH} zr~T6YBav%AGKE``S45RCyg>_@#^ox&*U$zXuV-640-jIs*Kr#%$6isQ8J)YxuL>Bw zTSMQebm(Y}GQ%x=#|*joC=b=)?2C>NRY_UJyT&L&hHolVFW*5bpe0T>#ME^!S^^0? z)%hS41F1<`80ERt2S8FD|Jo&hmfCV=;)FDEmz69L&6JA1LeECrJyuQ^UmsqDhSxe_ z5lIbgdkbWTx1T+*o#t^2an6Hm+k3pWira-H=ejGc$iDYHn20=BV>(LXE*Vo&fA|Ll zbEZ7Sqb%Ftoo99&DPS$7mzuw zLdM??jCmZjr6gjj`1pM!769s^yR$fvu1bkz0}(Gu1r!~!AEJMxShpPKAD~3O<7<8; z`Nt$h_wBwSOi9X)=~l}EhYXZXBkY?P zG{4&MmzK(r)3s=|h9e9(k2JDm_8k-wc?S!@+?I`=TGD-0KD!;6+1YwGf`_54rt=hz z_E_ib1X(e!R!+mH-jKoEqT+e*HM_msSJ-YJV7U!pD!1#6eu4-&W$Dhk4&TvsTYLwc=X2L8ewufX@c*rFA^L|@ zTSk~g*uu=j$@xDCw$iqe(ocfTy0L);GzJvIf@1XnN`OuT6|Ua`q-X@36Cg}B7}V3D zA$XIRb+kq9jGgCwqE$BQLrK@WgyyVS=5rzaT|RGz<0+ z38;@92QuRkBUyU&Do|4JalIkURNk2}{2K9UDe@WsN`TLHaqK$MVwEz*RswrCw@zSx zX1~CKgGPU?Y_+&k%P;15;J_xWu7Dm6f&SZb5sf{M>$V(&u{?7>C54~4gR{zysHzD_ zsAk{ikQr-HpR4JhhB@c)-FA52(dYhmYSEd%VwDE_aFGOB05bdgtyt8=^JOF_d8J-{ zRbim@G~7kzAn<5nM-ib~plFL~2F7?!Kf^+d9DI}^Kv{-clWr^Ud~ilv?I+A0=L3e& z&x}H3yfMQj`Va@sYc@-2EAZiQPne|?{yZgnRiDg`ATohAa{bAa>AH8?qna9sU{w=p zD8-RNr^d1h%DN6@`TzrqC=WtbPPtT-c)YZ=m}8Lwv}C>4(RZI<$I%jZgv*tH=gQ>Q-ro)Ra_-zo)aensYw zw&~mnFE1_;SeU!a3^0%5#8Qufz0c2QE*t4Y*?3x6_3o)IJa(H+b3Q9$>`xQ#Yo7x> z9dnPm;;qM2)^gPeZ=l6JuZbuxM1qH z?d9E>jJr9!>MS`(J0pkXKxFIMJzBy{ma#G{|8^!ojSV*{lf;0tHZ>|Elp0~ck>D59 zYjN&Y9QmoXzrL)y0C^ds&$Q;w3p=q((ry;J&$pf=P2QzAF7 z&34-x*_TvnSJ;U z999LMIRPUVUK>z!?X~qefFW4-MBMfJcLNHS)8roOC&@1Uxo`ftN%Bubft;bGiIKCY zfzgi&)#HEen~vsK*G znn~LYo{BrR?ghR%t)7ZlCfDvKGLJuR7omx;XEjZ;j;B6c8v0A?M@5&mU)6LCz*pd(d31vr2O&6KDJ|L3CAS0dOQ3zuAO?&RK zx+vl(k#J%00aFA0{{98eIr93ozLk@e{TidtEvFWve()D}D z=(i0(EoV*UnqQ~d41=^x^{a~SpFwBx#KVV*{WtD|WbXY@+BeF8#)n4SDurGE7Br-H z3;W&s-o&S%vWxCBXCZ=Am2Cq`28wW%B=+qH#kC8oq}s7NI_DR2Y%CB#12&4b2BeZf zO1CUE_At4+)Z&K-*XNb^TCI#2DAb^Rv>zX7QFV zd%vYhW$lwWt@QG)C24lny~^#KtQ1@cG1>n}ByB{1xtgxrEt_2Gs{)IXB5c;>wycmN74TX;HncOmA1aY^-^ch%}9buseDbJViF({26FmY$E$;M2x=NqGXeIR-GUp+D=VR{|8Xhco?1QHI7Oi6+*@x`2 zOlTil4>{r~jrbH!wnqRW-!Sm*Ns7+5e-X#7kCc@U39OVGhFqAtM43k#_(rKDo7-yX5WGh#7Ru)JcV;ZIPNJeWe#$)BKfp;eU1(5ze7hNbM0 zn3huRjD|gX3+=^IT67a$wkQDGXQ7jbC>+WTFY|~19T%I`xneP8m;)z9-mmzkkF49H zl*m5j40F4oy=(8UzaDLo`Tie9U`^%G=ZDXM2LEq}CjW=*L0(MI!q&ji-7WZCXjb`RV9S8eGLs|S*!?C53|KvN~)^r-mvX>gA9K_zfMjQ!v^|sRy26G z#t~CExGdAh^Qrq!sezzZw@lM`DE-?fg7#9?>jlwq5M7Rpz1#_AYlz>hb$b=$ANNEA z#Op8nV@f#v%S_7S<$3$8Il*Xo1!~p!`V*)~6JCgg-$el9#6RA&Nm~P(p#Ms*{yefs zPX7FT;Q!jm{3pspUQELFXEff`!1_P;of@=v@?y$&-c-_VmN5hjJR&_vJiUM*jVMGs z5TrgnJPRN!ufBMwu|6Y`87V}krq<@8N=@7niUUhaTyu(wH$A_`n&J6c>SgD8O;^k8 zrLC6Ma*J(Smk-60-_^6poj(5SC*yX<@z(XmH_vnSH^+9{jQ8mzKOz1CKWC5-DB(u<12<{rY_ zXfrI3+A~ls8fgJ`0Jc)74+rpgyoG77)u&G%27&fYlNV&0RcG$i9_{VyfIEOld4c5B zT=oRz*6i)94Q^}dQ|)yW8mniQk+;TM<@qqlmSXhw^Cj~_K2w8O8(&(vJ~fuW`6dSl zQf0Pty(GfSAWI*UfSthIl&p6zw~_g$Td@muq1l?deL?~AY85<7&;V)H%o)?#NHedQ z-9Q^uUjHay^=P>HstEN)t+e^7X;fN)99iv&h?!h-PnPQ;oz3q2KLd<^&tVeY=No#3 zo0Gt^G&fh;cP?Q)T&Hpf3Y;mY;!ELE}uo7 zgCvEvT1Y-JEza~PC52qB6mT&-Ze)7;I?roKbMv{A(30ljac5~M&BnFQ40E)F0X0p> z>HfY5yyfL=R0_<9sW{kD=Nxn}u~a*h&s4dJ96@TJ<+DXc399*3cXL&W+Su2-8RjdX zz)GX8x?{fF9Np5=oxfl^)C=%r$akA_j&8GRp6cwvlxDrvXmOb`9kY(5#n#qRx3$sR z;{yG?Y}4oXc=TwMVHcw0HwM<$1==RtueUQ8cm$L`>ftj4eaUnBH%78((&p(+9Kh#= zoQ`BI=WhR(qIk4$xrNnk-Ni%qf~u~mQ#o6Um73^2A^&D60q>*nWiq_3bN@|D5|Ic7 zEsY(A*&9Pb$Sq@+3HFFWrKPPEj-mOgX_8Ku%v+`|_YB!>c<6zimFI9{mNY`Weg6`# zX_6xnRba@d&F1!s>eL@|858QPbM3$sxzZ(g#iGn4MYS!KpL-K1rxfU%Sf3{4bM%rAexi~3FSNM(#M$~+D zG9a*#er*X-kXAimp$euK&$oqgJGzQI?&7`N(H?6KK3EhOzl(Ka_P5>2!8A)YijBlw z&uyKFT)&se5>NeN~*W8P|p@QCS zEBS7`>7@B=3%OpMucP_MqWOf|brwaU<_wvGsNQln<4n1>WS1u1d)+-qFf&(_RIgW| zPY|<}ZImawr0mR(w}9>&#Y4Ww%PA$@n!MW6`H*$FK8^4#eA#OAscw20AXhTwlM;@6 ziLBqI!sR(eio1OQ)7gg(SNq7+!TPIrEy<69Btw-}ayq9z7|5}>&m!xoE*E+gWl=4{ z)kKl_UA)V_5VAQXOJU;uz~J6IrO6o5qD(5~uI$r5RU}vX$IrB)roK4(QNDB%#ulNg zfG=|_nj%MNICu)>jPbg;OjA*M+I`6YiBmsSJ71LY6rOdg$cuFppzN(vqRH2lk|(Bu zHg|lXV)}L^l(^6LDxKETiE@2udpS+g%t&XjM75HpL;k2KD+Qva?nIhBrq=Jaa5(Dt zW|j`k0<}>pv-FgiF=qYg`AYgUp(+$VJLhZ$Gjzc46##a8_`{$5TQiT^;KuYWt7Z7) zuDpZS&4mb9`0QZbUz<=Wg2IVb+Np9hs5te^q$5zXV0w~vAvW$FkzwVE&PIZv^=BmH zwy>>|??cccVqu{)nIn^bYq=TM*yL)XiDHe7c~w;QEV{->Drj|zjP1MUW^k0u3Us_g z9CDpIXr^h!Bb8mQktUBR+3&R)ALsTwI8VQdU31)H*U9jJyi`PT(lPxtyO+4?)oN8K zJp@|Z(25*waCqBtK)wHxXhfMqt*XL>S!Kw~zqFE&g<}ep z9#NVk&-OqD!#)iSnzc%xNKZDmPf37rgEAMC7Ra zcoN;?FMZD#vM`i_VPNvu_J=z4hE7av7hAQQQI%tt#n;HR*AiZNq)JGYqk78b32seU zeHpQ71?ELL=Vc8OB&YTZ|Kzi#5?=JyjkZp3dp8Yw<-EZ|m*L&LLO_s-z{dcAZUt25 z(_A!IcK0*MiNIaNTfWe$^KNXkE{>-wduHC2;!f<^3g{3a5jjIdv=C*7PlgNa zBe*pC!TEYNtz+2tMwi~xFD%##fem$3>dU=bxPD6LpSK#nvwY1&S)izrD0Z^q9HZhM z#t_t{OYE#WsJxVxLGc)C2>C2g6ipsycf;UkLtY!0f-W9=KyU1P^Eq+jsQtoydkwWc za+_a>8+}{p1D#X*Ilu%FQ%}-C-yb9{JA-%y<2|w|B$?+dbj0dZA4ewC0TaVh z`0Hn)c1SlS#z+Q#D|@&S#O?`{XGN$2xyTy^QHS_#&INls7t~B+$g471|8o;C-dJ#Y z1zUp$zVNVeqi&dCQj#P<@`QbN^gMlQUFx`Wcb8p6kCmY+EU804q&i&R)h)BV#VD|j z(IKin`9oQxI$xx^ZG&HcX->7U_j9qDz7I4bi|yz*Q`I)=6HL^jE$00$>M=Oc7dhIC z5$AtG*bOh9yBgqlxLvT_4B6y5ejM2LR~Oi$VRZM}rmM7XF`xGNUZ-!Ve7(D4v~K%e z=)D5s_T<`e%U08eh(&!rd=38 z`!Z$SYu%8~ezwExKyr-OzN2uH$Z#t#4g6NQqcxp;=Z+IOx;JP@=R+gGTcRJ_9u!Tk=JJ$^EnYA*nzQ zf3sV>TFm?zdSxfSXE__-ggu~)D|S!*K!iJK@Vfv80WahQ^Bu#%~Uc_+>NT z#qP}Tko`oN$b94w2Zy%-(nr@yApzaqy!a$W{>t!U(ra%8KfStQa=3$srhTA{Q9a*3 z#{uoqxb8&vaXSyM{^pT!AdTVtf5AUE9j!m3PpgOONfHO;%69mkHu@S1_Z+0tokuW( z-4Z`sM~Ro|kYHH~3>D|;tOQY)dn}3pO4^j~l-#vI;X>S$?Ui0&K|@T_n!u5nJZ{P3{QpE-9^x7hN@sAToVU z-;1fz436^d110{73=R?^$?=U`XCpncZ)G{a_^ma^Z_a0o4P@ts@?B+1k43Ot{E_^5 z8=qhxB^hcuPOW(O69BnXAXQjzpiPKK#i1iL%qEPRt|&=nYQZ~1?aEq0xxPd{2f>aN zaJq|h_jmGtZK>)x-UR>JQiOB5p}^^`h&|q6;(V#tQavt@)YtR1!nLF-RZ2AQHQR-r zSmYK2KbmBvPOwt%uNyY)h^-QQCGQ&rT!W`jOXkr`RQ4$B2m z6>O3KHSJ>bO7_0k4uHq;PcVrHcF~c#D!$O8`rX+_fx50FTIW zlvZ&0se2TM(|}VYFO7`L02Ac7yrfM;Py0whdH{pJ8id^3wywKMB#+eb?d%$w0~b{mQ=9P&DL;r z6nI*m5_ezqcUp;^1mc2TaLaMbCe7Tp-+PPZ8J)VHYEZv`UO5*`xz*aFPsT}3uaxdu zL-BAsi#7Vgo)3JWowWSAs6={k9W~Z)R<_jZXIsrUI0(WbDiGn&D7BH4RgL|k&k^Kf ziI1U|2Hao}?~@}Sn%4JY$>PZ!)AWHx`hxja@tSa>W^45e03h$jo#CJRb^lzvN(u`K z$rxDtUzM2hr6Up>GLNM6MLIL2EM&5rfR#PO<{=R>slC^Yvqx-j`gS_qNP2`$ysxFrw1g_dOalXB6nEgz44IOY_Yi~5 zmPWQP4CV9k{1JHvU=s}Y_j5xm>zAW~kC6L}K+Qhj9;GQs9NQK`Ygp(IOoO5UipZ=ye+xv()R_h0xN0N0;cm;6{ z!z)#r0S8>4gx&2havHTU`+`m$_(dBLwuG<1hR1_b4@?PQTkjd;9+_HV!AlXuyOG+3 zW5x_3V>!FA;iKkKT)WAChQ(6Fd~G~tjX&ZOhllOc%gdV~JdB%*CJ2`2uGKRTrd4LE zJZwwQE^r;Wk`vBwJQWnq6a+g?QQn5K?@EszE=D)aeUv564OadZXRQw?#aX0fQ|?tb z10$gwUy5tU`*ui7?wL5iJ}n zt;m0X2`*tPg|S~fS1<+6E2sJ^a>uU#s;c?ygQq(j=R(=;50LO!0hdO~jHY6fO9FGh zKP=0uMOr#y-Yi3$$df>kx2MA=FVu26fp=)3W{Q{KS!P~rlOnF&kKEGdSK9y42N+}Z zfHFU2&g*z6H`PnqYWIg-EwFr_e46hMmlD3q)ch73Ud}hZbL3GT7Ich}okQU#m>JeF zm0!`Fb*DqYJ!)E>r*Vm}>Nl`z8RQLKiW`Jj;Uo!0?Jnmu%Yf|;sf5R?5;5o$QYZhp zNOfTVSM%DCMPs{;J@zZwzhFjck5+>6(?pa0udWRE|JX!Rwy^n+aNb3E)fPztndi`T zedMZ|n1DZ!zyQ4qhyFbkR0Jac5!+N05;tIFO_u6v&H=n@+U{lsygv$$KTvoN5EL?C z2pX>+?gjy2s>0ELIyKCBvvZQ;c&l?JjIK@>m_5egM-Fep(ueSOa4}QMZ|4}R;Q08v zqw%7q%K;*wmgTr0DJ>y&5?;JzVANPRzwK&?dz7xTr4voLZuXl5A9V^TFElH!jjtC) zJQ-)Zrk0&0ARrJ(3E63livm9Du2Pqs2!5K{I0|SmBSeqHGzyj4nG8Vy&S@}G4Go>* zL-)IQYL8;FGcnxIf9>3seHpcx?4GNT;37eI5H(T!valttr7EXIDC44TT|zng$MH?w z0W@0Lb!z~ynB-j`;42S$4_(So8*DlTbJ)@I9vd>t;)MYASzz#X^&~&_jB9c6W4nZ< z4O`aKPIC;O>bDJ~VG;v*O~Uc9_8z#waEX1>1-Qx`jJH)j)AWEtcDz3sO|-u9%uaJK z@3>4lbmik*MX1QAT|MvGSwkQEO-R(QwETmv$vdJsrJKsDmJ!eK8Vk8)#gpV~I!>&& zTx}@KmPW7DdmU^-sbuJJ3L>ytoS6!(KtF6go6~)wJFna}sVUatW!Wg22VS*tv=^K` zilp~BIC85t${um93d4P3_UislmX*HX!~+Vho)Cfe6VfMNaPD$MUQFshm6WHf6a;sYG%$r%b72^5N;aGAB$w#EWwzF_87$;B6{iKPo zhTee1!qawyJ|(CMSKbysY8iF)jT2Os=_O{#3H3O@iDDtX6CiF=Iv+$h4z4U6?3&v( zxSl~wn=Ou8PkMT)1cJ%9#UWHMILteR5$wRZ5v0mrh2D&uj`*^tFU<`BhK3j-X$Yy1-H%Hi)sh_K9T3cW(Xjp&$EOH{@96A5fCF=3a zvE(9>=fCosyd#6HB=z^lzo~KnUx0AUADpiKSDcdkSDZRI8`%6ujrv1g*&&G`^Xxya zjcj?tC&s51OAVy;{6Z%$;YY0e`zf!u092sb_t*8(`Vuxvr%Cr&P5BJi?h{Z%+yfwj zR1pupTfTxXP%lt&HX3{xw365TXeP&Nmg9Lw=lgZ}8V)dfFw!4qxJHufjI?Iud<%-Q zX9$i`jjwmt&TDgM^U9b2gtT=7Z!@wR_YMnaUnro=7)D2j?rAgsYFLL4icjyIpT9cG zjjhzL^V8s}g1`0@Ot<}X1Sp9Gv|*T51W3A zlBVTOXw8IK3{71IbxLoeys$(d7vd0s(ccxq*{X)2xWrbmT~nrT!8_?*a((ux0gLPe ze>0jXL)oXD>|kChdc_#QCl={5+c_iOPQ86$nmwjv9a%x58{07v{pzEzt+JlWP&BLA zG0{C%J6#8^x9sh3Pltu~F*xq2B$8%CcHPt!{RBFt zpTG}jIYak{CT|O5=OigwAs73qy8A}5&ZpM;5qX@%dCc&lsTDu;5cW7+PJG?&#=aav1C0Mu>`QA09QMHgfeRRuYayNW2w5OZ1j{In8egqnZ!=PRQH{TQC-dRR&V3~S{VS0^XXp69_o5nX}Oh5fmn%RAOD`x{UHq*R9 zC6<^)jeR*fvu!?4Sg}4?U6!+Ty6-{WCmpwkU&Yu57^t?f!Y}25YKD(iS{9mzV|B70Ie?+a}k4dq?|IjZ!Dw}pn zCg|TiJbCAwh z7>6!Gp&x)E5@gW)y80-Nu(PgD8>2FNDpKopQ^8DK5t5y-Gr2BtU{HN z=+0>Z4n?PKN4gO)U0)sFDGF1ELjVcltw)H;q4mT(m&vUoX_jjg7^_4-SY?hcarkt8 z3p(p9`NIFRkQ%;#_yt zS6$Wp)vL9h#T6WoF8$@t-Ne7UWNnPm5?T(qV4g$pmuNWpg!d}gF|wXybb7ck)%_SU zxeWUlR~1?g139Ue{y83H?5)00;k5v%P6K?ZLC%g-yB{_AOx4ZFrO2l7kelM!HXa{P zyBIC@U?sn$qVVdWGR>&1;2{-QPZ1$Mx}+k+cZy(>6rOWZnug~N#v$zBS~*u>Ol81S zw$&p)%S$vW5xNARI@?R$aJGJvaTKD*>VBoNIHGd5d`O1!xlAX0hF1+X?*Yvce*5Dy z3fe|5k^-1}=E_oP8~Q*bveYTZ{GR5I0^64mUbY1oDCh7oO6!6Pc2tBq}R!nOLVSESiyYj)d^)M-tgAWl-- zT7O*A_?w++)dQNQt-RorMaPnM&QM14lvpJyo0pFjAE`bu+psy@>-P=uo7U((jJ57F zzmj+4Oqi+&Gg1AbRCT{t1v%N9G;J|POZFU_`hW}2p223ICd`{-={XtthdusZh_pdA z>uuR5!v$Mr#qUlo%IoK(>CaVlN*zfhg{amZ7R|>{1L8eN<8hX(((9_ z%kyP19kwTN)#(80`kCUyvxI4YuWhR}!c?F6p`c&kc!NwxN(0?p(RdA?4a_KR(vRn0 zn+2a>2+C85&}R7sYf>XQ;O4H_yO3Ol@J93e40Xwi=BfpEs3nkJAUYN7F>d;<1IC8?L`OiF4c5wMzl36#G*o;09Z(Ju4xE_rXC` zQ!+Z{@|rKseYTl}%)8NF;Tn?Q{*P?`6>xr_2F1DKSv40`WcU(8N zI{=RwoaY#`SQPQ^yY+$G5?jv~H1NPyO!69iwcqq%-co=~7;E3~yx#z?4|$0lXm*W8 zd|H*te$9mP*h)E4t_SlEZ;e;p)RIx5<`qdjWr&RI$!%I!2h;Zzv{&ea^^(-n zyIVGP!nyO-Fos$-1H`6DmsjOgM+}NDtQYn0xzWNM#pay&d#V;!AW`(*Q4QJBvJdhN zg^}@Jqn8`|;p11#SsIUb_2rc5={-~AQUpKYidwz4={$Z@i>|5c7vm+N` z4KUb0tq&3#`ib5--?c1fDa6cugslMEJM(S?r{no;kq4D z?shfJcFeb04esgnuLPUDkWVq|!*64kl>wz{EvqOB-_z~b8Hq*uhpttz{A!W>Dc;3( zUm^chYR>y=1Mt4IP214_YhUuurN+k2*5tp+rbtySHB>dU4>=U50Vt+$3=m085nGhT zO=K8H7FICQ-=bOuP~U+eGAT0GbF1k#g^kI>OI1~iT{pXdu8py(YIfB==hG*rbG~NG zK@p1Wb>vP{{9b-uS6AnqN7cjKZxGvzT_`1Ukt+&P^6B*4Hl7HK9 zg>u?z0{C4tBGYX-!Ckch7>O}Op@wC-RL~b8%!vvclqk!#nWPE()+IcG1MB`;Jyu@k zi7=p3qGUgaJi)@{EhHz;k?h&-S)*0j=4aySZRP}n$r3|q>ti>q9N0`OJ?A2IK*=l?@#2?sRSb*a^qYTu zT3{h+Qx;Qn=6 zKj&;pZ4*Woxf8Go=^znuPwn(4ZvM0}H&wgAfFWwTgqNGV#;Shj1elbPq?mQRU9fL& zCj6xFR7@(tGpe9O#l}Tf^XX?|*iJNHb)2Bv=3ZMwP=B{Ft1zR(;aOmN6@q&*%K~_R zfVGyS64RW7&QjFk(+y(U?#1q)N1}C?$EC52nOv@xLi_&Yis|_A?*NS2OR_p_6~aI0+H_&;;TB9 z-n9NL^_nPL@-~)#1XQA|KD?Cf_HqCm0h`zn{ZLqv@isv2Km~b$Ays+KY2&5AQkDwi z#Y8(c|5yA3hmGn`3Bjy}e_HC)WIYH&+>D820Vlmu2)q26p=q4t$RYcp$JpRElT#rv z$pQ}5rBga4LqSmr@#`TEV;aT=4KGKgt#=nP_fVsZkL)$PtFZvT=$VDjUps>bJ)7%9 z9*8dKw_W9r@%oKqTI(f`FY`| zw1;=N&+nIbPry%}=R@cwBS`&9>fc26p=ZqFWpPjKis96-%BM$+_*~Mk^;{8UM@9g< zo^{~~O+$!lE;stDPUGC<735}A!RyZ8V>a23Ra#x$z{kTV>nFCEPO!4#dLQ0uZFrRo zab&+9rFxbKa=m^;`}U+AM_1PB?O!wz{eg5{NwiUfE~+hfTls&H<)Q>cv?A&QLh&^+ zY)kE1$xDY#Fnl~N4k-LM8Y_r|*weqHUvt^p-EDBq-pWnDv0m}tQLmwy-G;{Cc5lC> z=@4_@K6=9W!@w7qEK}tn8LH#rO~XmKw)@Ejm?rCqAaV^uG_XnSF`O_er9Cv0a}F%{ zL;$}4nuMfF2CD==5XEPsjj#+X^nT*{xXxMe%yQe~>O2KtP$(!ZQ4tuWm3l_r1 zKfO7Le69TIz^*=wNTs>nk(nfrt3IL@)}o4(^r=Px4#h`GL_GrJ3zmZJ_cj|4@qr-#01D`20&g_;J!Hn;6E z?Q5lazP-`!)qdJN&rUDU6=IiD4dt=uts#!p#{1XWgz zj_JO(ZtBmOq_th|->r25A1W)+wb4^|eZ!Rs8AyWEj+e`kICVpy3Il8EZQZ3|;Y+#b zT5+RqoxXiX($d}c0{u6!XuO=ORRU`&1A)$`u-$^mYYfTvq5mwFC%_8rZ{4cQHJA$Z#1CaR)aZm9; zrim3D3~OlKjPa?|XVWe_Q@_vG2mBsh3~Vvl_PoW)5an7AqqT*!C<9BY$I3Yj1|DWC zVMFPySvKWr)dq?#wuzZDO?YV<$F&*Ry-Ho?Rv?t{>4@K8gXOwc4EAnlO?_XWpyTEO zmoT#*nu4=+J|MS_n5S)}VE7n6-;`4tZb!ydSP)N#N#YozS2e#kW-1#X05S@HS<&wC z!h8`1W(s%2jVwec4Eb#9?(wRv2BPkr*8SQxaTaB;XbeZK!29{5uL{rb(X@`D_P7M> zmtxn(!lalqc2-Wr3MR}PRwVLyO8_huDk%k)VUqGeQ*?}VG>OJ<%2HJfq2?rHPT3}B z<3-2tNzaWs{4NimmYg7jMyzL=lpAd{gig62w`XFAlh_>d|%PSt=tywd{i zG*@c#SX*oEy!V&xBqB1G$4&ucQjN^^HA!6ov=o(r+w<8(u$qt`qq0cn@DVQFC}Tg? zTy%D4v&4aQFwPt*GgIG?*SuR!&&ipYo20c`!aGkI3buhJ3z<)1&Lc2s1`mrUMX;`D z=IlFdtWJlB(<$aX;g5SS0HNTz2=+PF64;J>oXM{mp$ql?Vgo8Vb(SEuh;(|{kh^`Z z0L5-0x|}EMcS8AGEEhW1hGKa*0)8I%R975nfhT;A&=Zx#Y^cuRgqQEReA=`!S0u6d z-8Y|ZbKG} zTr&*t{W#Q71*PIGQNc|(Q34Vz)YB^1wzu*i{@X$CR;g7u@kJ(R`k!<9KX2EZ?W{~} zzmh)w8zdA7`0uR#&U?{T9TgRA(*pr~fWu~{-8D791q}uX+#UJ_t>Z;&Qiy*+1$r7B zlH#5_8}Mb`+RoB7wS?G3GOC=3dp8#jt;DGvaYw!edcEto~#!c7v^W&n`F13BsAJ|B5l^8DJEb zXU<#@295j}1bO%W0a7l&xbF|EYP-CRtZ=BoOGR-m2yeMjlOxwtlr0yhf7YW6ldR$h z5%9~6sq7bDRbiYNxJdU;;nIdpYj#h?rK166j->uQ|L<~`h<2Jp1z~$4u+x$jCqcfe zB|vR8gGOAM*|Esw6Z0lD3JX8ZnX6u$ibS3>Fzwd2W!`o%KTbULiJ8E^*W=f}eohLV zWFBuD%(`p$Jhm8`I<d_Ew2H|WZsoLo|d|wG)~UfCzzVIOufY;3!6<{ax|vz zdy~BupG;hLcg)KsyZM{)vlBS8%fs?qo8U^BJ-hPLOlY1&j0Rm(+?Zt~;gFaByo%sH zPo7|$9%=|M%~2E6K1Fzm$lLgb;5=qgy+#}%NlVj<$`8Pk&LvOpH4aoI%VKVWZgKKt zEk6p0uiNWl9#Q)E&Ph3lUx1*=Z42gQzw9igZV@hES=U8uc-sc2-(7J^xj11VX4)dN zH-6#;H(c07;cggrE-MR>uc7<+;CMd1Nc#qZ#Q+Lp7&l(CFJz!YuBmqj$`MVILu{zh zi|tSCRLqen!6bK28KXv5K-8~geEIjNzBIyT#asrWqv~hWVmgd^22GqyLB1#dIKGx2 zdDSRQMwqCw@T@iSm<10prvIwHu_jN908fz#Y}V;-g2>3LXgRdajaV6e+<8|rWgN}X zm7yzgrh~-8JKil?1qJDJqyE2ao(TP8pTERABP|>AJs|$}&x`GYSCvolxzB#XT0(hB zp{f+4HCYf{WfN23k=Kl-ernY-$`JCt;pn8led>*l>c!HT+ieWphfyi9SnZ#*$ zwZ>;LZ}*?(_HM#%fJDz$I_i#M=a148MbF} zqPMz29ZvV2hqaL@iSHn6gY_HnmN*9;&*}9yKKIy8>mEC(Sx21J?mlgO7MCk>q2CT` z*s~Gr_c!~=jK6h$>vJ#+5devS${m$g+eDiOQ;?iNH162h`dHa}lwG}0zQ&jGzrV<1 z*O08*#4nmHM-rkAeY*ov25;X9Y8O^r2p$n`5SNydYm+WAFrCVpuBoh?7-j}CsG?hy z6@-?y8F{Iy-fGa1Ua)Lp>&cMQOl#)@u4--p$c3}(bf+5qn$1kjLB&oRgJZHCAZ1j= z4Tto!B$o4VeUr_#)j?)*FNVApiR2q1z7aYH6lK5OTtPHcxiCY?J>vJh?WrG1aZT-w zQFIr}=K7PHI4LZ%J4@;@Nj#%VWSKytfRp4fsHn|91o)#{D<|6rvKmZ0}{$Z{NA%43F=qF|+S z>aM|s>xde(g`>3-#_iNsHZv z)+9$N8_I^(C2g2=6>Ejqn7J}a)#ed+@v0w@ffr~G9iUe|7^LQ87}l}wlw){nW5Gcv z7+hH_A9vGkrgFD;f10npHC_K!Xs{MO(}=QK?(>+ReW_ZRebAat=eb(VJ4yqnfgr`DGC`G^v@p>W9<8#++dzUBvR*q+yEN*nSDL3; zoox?Ua+;)cQ6ZN@X;PYs=^|D8bh8spUs3ck zM{~CtL5VRC$O-B(->y7j2or=K3+ha+gRn{hJMtyh7b(xT;#ukp!FXwlOFW@%He>9B zBf&K@tnG%?evYK)MDd0#4`(`^nCGZ;<#x@3%Jn1)#zRn_BVpOV3B{m2&O`Uk;daE1 zYcyNwdthbsr$Z&OUohFe?aUL*6-0kgLFgt~AgN&0I6C@tQ+^m3J9_OTqtU z`n~4|AS)M!0I)I)Q&tor6F7l2qxr32I6MZ?IRwS8Y(lBjS5yZym^VjMj|sG4bdmzm zXfseJU@Qh3QMrGkM{BQmAPUfx^I@T1{4&}jmp0Hb!CZ~Vr+UxvuhGDr5DnY@tNoe$ zpY0FHKb9_aNw{Kfec2EMEC{uD(+R8i>J z;}93})W4g4^bugWOW#UQeM~?rWl^X4Gda*7)+;l2Ggq519FuI%!ndQ6l1rS11vQ+U1nG!GAiv1m%`iS+hB`R66r4(4ta;m6hFQ+xPA|)?} z7|0j;5RzZ(9A~QG$Ubpj5I-xTN1g~r(NSZW*ZVHXaUiy?Zc21I)Q2<2d*jZH97&n& z5GTnoszA&VHuP#Fw=P+d3cFuE#j55-g|1s`++ZgiZYo7VOm3=5jPDjVD-i-9yD(mN zrrvunrA*`>V_(LC$il1ij67@*9Zn%s`idd0JDiY?>v@VaZ}6aG5r^0=E^F`?IgqC zesu?{5<`}ZqL5F4gc$5ZeR>L=!2V^!oY=*batEGVX(yBA)v^$kPtJ~2aP~N*U@vSw zX01~de{Bw5GMQaZ%W2Nav?*hXxKNxWv+Jyho7%E_S8@70;a%uFb%Lrewcu~uNFXx5 zk+vdfMvNVSL#A=i3tDRHuH3pT!W=S7X{j*pYb++V6zN4Q!)BIiTwsGr*l*N$@eGXq ze3wiOI0BcWiirApJ)b}pN;4$@gl8xh+gN%U7WSI_B5}1~CMPutECa8d#b~FuxwEHx zTy9tGiFYS>TMauQi1kRnrj+6I@e>xA;?goJ1-#p%{|=w>!Xv0PeGj=p@R+hw%PST) z&a_<1Ne5R|8V@xyH!D}`hqi%Sb!UPgm>h`X%yRtCu4aXZXv7DM?`rK&rmtNj1@j={8S(?I&xMj5*W>e zin@micW|Vcp#uu49U>2F{iW8+GIrsvHzPPcK0qMMBEZSyB}rI8#y%D5DEQWHANw;F zAq|;wNnRL~?8PGbS7A2g=bLZ?*`dx;2w%P_NIgzE1m`VQk3*_w}pdyin7bV)Rd+AUALxw%d1aDc&hO|9&(BQQ0aAAo}beKkmj*$G3 z7KErjPH4D)MsLWYQ1&SMkP*gP*zoL*C{?TU#5|IJmPUOLAZR(r-#$Vwr}_ONq4ZEU z@lYWud3M1w8CY|9AjF`Yf6K=^2vN?6hE1^gkc@)qr`nQ-RWbj-j`9dmc5Q~5n12IA zJ%_kCtdle9-SKczv)Nf4wMgeE-J#;C7Wokl^MR_S`NbOfA6~FtC4*y_f2c-Tj`FB} z=wX&Dy`|%^#Z@c4t%0(o`6cHs*?U%B!7f;Se2?NDT=e{q$dS9twx?yyxP2?_5t{Uy zs+G81r2b$4$FTUYit-$7NBfNY*?HK#r%vlpt=UWghGF#~9tE+Bzfty?4UWV5Ni&SH zo5>1taOdVvmL@P+t8&A}Jk<@BWch(N%-nyn|0b@Vy6fCGTjH)}PG_b88ku%v&uXzr zunUA`wb1REwRXof69t`2OSY%|(@`GCqNU$@Xo5#0lXa0XiK?FKK_(uN+8keR>5nmK z#Rah3Y)z{d1*Kuro0ygIR)w_THIoL{WV73clB{}&rNe}>*zB7%VVLU544;$Igx|8 zD_Kfh(%RUXlgY>a@mj>v{IR61ZRim$5&=#YC}F4H#Zl*HZEopl_#`^^1AU*kOw5Zu z0ui6t2&UuaB#f`WlO(@Cea+m->DcdW=1@u_?Ax4oKDZccBuu`jSVUwJRwFP8r!f*D zG6|cGL({-HYxY@;CK7#Zc7_E7B)$>)d(&6Ga#s`+Drt=@2HL{B&|KHv zaJI=C&R6bZMU-XL$!;Pc-=}2eh59@F6;J+D`3FvNjAFD&VI20YZ-SgHUIbI$(k z|B;fLN}c!SS!YompEWotU>9OI`e6d0XQNv+J>27PZp|MR5p5V5Eo~}WAH7juG&H=a zVf4IgHqkgT-i5rP!J%AI!8QMA@OeI_q6pd}$USc4JT-IzhnLsXe>^CN5!%sFpC!y` zRbSzqtdvIGn<4ZU{)gB51{B;XWZn5J50fh{0+ko%T9%5d=E}I!IZZ;R(n|8tYPHG( zwTWJ)SvOz>#6)lSf`ig4tj?~%@q&YeyDvTXBWqEBS#P;G-T8_Re(> zO?9P}~`lKsg|A@MM zr1|74@ALin44L?u%QpQ{dy7c*S;MyVk$M|V`3YM-_mOxTP5qgoYVrwq9!~u1Z0z|6 zyp^Z^q$pqgh`9ZF4oCUWN9gS|<)?i4k}u%-DDksd)$CKvbEp8Z?pGt@NFDmz4w2`A7xn3#smqA@L?LN*pbmb>zhNUKsJncS-KK(I+SHZsk+4gj`dD%!>t zrcNh#NI7R#*%7Lq6fL}|-xO_O$2dHkxT#+iUEa~l`(oKCD3@K%VUD~iD`d?8-Rnd8 z%wI*GtLX+WnHzm385E5x5$?S%p>)1y8iztSEODIAFQ;_6XN$5nEE$&*{VFl$ok2|X z=pY~&91SUX`0W1MxGP#*g4%~yO6g$FAr72Bi?sCN1`QfL+DyXIhgV+dh()Y!#;lbz z!W$r=bj1>3Tsu7`iQ^3rts5|NA(i%7`dK$&CQBO0uO&IRUyl%Hn(Y!x`?w+&ht7XS zZgHcL?S{)vkWP2?s8pLE+87kBK&OLB=j>pc)7KD5-=pK4ik}m4D%DmHrO=)4ys|EW zIRV|KBBvYU3fEx-X=6QydvXEg-TgpgjcZDZPg{O16~xt<2uKzzF<|6c2g z+}ePmCNWb8$Oq)~3h+(lgXQ=+$gdD_;g1yOZ|m-lrsVG<0a?`()q{KvrybhcL)XG+ zkAewK&@<>iY%jTO;Zb@F`%B7N$l~%p10IbY%jWo3_=5QV3}5)i)!%*Swj&!0QnT(U%JeLqas zN0i`vY(7|zLSDw!zBh*HZ$)-o1&t~U0l_rEuU)#5ksq8yE{5t2tkJkw{7c+e6oxVc zzt3op_iOhXa|-GHeIq6^;KOCPQD##dK&_k8YgB+CGeM?2fl7Vj%tsFG(zN(E`!;OS zm3htA->PlbVHhO;44>$^2d*p+G*w5GA%~MOf;d*GUk|Gp`^$LNE6u?)q?fALl=ZNA zD3c-m*G#6hWgOPoM=tAN`|DUvc%a5?6x9w%Udh zaz55BXquRBt+YthQ}nM9q&hb#qYSSzC>_?%+Cr})Qwf;4{9)%&(-CT0r(7m!Cs zgGs-t8!w@?k08%Vz+VQ%d<&P0HHTdOPRhO0_y&6z5qzUFv%; zC+~5S*1Sn=;h?sE&>Da1_+{m=Q8!nG!NN*olos3)t;N-%1T9-svH3Tv^^_4KS4?nJ z#7(G#?8%)!3cu7SWGUOBKyzbJM)=4*nA{2QyO6p_5Z(Pu1?@|RmQ9juo4AGqU}j2k zXz@sZge|kW905ZwuO*+rY0(p9k_w8Qj#ly}rV-K?fpwXe8Fq<14nH-YOgLAp1;Onv z874f+#$~LgN=5qv`3Cn;;Idrii)?B0$x|uNz2ThwHlz*x zJ|TsLEcC6FgIMNt@Q=OUPv}_!l*A9itQi81Q2@(Ip$G+sT>p>fR!9mbM>m;k~Q`;T{2k%^Y7n1 z*Hv#?zBQuD$Moc(LlMY9>zVULp&HQkss&-HI8NhRG6YpKYw7+0)c9C-Dg)FXRb1#) znsDWYoUyabuC1~3`ki1*2VQ|sAkziSldyR&4@aWMx;+tj7hMC_q?5q@^{T2YlnMOW zjsP|Aq-vUyj!a{y>KppneX^t8j@O4Y^aUAggTu)hsuAsInhQZwwu6x})f+m+lH(O#X~yWe31IM)e-vd)4OJap7NhdBLl^7nC+ayDyQjwp36FC#L(tW{uiqF-OOOk? zz<`&*+qdMFO)Ez2J6`SP^{peymL-i-544&N<3Qn=hY%~Y3$C)dGsxgn}X_f-k|rk~yeBL8PNwOo9x)M6*Dg9epPD|ee z$Sf$7c!c|*sJG(9KYO+`HX+LFIf%sjasmV#@shldsml+NuL?8Tx|Q+ul8>W+`o5&s z20M%x3%)_SI1PJZZt4QW%=d#Qg* zhQw$G$=9bDS#yvTyI=?gFwO;8J_eLow%Y{_1YCk^g3_c*60{E)GF7LPOMhLTke%a* zU?aO`^)-~cn@>YMXeUSD@^TPx1t%K5Q+u{FSJNhm&aFu%;*UhnYj9>5??i3axcMd> zJzxeN4Wk_;K`8D<5}dXDve>*HrT0zt+ABU47sg0E;t5sQ1_k{vaQ1Aapq+D*lmzA89eT4zs1r) zma=8Uk~E$^PI9YL*8`_ewV0{0>_O9Hm#+2$;ZJCl8a(ka;jOzunh|5Nx9|s>e;JE8 zI!~bal#`cgB8T@Q41G0pxPy&}2V+ER)$LCY`>nKZX0PljiIAwcrENL9i~|qX`LG;y zMk;qQLF3=&5Xf!?S0vV%Xi0U1pkNSh!&-kMVlj(GRgDE;<|A_58nL`w8%2RKyKm%u z-({L2FyqetNtRVGv}gT|LZY~M87Av6{sTM9Gie_!$UBQ&k4RQe1cG4)OZRY8jq;tE zOmA;WvO`j{BT^9i?SxWETDX@v*8el7RsSJ~RvY&M%bJZpteF$#n%cnwLje1%MfZ_< zii>lox!(B=&uuzdS?hPUQso~Pj&Y}+3}!uyZk&n57n5`9*T3j*56l2}@*$i@JmRW^ zk-+QHbPd6$2sG%Ae_#BHHB* zO}k3vs+Lyejd>F2AgD-gLj~mH}slM}v>FZ8ctw&j2 z4_=$2h}mAqJdJVq*|*;Xqw_I%>7ZpLs6_Zk9D=7E1)EF z6(zxlb8fD-eQs%k5I-=B0tbx*(}dd6hmV`TG=aZ@6fT0Bmoc@!a%k@*T;jI-guT}S zkDK0)Rzx|syt=;hb7(fiCBR70NZi~AS8_uZet&*LGNZUQpAQ9|L%lBn?jFHBRixN5 z1sl9DKEYNQvUF&yG-XkvF*6950zs$R9U>k9piq`{iVTpZ7W!-_Jfq==4K`>mJin*u zXhFh6&&NV{78*QxO-%3LBvd6p%Sn5&da%)@O&G@TaG>W`nz)GQOo7f$p)+8VGi$J= zEFETp7-t3#Mvps#K}_010cR<~8V*(^l{8Oy>>C9gB`vAu#Xk_`10?4lB+HHBc+|os z&w`$A=Ol&GsHeyd&MP$47_a|w5gHK#kA|RzK-JpyscrkkZ9LaQUcI#I4@`7{9fm_? zocHIat2x^}vjQER1gY19g&Q%3BW3YdS%t$&!@-o)Ld9BOW6K9OeAl$LBC1NW%vNWX zWd>nGua?F2_vKD^wg@!pU?@bmUO=)Vm76qnEr{ea3)}qQcTuFxT-82-AaRmwBCh8@ z?ehc&FUr+d#UQzVbCZr1mqtqVnhB@Df;H7N)JUMNn`_F|!Kx0t#KX(uQ8RTg%R<=v z^<}CETCsVcNHr=Z6OK|EgQFgm(MP9!^{X5C9tyRPit4{wX8Ka8-#HgZP^)HGBudSJ z719>31WRnk6 z9~!F=?T_#!<&)5dy_2|_OraGtvQ-SAReo_d!O;_OL$F*oQJBU$&osnK-oz!bTK!Y{ zI45>rw^?pg8nhx0pBkSRmsVElv6I}|m8l)pTxo-9v7f@~=BY>>R;8*S;~j5WCb<#8 z9M+ljh`g32ld3xr*OE>eI^|4mK|W7a4gl*+p>wk{sXer1G_mv+ERb`esaqAzcp>E{ zJ6*C_2q&^x=mMCM-E6{C#Iv&9)Z6y_K^NH_vkvilWhqthhUDC`I?67{9%{h{~ zSJPOxK8Q>xv%{K$({%4z_XaAmS~yMk>Q2PJ$^*fxO~}`N(eq0BK%Uq|rr`a}c75Z{ zy50VkWjZnNG+jbj0^8z{vUvl>>5)_v(^ZKYJROOwDbup3OOP))L|UgfT$+D?g5~?-2uF(PhR!Y(3Bl<$n9FuCE2-w0XMV~9P zT0|?%=m|>J(~t793RC~ujCzmv-|!)u=^1zs-YXQ0sIAHckG66!lbo}oX}Yss@E#;A zl2>f=MP<>&RRTvm=Jc_G@WEe{*(t5S&qpYpj42t6KIHoIPu4K8 znD;FM0M=d?VFjVUlqJKJVO*I)*8aJl<2Bh-`mM!_>IsKoHO7zp@(IkaQw;{G@MbIa zP4MG3oWmhztM*m!@9Y_7{m<;Y;~}ut?oII1wFW%_CV6Xl)_%Jk-;QoDf)Pi-@jhiH zQ0-A+gUZUHa~#3gz#8*gDo&v=2>a&t)HnG85+6>nme97zD)7aWH6r%FIon{tJ@zSu zMBwx9u=0YBJwx7LZZM;qNbRf#$a~UUcJe!(tCPG%@ygx(*yvOP7tayXp{sigJH|7W zD2rPt?Zfn#kcG~vshaANLN^9%N^u0;79H*t#>%q>cTWwpHvla~hlA)*;0ICSNM#x| z*1`4bt(fI@bSfAXlyxLqr)uRSt>G`nYbXY1+677BO7EiTmq=Sp_L%rtp#k zHAkTL&xm}e1U^jbk<$Xv3)+IJv?V{vOZ@OBRi!KLZ7}JgfrjqfoKI@-YI-|SM59pD2$4~sjF-k5(lt`FQ;eSMMf z?CDB8!s)WApuL0TXfsLz zE$oDCBv>1N7fI|0`kK&X9?tIg!bjV3U|ViS^h!kz?<~7%NFVs^jpAml-tbHV^CEyH zoTbcafW{+8_)mi+WmCjgaE^tGXxJtD_FeMaO{S1QK7qSf zgqJspG7Y28g}(a^%=9TjuIIunau+oH4p%g;o@MUhx}A7K&Tn>s$JKcLd3fI0lxNlh zDW1T$5X)|t0+=pj!qsi(JC-UOwgd47WGN;lxZ~iWQF5(!{#>_&#iDS%Z%u5zhJA}u zWL5LP@5YJl;#o=bw>TU!I)8qst@g_BdVM|@7%l$zmi<^<10o+kE{M_5FLOyEGhyZ+ zASU6Hpfdb);D~3p?ICp!`XSf&F^Nd%J59-QUFXQ(ZJA`GQo8pjjYUCqMU!x^I`)+2 z$e^nh@_fP=&XExRrr@5Q_IpGxI1bT17Iqx_?SuNGGa5akD>@iYKqPQc_4ih5@p1y1 zrcX#tW8C4Nb4}x-kNGj(?ajIXgSSh{O)g-vcf;jU|MG!V{kD=`JhZ*sz-iEOhSC45q!W-VU(*+tM1> zg0r)ufO|)BzU8Fk8uaYJEGvGk>$~G{%cO`x>-^I&ivq1G{c?PR^o@QDo}szA#7dWt z$-neUTYZ=Jt`FwmPwA?Y+Rop%ci;#2&qQzh{w*A`JWRRW`PwTlV*amv<3H_{mCX$t zO^p8qU--Y0)Bk#Q5J1QWh)}@68xZK0eucPq`>X%VF^7{X`Q4cOgDYg#0K$y?cjuO` zDB;VgG-27&c3Js_Ry)8?>{Im5spV^C>Ms!CH4jcR(`=vTuFl7myEQ$5H?VE6E|le~ zmcjeDy=PH1&&LYqQI1My+g^JUgCXsNDu^F7dr`I41$6!NMa73#BOTR0ge(#@yXTO8 zKc5;cP_16*G36S} z8!f@U^altd{mf~UqWacTUqWN2Cd7e|)^vghEfUxHXU}}-0qb-YMI3G|O(7KEzxfF- z*DvS)h0i}Or3=w9k0wEo^;qpE@$0<@Yh(G0l@eM9Bz)X+O9iCwOKIR$>t{Q5WV1f; zq1LUZp8JHE;YAwk{{hpK;kg;pP4+vwPdf~mdelhK{ccO11B8JwNkW1 z$@n)vUU)8MDER7c(**-!z?Dr zMmkdl#9Cpc=`O3bX}fhvfzwt>b3q7A2V0R&3=L?&!=!YTwr;s($jN#h3aEpc=G?V$ zA+{EbqjLRZ(BuOEPm#4WDMP1xYH0imHCSj6WkHxd5p`g?%-49?qGZIrIaEo$KEMMi ztW36b2jAXfl$oqm=X5tW&zGjrrp?5s_lURQ>dj}zl{I%8Aaw?^Pq~S@T))UT+v9CkF;bhA1#+Au=-BxmRu$T%2=Wu^1dGc~3^b@;d!&-b;8E!8hcPW^iLa*MbgA)x+N zZ@*A=GdCcuue}0l^W}L(^RBpDCq)6ZuTq4IeDI! z=m+pDRSMD%-7f$odOfIgMaxiye8q^kWojvdpB?mk!j{j zF-#o?E`=7TXaCd2WF0>I5$VD|AX6O%otxOiJ$mV+G4uzuN?r?`08yF5Uq~CrxH)Co zS?tpcvQ7{sT++n5j%wkSpPtE_ZUPoONS8 zziFV6%Cc^2B50jPG>Wtfq_U_Kl^YC};gt<8pt)#sx3Mt+y%r$JXlVo}qFDoZ;l{?T zV9R%e`rtI|8}@R_kIub_+u{x_B&AW`Gveu4?+zz3-L76|^!x-~QF}mbVYQ+9GA((I zMR;=0z0XwJW6xA^6)7(^+H*H-$7@)tg`s5pj076WZ529CJnIgd+Z6-mV$oAL?{~uk zU@`=l8=?&Sch0J=#IB$w63(W%Aa)r5OEN$riX1ym-I-Wf5C?gp=H40GeF*+(HjumA zi$vnqHNXp)*jb<_rX*_Px|~H6_Mhkl(I=&6aQ#p&gzSX#y_At3fs&|3SZV;>ZTIKy z7UVBEqW#=}G$VSI{w|hSqKoEFiCtT7fZ8OL=C$s@shbmz{)x-y*p1gk_g zf7ExJE!`C-V=dJ$(6s)Dr2R@=oHKGYP5}cfR@2@Hf;7i)3#MKHZDJZUY(0dt_O6#M zn?Q1A6{cbkcT9OlSAl}+MCrhhYzGiF{K|#hDT1qlq1MRYMS`LYAbtG@?SrliuBo}z zb50Fmj1{uHEbxwXJs}Gi2fR#mN4&yy$AsgpyLf3j`XG|^&Y4@N5i%JUj9(7(++N;H z!*6>?qPQyg;&5EP+ydO(q(e%N)Jf_xAy*VvjzgkkARMd*)q-8#GgYx0 zLCNiwy!ArHvo=mf5T=-{BK`7*GB=776+0n^h8GtGc#eL582FNKg7_m^*c4sKY1F@_ z)X`rVt+p-fF||kMX->T%55N3A<1$7^F|+v5q#}Z>bu=0)82Mlh)FifokAF(hWe+Yl ze2sO(zDyK4RKr?ARq-9xI4d9KR9+@c{LA@Kl(l&TdCY!cmEoO>GnrA z_eWc4+v~dOQ@qp$LrQ~Zi=fjBbkdb3&e493v?-`eBfkA*-29O~1YQR_SN~B4%lC}5 zmuRIaQBReUj5JV`O< z7Vr_pJNP~YERayweql6w$f&=1U3;B4((`@6{`LK-KFB77Yd(|Zb_rN|ls)Qasd zHNfm*vqPmke&DPeLTb>T;VO1EWxkSnIk1qC)nMF0_Ee7b2t@$Bc2({$Y{Yy@Y8~~M zodp!%4coaHy)NzT9l17k_hw}#77TCm_X{)?C%K7_51dsuzTLMsX7o&BH_~ersysQL zP=rpGdT>25JycR2-SAk;LOdf|;A#jW7iYF{7O!s&IA{?uSXr3j&((0=U_&PFX5!2I zLx+OR$73`Z$C)%$RLSocLf$uP{+a^jR^lTgipoxNtsfB{T9Zpa&suICq^CefO(52p zL!ekYn;U?_yJXEhjW_s(m*75>T+sy=V#9BKU;aO|y>6=H5^UcQb>}uy<6Wqq5(|F50v}qFsBE0@<+~{T@Mhx&xs7s} zF0dSm$4n(1s|RsKeMB8OD4uyXc=<~3N8c0xgt^$TE=T@28(A*C7;_R&8SVZ+Rsc|L zCqvK(gChklMii_hEK!iK@LRAj zDN^w>v^4A!TxN)j&$U*Wqm3Qud_E*Un-avTrI2q{+#i$2V#dJt ziZGk-rSm~xmpBZ<>hkBR`n%4!4l8fRC8jBJ1wdID3GiUt9NKbvSttYrNJApx^Q&pl z{LRoD>$D&Yrnpf*v(wU@RkgY`CzE|Zz`Sb(b^9#N3Qqj}a1s*2{{B!s6h`Saw!pkE zpEZ4EK94B6dTyaZKJm4idxmcv^xTfbY!mZBkV}x@r-LZ6H>Vj zIM0H>xDL^TKZ?KlhGZiz^8{Qj1EEeN#W#v*$yR*mr zC3?-?{p6M~cNn~hhp_9PSiC2H&#i{ZmkTQ$ur781no`DVi)uXHH#bOu{vA6vxE&C?z+jM; zirPs}feHaPIH%@SQbSjmKA8D%UcB$AIgZku$N&ogYBWHWBDQ&g#hf;IdiYCt{OEzJ z>Bji(TBRIz@;W!mhY9ay93*i2EGMZOYX_|xzTjgQtk3)Isn^@4VH?s7Lb0m*NF}#~ zb*6Sgq|LVyCzEw%ZPp&h3a65_<^oCMf?ydo7(u7sxu?ikw$xCeFJQbV0D+Z^o|GNSOeuco42U5^}pa&7%^Rla%0*Z!#@k5YtivUtzIE z5u1=B63qAB3Lvvc=BO9*)Y8-xMh8P;C>~9ynh@Vr4Z5Le9NFbysu^>ZNgY1W+xy}f1YUmT= zJQH%a7}~rPpWsMthn9p}!A8l=7%G;IZr9{@YCRb3&&}gbty&e~B|&1~Y&$1;RhtWS z!M7d|L0%2b*=GRm9x=2i~`JF*gL|HLZ6`S z&)=S*Xc(F#A}&GP?+8BqlW)M(7k*aT-;COhvQg(t#L-V3#Yh&a7Sb+?km1HIDPtUH z0eAOI(bkYt<>!YU3h5JLDVv;>_#Z)#$p2zkxnZ^ZK=a&n@&cKTiZ?x&A2L~I$m*8H zEygbE*OAN?RriOvS2>xt;Oevl+Ycf_r=>FYvblWR&+EyZ1v{J5jV$#7+tggw`^o`?>k{t*(QRhc3R!)o z9%^9s&|SGa)_Cl2ztj8(kFtRBKGo!kezih4BvjL7(agtv(QVSqN0{rmXq_8vRYR#+ z9e3w->D4n2$8O8pr~KOHue>(8D0YuMz}#L(v7wVU8>IG&JipAqKl&DrOSP7_gOEGj z^^-JxJltZily)89kI!G6n9-^S|J842nMSyO*Pr=U#4Z*4Z}Vq+Q9Wxz%m3M-2~@ID z_*PZ%wnkJ%M3t3q2>YpP)h`@rYSl=Fim*@IVM>OoUM^7=ut=P4%_3g>LHr5O{VY^G zlA#27Fd-cmvH}5ClHE|X=bh|daf-|M}Y&``pXKI-Z zXX;zlg~nEe8UV-VLLU$D8J#J0Q&qNSJkY>Y4b>rS!;DMlD zZ;XY+wnXI{tJWb*Q|)KYqmQJ(aiveRBFn&erL)X95XTS$GsLzXsWMCM=Iog6!1@jn zjN|(mAHU~XqVkU;_rT)-aZtup%g&E}}%Gs7yNbeLh zoSKxSKiEG?uhtrC+6>=&rH=aogBp3Z39cYPK{o=gwyUrSpeL~ra&W*$-`!&%{jpg` z@nu{U2%ms-Tq%6h^P*u{+<|v3GPKCP=n-iIX|Q*iuccha3!ywiy;5^qrX(8{E8I!x zNZFdyFxqyOz@(|^JcncsKP)o9xil3R7K#`J*3!2R2aEIIV1AYB;~+fVPAznY9U|s z9%uL17VoFVxtKBZ*)YaW0cXzvOjWjga?dAT#@L9}Gy!RYdkhP5^JQT^1@xj$k%&^G zBB}XJEd3~5I07}ave3EOFBiT@lxZ1YX%hv%XVKVm|M zyP|qy_onlO#T+eSDz#+4wJtHe9duc zc!3j0{ig_FW-$15i0;vIY3l?K-I^+|I9tf4@@dw8r&43tzza8Nyd6?6DEpu&k_o- zk@pBawF`?jL&bbZu0`SxqEBTPpj;z$MzppEg~{-hC(yqz>V|7XYP%Uotftb*FNCqR zJu`PTgX(2gu&sYVJUAP)MtbHMkFPUYr!g33aH}#K$Q+0%P!P{+W}m~KVj@p6j?!~K zsseL1VYCE)!jdQrL#qv21AJ+@wdc?4*>Nv@NJ|A_}#qz*Fags|K34y)uRRaTkHG# z(2sAn;om<0Is)7GaT|LRT3Z_jM-zJ^2RlpJ?+CIYs(b=A*4E!{d}cP*ME~{k|CMVa zl`R~Q{_^IdA<|M%pF=f8Q6tlJCsgGt6e>VghdhZKfK;qpcN9yub{W4cqTYh%W!tlQ z&zo4F<(OjY7ct6lbVPnXm9fVjKC(1lXCgmwYtc`FK0S`w_K=w^3o@C;;6w_D|E&<2z8qI%d=S?k&)R~^ zC!6D@b#}ZgRTdAl)RDOuHqj60G{_ev&I!;c&wwBZ;+$wmWLuz*VJ35T51xep{+9QP z&O!qahMd>Ltf8x2LpPY!swFrI0$Wn)mf9tofvTUAdM2@?qtkLAsTSS5wj2^*fw4K@ zJ<6cj5B_nW28r3eQ0^zu9U_}Hy(GCEgN(o9M9s4!L1Sv~r6Re9e;ccnj8k;7wKcg? z?2?m~@meifgIIjZ6`HAsx`81RX|cx-P6azB^H7=A51g1zKHF@|}NutZ7Ec}U&*!^R(a$r#u zrXq0}h8L@9{o%WVc?L==7`+l3x!V&KBx*Kf{p#b5=+Zkzfk!VWz9k0fhXqNQp}PgY zCKfvzSgNB}f(CyWmZYU+b(lO=4S7Z$nQb1Zt+O~qLU(-MkG|m)<3p!zLW~kH6O;_T z>K&9$*2Mm1uR#h1{a1XxT#pdqPY8Zs-LKZITJ5aPkvP+AAZEc*-EJkkWP75Y$Dh|tW4mq!kb~AsMV7yGkdIx< zvZX*~$hb(|cB#k>$!8iKT8?xJI?p2+uI*};5wUh!oZg#ewMsg!_;vd{hYvu&7na5-<9M|I z-=p)R%C8jK2CjZ?Ggn%{&Ca}nduXiV<(;7U?16b+KEjw^Q)K~pinT%Q2#j%hDFi?H zO04FOd%0#=I8q&^_P|zcS$O>pLcwm0UdpCh>xwYY${mvJaKNbc4u%!i>ROOINuXtx z=a4dkn8fLwB4w+OaFAHJ!+Nb6q6PL5F$EELiggQM#gnkPq5RyEzD$ftzFC4KNw%$t zeXDW_#On7Us0nC;hp7g|>X(6c{ath~%QA!^I32uSkkZ1r^eq;}eMCV&(*k_6pGzf>mRfgq_zKth5BFzf8%jtAY|bRpm?1p#W3BswYNb znl`@nw=Fy%0YP6vj)f`-4nfkCDOOMPcE^uax{f}Q2&c_PDI z@m5-r3XBsSnbtn5hZ-_*)ET0uYEe+Sc{YK_)OZQ0(dI&?RZt<6JPQLg24%~nSKR(y z$9$=Wul;gL2-k@u8N_!;;OVo0OQ9)juu(%VWeVBc^i zw^TTT(x*<#ge4lCqDb-l!?qZeOibrB4)GppWE|i@&~K5+&#s1;4#5-A@1vdL(Zm-D zI7i!H^Y3{9#GN6FR~3D1p3O~RYA)4GyAWL0+RoO zqTuh%*-AAx&xOUtuPhysR6Pbu2thzTu#h;IJ`yqw2>72d0V#s?KLR4=-S37%bYNNGxJyk$meXCfqz5$;XUqw&6 zAAVkPA8j~v9eGT3zO1F|yhHvLx@GreMZB=U4jI_>l4EQlU0~a{I9K&?nokpDvwYp_ z6plrkkj<*}u2Ls#+4nS7b{X`t6Ssv5d&t-Abz3gLV}0)Pjlpozuh7-ss>vyEy8DKb zX8M&@j^zvqa-o|;3%$Pj{plJ~_D-KQ0u0WkJgHp5p8OPDu++Q=Pc<9OxOgPZlVim0 z=0F!6n{<(;>q#A?w-8}&^%JoJN=|?koCMHWfHpme|A^ge_rGbuSi!!C2taRItfFt?d8A5N7wdDf{ zPVtzGLDGJ;(vt9SP-)Joi`iaiFv6V}sGv{rHSbNB%{Ut%c2uP+@_um_V5%uIRt#;_ z;4a~-#HyDY{wM@E+~mC)D%|?GvvJJjqr>m4o$PEs<|RFZ)cojD{ldKP&r4fFg*(*i z!irS=rCWg35U^LoVu7HA6KzQsOtnoG+_-SqKH)#8x;s?Z5}|KanPcYoc9(2pG1;gD zrbnJsDn&zjyZh0bqI>8Dz;6mpnsjicTayIV-}@}yd(M@E!f$(_v{8wgZ|tZwyT-N8 z3RYpMBO$nsrAW)DY_(ZNr4#97%~rGJZ33`G{rk77 zc#gY8^l}S5?0P7dzj{@%C+!)z{?*%_>6Ih}AGR`%T-M7OS{y_dxRnyjN@D(#@V zkQ#||8^RBK7V6>0sE5=yI1&Yw@sKo50nhmrgh=QM2fqzEd`s9<9csNfnU(2)<4O#n zv!)L2#=~%Hh%4fG!Nt}3otEvc<%Sm<>91+VOZ;G8xiOF}N&Ve1J|F8dXdbrb9=T?&<+Xg4^~L?<@# zQhbjdtXuhqUCaIyk}iyi+dBLDQ1ZaEJwrLR$c*m~_;s{5dr)@6oB~~4DS7s2Jd$*_ zbb8iXqf3P8ZdPGMw?Hi#a#tek#3HdI+Yg)4o|?J?5GCVKuGR1_sB3%po_&%2Eh1`h zUtNQc$E2GrP{AjpDD9h}svB5Q1D%~ktQp{en$O6Ds|`i%2NZMLAE+N*!m`<*wXEoO zk0knU9sa$p-OIy+AI3~b$TVEPLWU6OLBI~RscP33IQ-hd_z$fgv5b2HrxB+nFD%lR z-LGQ`gF1IE#Nglr32#Dp5pPes`mvawh$hgNCm&d9gIBnFhN-YY$(b-2ygX2TndQi% zNkBsj=D8y@xB2}szb?YcLZRw|NqR@V(A&=f%WOj1*_M)RD9E8S^J!n##J#nWOOh;@?jVgH?x0lE0OnjWPcd z))=hXslk@V*cq3dPu~Y66eLbt{c8K`V8wc^q!0C`ZXL?4Rat;6F2v)6%-!;*e(1bp zKIxo-{NbjY4tG;esS>=q_>Y2jzp12DSk3?&L_7%@^dKZ2X#{ z5<ys^>U zYFbzQkikB|9Qpw%Svg`33X?(ZsQe*Y$Xmm=MEi#PI!{Uc(%0)D3`$u~yrt9%%5|xd za>PPYqA-{TJoi(fZ*IJGHUJ~-;YkhI%&bv8A={2j{3PNzP*BMWmN!Ntlt(7-_`}2( z=Dvu&4$u;$=kZo8)WMy0lP%Xdx453`_h16MwmpChrl`+RDR?&f3d6tX)Kz9l70 zmYLl^OFO^SwGN%HEYUtkppTZbSM!b}YQ^Vp2~2BdROkZlZYYG#>kV!;9p?-9r3tJAD`iWi%L|>?kL_}a7Wp^&;97<3G#ykN zEbh{*ZSd?msvI2BU2<$h7*JfG?d&32WuRS8*mYV5lLH(cd*6DEdae( z#a+#De=s()W9(c}mYP_PmQV*tUNKTsNoKk*QQ}e7Pi}xhWj$8UWK>exHbfBLlwlTr zcv!$LoFL}9?kCPC?b{tPM*MSxiU@%WLcX{>81!m6)%DPR%bo>Y?qDt4n982dB=Ut~k9sDjyZX@MMrw`W}pgyE# z!5TaX%X}Qm(;9KabRyGPS59B5pZpNkx)Zi?2U4lYAp+IlpGx&jl^$goIbEqkh_Tlw z1CkTc?DPAjjf6O=bQA4FD6U0d>=dBPIc}^C3M}Q;WMP2#=d3Tbw`S30l~$O2yd~hb zW=iMHgg3E^Q=1lo{0D3}#^Wt?)}UYO+hpP%A};n=YR9IT;7al~vn3y7X0W|U9ClUm zhxi-J%kn#j3flpR@s|d26icg7#0FI}#3y8jG#>{I4G9-ikZuJhhgGrtI8I=v(UC3`OtkRL!z%hr#c(rZ;8I^6C=scrtCvcO&Be_0Hm z=SeQx`;2s5IM1y(yDtzvm5iaqcvL2hzfSkJs+aqHf!>bjwN6K_-jZLA=Uvw+KhP$X zui%sywXVN{4Y@vI7<=fuRAV%X49)R>Iazf9yft$=LBT8Fh$lsO0g16+(%`f^@qNoe z_FV`+pj2S=L!;YXR|C_q(JOt-2jMuRwwWC@=T@oRyMWNlY%82^CuWp)6`x!&@F?kV z2womlgA=a{AHxo*>8u9b&4&c zYoPUkWLn6cp522Yo*bK7&QMq`f3-HJ6H0 zJ+eC1gyJ-8XJoOt*W%ZP`@4P14sjitE7XqL>0$Whk>#@81^B~}Kc~3F66#5(sl5CT zFlg3L(w_vRjwHJE8huUS{zuu|WSS@f;X*T{_UBdqo0YL`o~h$SYdbz|kw7GkI_M}u zz2Fkx?uFTr5-jP~euGF=^~NAX?z!pdPV|N*^MDgXuad7Ku zyj~na*KNBEH7EE+B_lkx2(|BTu80$v-Kwm*Xf`ImGU*)yEmGU7faR#YuHsXfeE#ka zM}+O7AZi(0w;pddrkC5RQ)1$6lWteKmtB~%L9na--;Ixd2u&9hc&--A&ra;SFfLEY zm66)q#pQ#J8y`*&z;Stj@9@-&DLr=Z6qKF7p-!KR9*DZgWZ4cJX2rP7cF2kvEaY^W znps4s-CoK4p27JlesF7&%IvJR<&oN+qW8CHZ_)4st@_F0V9$-8e^6v8=*DrzlO4^Q z9o8HdAK49o&Rd=r+x4tlF#KQ~1TKDlyzbXD|9)Zy~RS$9y`49l4Pi8fo7F{JgzXWdP<$AU|7 z*;&5zeisIE;o7J-rz|U?((pWSCQTzPyl#*7(UHiLRYnM;5Xqtq>8m!$uQ|sGMuF`v zwR^7gfehYLWIJQ#sSx!U4r@Tsj!TVV0@D8eS35(^Yh<6Q5f@&Q7&+rpwoL5Y-Kgyi zIZhP_H1aiT31^0yD@^h(jOAeg4Z^wMk4Fjms4%Q(QSz)LhKxgm_1(ZYwFi{=(_+Jy zhxTU`&i1QZoly$=oE)9*>;sj?+4+?`mRD>J22{;B^=lvxzSZtKJ}F7+r7G7_wv!H% z#yk1TIzgGmc<=oh2eD2s?w6%7KD|m_Y4eZLLMJwjvuOqOU@P?3GN#Lt0F=l zct*I|2_VnqR72@?f+XYerEx~`)Z=E;>xNZKvs26s4Qfr}9BXS6{yXltg6gg@D`am* z@k6^@MX$Ff^R(HQ+~a^}y3;!Y>C!A31C4Bhw%JC5tQC5&IqXRF89Q~YJH%DCx09u2 z2MmXFm@fxB5ou;%a+AYz8J^im-}dgKQo%d=(p~HsVfq>Ztr6VhNH7h&$acc&kG_XqJt7grHh?3kN(`EezOe;X^-B1x_i4TcoA{KRYb^! zJK~>CFVPRkl>d`(i!r1o+l<$pdjpH~9_kzg3mRD+GnT9zr@?|#qPMcil#`S=W zN}{&+(>%_t;#LJLb3{lP6IV!tq87)Uh<9+@=s;uI&N;U@YFBbSfK{1?#6rZ-t3SjN zJ5~zJ4u&|JBf#zfl{apY#rWJ@&0WRnv1-i7Ax&y=*B@PhMg?0)tkqF1$aWb?Tc=bp zBZeBRmQFy|NnJOZCEIxC(S9{a`{h&|Ds4TSu^nA&60?Xh2A6PZm+iL)Muvx-s*lPZ z0(5bTDY3_}MX21QU`G3hJ^>5zbR7&^f3bm}VO%_@LIzVxub9W`MH$H;A>J?MRrA^n zDd|@-wF`q4BD`T1c0unpu=aiJfde|&k>ZdJnLTZ9pCn~2f?;||vEh);VTb|+!PoHH zpWY;Jql#{V-zGg1Nd^P&26NQW@zo0-V-S%G7W7T-H)@#KG7{B&omnHEKxmYnS%Yy4 z*q;qA=3i<~6=Uc$bwT7qMpQ*1Q1!n%{WYy|h(3GhmA;xy1S@!OYPGQdl{oeRaBee8 zdm`sLZ0*Tq@DRBmlV4#ESg_U=5^A^?EiIEbxmMLCha{U|Vrc2%b&P*z4;kG;1KEZp z+$rJGN$+8@8x*^Ysx7Q|crlKnmDWOwC?;?)bm*3x38v3p)wH*(#If7KGg6BR-{PmP z(oZzlo24{eZ6XlSWq(w*DAvS>YwozmVQ84PF*Fwe6Rx_K3i5!w_ zohnJHu?xkfGiMTX(X%{wuU}FAoleUJWuiR(JY9P~s7B>QdKNP{ht(=wXkg~G31rI= z)hBmvI|ZX`Mxh{a;D3w1ZuQDPXu7aY7DR8HXlT|#nW}⩔@UPTzQ5!&INR=bs#NH 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≶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 diff --git a/scripts/installer/pgdriver/postgresql-42.2.9.jar b/scripts/installer/pgdriver/postgresql-42.2.9.jar new file mode 100644 index 0000000000000000000000000000000000000000..7aba6626fb2071a368a783a06cf7b3b2ba1b9d2b GIT binary patch literal 914037 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 z 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�gu_M<9V23K=_iEO5mnVMdh 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

NVP~ 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∋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

fViZ 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

E(NOdf=b>iu5Wj@vRh# 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

uipI=!zTB{ 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

From db4961fa7da3bea796eecff7a76858549c07bc13 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Thu, 6 Feb 2020 17:47:02 -0500 Subject: [PATCH 221/475] Simplified version of the diag. script, with (potentially) less confusing output. (#6522) --- scripts/issues/6522/find_duplicates.sh | 45 ++++++-------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/scripts/issues/6522/find_duplicates.sh b/scripts/issues/6522/find_duplicates.sh index b9773c82a50..3ed0a0851e6 100755 --- a/scripts/issues/6522/find_duplicates.sh +++ b/scripts/issues/6522/find_duplicates.sh @@ -1,7 +1,6 @@ #!/bin/sh # begin config - # PostgresQL credentials: # edit the following lines so that psql can talk to your database pg_host=localhost @@ -18,11 +17,9 @@ PSQL_EXEC=psql PG_QUERY_0="SELECT COUNT(DISTINCT o.id) FROM datafile f, dataset s, dvobject p, dvobject o WHERE s.id = p.id AND o.id = f.id AND o.owner_id = s.id AND s.harvestingclient_id IS null AND o.storageidentifier IS NOT null" -PG_QUERY_1="SELECT COUNT(DISTINCT (o.owner_id,o.storageidentifier)) FROM datafile f, dataset s, dvobject p, dvobject o WHERE s.id = p.id AND o.id = f.id AND o.owner_id = s.id AND s.harvestingclient_id IS null AND o.storageidentifier IS NOT null" - -PG_QUERY_2="SELECT s.id, o.storageidentifier FROM datafile f, dataset s, dvobject o WHERE o.id = f.id AND o.owner_id = s.id AND s.harvestingclient_id IS null AND o.storageidentifier IS NOT null ORDER by o.storageidentifier" +PG_QUERY_1="SELECT s.id, o.storageidentifier FROM datafile f, dataset s, dvobject o WHERE o.id = f.id AND o.owner_id = s.id AND s.harvestingclient_id IS null AND o.storageidentifier IS NOT null ORDER by o.storageidentifier" -PG_QUERY_3="SELECT p.authority, p.identifier, o.storageidentifier, o.id, o.createdate, f.contenttype FROM datafile f, dvobject p, dvobject o WHERE o.id = f.id AND o.owner_id = p.id AND o.storageidentifier='%s' ORDER by o.id" +PG_QUERY_2="SELECT p.authority, p.identifier, o.storageidentifier, o.id, o.createdate, f.contenttype FROM datafile f, dvobject p, dvobject o WHERE o.id = f.id AND o.owner_id = p.id AND o.storageidentifier='%s' ORDER by o.id" PGPASSWORD=$pg_pass; export PGPASSWORD @@ -41,54 +38,32 @@ fi echo $NUM_DATAFILES total. -echo "Checking the number of unique storage identifiers, within unique datasets..." - -NUM_STORAGEIDENTIFIERS=`${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_1}"` +echo "Let's check if any storage identifiers are referenced more than once within the same dataset:" -echo $NUM_STORAGEIDENTIFIERS total. - - -if [ $NUM_DATAFILES == $NUM_STORAGEIDENTIFIERS ] -then - echo - echo "Good news - the numbers check out!" - echo "It looks like there are no duplicate dvObjects in your database." - echo "Your installation is ready to be upgraded to Dataverse 4.20." - echo - exit 0 -fi - -echo -echo "A (potential) mismatch is detected!" -echo "Some cleanup may be required before your installation can be upgraded to Dataverse 4.20." -echo - -echo "The following storage identifiers appear to be referenced from multiple DvObjects:" - -${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_2}" | +${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_1}" | uniq -c | -awk '{if ($1 > 1) print $NF}' | tee /tmp/storageidentifiers.tmp - -echo "(output saved in /tmp/storageidentifiers.tmp)" +awk '{if ($1 > 1) print $NF}' > /tmp/storageidentifiers.tmp NUM_CONFIRMED=`cat /tmp/storageidentifiers.tmp | wc -l` if [ $NUM_CONFIRMED == 0 ] then echo - echo "Good news - on a closer look, it appears that " - echo "there are NO duplicate dvObjects in your database." + echo "Good news - it appears that there are NO duplicate dvObjects in your database." echo "Your installation is ready to be upgraded to Dataverse 4.20." echo exit 0 fi +echo "The following storage identifiers appear to be referenced from multiple DvObjects:" +cat /tmp/storageidentifiers.tmp +echo "(output saved in /tmp/storageidentifiers.tmp)" echo "Looking up details for the affected datafiles:" cat /tmp/storageidentifiers.tmp | while read si do - PG_QUERY_SI=`printf "${PG_QUERY_3}" $si` + PG_QUERY_SI=`printf "${PG_QUERY_2}" $si` ${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_SI}" done | tee /tmp/duplicates_info.tmp From 6b660c5a67de9fa443805bcdb70373809ca82146 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 7 Feb 2020 10:38:18 -0500 Subject: [PATCH 222/475] fix storagedriver assignment the change to the inheritance model changed the meaning of getStorageDriverId() which now returns what is locally set on a dataverse. getEffectiveStorageDriverId() properly recurses as needed to find the effective one (and should never return null). --- src/main/java/edu/harvard/iq/dataverse/DataversePage.java | 2 -- src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java | 2 +- src/main/java/edu/harvard/iq/dataverse/api/Admin.java | 1 + src/main/java/edu/harvard/iq/dataverse/api/Datasets.java | 2 +- .../java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java | 2 +- .../engine/command/impl/AbstractCreateDatasetCommand.java | 2 +- src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java | 2 +- 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java index 17d56e94671..12f398c9c7d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java @@ -355,8 +355,6 @@ public String init() { if (dataverse.getName() == null) { dataverse.setName(DataverseUtil.getSuggestedDataverseNameOnCreate(session.getUser())); } - //Inherit storage driver by default (superuser can change it in the form) - dataverse.setStorageDriverId(dataverse.getOwner().getStorageDriverId()); } return null; diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 55318bac371..8425af60335 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -2761,7 +2761,7 @@ public boolean rsyncUploadSupported() { // ToDo - rsync was written before multiple store support and currently is hardcoded to use the "s3" store. // When those restrictions are lifted/rsync can be configured per store, this test should check that setting // instead of testing for the 's3" store. - return settingsWrapper.isRsyncUpload() && dataset.getDataverseContext().getStorageDriverId().equals("s3"); + return settingsWrapper.isRsyncUpload() && dataset.getDataverseContext().getEffectiveStorageDriverId().equals("s3"); } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index c80471fa5f2..c5f358e8f71 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -1665,6 +1665,7 @@ public Response getStorageDriver(@PathParam("alias") String alias) throws Wrappe } catch (WrappedResponse wr) { return wr.getResponse(); } + //Note that this returns what's set directly on this dataverse. If null, the user would have to recurse the chain of parents to find the effective storageDriver return ok(dataverse.getStorageDriverId()); } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index 65f3a214fea..3999b45be14 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -1300,7 +1300,7 @@ public Response receiveChecksumValidationResults(@PathParam("identifier") String if ("validation passed".equals(statusMessageFromDcm)) { logger.log(Level.INFO, "Checksum Validation passed for DCM."); - String storageDriver = dataset.getDataverseContext().getStorageDriverId(); + String storageDriver = dataset.getDataverseContext().getEffectiveStorageDriverId(); String uploadFolder = jsonFromDcm.getString("uploadFolder"); int totalSize = jsonFromDcm.getInt("totalSize"); String storageDriverType = System.getProperty("dataverse.file." + storageDriver + ".type"); diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index ae6e48742e9..f4f4d15b25a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -137,7 +137,7 @@ public static StorageIO createNewStorageIO(T dvObject, S || storageTag.isEmpty()) { throw new IOException("getDataAccessObject: null or invalid datafile."); } - return createNewStorageIO(dvObject, storageTag, dvObject.getDataverseContext().getStorageDriverId()); + return createNewStorageIO(dvObject, storageTag, dvObject.getDataverseContext().getEffectiveStorageDriverId()); } public static StorageIO createNewStorageIO(T dvObject, String storageTag, String storageDriverId) throws IOException { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java index 971c005a902..5059b15914e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractCreateDatasetCommand.java @@ -96,7 +96,7 @@ public Dataset execute(CommandContext ctxt) throws CommandException { theDataset.setAuthority(ctxt.settings().getValueForKey(SettingsServiceBean.Key.Authority, nonNullDefaultIfKeyNotFound)); } if (theDataset.getStorageIdentifier() == null) { - String driverId = theDataset.getDataverseContext().getStorageDriverId(); + String driverId = theDataset.getDataverseContext().getEffectiveStorageDriverId(); theDataset.setStorageIdentifier(driverId + "://" + theDataset.getGlobalId().asString()); } if (theDataset.getIdentifier()==null) { diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index bc55c23bb51..09c102aa82e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -1284,7 +1284,7 @@ public static String getFilesTempDirectory() { } public static void generateS3PackageStorageIdentifier(DataFile dataFile) { - String driverId = dataFile.getDataverseContext().getStorageDriverId(); + String driverId = dataFile.getDataverseContext().getEffectiveStorageDriverId(); String bucketName = System.getProperty("dataverse.files." + driverId + ".bucket-name"); String storageId = driverId + "://" + bucketName + ":" + dataFile.getFileMetadata().getLabel(); From 7396140aa47bd93f46f617022935b7cdd56aa8b6 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Fri, 7 Feb 2020 13:28:29 -0500 Subject: [PATCH 223/475] allow file preview for Private URL users #6537 --- .../iq/dataverse/FileDownloadHelper.java | 16 ++++++++++- .../iq/dataverse/FileDownloadServiceBean.java | 12 ++++++++- .../edu/harvard/iq/dataverse/FilePage.java | 27 ++++++++++++++++++- src/main/webapp/file.xhtml | 6 ++--- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/FileDownloadHelper.java b/src/main/java/edu/harvard/iq/dataverse/FileDownloadHelper.java index 70a47449e11..a6be412990b 100644 --- a/src/main/java/edu/harvard/iq/dataverse/FileDownloadHelper.java +++ b/src/main/java/edu/harvard/iq/dataverse/FileDownloadHelper.java @@ -7,6 +7,7 @@ import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; +import edu.harvard.iq.dataverse.authorization.users.PrivateUrlUser; import edu.harvard.iq.dataverse.externaltools.ExternalTool; import edu.harvard.iq.dataverse.util.BundleUtil; import static edu.harvard.iq.dataverse.util.JsfHelper.JH; @@ -441,7 +442,20 @@ public boolean canDownloadFile(FileMetadata fileMetadata){ this.fileDownloadPermissionMap.put(fid, false); return false; } - + + /** + * In Dataverse 4.19 and below file preview was determined by + * canDownloadFile. Now we always allow a PrivateUrlUser to preview files. + */ + public boolean isPreviewAllowed(FileMetadata fileMetadata) { + if (session.getUser() instanceof PrivateUrlUser) { + // Always allow preview for PrivateUrlUser + return true; + } else { + return canDownloadFile(fileMetadata); + } + } + public boolean doesSessionUserHavePermission(Permission permissionToCheck, FileMetadata fileMetadata){ if (permissionToCheck == null){ return false; diff --git a/src/main/java/edu/harvard/iq/dataverse/FileDownloadServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/FileDownloadServiceBean.java index bb9bd830339..8e9695e086d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/FileDownloadServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/FileDownloadServiceBean.java @@ -4,6 +4,7 @@ import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.ApiToken; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; +import edu.harvard.iq.dataverse.authorization.users.PrivateUrlUser; import edu.harvard.iq.dataverse.authorization.users.User; import edu.harvard.iq.dataverse.datasetutility.WorldMapPermissionHelper; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; @@ -13,6 +14,8 @@ import edu.harvard.iq.dataverse.externaltools.ExternalToolHandler; import edu.harvard.iq.dataverse.makedatacount.MakeDataCountLoggingServiceBean; import edu.harvard.iq.dataverse.makedatacount.MakeDataCountLoggingServiceBean.MakeDataCountEntry; +import edu.harvard.iq.dataverse.privateurl.PrivateUrl; +import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.util.FileUtil; import java.io.IOException; import java.sql.Timestamp; @@ -63,7 +66,9 @@ public class FileDownloadServiceBean implements java.io.Serializable { UserNotificationServiceBean userNotificationService; @EJB AuthenticationServiceBean authService; - + @EJB + PrivateUrlServiceBean privateUrlService; + @Inject DataverseSession session; @@ -251,6 +256,11 @@ public void explore(GuestbookResponse guestbookResponse, FileMetadata fmd, Exter //No un-expired token apiToken = authService.generateApiTokenForUser(authenticatedUser); } + } else if (user instanceof PrivateUrlUser) { + PrivateUrlUser privateUrlUser = (PrivateUrlUser) user; + PrivateUrl privateUrl = privateUrlService.getPrivateUrlFromDatasetId(privateUrlUser.getDatasetId()); + apiToken = new ApiToken(); + apiToken.setTokenString(privateUrl.getToken()); } } DataFile dataFile = null; diff --git a/src/main/java/edu/harvard/iq/dataverse/FilePage.java b/src/main/java/edu/harvard/iq/dataverse/FilePage.java index a64074afc07..d72a95e3e95 100644 --- a/src/main/java/edu/harvard/iq/dataverse/FilePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/FilePage.java @@ -11,6 +11,7 @@ import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.users.ApiToken; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; +import edu.harvard.iq.dataverse.authorization.users.PrivateUrlUser; import edu.harvard.iq.dataverse.authorization.users.User; import edu.harvard.iq.dataverse.dataaccess.StorageIO; import edu.harvard.iq.dataverse.datasetutility.WorldMapPermissionHelper; @@ -30,6 +31,8 @@ import edu.harvard.iq.dataverse.makedatacount.MakeDataCountLoggingServiceBean; import edu.harvard.iq.dataverse.makedatacount.MakeDataCountLoggingServiceBean.MakeDataCountEntry; import edu.harvard.iq.dataverse.makedatacount.MakeDataCountUtil; +import edu.harvard.iq.dataverse.privateurl.PrivateUrl; +import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import edu.harvard.iq.dataverse.util.FileUtil; @@ -107,6 +110,8 @@ public class FilePage implements java.io.Serializable { EjbDataverseEngine commandEngine; @EJB ExternalToolServiceBean externalToolService; + @EJB + PrivateUrlServiceBean privateUrlService; @Inject DataverseRequestServiceBean dvRequestService; @@ -859,7 +864,21 @@ public boolean isReplacementFile(){ public boolean isPubliclyDownloadable() { return FileUtil.isPubliclyDownloadable(fileMetadata); } - + + /** + * In Dataverse 4.19 and below file preview was determined by + * isPubliclyDownloadable. Now we always allow a PrivateUrlUser to preview + * files. + */ + public boolean isPreviewAllowed() { + if (session.getUser() instanceof PrivateUrlUser) { + // Always allow preview for PrivateUrlUser + return true; + } else { + return isPubliclyDownloadable(); + } + } + private Boolean lockedFromEditsVar; private Boolean lockedFromDownloadVar; @@ -955,6 +974,12 @@ public String preview(ExternalTool externalTool) { User user = session.getUser(); if (user instanceof AuthenticatedUser) { apiToken = authService.findApiTokenByUser((AuthenticatedUser) user); + } else if (user instanceof PrivateUrlUser) { + PrivateUrlUser privateUrlUser = (PrivateUrlUser) user; + PrivateUrl privateUrl = privateUrlService.getPrivateUrlFromDatasetId(privateUrlUser.getDatasetId()); + privateUrl.getToken(); + apiToken = new ApiToken(); + apiToken.setTokenString(privateUrl.getToken()); } if(externalTool == null){ return ""; diff --git a/src/main/webapp/file.xhtml b/src/main/webapp/file.xhtml index 3059c3b8705..03188e86ca1 100644 --- a/src/main/webapp/file.xhtml +++ b/src/main/webapp/file.xhtml @@ -371,10 +371,10 @@ + rendered="#{FilePage.toolsWithPreviews.size() > 0 and FilePage.previewAllowed}">
From cd5cf39f70bb17bac9cc4f9091cbbb6951f76ca8 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Wed, 19 Feb 2020 17:44:54 -0500 Subject: [PATCH 307/475] Removing the flyway script with the unique constraint, until we figure out what to do with harvested files. (#6522) --- .../V4.19.0.0__6522-unique-constraint-storageidentifier.sql | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/main/resources/db/migration/V4.19.0.0__6522-unique-constraint-storageidentifier.sql diff --git a/src/main/resources/db/migration/V4.19.0.0__6522-unique-constraint-storageidentifier.sql b/src/main/resources/db/migration/V4.19.0.0__6522-unique-constraint-storageidentifier.sql deleted file mode 100644 index 2275d88c28d..00000000000 --- a/src/main/resources/db/migration/V4.19.0.0__6522-unique-constraint-storageidentifier.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE dvobject ADD CONSTRAINT unq_dvobject_storageidentifier UNIQUE(owner_id, storageidentifier); \ No newline at end of file From 34f637642db373b7a836eb2a934aaf8130731dad Mon Sep 17 00:00:00 2001 From: Peter Kiraly Date: Thu, 20 Feb 2020 08:55:10 +0100 Subject: [PATCH 308/475] #6083 update examples in File part of Native API: change 'file to replace' to 'file to get metadata from' --- doc/sphinx-guides/source/api/native-api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index e0e8ae76e73..827d3ef47fb 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1782,7 +1782,7 @@ Example:: Getting File Metadata ~~~~~~~~~~~~~~~~~~~~~ -Provides a json representation of the file metadata for an existing file where ``ID`` is the database id of the file to replace or ``PERSISTENT_ID`` is the persistent id (DOI or Handle) of the file +Provides a json representation of the file metadata for an existing file where ``ID`` is the database id of the file to get metadata from or ``PERSISTENT_ID`` is the persistent id (DOI or Handle) of the file. A curl example using an ``ID`` From 76c393e9680349cda212ece16f140a733d766104 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 20 Feb 2020 10:24:31 -0500 Subject: [PATCH 309/475] #6587 suppress deleted files for assign access --- .../iq/dataverse/ManageFilePermissionsPage.java | 10 +++++++--- src/main/webapp/permissions-manage-files.xhtml | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java b/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java index 4b61c6d540a..2d3762c7dd4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java @@ -315,6 +315,10 @@ public AuthenticatedUser getFileRequester() { public void initAssignDialog(ActionEvent ae) { + + showDeleted = false; + initMaps(); + fileRequester = null; selectedRoleAssignees = null; selectedFiles.clear(); @@ -322,6 +326,8 @@ public void initAssignDialog(ActionEvent ae) { } public void initAssignDialogByFile(DataFile file) { + showDeleted = false; + initMaps(); fileRequester = null; selectedRoleAssignees = null; selectedFiles.clear(); @@ -501,9 +507,7 @@ public RoleAssignmentRow(RoleAssignment anRa, RoleAssigneeDisplayInfo disInf, bo this.ra = anRa; this.assigneeDisplayInfo = disInf; this.deleted = deleted; - if(deleted){ - System.out.print(ra.getDefinitionPoint().getDisplayName() + " (Deleted)"); - } + } diff --git a/src/main/webapp/permissions-manage-files.xhtml b/src/main/webapp/permissions-manage-files.xhtml index be45c7e73f4..3627d59ed56 100644 --- a/src/main/webapp/permissions-manage-files.xhtml +++ b/src/main/webapp/permissions-manage-files.xhtml @@ -201,7 +201,7 @@ - #{bundle['dataverse.permissionsFiles.files.assignBtn']} From 0f394eaf3894b633a864c67928be02f344756d49 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Thu, 20 Feb 2020 10:55:29 -0500 Subject: [PATCH 310/475] A diagnostics script to be sent to the remote installations. (this is a *compbined* script for BOTH #6510 and #6522!) --- .../issues/6510/check_datafiles_6522_6510.sh | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100755 scripts/issues/6510/check_datafiles_6522_6510.sh diff --git a/scripts/issues/6510/check_datafiles_6522_6510.sh b/scripts/issues/6510/check_datafiles_6522_6510.sh new file mode 100755 index 00000000000..2cb873e92e1 --- /dev/null +++ b/scripts/issues/6510/check_datafiles_6522_6510.sh @@ -0,0 +1,131 @@ +#!/bin/sh + +# begin config +# PostgresQL credentials: +# edit the following lines so that psql can talk to your database +pg_host=localhost +pg_port=5432 +pg_user=dvnapp +pg_db=dvndb +# you can leave the password blank, if Postgres is configured +# to accept connections without auth: +pg_pass= +# psql executable - add full path, if necessary: +PSQL_EXEC=psql + +# end config + +# first issue, duplicate datafiles: (#6522) + +PG_QUERY_0="SELECT COUNT(DISTINCT o.id) FROM datafile f, dataset s, dvobject p, dvobject o WHERE s.id = p.id AND o.id = f.id AND o.owner_id = s.id AND s.harvestingclient_id IS null AND o.storageidentifier IS NOT null" + +PG_QUERY_1="SELECT s.id, o.storageidentifier FROM datafile f, dataset s, dvobject o WHERE o.id = f.id AND o.owner_id = s.id AND s.harvestingclient_id IS null AND o.storageidentifier IS NOT null ORDER by o.storageidentifier" + +PG_QUERY_2="SELECT p.authority, p.identifier, o.storageidentifier, o.id, o.createdate, f.contenttype FROM datafile f, dvobject p, dvobject o WHERE o.id = f.id AND o.owner_id = p.id AND o.storageidentifier='%s' ORDER by o.id" + +PGPASSWORD=$pg_pass; export PGPASSWORD + +echo "Checking the number of non-harvested datafiles in the database..." + +NUM_DATAFILES=`${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_0}"` +if [ $? != 0 ] +then + echo "FAILED to execute psql! Check the credentials and try again?" + echo "exiting..." + echo + echo "the command line that failed:" + echo "${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c \"${PG_QUERY_0}\"" + exit 1 +fi + +echo $NUM_DATAFILES total. +echo + +echo "Let's check if any storage identifiers are referenced more than once within the same dataset:" + +${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_1}" | +uniq -c | +awk '{if ($1 > 1) print $NF}' > /tmp/storageidentifiers.tmp + +NUM_CONFIRMED=`cat /tmp/storageidentifiers.tmp | wc -l` + +if [ $NUM_CONFIRMED == 0 ] +then + echo + echo "Good news - it appears that there are NO duplicate DataFile objects in your database." + echo "Your installation is ready to be upgraded to Dataverse 4.20." + echo +else + + echo "The following storage identifiers appear to be referenced from multiple DvObjects:" + cat /tmp/storageidentifiers.tmp + echo "(output saved in /tmp/storageidentifiers.tmp)" + + echo "Looking up details for the affected datafiles:" + + cat /tmp/storageidentifiers.tmp | while read si + do + PG_QUERY_SI=`printf "${PG_QUERY_2}" $si` + ${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_SI}" + done | tee /tmp/duplicates_info.tmp + + echo "(output saved in /tmp/duplicates_info.tmp)" + + echo + echo "Please send the output above to Dataverse support." + echo "We will assist you in the process of cleaning up the affected files above." + echo "We apologize for any inconvenience." + echo +fi + +# second issue, repeated ingests: (issue #6510) + +PG_QUERY_3="SELECT COUNT(DISTINCT o.id) FROM datafile f, dataset s, dvobject o, datatable t WHERE o.id = f.id AND o.owner_id = s.id AND t.datafile_id = f.id AND s.harvestingclient_id IS null AND o.storageidentifier IS NOT null" + +PG_QUERY_4="SELECT t.id, f.id FROM datafile f, dataset s, dvobject o, datatable t WHERE o.id = f.id AND o.owner_id = s.id AND t.datafile_id = f.id AND s.harvestingclient_id IS null AND o.storageidentifier IS NOT null ORDER by f.id, t.id" + +PG_QUERY_5="SELECT p.authority, p.identifier, o.storageidentifier, o.id, t.id, o.createdate, f.contenttype, t.originalfileformat FROM datafile f, dvobject p, dvobject o, datatable t WHERE o.id = f.id AND t.datafile_id = f.id AND o.owner_id = p.id AND o.id='%s' ORDER by t.id" + +echo +echo "Checking the number of ingested (\"tabular\") datafiles in the database..." + +NUM_DATAFILES=`${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_3}"` + +echo $NUM_DATAFILES total. +echo + +echo "Let's check if any of these ingested files have MORE THAN ONE linked datatable objects:" + +${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_4}" | +uniq -c -f 1 | +awk '{if ($1 > 1) print $NF}' > /tmp/datafileids.tmp + +NUM_CONFIRMED=`cat /tmp/datafileids.tmp | wc -l` + +if [ $NUM_CONFIRMED == 0 ] +then + echo + echo "Good news - it appears that there are no tabular files affected by this issue in your database." + echo + exit 0 +fi + +echo "The following "${NUM_CONFIRMED}" DataFile ids appear to be referenced from multiple DataTables:" +cat /tmp/datafileids.tmp +echo "(output saved in /tmp/datafileids.tmp)" + +echo "Looking up details for the affected tabular files:" + +cat /tmp/datafileids.tmp | while read si +do + PG_QUERY_SI=`printf "${PG_QUERY_5}" $si` + ${PSQL_EXEC} -h ${pg_host} -U ${pg_user} -d ${pg_db} -tA -F ' ' -c "${PG_QUERY_SI}" +done | tee /tmp/multiple_ingests_info.tmp + +echo "(output saved in /tmp/multiple_ingests_info.tmp)" + +echo +echo "Please send the output above to Dataverse support." +echo "We will assist you in fixing this issue in your Dataverse database." +echo "We apologize for any inconvenience." +echo From 9d6729b2a69e1de791c8c0994ba1fb798bad1bd0 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Thu, 20 Feb 2020 11:13:03 -0500 Subject: [PATCH 311/475] "pre-release note" to be sent out to the remote installations. This (and the proper release note) SUPERCEDES what was in PR #6522! i.e. we are sending out only ONE note, not TWO, there's only one script to run, etc. (ref. #6510) --- ...6510-duplicate-datafiles-and-datatables.md | 24 +++++++++++++++++ doc/release-notes/6522-datafile-duplicates.md | 27 ------------------- scripts/issues/6510/PRE-RELEASE-INFO.txt | 24 +++++++++++++++++ 3 files changed, 48 insertions(+), 27 deletions(-) create mode 100644 doc/release-notes/6510-duplicate-datafiles-and-datatables.md delete mode 100644 doc/release-notes/6522-datafile-duplicates.md create mode 100644 scripts/issues/6510/PRE-RELEASE-INFO.txt diff --git a/doc/release-notes/6510-duplicate-datafiles-and-datatables.md b/doc/release-notes/6510-duplicate-datafiles-and-datatables.md new file mode 100644 index 00000000000..d0440374def --- /dev/null +++ b/doc/release-notes/6510-duplicate-datafiles-and-datatables.md @@ -0,0 +1,24 @@ +We recently discovered that *potential* data integrity issues in +Dataverse databases. One manifests itself as duplicate DataFile +objects created for the same uploaded file; the other as duplicate +DataTable (tabular metadata) objects linked to the same +DataFile. (GitHub issues https://github.com/IQSS/dataverse/issues/6522 +and https://github.com/IQSS/dataverse/issues/6510 respectively). + +Please run the diagnostic script provided at +https://github.com/IQSS/dataverse/raw/6510-repeated-ingests/scripts/issues/6510/check_datafiles_6522_6510.sh +[NOTE!! the branch name must be changed to "develop" in the URL above before we merge!!] + +The script relies on the PostgreSQL utility psql to access the +database. You will need to edit the credentials at the top of the script +to match your database configuration. + +If neither of the two issues is present in your database, you will see +a message "... no duplicate DataFile objects in your database" and "no +tabular files affected by this issue in your database". + +If either, or both kinds of duplicates are detected, the script will +provide further instructions. We will need you to send us the produced +output. We will then assist you in resolving the issues in your +database. + diff --git a/doc/release-notes/6522-datafile-duplicates.md b/doc/release-notes/6522-datafile-duplicates.md deleted file mode 100644 index 39abb49cd69..00000000000 --- a/doc/release-notes/6522-datafile-duplicates.md +++ /dev/null @@ -1,27 +0,0 @@ -In this Dataverse release, we are adding a database constraint to -prevent duplicate DataFile objects pointing to the same physical file -from being created. - -Before this release can be deployed, your database must be checked -for any such duplicates that may already exist. If present, -the duplicates will need to be deleted, and the integrity of the -stored physical files verified. - -(We have notified the community about this issue ahead of the release, -so you may have already addressed it. In this case, please disregard -this release note) - -Please run the diagnostic script provided at -https://github.com/IQSS/dataverse/raw/develop/scripts/issues/6522/find_duplicates.sh. -The script relies on the PostgreSQL utility `psql` to access the -database. You will need to edit the credentials at the top of the script -to match your database configuration. - -If this issue is not present in your database, you will see a message -`... no duplicate dvObjects in your database. Your installation is -ready to be upgraded to Dataverse 4.20`. - -If duplicates are detected, it will provide further instructions. We -will need you to send us the produced output. We will then assist you -in resolving this problem in your database. - diff --git a/scripts/issues/6510/PRE-RELEASE-INFO.txt b/scripts/issues/6510/PRE-RELEASE-INFO.txt new file mode 100644 index 00000000000..d0440374def --- /dev/null +++ b/scripts/issues/6510/PRE-RELEASE-INFO.txt @@ -0,0 +1,24 @@ +We recently discovered that *potential* data integrity issues in +Dataverse databases. One manifests itself as duplicate DataFile +objects created for the same uploaded file; the other as duplicate +DataTable (tabular metadata) objects linked to the same +DataFile. (GitHub issues https://github.com/IQSS/dataverse/issues/6522 +and https://github.com/IQSS/dataverse/issues/6510 respectively). + +Please run the diagnostic script provided at +https://github.com/IQSS/dataverse/raw/6510-repeated-ingests/scripts/issues/6510/check_datafiles_6522_6510.sh +[NOTE!! the branch name must be changed to "develop" in the URL above before we merge!!] + +The script relies on the PostgreSQL utility psql to access the +database. You will need to edit the credentials at the top of the script +to match your database configuration. + +If neither of the two issues is present in your database, you will see +a message "... no duplicate DataFile objects in your database" and "no +tabular files affected by this issue in your database". + +If either, or both kinds of duplicates are detected, the script will +provide further instructions. We will need you to send us the produced +output. We will then assist you in resolving the issues in your +database. + From 4b0528b6566f03def8634ae478a41cbc872465c6 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 20 Feb 2020 15:23:22 -0500 Subject: [PATCH 312/475] fix merge issue --- doc/release-notes/6485-multiple-stores.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/release-notes/6485-multiple-stores.md b/doc/release-notes/6485-multiple-stores.md index ea2d224d612..e9c7e654d96 100644 --- a/doc/release-notes/6485-multiple-stores.md +++ b/doc/release-notes/6485-multiple-stores.md @@ -29,8 +29,4 @@ Any additional S3 options you have set will need to be replaced as well, followi Once these options are set, restarting the glassfish service is all that is needed to complete the change. -<<<<<<< HEAD Note that the "\-Ddataverse.files.directory", if defined, continues to control where temporary files are stored (in the /temp subdir of that directory), independent of the location of any 'file' store defined above. -======= -Note that the "\-Ddataverse.files.directory", if defined, continues to control where temporary files are stored (in the /temp subdir of that directory), independent of the location of any 'file' store defined above. ->>>>>>> branch 'IQSS/6485' of https://github.com/TexasDigitalLibrary/dataverse.git From 019862b11e4239c1c75b03d31aa080a8fda71392 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 20 Feb 2020 15:23:33 -0500 Subject: [PATCH 313/475] direct upload release notes --- doc/release-notes/6489-release-notes.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 doc/release-notes/6489-release-notes.md diff --git a/doc/release-notes/6489-release-notes.md b/doc/release-notes/6489-release-notes.md new file mode 100644 index 00000000000..3c21cd52bdb --- /dev/null +++ b/doc/release-notes/6489-release-notes.md @@ -0,0 +1,17 @@ +# S3 Direct Upload support + +S3 stores can now optionally be configured to support direct upload of files, as one option for supporting upload of larger files. + +General information about this capability can be found in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. + +**Upgrade Information:** + +Direct upload to S3 is enabled per store by one new jvm option: + + ./asadmin create-jvm-options "\-Ddataverse.files..upload-redirect=true" + +The existing :MaxFileUploadSizeInBytes property and dataverse.files..url-expiration-minutes jvm option for the same store also apply to direct upload. + +Direct upload via the Dataverse web interface is transparent to the user and handled automatically by the browser. Some minor differences in file upload exist: directly uploaded files are not unzipped and Dataverse does not scan their content to help in assigning a MIME type. Ingest of tabular files and metadata extraction from FITS files will occur, but can be turned off for files above a specified size limit through the new dataverse.files..ingestsizelimit jvm option. + +API calls to support direct upload also exist, and, if direct upload is enabled for a store in Dataverse, the latest DVUploader (v1.0.8) provides a'-directupload' flag that enables its use. \ No newline at end of file From f2748b7968371974d55acc6fc96edabc53261b2b Mon Sep 17 00:00:00 2001 From: Michael Heppler Date: Thu, 20 Feb 2020 16:26:06 -0500 Subject: [PATCH 314/475] Added text-muted styles to file path in Manage Restricted Files pg [ref #6587] --- .../webapp/permissions-manage-files.xhtml | 291 +++++++++--------- 1 file changed, 146 insertions(+), 145 deletions(-) diff --git a/src/main/webapp/permissions-manage-files.xhtml b/src/main/webapp/permissions-manage-files.xhtml index 3627d59ed56..1c7ef126b7c 100644 --- a/src/main/webapp/permissions-manage-files.xhtml +++ b/src/main/webapp/permissions-manage-files.xhtml @@ -41,102 +41,101 @@ -
- - #{bundle['dataverse.permissionsFiles.usersOrGroups.assignBtn']} - -
-
- - - -
-
- -

- #{manageFilePermissionsPage.fileAccessRequestMap.size()} #{bundle['dataverse.permissions.requests']} -

- - - - - - - - - - - - - - - - - - - - -
- - #{bundle['dataverse.permissionsFiles.assignDialog.grantBtn']} +
+ + #{bundle['dataverse.permissionsFiles.usersOrGroups.assignBtn']} + +
+
+ + + +
+
+ +

+ #{manageFilePermissionsPage.fileAccessRequestMap.size()} #{bundle['dataverse.permissions.requests']} +

+ + + + + + + + + + + + + + + + + + + +
+ + #{bundle['dataverse.permissionsFiles.assignDialog.grantBtn']} + + + #{bundle['dataverse.permissionsFiles.assignDialog.rejectBtn']} + +
+
+
+
+ +

+ #{manageFilePermissionsPage.roleAssigneeMap.size()} #{bundle['dataverse.permissions.usersOrGroups']} +

+ + + + + + + + + + + + + + - #{bundle['dataverse.permissionsFiles.assignDialog.rejectBtn']} + update=":#{p:resolveClientId('rolesPermissionsForm:userGroups', view)} :#{p:resolveClientId('rolesPermissionsForm:restrictedFiles', view)} @([id$=Messages])" + actionListener="#{manageFilePermissionsPage.showUserGroupMessages}" + onclick="PF('confirmation').show()"> + + #{bundle['dataverse.permissionsFiles.viewRemoveDialog.removeBtn']} -
- - - - -

- #{manageFilePermissionsPage.roleAssigneeMap.size()} #{bundle['dataverse.permissions.usersOrGroups']} -

- - - - - - - - - - - - - - - - - - #{bundle['dataverse.permissionsFiles.viewRemoveDialog.removeBtn']} - - - -
-
+
+
+
+
@@ -155,58 +154,58 @@ - -

- - - -

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #{bundle['dataverse.permissionsFiles.files.assignBtn']} - - + +
+ + + +
+

+ + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #{bundle['dataverse.permissionsFiles.files.assignBtn']} + +
@@ -239,6 +238,7 @@ + @@ -328,6 +328,7 @@ + From 61b24ee4833b386f9c24ea40f49e0941f1105f40 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 20 Feb 2020 17:19:33 -0500 Subject: [PATCH 315/475] #6587 fix refresh - default show deleted --- .../edu/harvard/iq/dataverse/ManageFilePermissionsPage.java | 2 +- src/main/webapp/permissions-manage-files.xhtml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java b/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java index 2d3762c7dd4..a9a8bbc4ff0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java @@ -84,7 +84,7 @@ public class ManageFilePermissionsPage implements java.io.Serializable { private final TreeMap> roleAssigneeMap = new TreeMap<>(); private final TreeMap> fileMap = new TreeMap<>(); private final TreeMap> fileAccessRequestMap = new TreeMap<>(); - private boolean showDeleted = false; + private boolean showDeleted = true; public boolean isShowDeleted() { return showDeleted; diff --git a/src/main/webapp/permissions-manage-files.xhtml b/src/main/webapp/permissions-manage-files.xhtml index 1c7ef126b7c..054f97aec80 100644 --- a/src/main/webapp/permissions-manage-files.xhtml +++ b/src/main/webapp/permissions-manage-files.xhtml @@ -44,7 +44,7 @@
#{bundle['dataverse.permissionsFiles.usersOrGroups.assignBtn']} @@ -202,7 +202,7 @@ #{bundle['dataverse.permissionsFiles.files.assignBtn']} From c682249ec89fba7130cfd8dfeac24bc0a03f8a50 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Fri, 21 Feb 2020 09:24:58 -0500 Subject: [PATCH 316/475] #6587 remove stray ; --- .../edu/harvard/iq/dataverse/ManageFilePermissionsPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java b/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java index a9a8bbc4ff0..82e1681b37d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/ManageFilePermissionsPage.java @@ -150,7 +150,7 @@ private void initMaps() { // we get the direct role assignments assigned to the file List ras = roleService.directRoleAssignments(file); List raList = new ArrayList<>(ras.size()); - for (RoleAssignment ra : ras) {; + for (RoleAssignment ra : ras) { // for files, only show role assignments which can download if (ra.getRole().permissions().contains(Permission.DownloadFile)) { raList.add(new RoleAssignmentRow(ra, roleAssigneeService.getRoleAssignee(ra.getAssigneeIdentifier(), true).getDisplayInfo(), fileIsDeleted)); From 634541ab26cd646e2f7c939303b72dcb1e86a446 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Fri, 21 Feb 2020 11:30:19 -0500 Subject: [PATCH 317/475] text edits --- .../6510-duplicate-datafiles-and-datatables.md | 12 +++++------- scripts/issues/6510/PRE-RELEASE-INFO.txt | 14 ++++++-------- scripts/issues/6510/check_datafiles_6522_6510.sh | 4 ++-- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/doc/release-notes/6510-duplicate-datafiles-and-datatables.md b/doc/release-notes/6510-duplicate-datafiles-and-datatables.md index d0440374def..6182bd97162 100644 --- a/doc/release-notes/6510-duplicate-datafiles-and-datatables.md +++ b/doc/release-notes/6510-duplicate-datafiles-and-datatables.md @@ -1,13 +1,12 @@ -We recently discovered that *potential* data integrity issues in +We recently discovered a *potential* data integrity issue in Dataverse databases. One manifests itself as duplicate DataFile -objects created for the same uploaded file; the other as duplicate +objects created for the same uploaded file (https://github.com/IQSS/dataverse/issues/6522); the other as duplicate DataTable (tabular metadata) objects linked to the same -DataFile. (GitHub issues https://github.com/IQSS/dataverse/issues/6522 -and https://github.com/IQSS/dataverse/issues/6510 respectively). +DataFile (https://github.com/IQSS/dataverse/issues/6510). This issue impacted approximately .0003% of datasets in Harvard's Dataverse. + +To see if any datasets in your installation have been impacted by this data integrity issue, we've provided a diagnostic script here: -Please run the diagnostic script provided at https://github.com/IQSS/dataverse/raw/6510-repeated-ingests/scripts/issues/6510/check_datafiles_6522_6510.sh -[NOTE!! the branch name must be changed to "develop" in the URL above before we merge!!] The script relies on the PostgreSQL utility psql to access the database. You will need to edit the credentials at the top of the script @@ -21,4 +20,3 @@ If either, or both kinds of duplicates are detected, the script will provide further instructions. We will need you to send us the produced output. We will then assist you in resolving the issues in your database. - diff --git a/scripts/issues/6510/PRE-RELEASE-INFO.txt b/scripts/issues/6510/PRE-RELEASE-INFO.txt index d0440374def..2af6887571b 100644 --- a/scripts/issues/6510/PRE-RELEASE-INFO.txt +++ b/scripts/issues/6510/PRE-RELEASE-INFO.txt @@ -1,13 +1,12 @@ -We recently discovered that *potential* data integrity issues in +We recently discovered a *potential* data integrity issue in Dataverse databases. One manifests itself as duplicate DataFile -objects created for the same uploaded file; the other as duplicate +objects created for the same uploaded file (https://github.com/IQSS/dataverse/issues/6522); the other as duplicate DataTable (tabular metadata) objects linked to the same -DataFile. (GitHub issues https://github.com/IQSS/dataverse/issues/6522 -and https://github.com/IQSS/dataverse/issues/6510 respectively). +DataFile (https://github.com/IQSS/dataverse/issues/6510). This issue impacted approximately .03% of datasets in Harvard's Dataverse. + +To see if any datasets in your installation have been impacted by this data integrity issue, we've provided a diagnostic script here: -Please run the diagnostic script provided at https://github.com/IQSS/dataverse/raw/6510-repeated-ingests/scripts/issues/6510/check_datafiles_6522_6510.sh -[NOTE!! the branch name must be changed to "develop" in the URL above before we merge!!] The script relies on the PostgreSQL utility psql to access the database. You will need to edit the credentials at the top of the script @@ -19,6 +18,5 @@ tabular files affected by this issue in your database". If either, or both kinds of duplicates are detected, the script will provide further instructions. We will need you to send us the produced -output. We will then assist you in resolving the issues in your +output to support@dataverse.org and we will assist you in resolving the issues in your database. - diff --git a/scripts/issues/6510/check_datafiles_6522_6510.sh b/scripts/issues/6510/check_datafiles_6522_6510.sh index 2cb873e92e1..ce6e5db5b59 100755 --- a/scripts/issues/6510/check_datafiles_6522_6510.sh +++ b/scripts/issues/6510/check_datafiles_6522_6510.sh @@ -72,7 +72,7 @@ else echo "(output saved in /tmp/duplicates_info.tmp)" echo - echo "Please send the output above to Dataverse support." + echo "Please send the output above to Dataverse support at support@dataverse.org." echo "We will assist you in the process of cleaning up the affected files above." echo "We apologize for any inconvenience." echo @@ -125,7 +125,7 @@ done | tee /tmp/multiple_ingests_info.tmp echo "(output saved in /tmp/multiple_ingests_info.tmp)" echo -echo "Please send the output above to Dataverse support." +echo "Please send the output above to Dataverse support at support@dataverse.org." echo "We will assist you in fixing this issue in your Dataverse database." echo "We apologize for any inconvenience." echo From ca3cd6e3434beea4295111ea2278d87530490b7d Mon Sep 17 00:00:00 2001 From: Peter Kiraly Date: Fri, 21 Feb 2020 18:33:38 +0100 Subject: [PATCH 318/475] #6083 update examples in File part of Native API: 'Updating File Metadata' section. --- doc/sphinx-guides/source/api/native-api.rst | 42 +++++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index aefe5c66a41..f08c776ffb2 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1970,13 +1970,47 @@ Note: The ``id`` returned in the json response is the id of the file metadata ve Updating File Metadata ~~~~~~~~~~~~~~~~~~~~~~ -Updates the file metadata for an existing file where ``id`` is the database id of the file to replace or ``pid`` is the persistent id (DOI or Handle) of the file. Requires a ``jsonString`` expressing the new metadata. No metadata from the previous version of this file will be persisted, so if you want to update a specific field first get the json with the above command and alter the fields you want:: +Updates the file metadata for an existing file where ``ID`` is the database id of the file to update or ``PERSISTENT_ID`` is the persistent id (DOI or Handle) of the file. Requires a ``jsonString`` expressing the new metadata. No metadata from the previous version of this file will be persisted, so if you want to update a specific field first get the json with the above command and alter the fields you want. - POST -F 'jsonData={json}' http://$SERVER/api/files/{id}/metadata?key={apiKey} +A curl example using an ``ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=24 -Example:: + curl -H "X-Dataverse-key:$API_TOKEN" -X POST \ + -F 'jsonData={"description":"My description bbb.","provFreeform":"Test prov freeform","categories":["Data"],"restrict":false}' \ + $SERVER_URL/api/files/$ID/metadata + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \ + -F 'jsonData={"description":"My description bbb.","provFreeform":"Test prov freeform","categories":["Data"],"restrict":false}' \ + http://demo.dataverse.org/api/files/24/metadata + +A curl example using a ``PERSISTENT_ID`` - curl -H "X-Dataverse-key:{apiKey}" -X POST -F 'jsonData={"description":"My description bbb.","provFreeform":"Test prov freeform","categories":["Data"],"restrict":false}' 'http://localhost:8080/api/files/264/metadata' +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export PERSISTENT_ID=doi:10.5072/FK2/AAA000 + + curl -H "X-Dataverse-key:$API_TOKEN" -X POST \ + -F 'jsonData={"description":"My description bbb.","provFreeform":"Test prov freeform","categories":["Data"],"restrict":false}' \ + "$SERVER_URL/api/files/:persistentId/metadata?persistentId=$PERSISTENT_ID" + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \ + -F 'jsonData={"description":"My description bbb.","provFreeform":"Test prov freeform","categories":["Data"],"restrict":false}' \ + "https://demo.dataverse.org/api/files/:persistentId/metadata?persistentId=doi:10.5072/FK2/AAA000" Also note that dataFileTags are not versioned and changes to these will update the published version of the file. From eed01cf8b67a6c6a487343d9e718e71841b67d0d Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Fri, 21 Feb 2020 12:47:29 -0500 Subject: [PATCH 319/475] changed sh -> bash. (#6510) --- scripts/issues/6510/check_datafiles_6522_6510.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/issues/6510/check_datafiles_6522_6510.sh b/scripts/issues/6510/check_datafiles_6522_6510.sh index ce6e5db5b59..15bc7e80b5a 100755 --- a/scripts/issues/6510/check_datafiles_6522_6510.sh +++ b/scripts/issues/6510/check_datafiles_6522_6510.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # begin config # PostgresQL credentials: From 3e791d6a0e2a53f0c3b1a37c4809c4e1ecd0e020 Mon Sep 17 00:00:00 2001 From: Peter Kiraly Date: Fri, 21 Feb 2020 18:49:33 +0100 Subject: [PATCH 320/475] #6083 update examples in File part of Native API: 'Editing Variable Level Metadata' section. --- doc/sphinx-guides/source/api/native-api.rst | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index aefe5c66a41..dd33f686628 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1985,11 +1985,24 @@ Also note that dataFileTags are not versioned and changes to these will update t Editing Variable Level Metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Updates variable level metadata using ddi xml ``$file``, where ``$id`` is file id:: +Updates variable level metadata using ddi xml ``FILE``, where ``ID`` is file id. - PUT https://$SERVER/api/edit/$id --upload-file $file +A curl example using an ``ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=24 + export FILE=dct.xml + + curl -H "X-Dataverse-key:$API_TOKEN" -X PUT $SERVER_URL/api/edit/$ID --upload-file $FILE + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash -Example: ``curl -H "X-Dataverse-key:$API_TOKEN" -X PUT http://localhost:8080/api/edit/95 --upload-file dct.xml`` + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X PUT https://demo.dataverse.org/api/edit/24 --upload-file dct.xml You can download :download:`dct.xml <../../../../src/test/resources/xml/dct.xml>` from the example above to see what the XML looks like. From f33a06368c31fe26e361e0186c85d95e291406ae Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Fri, 21 Feb 2020 13:16:38 -0500 Subject: [PATCH 321/475] updating to develop pre-merge --- doc/release-notes/6510-duplicate-datafiles-and-datatables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/6510-duplicate-datafiles-and-datatables.md b/doc/release-notes/6510-duplicate-datafiles-and-datatables.md index 6182bd97162..680635f7e17 100644 --- a/doc/release-notes/6510-duplicate-datafiles-and-datatables.md +++ b/doc/release-notes/6510-duplicate-datafiles-and-datatables.md @@ -6,7 +6,7 @@ DataFile (https://github.com/IQSS/dataverse/issues/6510). This issue impacted ap To see if any datasets in your installation have been impacted by this data integrity issue, we've provided a diagnostic script here: -https://github.com/IQSS/dataverse/raw/6510-repeated-ingests/scripts/issues/6510/check_datafiles_6522_6510.sh +https://github.com/IQSS/dataverse/raw/develop/scripts/issues/6510/check_datafiles_6522_6510.sh The script relies on the PostgreSQL utility psql to access the database. You will need to edit the credentials at the top of the script From 9e3e8cf77e428b2922741eccb4c6a33c2ab47dfd Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Fri, 21 Feb 2020 13:17:31 -0500 Subject: [PATCH 322/475] update to develop pre-merge --- scripts/issues/6510/PRE-RELEASE-INFO.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/issues/6510/PRE-RELEASE-INFO.txt b/scripts/issues/6510/PRE-RELEASE-INFO.txt index 2af6887571b..7b71581eb8f 100644 --- a/scripts/issues/6510/PRE-RELEASE-INFO.txt +++ b/scripts/issues/6510/PRE-RELEASE-INFO.txt @@ -6,7 +6,7 @@ DataFile (https://github.com/IQSS/dataverse/issues/6510). This issue impacted ap To see if any datasets in your installation have been impacted by this data integrity issue, we've provided a diagnostic script here: -https://github.com/IQSS/dataverse/raw/6510-repeated-ingests/scripts/issues/6510/check_datafiles_6522_6510.sh +https://github.com/IQSS/dataverse/raw/develop/scripts/issues/6510/check_datafiles_6522_6510.sh The script relies on the PostgreSQL utility psql to access the database. You will need to edit the credentials at the top of the script From b710561b4b3ef1bce0b6fffc9867f59f46b7407d Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Fri, 21 Feb 2020 13:29:18 -0500 Subject: [PATCH 323/475] Correcting my incorrect math --- doc/release-notes/6510-duplicate-datafiles-and-datatables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/6510-duplicate-datafiles-and-datatables.md b/doc/release-notes/6510-duplicate-datafiles-and-datatables.md index 680635f7e17..18ac58860d8 100644 --- a/doc/release-notes/6510-duplicate-datafiles-and-datatables.md +++ b/doc/release-notes/6510-duplicate-datafiles-and-datatables.md @@ -2,7 +2,7 @@ We recently discovered a *potential* data integrity issue in Dataverse databases. One manifests itself as duplicate DataFile objects created for the same uploaded file (https://github.com/IQSS/dataverse/issues/6522); the other as duplicate DataTable (tabular metadata) objects linked to the same -DataFile (https://github.com/IQSS/dataverse/issues/6510). This issue impacted approximately .0003% of datasets in Harvard's Dataverse. +DataFile (https://github.com/IQSS/dataverse/issues/6510). This issue impacted approximately .03% of datasets in Harvard's Dataverse. To see if any datasets in your installation have been impacted by this data integrity issue, we've provided a diagnostic script here: From 9b98584c16ce3e0c2212ce0e274e262dfce9b880 Mon Sep 17 00:00:00 2001 From: Victoria Lubitch Date: Fri, 21 Feb 2020 14:18:04 -0500 Subject: [PATCH 324/475] export import ddi --- .../api/imports/ImportDDIServiceBean.java | 58 +- .../dataverse/export/ddi/DdiExportUtil.java | 49 +- .../harvard/iq/dataverse/api/DatasetsIT.java | 10 +- .../export/ddi/DdiExportUtilTest.java | 10 +- .../dataset-create-new-all-ddi-fields.json | 983 ++++++++++++++++++ .../iq/dataverse/export/ddi/exportfull.xml | 156 +++ 6 files changed, 1199 insertions(+), 67 deletions(-) create mode 100644 src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-create-new-all-ddi-fields.json create mode 100644 src/test/java/edu/harvard/iq/dataverse/export/ddi/exportfull.xml diff --git a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java index 3617e561837..528070c31d6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java @@ -27,6 +27,8 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLInputFactory; + +import edu.harvard.iq.dataverse.util.json.ControlledVocabularyException; import org.apache.commons.lang.StringUtils; /** @@ -344,7 +346,8 @@ private void processStdyDscr(ImportType importType, XMLStreamReader xmlr, Datase else if (xmlr.getLocalName().equals("stdyInfo")) processStdyInfo(xmlr, datasetDTO.getDatasetVersion()); else if (xmlr.getLocalName().equals("method")) processMethod(xmlr, datasetDTO.getDatasetVersion()); - else if (xmlr.getLocalName().equals("dataAccs")) processDataAccs(xmlr, datasetDTO.getDatasetVersion()); + else if (xmlr.getLocalName().equals("dataAccs")) processDataAccs(xmlr, datasetDTO.getDatasetVersion()); + else if (xmlr.getLocalName().equals("notes")) processStdyNotes(xmlr, datasetDTO.getDatasetVersion()); else if (xmlr.getLocalName().equals("othrStdyMat")) processOthrStdyMat(xmlr, datasetDTO.getDatasetVersion()); else if (xmlr.getLocalName().equals("notes")) processNotes(xmlr, datasetDTO.getDatasetVersion()); @@ -620,6 +623,16 @@ private void processNotes (XMLStreamReader xmlr, DatasetVersionDTO dvDTO) throws this.addNote(formattedNotes, dvDTO); } } + private void processStdyNotes(XMLStreamReader xmlr, DatasetVersionDTO dvDTO) throws XMLStreamException { + FieldDTO notesText = null; + // Add notes, if they exist + String attrVal = parseText(xmlr, "notes"); + if ((attrVal != null) && (!attrVal.isEmpty())){ + notesText = FieldDTO.createPrimitiveFieldDTO("datasetLevelErrorNotes", attrVal); + getSocialScience(dvDTO).addField(notesText); + } + } + private void processNotesSocialScience(XMLStreamReader xmlr, DatasetVersionDTO dvDTO) throws XMLStreamException { //String formattedNotes = this.formatNotesfromXML(xmlr); @@ -683,7 +696,10 @@ private void processSumDscr(XMLStreamReader xmlr, DatasetVersionDTO dvDTO) throw FieldDTO dateOfCollectionStart = null; FieldDTO dateOfCollectionEnd = null; + HashSet geoCoverageSet = null; + String otherGeographicCoverage = null; for (int event = xmlr.next(); event != XMLStreamConstants.END_DOCUMENT; event = xmlr.next()) { + if (event == XMLStreamConstants.START_ELEMENT) { if (xmlr.getLocalName().equals("timePrd")) { @@ -705,13 +721,28 @@ private void processSumDscr(XMLStreamReader xmlr, DatasetVersionDTO dvDTO) throw } } else if (xmlr.getLocalName().equals("nation")) { - HashSet set = new HashSet<>(); - set.add(FieldDTO.createVocabFieldDTO("country", parseText(xmlr))); - geoCoverages.add(set); + if (otherGeographicCoverage != null && !otherGeographicCoverage.equals("")) { + geoCoverageSet.add(FieldDTO.createPrimitiveFieldDTO("otherGeographicCoverage", otherGeographicCoverage)); + otherGeographicCoverage = null; + } + if (geoCoverageSet != null && geoCoverageSet.size() > 0) { + geoCoverages.add(geoCoverageSet); + } + geoCoverageSet = new HashSet<>(); + //HashSet set = new HashSet<>(); + //set.add(FieldDTO.createVocabFieldDTO("country", parseText(xmlr))); + geoCoverageSet.add(FieldDTO.createVocabFieldDTO("country", parseText(xmlr))); + } else if (xmlr.getLocalName().equals("geogCover")) { - HashSet set = new HashSet<>(); - set.add(FieldDTO.createPrimitiveFieldDTO("otherGeographicCoverage", parseText(xmlr))); - geoCoverages.add(set); + if (geoCoverageSet == null) { + geoCoverageSet = new HashSet<>(); + } + if (otherGeographicCoverage != null) { + otherGeographicCoverage = otherGeographicCoverage + "; " + parseText(xmlr); + } else { + otherGeographicCoverage = parseText(xmlr); + } + } else if (xmlr.getLocalName().equals("geogUnit")) { geoUnit.add(parseText(xmlr)); } else if (xmlr.getLocalName().equals("geoBndBox")) { @@ -744,8 +775,15 @@ private void processSumDscr(XMLStreamReader xmlr, DatasetVersionDTO dvDTO) throw if (kindOfData.size() > 0) { getCitation(dvDTO).addField(FieldDTO.createMultiplePrimitiveFieldDTO("kindOfData", kindOfData)); } - if (geoCoverages.size()>0) { - getGeospatial(dvDTO).addField(FieldDTO.createMultipleCompoundFieldDTO("geographicCoverage", geoCoverages)); + if (otherGeographicCoverage != null && !otherGeographicCoverage.equals("") ) { + geoCoverageSet.add(FieldDTO.createPrimitiveFieldDTO("otherGeographicCoverage", otherGeographicCoverage)); + } + if (geoCoverageSet != null && geoCoverageSet.size() > 0) { + //FieldDTO geoCoverageDTO = FieldDTO.createMultipleCompoundFieldDTO(DatasetFieldConstant.geographicCoverage, geoCoverageList); + geoCoverages.add(geoCoverageSet); + } + if (geoCoverages.size() > 0) { + getGeospatial(dvDTO).addField(FieldDTO.createMultipleCompoundFieldDTO(DatasetFieldConstant.geographicCoverage, geoCoverages)); } if (geoBoundBox.size()>0) { getGeospatial(dvDTO).addField(FieldDTO.createMultipleCompoundFieldDTO("geographicBoundingBox", geoBoundBox)); @@ -756,8 +794,6 @@ private void processSumDscr(XMLStreamReader xmlr, DatasetVersionDTO dvDTO) throw } } - - private HashSet processGeoBndBox(XMLStreamReader xmlr) throws XMLStreamException { HashSet set = new HashSet<>(); diff --git a/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java b/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java index fe61f201466..db019d5a39a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java @@ -221,48 +221,7 @@ private static void createStdyDscr(XMLStreamWriter xmlw, DatasetDTO datasetDto) writeDataAccess(xmlw , version); writeOtherStudyMaterial(xmlw , version); - /* - writeRelPublElement(xmlw, version); - - writeOtherIdElement(xmlw, version); - writeDistributorsElement(xmlw, version); - writeContactsElement(xmlw, version); - writeFullElement(xmlw, "depositr", dto2Primitive(version, DatasetFieldConstant.depositor)); - writeFullElement(xmlw, "depDate", dto2Primitive(version, DatasetFieldConstant.dateOfDeposit)); - - writeFullElementList(xmlw, "relMat", dto2PrimitiveList(version, DatasetFieldConstant.relatedMaterial)); - writeFullElementList(xmlw, "relStdy", dto2PrimitiveList(version, DatasetFieldConstant.relatedDatasets)); - writeFullElementList(xmlw, "othRefs", dto2PrimitiveList(version, DatasetFieldConstant.otherReferences)); - writeSeriesElement(xmlw, version); - writeSoftwareElement(xmlw, version); - writeFullElementList(xmlw, "dataSrc", dto2PrimitiveList(version, DatasetFieldConstant.dataSources)); - writeFullElement(xmlw, "srcOrig", dto2Primitive(version, DatasetFieldConstant.originOfSources)); - writeFullElement(xmlw, "srcChar", dto2Primitive(version, DatasetFieldConstant.characteristicOfSources)); - writeFullElement(xmlw, "srcDocu", dto2Primitive(version, DatasetFieldConstant.accessToSources)); - xmlw.writeEndElement(); // stdyInfo - // End Info Block - - //Social Science Metadata block - - writeMethodElement(xmlw, version); - - //Terms of Use and Access - writeFullElement(xmlw, "useStmt", version.getTermsOfUse()); - writeFullElement(xmlw, "confDec", version.getConfidentialityDeclaration()); - writeFullElement(xmlw, "specPerm", version.getSpecialPermissions()); - writeFullElement(xmlw, "restrctn", version.getRestrictions()); - writeFullElement(xmlw, "citeReq", version.getCitationRequirements()); - writeFullElement(xmlw, "deposReq", version.getDepositorRequirements()); - writeFullElement(xmlw, "dataAccs", version.getTermsOfAccess()); - writeFullElement(xmlw, "accsPlac", version.getDataAccessPlace()); - writeFullElement(xmlw, "conditions", version.getConditions()); - writeFullElement(xmlw, "disclaimer", version.getDisclaimer()); - writeFullElement(xmlw, "origArch", version.getOriginalArchive()); - writeFullElement(xmlw, "avlStatus", version.getAvailabilityStatus()); - writeFullElement(xmlw, "contact", version.getContactForAccess()); - writeFullElement(xmlw, "collSize", version.getSizeOfCollection()); - writeFullElement(xmlw, "complete", version.getStudyCompletion()); - */ + writeFullElement(xmlw, "notes", dto2Primitive(version, DatasetFieldConstant.datasetLevelErrorNotes)); xmlw.writeEndElement(); // stdyDscr @@ -430,21 +389,18 @@ private static void writeSummaryDescriptionElement(XMLStreamWriter xmlw, Dataset FieldDTO next = iterator.next(); if (DatasetFieldConstant.country.equals(next.getTypeName())) { geoMap.put("country", next.getSinglePrimitive()); - //writeFullElement(xmlw, "nation", next.getSinglePrimitive()); } if (DatasetFieldConstant.city.equals(next.getTypeName())) { geoMap.put("city", next.getSinglePrimitive()); - //writeFullElement(xmlw, "geogCover", next.getSinglePrimitive()); } if (DatasetFieldConstant.state.equals(next.getTypeName())) { geoMap.put("state", next.getSinglePrimitive()); - //writeFullElement(xmlw, "geogCover", next.getSinglePrimitive()); } if (DatasetFieldConstant.otherGeographicCoverage.equals(next.getTypeName())) { geoMap.put("otherGeographicCoverage", next.getSinglePrimitive()); - //writeFullElement(xmlw, "geogCover", next.getSinglePrimitive()); } } + if (geoMap.get("country") != null) { writeFullElement(xmlw, "nation", geoMap.get("country")); } @@ -457,6 +413,7 @@ private static void writeSummaryDescriptionElement(XMLStreamWriter xmlw, Dataset if (geoMap.get("otherGeographicCoverage") != null) { writeFullElement(xmlw, "geogCover", geoMap.get("otherGeographicCoverage")); } + } } if (DatasetFieldConstant.geographicBoundingBox.equals(fieldDTO.getTypeName())) { diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java index 51d3a214d5d..713fb770cb0 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -446,9 +446,9 @@ public void testCreatePublishDestroyDataset() { */ boolean nameRequiredForContactToAppear = true; if (nameRequiredForContactToAppear) { - assertEquals("Finch, Fiona", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.stdyInfo.contact")); + assertEquals("Finch, Fiona", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.citation.distStmt.contact")); } else { - assertEquals("finch@mailinator.com", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.stdyInfo.contact.@email")); + assertEquals("finch@mailinator.com", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.citation.distStmt.contact.@email")); } assertEquals(datasetPersistentId, XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.docDscr.citation.titlStmt.IDNo")); @@ -659,10 +659,10 @@ public void testExcludeEmail() { exportDatasetAsDdi.then().assertThat() .statusCode(OK.getStatusCode()); - assertEquals("Dataverse, Admin", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.stdyInfo.contact")); + assertEquals("Dataverse, Admin", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.citation.distStmt.contact")); // no "sammi@sample.com" to be found https://github.com/IQSS/dataverse/issues/3443 - assertEquals("[]", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.stdyInfo.contact.@email")); - assertEquals("Sample Datasets, inc.", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.stdyInfo.contact.@affiliation")); + assertEquals("[]", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.citation.distStmt.contact.@email")); + assertEquals("Sample Datasets, inc.", XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.stdyDscr.citation.distStmt.contact.@affiliation")); assertEquals(datasetPersistentId, XmlPath.from(exportDatasetAsDdi.body().asString()).getString("codeBook.docDscr.citation.titlStmt.IDNo")); List datasetContactsFromNativeGet = with(getDatasetJsonAfterPublishing.body().asString()).param("datasetContact", "datasetContact") diff --git a/src/test/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtilTest.java index 09be153b647..a76ce8475f2 100644 --- a/src/test/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtilTest.java @@ -35,17 +35,17 @@ public void testJson2DdiNoFiles() throws Exception { assertEquals(datasetAsDdi, result); } - /* @Test - public void testJson2DdiNoFiles2() throws Exception { - File datasetVersionJson = new File("dataset.json"); + @Test + public void testExportDDI() throws Exception { + File datasetVersionJson = new File("src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-create-new-all-ddi-fields.json"); String datasetVersionAsJson = new String(Files.readAllBytes(Paths.get(datasetVersionJson.getAbsolutePath()))); - File ddiFile = new File("exportfull.xml"); + File ddiFile = new File("src/test/java/edu/harvard/iq/dataverse/export/ddi/exportfull.xml"); String datasetAsDdi = XmlPrinter.prettyPrintXml(new String(Files.readAllBytes(Paths.get(ddiFile.getAbsolutePath())))); logger.info(datasetAsDdi); String result = DdiExportUtil.datasetDtoAsJson2ddi(datasetVersionAsJson); logger.info(result); assertEquals(datasetAsDdi, result); - }*/ + } @Test public void testJson2ddiHasFiles() throws Exception { diff --git a/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-create-new-all-ddi-fields.json b/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-create-new-all-ddi-fields.json new file mode 100644 index 00000000000..31d43eb5377 --- /dev/null +++ b/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-create-new-all-ddi-fields.json @@ -0,0 +1,983 @@ +{ + "id": 11, + "identifier": "WKUKGV", + "persistentUrl": "https://doi.org/10.5072/FK2/WKUKGV", + "protocol": "doi", + "authority": "10.5072/FK2", + "publisher": "Root", + "publicationDate": "2020-02-19", + "datasetVersion": { + "id": 2, + "versionNumber": 1, + "versionMinorNumber": 0, + "versionState": "RELEASED", + "productionDate": "Production Date", + "lastUpdateTime": "2015-09-24T17:07:57Z", + "releaseTime": "2020-02-19", + "createTime": "2015-09-24T16:47:51Z", + "license": "CC0", + "termsOfUse": "CC0 Waiver", + "metadataBlocks": { + "citation": { + "displayName": "Citation Metadata", + "fields": [ + { + "typeName": "title", + "multiple": false, + "typeClass": "primitive", + "value": "Replication Data for: Title" + }, + { + "typeName": "subtitle", + "multiple": false, + "typeClass": "primitive", + "value": "Subtitle" + }, + { + "typeName": "alternativeTitle", + "multiple": false, + "typeClass": "primitive", + "value": "Alternative Title" + }, + { + "typeName": "author", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "authorName": { + "typeName": "authorName", + "multiple": false, + "typeClass": "primitive", + "value": "LastAuthor1, FirstAuthor1" + }, + "authorAffiliation": { + "typeName": "authorAffiliation", + "multiple": false, + "typeClass": "primitive", + "value": "AuthorAffiliation1" + } + }, + { + "authorName": { + "typeName": "authorName", + "multiple": false, + "typeClass": "primitive", + "value": "LastAuthor2, FirstAuthor2" + }, + "authorAffiliation": { + "typeName": "authorAffiliation", + "multiple": false, + "typeClass": "primitive", + "value": "AuthorAffiliation2" + } + } + ] + }, + { + "typeName": "datasetContact", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "datasetContactName": { + "typeName": "datasetContactName", + "multiple": false, + "typeClass": "primitive", + "value": "LastContact1, FirstContact1" + }, + "datasetContactAffiliation": { + "typeName": "datasetContactAffiliation", + "multiple": false, + "typeClass": "primitive", + "value": "ContactAffiliation1" + }, + "datasetContactEmail": { + "typeName": "datasetContactEmail", + "multiple": false, + "typeClass": "primitive", + "value": "ContactEmail1@mailinator.com" + } + }, + { + "datasetContactName": { + "typeName": "datasetContactName", + "multiple": false, + "typeClass": "primitive", + "value": "LastContact2, FirstContact2" + }, + "datasetContactAffiliation": { + "typeName": "datasetContactAffiliation", + "multiple": false, + "typeClass": "primitive", + "value": "ContactAffiliation2" + }, + "datasetContactEmail": { + "typeName": "datasetContactEmail", + "multiple": false, + "typeClass": "primitive", + "value": "ContactEmail2@mailinator.com" + } + } + ] + }, + { + "typeName": "dsDescription", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "dsDescriptionValue": { + "typeName": "dsDescriptionValue", + "multiple": false, + "typeClass": "primitive", + "value": "DescriptionText 1" + }, + "dsDescriptionDate": { + "typeName": "dsDescriptionDate", + "multiple": false, + "typeClass": "primitive", + "value": "1000-01-01" + } + }, + { + "dsDescriptionValue": { + "typeName": "dsDescriptionValue", + "multiple": false, + "typeClass": "primitive", + "value": "DescriptionText2" + }, + "dsDescriptionDate": { + "typeName": "dsDescriptionDate", + "multiple": false, + "typeClass": "primitive", + "value": "1000-02-02" + } + } + ] + }, + { + "typeName": "subject", + "multiple": true, + "typeClass": "controlledVocabulary", + "value": [ + "Agricultural Sciences", + "Business and Management", + "Engineering", + "Law" + ] + }, + { + "typeName": "keyword", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "keywordValue": { + "typeName": "keywordValue", + "multiple": false, + "typeClass": "primitive", + "value": "KeywordTerm1" + }, + "keywordVocabulary": { + "typeName": "keywordVocabulary", + "multiple": false, + "typeClass": "primitive", + "value": "KeywordVocabulary1" + }, + "keywordVocabularyURI": { + "typeName": "keywordVocabularyURI", + "multiple": false, + "typeClass": "primitive", + "value": "http://KeywordVocabularyURL1.org" + } + }, + { + "keywordValue": { + "typeName": "keywordValue", + "multiple": false, + "typeClass": "primitive", + "value": "KeywordTerm2" + }, + "keywordVocabulary": { + "typeName": "keywordVocabulary", + "multiple": false, + "typeClass": "primitive", + "value": "KeywordVocabulary2" + }, + "keywordVocabularyURI": { + "typeName": "keywordVocabularyURI", + "multiple": false, + "typeClass": "primitive", + "value": "http://KeywordVocabularyURL2.org" + } + } + ] + }, + { + "typeName": "publication", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "publicationCitation": { + "typeName": "publicationCitation", + "multiple": false, + "typeClass": "primitive", + "value": "RelatedPublicationCitation1" + }, + "publicationIDType": { + "typeName": "publicationIDType", + "multiple": false, + "typeClass": "controlledVocabulary", + "value": "ark" + }, + "publicationIDNumber": { + "typeName": "publicationIDNumber", + "multiple": false, + "typeClass": "primitive", + "value": "RelatedPublicationIDNumber1" + }, + "publicationURL": { + "typeName": "publicationURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://RelatedPublicationURL1.org" + } + }, + { + "publicationCitation": { + "typeName": "publicationCitation", + "multiple": false, + "typeClass": "primitive", + "value": "RelatedPublicationCitation2" + }, + "publicationIDType": { + "typeName": "publicationIDType", + "multiple": false, + "typeClass": "controlledVocabulary", + "value": "arXiv" + }, + "publicationIDNumber": { + "typeName": "publicationIDNumber", + "multiple": false, + "typeClass": "primitive", + "value": "RelatedPublicationIDNumber2" + }, + "publicationURL": { + "typeName": "publicationURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://RelatedPublicationURL2.org" + } + } + ] + }, + { + "typeName": "notesText", + "multiple": false, + "typeClass": "primitive", + "value": "Notes1" + }, + { + "typeName": "producer", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "producerName": { + "typeName": "producerName", + "multiple": false, + "typeClass": "primitive", + "value": "LastProducer1, FirstProducer1" + }, + "producerAffiliation": { + "typeName": "producerAffiliation", + "multiple": false, + "typeClass": "primitive", + "value": "ProducerAffiliation1" + }, + "producerAbbreviation": { + "typeName": "producerAbbreviation", + "multiple": false, + "typeClass": "primitive", + "value": "ProducerAbbreviation1" + }, + "producerURL": { + "typeName": "producerURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://ProducerURL1.org" + }, + "producerLogoURL": { + "typeName": "producerLogoURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://ProducerLogoURL1.org" + } + }, + { + "producerName": { + "typeName": "producerName", + "multiple": false, + "typeClass": "primitive", + "value": "LastProducer2, FirstProducer2" + }, + "producerAffiliation": { + "typeName": "producerAffiliation", + "multiple": false, + "typeClass": "primitive", + "value": "ProducerAffiliation2" + }, + "producerAbbreviation": { + "typeName": "producerAbbreviation", + "multiple": false, + "typeClass": "primitive", + "value": "ProducerAbbreviation2" + }, + "producerURL": { + "typeName": "producerURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://ProducerURL2.org" + }, + "producerLogoURL": { + "typeName": "producerLogoURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://ProducerLogoURL2.org" + } + } + ] + }, + { + "typeName": "productionDate", + "multiple": false, + "typeClass": "primitive", + "value": "1003-01-01" + }, + { + "typeName": "productionPlace", + "multiple": false, + "typeClass": "primitive", + "value": "ProductionPlace" + }, + { + "typeName": "grantNumber", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "grantNumberAgency": { + "typeName": "grantNumberAgency", + "multiple": false, + "typeClass": "primitive", + "value": "GrantInformationGrantAgency1" + }, + "grantNumberValue": { + "typeName": "grantNumberValue", + "multiple": false, + "typeClass": "primitive", + "value": "GrantInformationGrantNumber1" + } + }, + { + "grantNumberAgency": { + "typeName": "grantNumberAgency", + "multiple": false, + "typeClass": "primitive", + "value": "GrantInformationGrantAgency2" + }, + "grantNumberValue": { + "typeName": "grantNumberValue", + "multiple": false, + "typeClass": "primitive", + "value": "GrantInformationGrantNumber2" + } + } + ] + }, + { + "typeName": "distributor", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "distributorName": { + "typeName": "distributorName", + "multiple": false, + "typeClass": "primitive", + "value": "LastDistributor1, FirstDistributor1" + }, + "distributorAffiliation": { + "typeName": "distributorAffiliation", + "multiple": false, + "typeClass": "primitive", + "value": "DistributorAffiliation1" + }, + "distributorAbbreviation": { + "typeName": "distributorAbbreviation", + "multiple": false, + "typeClass": "primitive", + "value": "DistributorAbbreviation1" + }, + "distributorURL": { + "typeName": "distributorURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://DistributorURL1.org" + }, + "distributorLogoURL": { + "typeName": "distributorLogoURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://DistributorLogoURL1.org" + } + }, + { + "distributorName": { + "typeName": "distributorName", + "multiple": false, + "typeClass": "primitive", + "value": "LastDistributor2, FirstDistributor2" + }, + "distributorAffiliation": { + "typeName": "distributorAffiliation", + "multiple": false, + "typeClass": "primitive", + "value": "DistributorAffiliation2" + }, + "distributorAbbreviation": { + "typeName": "distributorAbbreviation", + "multiple": false, + "typeClass": "primitive", + "value": "DistributorAbbreviation2" + }, + "distributorURL": { + "typeName": "distributorURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://DistributorURL2.org" + }, + "distributorLogoURL": { + "typeName": "distributorLogoURL", + "multiple": false, + "typeClass": "primitive", + "value": "http://DistributorLogoURL2.org" + } + } + ] + }, + { + "typeName": "distributionDate", + "multiple": false, + "typeClass": "primitive", + "value": "1004-01-01" + }, + { + "typeName": "depositor", + "multiple": false, + "typeClass": "primitive", + "value": "LastDepositor, FirstDepositor" + }, + { + "typeName": "dateOfDeposit", + "multiple": false, + "typeClass": "primitive", + "value": "1002-01-01" + }, + { + "typeName": "timePeriodCovered", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "timePeriodCoveredStart": { + "typeName": "timePeriodCoveredStart", + "multiple": false, + "typeClass": "primitive", + "value": "1005-01-01" + }, + "timePeriodCoveredEnd": { + "typeName": "timePeriodCoveredEnd", + "multiple": false, + "typeClass": "primitive", + "value": "1005-01-02" + } + }, + { + "timePeriodCoveredStart": { + "typeName": "timePeriodCoveredStart", + "multiple": false, + "typeClass": "primitive", + "value": "1005-02-01" + }, + "timePeriodCoveredEnd": { + "typeName": "timePeriodCoveredEnd", + "multiple": false, + "typeClass": "primitive", + "value": "1005-02-02" + } + } + ] + }, + { + "typeName": "dateOfCollection", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "dateOfCollectionStart": { + "typeName": "dateOfCollectionStart", + "multiple": false, + "typeClass": "primitive", + "value": "1006-01-01" + }, + "dateOfCollectionEnd": { + "typeName": "dateOfCollectionEnd", + "multiple": false, + "typeClass": "primitive", + "value": "1006-01-01" + } + }, + { + "dateOfCollectionStart": { + "typeName": "dateOfCollectionStart", + "multiple": false, + "typeClass": "primitive", + "value": "1006-02-01" + }, + "dateOfCollectionEnd": { + "typeName": "dateOfCollectionEnd", + "multiple": false, + "typeClass": "primitive", + "value": "1006-02-02" + } + } + ] + }, + { + "typeName": "kindOfData", + "multiple": true, + "typeClass": "primitive", + "value": [ + "KindOfData1", + "KindOfData2" + ] + }, + { + "typeName": "series", + "multiple": false, + "typeClass": "compound", + "value": { + "seriesName": { + "typeName": "seriesName", + "multiple": false, + "typeClass": "primitive", + "value": "SeriesName" + }, + "seriesInformation": { + "typeName": "seriesInformation", + "multiple": false, + "typeClass": "primitive", + "value": "SeriesInformation" + } + } + }, + { + "typeName": "software", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "softwareName": { + "typeName": "softwareName", + "multiple": false, + "typeClass": "primitive", + "value": "SoftwareName1" + }, + "softwareVersion": { + "typeName": "softwareVersion", + "multiple": false, + "typeClass": "primitive", + "value": "SoftwareVersion1" + } + }, + { + "softwareName": { + "typeName": "softwareName", + "multiple": false, + "typeClass": "primitive", + "value": "SoftwareName2" + }, + "softwareVersion": { + "typeName": "softwareVersion", + "multiple": false, + "typeClass": "primitive", + "value": "SoftwareVersion2" + } + } + ] + }, + { + "typeName": "relatedMaterial", + "multiple": true, + "typeClass": "primitive", + "value": [ + "RelatedMaterial1", + "RelatedMaterial2" + ] + }, + { + "typeName": "relatedDatasets", + "multiple": true, + "typeClass": "primitive", + "value": [ + "RelatedDatasets1", + "RelatedDatasets2" + ] + }, + { + "typeName": "otherReferences", + "multiple": true, + "typeClass": "primitive", + "value": [ + "OtherReferences1", + "OtherReferences2" + ] + }, + { + "typeName": "dataSources", + "multiple": true, + "typeClass": "primitive", + "value": [ + "DataSources1", + "DataSources2" + ] + }, + { + "typeName": "originOfSources", + "multiple": false, + "typeClass": "primitive", + "value": "OriginOfSources" + }, + { + "typeName": "characteristicOfSources", + "multiple": false, + "typeClass": "primitive", + "value": "CharacteristicOfSourcesNoted" + }, + { + "typeName": "accessToSources", + "multiple": false, + "typeClass": "primitive", + "value": "DocumentationAndAccessToSources" + } + ] + }, + "geospatial": { + "displayName": "Geospatial Metadata", + "fields": [ + { + "typeName": "geographicCoverage", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "country": { + "typeName": "country", + "multiple": false, + "typeClass": "controlledVocabulary", + "value": "Afghanistan" + }, + "state": { + "typeName": "state", + "multiple": false, + "typeClass": "primitive", + "value": "GeographicCoverageStateProvince1" + }, + "city": { + "typeName": "city", + "multiple": false, + "typeClass": "primitive", + "value": "GeographicCoverageCity1" + }, + "otherGeographicCoverage": { + "typeName": "otherGeographicCoverage", + "multiple": false, + "typeClass": "primitive", + "value": "GeographicCoverageOther1" + } + }, + { + "country": { + "typeName": "country", + "multiple": false, + "typeClass": "controlledVocabulary", + "value": "Albania" + }, + "state": { + "typeName": "state", + "multiple": false, + "typeClass": "primitive", + "value": "GeographicCoverageStateProvince2" + }, + "city": { + "typeName": "city", + "multiple": false, + "typeClass": "primitive", + "value": "GeographicCoverageCity2" + }, + "otherGeographicCoverage": { + "typeName": "otherGeographicCoverage", + "multiple": false, + "typeClass": "primitive", + "value": "GeographicCoverageOther2" + } + } + ] + }, + { + "typeName": "geographicUnit", + "multiple": true, + "typeClass": "primitive", + "value": [ + "GeographicUnit1", + "GeographicUnit2" + ] + }, + { + "typeName": "geographicBoundingBox", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "westLongitude": { + "typeName": "westLongitude", + "multiple": false, + "typeClass": "primitive", + "value": "10" + }, + "eastLongitude": { + "typeName": "eastLongitude", + "multiple": false, + "typeClass": "primitive", + "value": "20" + }, + "northLongitude": { + "typeName": "northLongitude", + "multiple": false, + "typeClass": "primitive", + "value": "30" + }, + "southLongitude": { + "typeName": "southLongitude", + "multiple": false, + "typeClass": "primitive", + "value": "40" + } + }, + { + "westLongitude": { + "typeName": "westLongitude", + "multiple": false, + "typeClass": "primitive", + "value": "50" + }, + "eastLongitude": { + "typeName": "eastLongitude", + "multiple": false, + "typeClass": "primitive", + "value": "60" + }, + "northLongitude": { + "typeName": "northLongitude", + "multiple": false, + "typeClass": "primitive", + "value": "70" + }, + "southLongitude": { + "typeName": "southLongitude", + "multiple": false, + "typeClass": "primitive", + "value": "80" + } + } + ] + } + ] + }, + "socialscience": { + "displayName": "Social Science and Humanities Metadata", + "fields": [ + { + "typeName": "unitOfAnalysis", + "multiple": true, + "typeClass": "primitive", + "value": [ + "UnitOfAnalysis1", + "UnitOfAnalysis2" + ] + }, + { + "typeName": "universe", + "multiple": true, + "typeClass": "primitive", + "value": [ + "Universe1", + "Universe2" + ] + }, + { + "typeName": "timeMethod", + "multiple": false, + "typeClass": "primitive", + "value": "TimeMethod" + }, + { + "typeName": "dataCollector", + "multiple": false, + "typeClass": "primitive", + "value": "LastDataCollector1, FirstDataCollector1" + }, + { + "typeName": "collectorTraining", + "multiple": false, + "typeClass": "primitive", + "value": "CollectorTraining" + }, + { + "typeName": "frequencyOfDataCollection", + "multiple": false, + "typeClass": "primitive", + "value": "Frequency" + }, + { + "typeName": "samplingProcedure", + "multiple": false, + "typeClass": "primitive", + "value": "SamplingProcedure" + }, + { + "typeName": "targetSampleSize", + "multiple": false, + "typeClass": "compound", + "value": { + "targetSampleActualSize": { + "typeName": "targetSampleActualSize", + "multiple": false, + "typeClass": "primitive", + "value": "100" + }, + "targetSampleSizeFormula": { + "typeName": "targetSampleSizeFormula", + "multiple": false, + "typeClass": "primitive", + "value": "TargetSampleSizeFormula" + } + } + }, + { + "typeName": "deviationsFromSampleDesign", + "multiple": false, + "typeClass": "primitive", + "value": "MajorDeviationsForSampleDesign" + }, + { + "typeName": "collectionMode", + "multiple": false, + "typeClass": "primitive", + "value": "CollectionMode" + }, + { + "typeName": "researchInstrument", + "multiple": false, + "typeClass": "primitive", + "value": "TypeOfResearchInstrument" + }, + { + "typeName": "dataCollectionSituation", + "multiple": false, + "typeClass": "primitive", + "value": "CharacteristicsOfDataCollectionSituation" + }, + { + "typeName": "actionsToMinimizeLoss", + "multiple": false, + "typeClass": "primitive", + "value": "ActionsToMinimizeLosses" + }, + { + "typeName": "controlOperations", + "multiple": false, + "typeClass": "primitive", + "value": "ControlOperations" + }, + { + "typeName": "weighting", + "multiple": false, + "typeClass": "primitive", + "value": "Weighting" + }, + { + "typeName": "cleaningOperations", + "multiple": false, + "typeClass": "primitive", + "value": "CleaningOperations" + }, + { + "typeName": "datasetLevelErrorNotes", + "multiple": false, + "typeClass": "primitive", + "value": "StudyLevelErrorNotes" + }, + { + "typeName": "responseRate", + "multiple": false, + "typeClass": "primitive", + "value": "ResponseRate" + }, + { + "typeName": "samplingErrorEstimates", + "multiple": false, + "typeClass": "primitive", + "value": "EstimatesOfSamplingError" + }, + { + "typeName": "otherDataAppraisal", + "multiple": false, + "typeClass": "primitive", + "value": "OtherFormsOfDataAppraisal" + }, + { + "typeName": "socialScienceNotes", + "multiple": false, + "typeClass": "compound", + "value": { + "socialScienceNotesType": { + "typeName": "socialScienceNotesType", + "multiple": false, + "typeClass": "primitive", + "value": "NotesType" + }, + "socialScienceNotesSubject": { + "typeName": "socialScienceNotesSubject", + "multiple": false, + "typeClass": "primitive", + "value": "NotesSubject" + }, + "socialScienceNotesText": { + "typeName": "socialScienceNotesText", + "multiple": false, + "typeClass": "primitive", + "value": "NotesText" + } + } + } + ] + } + }, + "files": [], + "citation": "LastAuthor1, FirstAuthor1; LastAuthor2, FirstAuthor2, 2020, \"Replication Data for: Title\", https://doi.org/10.5072/FK2/WKUKGV, Root, V1" + } +} diff --git a/src/test/java/edu/harvard/iq/dataverse/export/ddi/exportfull.xml b/src/test/java/edu/harvard/iq/dataverse/export/ddi/exportfull.xml new file mode 100644 index 00000000000..390f1968d9a --- /dev/null +++ b/src/test/java/edu/harvard/iq/dataverse/export/ddi/exportfull.xml @@ -0,0 +1,156 @@ + + + + + + Replication Data for: Title + doi:10.5072/FK2/WKUKGV + + + Root + 2020-02-19 + + + 1 + + LastAuthor1, FirstAuthor1; LastAuthor2, FirstAuthor2, 2020, "Replication Data for: Title", https://doi.org/10.5072/FK2/WKUKGV, Root, V1 + + + + + + Replication Data for: Title + Subtitle + Alternative Title + doi:10.5072/FK2/WKUKGV + + + LastAuthor1, FirstAuthor1 + LastAuthor2, FirstAuthor2 + + + LastProducer1, FirstProducer1 + LastProducer2, FirstProducer2 + 1003-01-01 + ProductionPlace + SoftwareName1 + SoftwareName2 + GrantInformationGrantNumber1 + GrantInformationGrantNumber2 + + + LastDistributor1, FirstDistributor1 + LastDistributor2, FirstDistributor2 + LastContact1, FirstContact1 + LastContact2, FirstContact2 + 1004-01-01 + LastDepositor, FirstDepositor + 1002-01-01 + + + SeriesName + SeriesInformation + + + + + Agricultural Sciences + Business and Management + Engineering + Law + KeywordTerm1 + KeywordTerm2 + + DescriptionText 1 + DescriptionText2 + + 1005-01-01 + 1005-01-02 + 1005-02-01 + 1005-02-02 + 1006-01-01 + 1006-01-01 + 1006-02-01 + 1006-02-02 + KindOfData1 + KindOfData2 + Afghanistan + GeographicCoverageCity1 + GeographicCoverageStateProvince1 + GeographicCoverageOther1 + Albania + GeographicCoverageCity2 + GeographicCoverageStateProvince2 + GeographicCoverageOther2 + + 10 + 20 + 30 + 40 + + + 80 + 70 + 60 + 50 + + GeographicUnit1 + GeographicUnit2 + UnitOfAnalysis1 + UnitOfAnalysis2 + Universe1 + Universe2 + + Notes1 + + + + TimeMethod + LastDataCollector1, FirstDataCollector1 + CollectorTraining + Frequency + SamplingProcedure + + TargetSampleSizeFormula + 100 + + MajorDeviationsForSampleDesign + + DataSources1 + DataSources2 + OriginOfSources + CharacteristicOfSourcesNoted + DocumentationAndAccessToSources + + CollectionMode + TypeOfResearchInstrument + CharacteristicsOfDataCollectionSituation + ActionsToMinimizeLosses + ControlOperations + Weighting + CleaningOperations + + + ResponseRate + EstimatesOfSamplingError + OtherFormsOfDataAppraisal + + NotesText + + + CC0 Waiver + + + + RelatedMaterial1 + RelatedMaterial2 + RelatedDatasets1 + RelatedDatasets2 + RelatedPublicationCitation1, ark, RelatedPublicationIDNumber1, http://RelatedPublicationURL1.org + RelatedPublicationCitation2, arXiv, RelatedPublicationIDNumber2, http://RelatedPublicationURL2.org + OtherReferences1 + OtherReferences2 + + StudyLevelErrorNotes + + From 03d48a8568bec89d2b7757df66fc1f4b16fccc8c Mon Sep 17 00:00:00 2001 From: Victoria Lubitch Date: Fri, 21 Feb 2020 14:29:55 -0500 Subject: [PATCH 325/475] remove commented lines --- .../harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java index 528070c31d6..03179f1e29d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java @@ -779,7 +779,6 @@ private void processSumDscr(XMLStreamReader xmlr, DatasetVersionDTO dvDTO) throw geoCoverageSet.add(FieldDTO.createPrimitiveFieldDTO("otherGeographicCoverage", otherGeographicCoverage)); } if (geoCoverageSet != null && geoCoverageSet.size() > 0) { - //FieldDTO geoCoverageDTO = FieldDTO.createMultipleCompoundFieldDTO(DatasetFieldConstant.geographicCoverage, geoCoverageList); geoCoverages.add(geoCoverageSet); } if (geoCoverages.size() > 0) { @@ -826,8 +825,6 @@ private void processMethod(XMLStreamReader xmlr, DatasetVersionDTO dvDTO ) throw processCustomField(xmlr, dvDTO); } else { processNotesSocialScience(xmlr, dvDTO); -// addNote("Subject: Study Level Error Note, Notes: "+ parseText( xmlr,"notes" ) +";", dvDTO); - } } else if (xmlr.getLocalName().equals("anlyInfo")) { processAnlyInfo(xmlr, getSocialScience(dvDTO)); From ddfeb3e05edd25512165abfbbb3e28f9397f66de Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 21 Feb 2020 15:17:34 -0500 Subject: [PATCH 326/475] Disallow 'placeholder' storageIO ~clones --- .../harvard/iq/dataverse/dataaccess/DataAccess.java | 13 +++++++++++-- .../harvard/iq/dataverse/dataset/DatasetUtil.java | 2 +- .../harvard/iq/dataverse/export/ExportService.java | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index f5ec98f14be..907a2173138 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -63,7 +63,7 @@ public static StorageIO getStorageIO(T dvObject, DataAcc } String storageIdentifier = dvObject.getStorageIdentifier(); int separatorIndex = storageIdentifier.indexOf("://"); - String storageDriverId = "file"; //default + String storageDriverId = DEFAULT_STORAGE_DRIVER_IDENTIFIER; //default if(separatorIndex>0) { storageDriverId = storageIdentifier.substring(0,separatorIndex); } @@ -142,6 +142,7 @@ public static StorageIO createNewStorageIO(T dvObject, S || storageTag.isEmpty()) { throw new IOException("getDataAccessObject: null or invalid datafile."); } + return createNewStorageIO(dvObject, storageTag, dvObject.getDataverseContext().getEffectiveStorageDriverId()); } @@ -151,13 +152,21 @@ public static StorageIO createNewStorageIO(T dvObject, S || storageTag.isEmpty()) { throw new IOException("getDataAccessObject: null or invalid datafile."); } + + /* Prior versions sometimes called createNewStorageIO(object, "placeholder") with an existing object to get a ~clone for use in storing/reading Aux files + * Since PR #6488 for multi-store - this can return a clone using a different store than the original (e.g. if the default store changes) which causes errors + * This if will catch any cases where that's attempted. + */ + if(dvObject.getStorageIdentifier().contains("://")) { + throw new IOException("Attempt to create new StorageIO for already stored object: " + dvObject.getStorageIdentifier()); + } StorageIO storageIO = null; dvObject.setStorageIdentifier(storageTag); if (StringUtils.isEmpty(storageDriverId)) { - storageDriverId = "file"; + storageDriverId = DEFAULT_STORAGE_DRIVER_IDENTIFIER; } String storageType = getDriverType(storageDriverId); switch(storageType) { diff --git a/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java b/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java index b844a9d109f..a5931da26f4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java @@ -274,7 +274,7 @@ public static Dataset persistDatasetLogoToStorageAndCreateThumbnail(Dataset data StorageIO dataAccess = null; try{ - dataAccess = DataAccess.createNewStorageIO(dataset,"placeholder"); + dataAccess = DataAccess.getStorageIO(dataset); } catch(IOException ioex){ //TODO: Add a suitable waing message diff --git a/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java b/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java index e61efca2ddf..122a0e482bf 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java @@ -253,7 +253,7 @@ private void cacheExport(DatasetVersion version, String format, JsonObject datas // to save the output into a temp file, and then copy it over to the // permanent storage using the IO "save" command: try { - storageIO = DataAccess.createNewStorageIO(dataset, "placeholder"); + storageIO = DataAccess.getStorageIO(dataset); Channel outputChannel = storageIO.openAuxChannel("export_" + format + ".cached", DataAccessOption.WRITE_ACCESS); outputStream = Channels.newOutputStream((WritableByteChannel) outputChannel); } catch (IOException ioex) { From de4c5d01ad6e85a9a515da96f59af7740eff4869 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 21 Feb 2020 15:41:04 -0500 Subject: [PATCH 327/475] bug fix for exporting plus some cleanup to let one exporter fail without stopping an overall loop through all formats. --- .../iq/dataverse/export/ExportService.java | 102 +++++++++--------- 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java b/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java index 122a0e482bf..9eaf0dbced0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java @@ -240,58 +240,56 @@ public Exporter getExporter(String formatName) throws ExportException { // This method runs the selected metadata exporter, caching the output // in a file in the dataset directory / container based on its DOI: private void cacheExport(DatasetVersion version, String format, JsonObject datasetAsJson, Exporter exporter) throws ExportException { - boolean tempFileRequired = false; - File tempFile = null; - OutputStream outputStream = null; - Dataset dataset = version.getDataset(); - StorageIO storageIO = null; - try { - // With some storage drivers, we can open a WritableChannel, or OutputStream - // to directly write the generated metadata export that we want to cache; - // Some drivers (like Swift) do not support that, and will give us an - // "operation not supported" exception. If that's the case, we'll have - // to save the output into a temp file, and then copy it over to the - // permanent storage using the IO "save" command: - try { - storageIO = DataAccess.getStorageIO(dataset); - Channel outputChannel = storageIO.openAuxChannel("export_" + format + ".cached", DataAccessOption.WRITE_ACCESS); - outputStream = Channels.newOutputStream((WritableByteChannel) outputChannel); - } catch (IOException ioex) { - tempFileRequired = true; - tempFile = File.createTempFile("tempFileToExport", ".tmp"); - outputStream = new FileOutputStream(tempFile); - } - - try { - Path cachedMetadataFilePath = Paths.get(version.getDataset().getFileSystemDirectory().toString(), "export_" + format + ".cached"); - - if (!tempFileRequired) { - FileOutputStream cachedExportOutputStream = new FileOutputStream(cachedMetadataFilePath.toFile()); - exporter.exportDataset(version, datasetAsJson, cachedExportOutputStream); - cachedExportOutputStream.flush(); - cachedExportOutputStream.close(); - outputStream.close(); - } else { - // this method copies a local filesystem Path into this DataAccess Auxiliary location: - exporter.exportDataset(version, datasetAsJson, outputStream); - outputStream.flush(); - outputStream.close(); - - logger.fine("Saving path as aux for temp file in: " + Paths.get(tempFile.getAbsolutePath())); - storageIO.savePathAsAux(Paths.get(tempFile.getAbsolutePath()), "export_" + format + ".cached"); - boolean tempFileDeleted = tempFile.delete(); - logger.fine("tempFileDeleted: " + tempFileDeleted); - } - - } catch (IOException ioex) { - throw new ExportException("IO Exception thrown exporting as " + "export_" + format + ".cached"); - } - - } catch (IOException ioex) { - throw new ExportException("IO Exception thrown exporting as " + "export_" + format + ".cached"); - } finally { - IOUtils.closeQuietly(outputStream); - } + boolean tempFileUsed = false; + File tempFile = null; + OutputStream outputStream = null; + Dataset dataset = version.getDataset(); + StorageIO storageIO = null; + try { + // With some storage drivers, we can open a WritableChannel, or OutputStream + // to directly write the generated metadata export that we want to cache; + // Some drivers (like Swift) do not support that, and will give us an + // "operation not supported" exception. If that's the case, we'll have + // to save the output into a temp file, and then copy it over to the + // permanent storage using the IO "save" command: + try { + storageIO = DataAccess.getStorageIO(dataset); + Channel outputChannel = storageIO.openAuxChannel("export_" + format + ".cached", DataAccessOption.WRITE_ACCESS); + outputStream = Channels.newOutputStream((WritableByteChannel) outputChannel); + } catch (IOException ioex) { + // A common case = an IOException in openAuxChannel which is not supported by S3 stores for WRITE_ACCESS + tempFileUsed = true; + tempFile = File.createTempFile("tempFileToExport", ".tmp"); + outputStream = new FileOutputStream(tempFile); + } + + try { + // Write the metadata export file to the outputStream, which may be the final location or a temp file + exporter.exportDataset(version, datasetAsJson, outputStream); + outputStream.flush(); + outputStream.close(); + if(tempFileUsed) { + logger.fine("Saving export_" + format + ".cached aux file from temp file: " + Paths.get(tempFile.getAbsolutePath())); + storageIO.savePathAsAux(Paths.get(tempFile.getAbsolutePath()), "export_" + format + ".cached"); + boolean tempFileDeleted = tempFile.delete(); + logger.fine("tempFileDeleted: " + tempFileDeleted); + } + } catch (ExportException exex) { + /*This exception is from the particular exporter and may not affect other exporters (versus other exceptions in this method which are from the basic mechanism to create a file) + * So we'll catch it here and report so that loops over other exporters can continue. + * Todo: Might be better to create a new exception subtype and send it upward, but the callers currently just log and ignore beyond terminating any loop over exporters. + */ + logger.warning("Exception thrown while creating export_" + format + ".cached : " + exex.getMessage()); + } catch (IOException ioex) { + throw new ExportException("IO Exception thrown exporting as " + "export_" + format + ".cached"); + } + + } catch (IOException ioex) { + //This catches any problem creating a local temp file in the catch clause above + throw new ExportException("IO Exception thrown before exporting as " + "export_" + format + ".cached"); + } finally { + IOUtils.closeQuietly(outputStream); + } } From 30dffb6dd504e6005adbe4a0044b6c72c10a09d4 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 21 Feb 2020 15:17:34 -0500 Subject: [PATCH 328/475] Disallow 'placeholder' storageIO ~clones --- .../harvard/iq/dataverse/dataaccess/DataAccess.java | 13 +++++++++++-- .../harvard/iq/dataverse/dataset/DatasetUtil.java | 2 +- .../harvard/iq/dataverse/export/ExportService.java | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index 1465506f9c9..44da234eaad 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -62,7 +62,7 @@ public static StorageIO getStorageIO(T dvObject, DataAcc } String storageIdentifier = dvObject.getStorageIdentifier(); int separatorIndex = storageIdentifier.indexOf("://"); - String storageDriverId = "file"; //default + String storageDriverId = DEFAULT_STORAGE_DRIVER_IDENTIFIER; //default if(separatorIndex>0) { storageDriverId = storageIdentifier.substring(0,separatorIndex); } @@ -141,6 +141,7 @@ public static StorageIO createNewStorageIO(T dvObject, S || storageTag.isEmpty()) { throw new IOException("getDataAccessObject: null or invalid datafile."); } + return createNewStorageIO(dvObject, storageTag, dvObject.getDataverseContext().getEffectiveStorageDriverId()); } @@ -150,13 +151,21 @@ public static StorageIO createNewStorageIO(T dvObject, S || storageTag.isEmpty()) { throw new IOException("getDataAccessObject: null or invalid datafile."); } + + /* Prior versions sometimes called createNewStorageIO(object, "placeholder") with an existing object to get a ~clone for use in storing/reading Aux files + * Since PR #6488 for multi-store - this can return a clone using a different store than the original (e.g. if the default store changes) which causes errors + * This if will catch any cases where that's attempted. + */ + if(dvObject.getStorageIdentifier().contains("://")) { + throw new IOException("Attempt to create new StorageIO for already stored object: " + dvObject.getStorageIdentifier()); + } StorageIO storageIO = null; dvObject.setStorageIdentifier(storageTag); if (StringUtils.isEmpty(storageDriverId)) { - storageDriverId = "file"; + storageDriverId = DEFAULT_STORAGE_DRIVER_IDENTIFIER; } String storageType = getDriverType(storageDriverId); switch(storageType) { diff --git a/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java b/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java index b844a9d109f..a5931da26f4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java @@ -274,7 +274,7 @@ public static Dataset persistDatasetLogoToStorageAndCreateThumbnail(Dataset data StorageIO dataAccess = null; try{ - dataAccess = DataAccess.createNewStorageIO(dataset,"placeholder"); + dataAccess = DataAccess.getStorageIO(dataset); } catch(IOException ioex){ //TODO: Add a suitable waing message diff --git a/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java b/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java index e61efca2ddf..122a0e482bf 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java @@ -253,7 +253,7 @@ private void cacheExport(DatasetVersion version, String format, JsonObject datas // to save the output into a temp file, and then copy it over to the // permanent storage using the IO "save" command: try { - storageIO = DataAccess.createNewStorageIO(dataset, "placeholder"); + storageIO = DataAccess.getStorageIO(dataset); Channel outputChannel = storageIO.openAuxChannel("export_" + format + ".cached", DataAccessOption.WRITE_ACCESS); outputStream = Channels.newOutputStream((WritableByteChannel) outputChannel); } catch (IOException ioex) { From 4079e9e847fd9e68765c22742c0d49640647e108 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 21 Feb 2020 15:41:04 -0500 Subject: [PATCH 329/475] bug fix for exporting plus some cleanup to let one exporter fail without stopping an overall loop through all formats. --- .../iq/dataverse/export/ExportService.java | 102 +++++++++--------- 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java b/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java index 122a0e482bf..9eaf0dbced0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/ExportService.java @@ -240,58 +240,56 @@ public Exporter getExporter(String formatName) throws ExportException { // This method runs the selected metadata exporter, caching the output // in a file in the dataset directory / container based on its DOI: private void cacheExport(DatasetVersion version, String format, JsonObject datasetAsJson, Exporter exporter) throws ExportException { - boolean tempFileRequired = false; - File tempFile = null; - OutputStream outputStream = null; - Dataset dataset = version.getDataset(); - StorageIO storageIO = null; - try { - // With some storage drivers, we can open a WritableChannel, or OutputStream - // to directly write the generated metadata export that we want to cache; - // Some drivers (like Swift) do not support that, and will give us an - // "operation not supported" exception. If that's the case, we'll have - // to save the output into a temp file, and then copy it over to the - // permanent storage using the IO "save" command: - try { - storageIO = DataAccess.getStorageIO(dataset); - Channel outputChannel = storageIO.openAuxChannel("export_" + format + ".cached", DataAccessOption.WRITE_ACCESS); - outputStream = Channels.newOutputStream((WritableByteChannel) outputChannel); - } catch (IOException ioex) { - tempFileRequired = true; - tempFile = File.createTempFile("tempFileToExport", ".tmp"); - outputStream = new FileOutputStream(tempFile); - } - - try { - Path cachedMetadataFilePath = Paths.get(version.getDataset().getFileSystemDirectory().toString(), "export_" + format + ".cached"); - - if (!tempFileRequired) { - FileOutputStream cachedExportOutputStream = new FileOutputStream(cachedMetadataFilePath.toFile()); - exporter.exportDataset(version, datasetAsJson, cachedExportOutputStream); - cachedExportOutputStream.flush(); - cachedExportOutputStream.close(); - outputStream.close(); - } else { - // this method copies a local filesystem Path into this DataAccess Auxiliary location: - exporter.exportDataset(version, datasetAsJson, outputStream); - outputStream.flush(); - outputStream.close(); - - logger.fine("Saving path as aux for temp file in: " + Paths.get(tempFile.getAbsolutePath())); - storageIO.savePathAsAux(Paths.get(tempFile.getAbsolutePath()), "export_" + format + ".cached"); - boolean tempFileDeleted = tempFile.delete(); - logger.fine("tempFileDeleted: " + tempFileDeleted); - } - - } catch (IOException ioex) { - throw new ExportException("IO Exception thrown exporting as " + "export_" + format + ".cached"); - } - - } catch (IOException ioex) { - throw new ExportException("IO Exception thrown exporting as " + "export_" + format + ".cached"); - } finally { - IOUtils.closeQuietly(outputStream); - } + boolean tempFileUsed = false; + File tempFile = null; + OutputStream outputStream = null; + Dataset dataset = version.getDataset(); + StorageIO storageIO = null; + try { + // With some storage drivers, we can open a WritableChannel, or OutputStream + // to directly write the generated metadata export that we want to cache; + // Some drivers (like Swift) do not support that, and will give us an + // "operation not supported" exception. If that's the case, we'll have + // to save the output into a temp file, and then copy it over to the + // permanent storage using the IO "save" command: + try { + storageIO = DataAccess.getStorageIO(dataset); + Channel outputChannel = storageIO.openAuxChannel("export_" + format + ".cached", DataAccessOption.WRITE_ACCESS); + outputStream = Channels.newOutputStream((WritableByteChannel) outputChannel); + } catch (IOException ioex) { + // A common case = an IOException in openAuxChannel which is not supported by S3 stores for WRITE_ACCESS + tempFileUsed = true; + tempFile = File.createTempFile("tempFileToExport", ".tmp"); + outputStream = new FileOutputStream(tempFile); + } + + try { + // Write the metadata export file to the outputStream, which may be the final location or a temp file + exporter.exportDataset(version, datasetAsJson, outputStream); + outputStream.flush(); + outputStream.close(); + if(tempFileUsed) { + logger.fine("Saving export_" + format + ".cached aux file from temp file: " + Paths.get(tempFile.getAbsolutePath())); + storageIO.savePathAsAux(Paths.get(tempFile.getAbsolutePath()), "export_" + format + ".cached"); + boolean tempFileDeleted = tempFile.delete(); + logger.fine("tempFileDeleted: " + tempFileDeleted); + } + } catch (ExportException exex) { + /*This exception is from the particular exporter and may not affect other exporters (versus other exceptions in this method which are from the basic mechanism to create a file) + * So we'll catch it here and report so that loops over other exporters can continue. + * Todo: Might be better to create a new exception subtype and send it upward, but the callers currently just log and ignore beyond terminating any loop over exporters. + */ + logger.warning("Exception thrown while creating export_" + format + ".cached : " + exex.getMessage()); + } catch (IOException ioex) { + throw new ExportException("IO Exception thrown exporting as " + "export_" + format + ".cached"); + } + + } catch (IOException ioex) { + //This catches any problem creating a local temp file in the catch clause above + throw new ExportException("IO Exception thrown before exporting as " + "export_" + format + ".cached"); + } finally { + IOUtils.closeQuietly(outputStream); + } } From 241d301e18affdbd4310677bd326184428bb5512 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 21 Feb 2020 17:33:57 -0500 Subject: [PATCH 330/475] one test fix --- .../java/edu/harvard/iq/dataverse/dataaccess/DataAccessTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/edu/harvard/iq/dataverse/dataaccess/DataAccessTest.java b/src/test/java/edu/harvard/iq/dataverse/dataaccess/DataAccessTest.java index 5c148c8b77f..1ff914adff9 100644 --- a/src/test/java/edu/harvard/iq/dataverse/dataaccess/DataAccessTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/dataaccess/DataAccessTest.java @@ -55,6 +55,7 @@ void testCreateNewStorageIO_throwsOnUnsupported() { @Test void testCreateNewStorageIO_createsFileAccessIObyDefault() throws IOException { System.setProperty("dataverse.files.file.type", "file"); + System.setProperty("dataverse.files.storage-driver-id", "file"); StorageIO storageIo = DataAccess.createNewStorageIO(dataset, "valid-tag"); assertTrue(storageIo.getClass().equals(FileAccessIO.class)); } From 50b14d19bab565c44501eed51222f644c76d616f Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 21 Feb 2020 17:49:32 -0500 Subject: [PATCH 331/475] test fix 2 --- .../java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index 44da234eaad..2a8069fd2bd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -156,7 +156,8 @@ public static StorageIO createNewStorageIO(T dvObject, S * Since PR #6488 for multi-store - this can return a clone using a different store than the original (e.g. if the default store changes) which causes errors * This if will catch any cases where that's attempted. */ - if(dvObject.getStorageIdentifier().contains("://")) { + // Tests send objects with no storageIdentifier set + if(!dvObject.getStorageIdentifier().isEmpty() && dvObject.getStorageIdentifier().contains("://")) { throw new IOException("Attempt to create new StorageIO for already stored object: " + dvObject.getStorageIdentifier()); } From c8a0b81b89ee96adb96eceb4fabec7a8e89856d6 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 21 Feb 2020 17:59:50 -0500 Subject: [PATCH 332/475] just check null --- .../java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index 2a8069fd2bd..4a3bc0c4b2d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -157,7 +157,7 @@ public static StorageIO createNewStorageIO(T dvObject, S * This if will catch any cases where that's attempted. */ // Tests send objects with no storageIdentifier set - if(!dvObject.getStorageIdentifier().isEmpty() && dvObject.getStorageIdentifier().contains("://")) { + if((dvObject.getStorageIdentifier()!=null) && dvObject.getStorageIdentifier().contains("://")) { throw new IOException("Attempt to create new StorageIO for already stored object: " + dvObject.getStorageIdentifier()); } From f7597a190859301c0dbbe6d38721751c27dbe7ef Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 21 Feb 2020 18:20:09 -0500 Subject: [PATCH 333/475] fixing fileAccessIO logic to not use deprecated/pre multistore method --- src/main/java/edu/harvard/iq/dataverse/Dataset.java | 4 ++++ .../edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataset.java b/src/main/java/edu/harvard/iq/dataverse/Dataset.java index 659eecdec18..9e71ff56085 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataset.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataset.java @@ -504,6 +504,10 @@ private Collection getCategoryNames() { } } + /*Only used with packageFiles after the implementation of multi-store in #6488 + * + */ + @Deprecated public Path getFileSystemDirectory() { Path studyDir = null; diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java index 629cf630936..a961c3a9e32 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java @@ -529,7 +529,7 @@ public FileOutputStream openLocalFileAsOutputStream () { return out; } - private String getDatasetDirectory() throws IOException { + public String getDatasetDirectory() throws IOException { if (dvObject == null) { throw new IOException("No DvObject defined in the Data Access Object"); } @@ -587,7 +587,7 @@ private List listCachedFiles() throws IOException { baseName = stripDriverId(this.getDataFile().getStorageIdentifier()); - datasetDirectoryPath = this.getDataFile().getOwner().getFileSystemDirectory(); + datasetDirectoryPath = Paths.get(getDatasetDirectory()); } if (datasetDirectoryPath == null) { From e5a60ace28e1e91fa6d4b2c1baea4215d53710db Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 21 Feb 2020 18:32:06 -0500 Subject: [PATCH 334/475] set a default for tests looks like setting this property in the test occurs too late to be picked up in a static variable --- .../java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index 4a3bc0c4b2d..c2b7cbffd62 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -42,8 +42,8 @@ public DataAccess() { }; - - public static final String DEFAULT_STORAGE_DRIVER_IDENTIFIER = System.getProperty("dataverse.files.storage-driver-id"); + //Default is only for tests + public static final String DEFAULT_STORAGE_DRIVER_IDENTIFIER = System.getProperty("dataverse.files.storage-driver-id", "file"); // The getStorageIO() methods initialize StorageIO objects for // datafiles that are already saved using one of the supported Dataverse From 14d4abd9eac9882f1242adcbf70af323b50d0df6 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Mon, 24 Feb 2020 10:39:29 -0500 Subject: [PATCH 335/475] adding note to external developers --- doc/release-notes/6644-role-name-change.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/release-notes/6644-role-name-change.md diff --git a/doc/release-notes/6644-role-name-change.md b/doc/release-notes/6644-role-name-change.md new file mode 100644 index 00000000000..cc4df2fee75 --- /dev/null +++ b/doc/release-notes/6644-role-name-change.md @@ -0,0 +1 @@ +Note for integrators - the role alias has changed, so if anything was hard-coded to "editor" instead of "contributor" it'll need to be updated. \ No newline at end of file From 38760b05e14a078d3b03a031a43dd27965869543 Mon Sep 17 00:00:00 2001 From: Michael Heppler Date: Mon, 24 Feb 2020 15:35:22 -0500 Subject: [PATCH 336/475] Swapped extra quotes in bibtex citation for title for double brackets [ref #6658] --- .../java/edu/harvard/iq/dataverse/DataCitation.java | 4 ++-- .../edu/harvard/iq/dataverse/DataCitationTest.java | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataCitation.java b/src/main/java/edu/harvard/iq/dataverse/DataCitation.java index 051055efb42..a16cf3b67b7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataCitation.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataCitation.java @@ -265,12 +265,12 @@ public void writeAsBibtexCitation(OutputStream os) throws IOException { out.write(title); out.write("},\r\n"); } else { - out.write("title = \"{"); + out.write("title = {{"); String doubleQ = "\""; String doubleTick = "``"; String doubleAp = "''"; out.write(title.replaceFirst(doubleQ, doubleTick).replaceFirst(doubleQ, doubleAp)); - out.write("}\",\r\n"); + out.write("}},\r\n"); } if(UNF != null){ out.write("UNF = {"); diff --git a/src/test/java/edu/harvard/iq/dataverse/DataCitationTest.java b/src/test/java/edu/harvard/iq/dataverse/DataCitationTest.java index a2abf573e46..b32243d446d 100644 --- a/src/test/java/edu/harvard/iq/dataverse/DataCitationTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/DataCitationTest.java @@ -72,7 +72,7 @@ public void testWriteAsBibtexCitation() throws ParseException, IOException { "@data{LK0D1H_1955,\r\n" + "author = {First Last},\r\n" + "publisher = {LibraScholar},\r\n" - + "title = \"{Dataset Title}\",\r\n" + + "title = {{Dataset Title}},\r\n" + "year = {1955},\r\n" + "version = {V1},\r\n" + "doi = {10.5072/FK2/LK0D1H},\r\n" @@ -95,7 +95,7 @@ public void testToBibtexString() throws ParseException { "@data{LK0D1H_1955,\r\n" + "author = {First Last},\r\n" + "publisher = {LibraScholar},\r\n" - + "title = \"{Dataset Title}\",\r\n" + + "title = {{Dataset Title}},\r\n" + "year = {1955},\r\n" + "version = {V1},\r\n" + "doi = {10.5072/FK2/LK0D1H},\r\n" @@ -119,7 +119,7 @@ public void testToBibtexString_withoutAuthor() throws ParseException { "@data{LK0D1H_1955,\r\n" + "author = {},\r\n" + "publisher = {LibraScholar},\r\n" - + "title = \"{Dataset Title}\",\r\n" + + "title = {{Dataset Title}},\r\n" + "year = {1955},\r\n" + "version = {V1},\r\n" + "doi = {10.5072/FK2/LK0D1H},\r\n" @@ -144,7 +144,7 @@ public void testToBibtexString_withoutTitle() throws ParseException { "@data{LK0D1H_1955,\r\n" + "author = {First Last},\r\n" + "publisher = {LibraScholar},\r\n" - + "title = \"{}\",\r\n" + + "title = {{}},\r\n" + "year = {1955},\r\n" + "version = {V1},\r\n" + "doi = {10.5072/FK2/LK0D1H},\r\n" @@ -169,7 +169,7 @@ public void testToBibtexString_withoutTitleAndAuthor() throws ParseException { "@data{LK0D1H_1955,\r\n" + "author = {},\r\n" + "publisher = {LibraScholar},\r\n" - + "title = \"{}\",\r\n" + + "title = {{}},\r\n" + "year = {1955},\r\n" + "version = {V1},\r\n" + "doi = {10.5072/FK2/LK0D1H},\r\n" @@ -335,7 +335,7 @@ public void testTitleWithQuotes() throws ParseException { "@data{LK0D1H_1955,\r\n" + "author = {First Last},\r\n" + "publisher = {LibraScholar},\r\n" - + "title = \"{This Title ``Has Quotes'' In It}\",\r\n" + + "title = {{This Title ``Has Quotes'' In It}},\r\n" + "year = {1955},\r\n" + "version = {V1},\r\n" + "doi = {10.5072/FK2/LK0D1H},\r\n" From 5490a31b2d6eb4f88ac9b8faf65cce857f583ec7 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Mon, 24 Feb 2020 17:43:58 -0500 Subject: [PATCH 337/475] small improvements for handling harvested datasets and configuring harvesting clients, per #4964. --- .../edu/harvard/iq/dataverse/Dataset.java | 26 +++++++++++++++++++ .../iq/dataverse/HarvestingClientsPage.java | 2 +- .../harvest/client/HarvestingClient.java | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataset.java b/src/main/java/edu/harvard/iq/dataverse/Dataset.java index 659eecdec18..cd001221800 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataset.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataset.java @@ -32,6 +32,7 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; import edu.harvard.iq.dataverse.util.BundleUtil; +import edu.harvard.iq.dataverse.util.StringUtil; /** * @@ -748,7 +749,32 @@ public String getRemoteArchiveURL() { } } return this.getHarvestedFrom().getArchiveUrl(); + } else if (HarvestingClient.HARVEST_STYLE_DEFAULT.equals(this.getHarvestedFrom().getHarvestStyle())) { + // This is a generic OAI archive. + // The metadata we harvested for this dataset is most likely a + // simple DC record that does not contain a URL pointing back at + // the specific location on the source archive. But, it probably + // has a global identifier, a DOI or a Handle - so we should be + // able to redirect to the proper global resolver. + // But since this is a harvested dataset, we will assume that + // there is a possibility tha this object does NOT have all the + // valid persistent identifier components. + + if (StringUtil.nonEmpty(this.getProtocol()) + && StringUtil.nonEmpty(this.getAuthority()) + && StringUtil.nonEmpty(this.getIdentifier())) { + return this.getPersistentURL(); + } + + // All we can do is redirect them to the top-level URL we have + // on file for this remote archive: + return this.getHarvestedFrom().getArchiveUrl(); } else { + // This is really not supposed to happen - this is a harvested + // dataset for which we don't have ANY information on the nature + // of the archive we got it from. So all we can do is redirect + // the user to the top-level URL we have on file for this remote + // archive: return this.getHarvestedFrom().getArchiveUrl(); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java index c0d7ed01c8e..ac9a10b18fb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java @@ -674,7 +674,7 @@ public void initNewClient(ActionEvent ae) { this.initialSettingsValidated = false; this.newOaiSet = ""; this.newMetadataFormat = ""; - this.newHarvestingStyle = HarvestingClient.HARVEST_STYLE_DATAVERSE; + this.newHarvestingStyle = ""; this.harvestTypeRadio = harvestTypeRadioOAI; this.harvestingScheduleRadio = harvestingScheduleRadioNone; diff --git a/src/main/java/edu/harvard/iq/dataverse/harvest/client/HarvestingClient.java b/src/main/java/edu/harvard/iq/dataverse/harvest/client/HarvestingClient.java index b4ed7c3d32f..32365e17852 100644 --- a/src/main/java/edu/harvard/iq/dataverse/harvest/client/HarvestingClient.java +++ b/src/main/java/edu/harvard/iq/dataverse/harvest/client/HarvestingClient.java @@ -90,7 +90,7 @@ public void setId(Long id) { public static final String HARVEST_STYLE_DESCRIPTION_NESSTAR="Nesstar archive"; public static final String HARVEST_STYLE_DESCRIPTION_ROPER="Roper Archive"; public static final String HARVEST_STYLE_DESCRIPTION_HGL="HGL"; - public static final String HARVEST_STYLE_DESCRIPTION_DEFAULT="Generic OAI resource (DC)"; + public static final String HARVEST_STYLE_DESCRIPTION_DEFAULT="Generic OAI archive"; public static final List HARVEST_STYLE_LIST = Arrays.asList(HARVEST_STYLE_DATAVERSE, HARVEST_STYLE_VDC, HARVEST_STYLE_ICPSR, HARVEST_STYLE_NESSTAR, HARVEST_STYLE_ROPER, HARVEST_STYLE_HGL, HARVEST_STYLE_DEFAULT); From 2e5009c64ccecceaad3affb2adfecc88da503424 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Mon, 24 Feb 2020 18:56:44 -0500 Subject: [PATCH 338/475] typo --- doc/sphinx-guides/source/developers/big-data-support.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/developers/big-data-support.rst b/doc/sphinx-guides/source/developers/big-data-support.rst index f1371f41759..8f1103cf720 100644 --- a/doc/sphinx-guides/source/developers/big-data-support.rst +++ b/doc/sphinx-guides/source/developers/big-data-support.rst @@ -23,7 +23,7 @@ To configure these options, an administrator must set two JVM options for the Da With multiple stores configured, it is possible to configure one S3 store with direct upload and/or download to support large files (in general or for specific dataverses) while configuring only direct download, or no direct access for another store. -At present, one potential drawback for direct-upload is that files are only partially 'ingested', tabular and FITS files are processed, but zip files are not unzipped, and the file contents are not inspected to evaluate their mimetype. This could be appropriate for large files, or it may be useful to completely turn off ingest processing for performance reasons (ingest processing requires a copy of the file to be retrieved by Dataverse from the S3 store). A store using direct uplod can be configured to disable all ingest processing for files above a given size limit: +At present, one potential drawback for direct-upload is that files are only partially 'ingested', tabular and FITS files are processed, but zip files are not unzipped, and the file contents are not inspected to evaluate their mimetype. This could be appropriate for large files, or it may be useful to completely turn off ingest processing for performance reasons (ingest processing requires a copy of the file to be retrieved by Dataverse from the S3 store). A store using direct upload can be configured to disable all ingest processing for files above a given size limit: ``./asadmin create-jvm-options "-Ddataverse.files..ingestsizelimit="`` From 3e30bcbfa3773f858d48dbff842b263c5405f8e9 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Tue, 25 Feb 2020 14:14:25 -0500 Subject: [PATCH 339/475] more aggressive validation, forcing the user to pick the remote archive type. (#4964) --- .../iq/dataverse/HarvestingClientsPage.java | 28 ++++++++++++++++++- .../harvest/client/oai/OaiHandler.java | 4 +++ src/main/java/propertyFiles/Bundle.properties | 1 + src/main/webapp/harvestclients.xhtml | 24 ++++++++++------ 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java index ac9a10b18fb..f72afdbd3cb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java @@ -492,6 +492,23 @@ public void validateMetadataFormat(FacesContext context, UIComponent toValidate, } } + public void validateRemoteArchiveStyle(FacesContext context, UIComponent toValidate, Object rawValue) { + String value = (String) rawValue; + UIInput input = (UIInput) toValidate; + input.setValid(true); // Optimistic approach + + // the only validation we want is to make sure the select one of the + // values from the menu. + if (context.getExternalContext().getRequestParameterMap().get("DO_VALIDATION") != null + && StringUtils.isEmpty(value)) { + + input.setValid(false); + context.addMessage(toValidate.getClientId(), + new FacesMessage(FacesMessage.SEVERITY_ERROR, "", BundleUtil.getStringFromBundle("harvestclients.newClientDialog.harvestingStyle.required"))); + + } + } + public boolean validateNickname() { if ( !StringUtils.isEmpty(getNewNickname()) ) { @@ -643,7 +660,8 @@ public void backToStepThree() { UIInput newClientNicknameInputField; UIInput newClientUrlInputField; UIInput hiddenInputField; - /*UISelectOne*/ UIInput metadataFormatMenu; + /*UISelectOne*/ UIInput metadataFormatMenu; + UIInput remoteArchiveStyleMenu; UIInput selectedDataverseMenu; private String newNickname = ""; @@ -840,6 +858,14 @@ public void setMetadataFormatMenu(UIInput metadataFormatMenu) { this.metadataFormatMenu = metadataFormatMenu; } + public UIInput getRemoteArchiveStyleMenu() { + return remoteArchiveStyleMenu; + } + + public void setRemoteArchiveStyleMenu(UIInput remoteArchiveStyleMenu) { + this.remoteArchiveStyleMenu = remoteArchiveStyleMenu; + } + public UIInput getSelectedDataverseMenu() { return selectedDataverseMenu; } diff --git a/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java b/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java index e4642fe0a4d..c0f04f06b0e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java +++ b/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java @@ -157,7 +157,9 @@ public List runListSets() throws OaiHandlerException { List sets = new ArrayList<>(); + int count = 0; while ( setIter.hasNext()) { + count++; Set set = setIter.next(); String setSpec = set.getSpec(); /* @@ -166,6 +168,8 @@ public List runListSets() throws OaiHandlerException { } */ + System.out.println("on set " + count + ", name: " + setSpec); + if (!StringUtils.isEmpty(setSpec)) { sets.add(setSpec); } diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index ae4dcab6a57..72386cb6e43 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -503,6 +503,7 @@ harvestclients.newClientDialog.step4=Step 4 of 4 - Display harvestclients.newClientDialog.harvestingStyle=Archive Type harvestclients.newClientDialog.harvestingStyle.tip=Type of remote archive. harvestclients.newClientDialog.harvestingStyle.helptext=Select the archive type that best describes this remote server in order to properly apply formatting rules and styles to the harvested metadata as they are shown in the search results. Note that improperly selecting the type of the remote archive can result in incomplete entries in the search results, and a failure to redirect the user to the archival source of the data. +harvestclients.newClientDialog.harvestingStyle.required=Please select one of the values from the menu harvestclients.viewEditDialog.title=Edit Harvesting Client harvestclients.viewEditDialog.archiveUrl=Archive URL harvestclients.viewEditDialog.archiveUrl.tip=The URL of the archive that serves the data harvested by this client, which is used in search results for links to the original sources of the harvested content. diff --git a/src/main/webapp/harvestclients.xhtml b/src/main/webapp/harvestclients.xhtml index 4190cb313d0..5e9b1c8e0c2 100644 --- a/src/main/webapp/harvestclients.xhtml +++ b/src/main/webapp/harvestclients.xhtml @@ -320,7 +320,7 @@ - +
- + - - +
@@ -487,8 +487,12 @@
+ binding="#{harvestingClientsPage.remoteArchiveStyleMenu}" + styleClass="form-control" + value="#{harvestingClientsPage.newHarvestingStyle}" + rendered="#{harvestingClientsPage.initialSettingsValidated}" + validator="#{harvestingClientsPage.validateRemoteArchiveStyle}"> + @@ -547,7 +551,9 @@ value="#{bundle['harvestclients.viewEditDialog.btn.save']}" update="newHarvestingClientDialogContent :messagePanel :harvestingClientsForm clientsTable emptyClientsTable" actionListener="#{harvestingClientsPage.saveClient}" - oncomplete="if (args && !args.validationFailed) PF('newHarvestingClientForm').hide(); else PF('newHarvestingClientForm').show();bind_bsui_components();"/> + oncomplete="if (args && !args.validationFailed) PF('newHarvestingClientForm').hide(); else PF('newHarvestingClientForm').show();bind_bsui_components();"> + + From e5465f0b15eb96aa845b16b66a94f55bf50d62e0 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Tue, 25 Feb 2020 18:34:25 -0500 Subject: [PATCH 340/475] a simple solution for the "too many sets" problem. (#4964). --- .../iq/dataverse/HarvestingClientsPage.java | 7 ++++++ .../harvest/client/oai/OaiHandler.java | 22 ++++++++++++++++++- src/main/java/propertyFiles/Bundle.properties | 1 + src/main/webapp/harvestclients.xhtml | 5 +++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java index f72afdbd3cb..44b33e807ac 100644 --- a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java @@ -77,6 +77,7 @@ public class HarvestingClientsPage implements java.io.Serializable { private Dataverse dataverse; private Long dataverseId = null; private HarvestingClient selectedClient; + private boolean setListTruncated = false; //private static final String solrDocIdentifierDataset = "dataset_"; @@ -206,6 +207,9 @@ public boolean isCreateStepFour() { return CreateStep.FOUR == this.createStep; } + public boolean isSetListTruncated() { + return setListTruncated; + } public void runHarvest(HarvestingClient harvestingClient) { try { @@ -593,6 +597,9 @@ public boolean validateServerUrlOAI() { } if (success) { + if (oaiHandler.isSetListTruncated()) { + setListTruncated = true; + } return true; } diff --git a/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java b/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java index c0f04f06b0e..e5fd1300c5e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java +++ b/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java @@ -82,6 +82,7 @@ public OaiHandler(HarvestingClient harvestingClient) throws OaiHandlerException private String metadataPrefix; // = harvestingClient.getMetadataPrefix(); private String setName; private Date fromDate; + private Boolean setListTruncated = false; private ServiceProvider serviceProvider; @@ -123,6 +124,9 @@ public void setHarvestingClient(HarvestingClient harvestingClient) { this.harvestingClient = harvestingClient; } + public boolean isSetListTruncated() { + return setListTruncated; + } private ServiceProvider getServiceProvider() throws OaiHandlerException { if (serviceProvider == null) { @@ -147,6 +151,8 @@ public List runListSets() throws OaiHandlerException { Iterator setIter; + long startMilSec = new Date().getTime(); + try { setIter = sp.listSets(); } catch (NoSetHierarchyException nshe) { @@ -158,6 +164,7 @@ public List runListSets() throws OaiHandlerException { List sets = new ArrayList<>(); int count = 0; + while ( setIter.hasNext()) { count++; Set set = setIter.next(); @@ -168,7 +175,20 @@ public List runListSets() throws OaiHandlerException { } */ - System.out.println("on set " + count + ", name: " + setSpec); + + Date now = new Date(); + long seconds = (now.getTime() - startMilSec) / 1000; + + if (count >= 100) { + // Have we been waiting more than 30 seconds? + if (new Date().getTime() - startMilSec > 30000) { + System.out.println("EXITING on set " + count + ", name: " + setSpec + "seconds: "+seconds); + setListTruncated = true; + break; + } + } + + System.out.println("on set " + count + ", name: " + setSpec + "seconds: "+seconds); if (!StringUtils.isEmpty(setSpec)) { sets.add(setSpec); diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 72386cb6e43..067a4f22ba9 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -482,6 +482,7 @@ harvestclients.newClientDialog.oaiSets.tip=Harvesting sets offered by this OAI s harvestclients.newClientDialog.oaiSets.noset=None harvestclients.newClientDialog.oaiSets.helptext=Selecting "none" will harvest the default set, as defined by the server. Often this will be the entire body of content across all sub-sets. harvestclients.newClientDialog.oaiSets.helptext.noset=This OAI server does not support named sets. The entire body of content offered by the server will be harvested. +harvestclients.newClientDialog.oaiSets.listTruncated=Please note that the remote server was taking too long to return the full list of available OAI sets, so the list was truncated! Please select a set from the current list (or select the "no set" option), and try again later if you need to change it. harvestclients.newClientDialog.oaiMetadataFormat=Metadata Format harvestclients.newClientDialog.oaiMetadataFormat.tip=Metadata formats offered by the remote server. harvestclients.newClientDialog.oaiMetadataFormat.required=Please select the metadata format to harvest from this archive. diff --git a/src/main/webapp/harvestclients.xhtml b/src/main/webapp/harvestclients.xhtml index 5e9b1c8e0c2..d43945ddddf 100644 --- a/src/main/webapp/harvestclients.xhtml +++ b/src/main/webapp/harvestclients.xhtml @@ -327,6 +327,11 @@ value="#{harvestingClientsPage.newOaiSet}"/>

#{bundle['harvestclients.newClientDialog.oaiSets.helptext']}

#{bundle['harvestclients.newClientDialog.oaiSets.helptext.noset']}

+ +

+ + #{bundle['harvestclients.newClientDialog.oaiSets.listTruncated']} +

From 508f10e675f76c98a49d88de153f574d34c44386 Mon Sep 17 00:00:00 2001 From: Benjamin Peuch Date: Wed, 26 Feb 2020 11:19:27 +0100 Subject: [PATCH 341/475] Fixing the link to the 4.19 milestone page --- doc/release-notes/4.19-release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/4.19-release-notes.md b/doc/release-notes/4.19-release-notes.md index 56977f5b277..70c8711582c 100644 --- a/doc/release-notes/4.19-release-notes.md +++ b/doc/release-notes/4.19-release-notes.md @@ -83,7 +83,7 @@ Additional fields are now available via the Search API, mostly related to inform ## Complete List of Changes -For the complete list of code changes in this release, see the 4.19 milestone in Github. +For the complete list of code changes in this release, see the 4.19 milestone in Github. For help with upgrading, installing, or general questions please post to the Dataverse Google Group or email support@dataverse.org. From e6aee06c8d5742053af275f244eb10c9e6f70013 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 26 Feb 2020 09:38:52 -0500 Subject: [PATCH 342/475] get the effective storage driver --- src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java | 2 +- src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 5ec37030024..681c9c15dd9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -358,7 +358,7 @@ public boolean doesSessionUserHaveDataSetPermission(Permission permissionToCheck } public boolean directUploadEnabled() { - return Boolean.getBoolean("dataverse.files." + this.dataset.getDataverseContext().getStorageDriverId() + ".upload-redirect"); + return Boolean.getBoolean("dataverse.files." + this.dataset.getDataverseContext().getEffectiveStorageDriverId() + ".upload-redirect"); } public void reset() { diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index 99ff6994db2..820a7037605 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -1650,7 +1650,7 @@ public static boolean isPackageFile(DataFile dataFile) { } public static S3AccessIO getS3AccessForDirectUpload(Dataset dataset) { - String driverId = dataset.getDataverseContext().getStorageDriverId(); + String driverId = dataset.getDataverseContext().getEffectiveStorageDriverId(); boolean directEnabled = Boolean.getBoolean("dataverse.files." + driverId + ".upload-redirect"); //Should only be requested when it is allowed, but we'll log a warning otherwise if(!directEnabled) { From c0196f8a5b3a3a0b6813eee1fea7b83bfab367da Mon Sep 17 00:00:00 2001 From: Brian Cassidy Date: Wed, 26 Feb 2020 10:50:56 -0400 Subject: [PATCH 343/475] add paragraph about support Solr versions --- doc/sphinx-guides/source/installation/prerequisites.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/sphinx-guides/source/installation/prerequisites.rst b/doc/sphinx-guides/source/installation/prerequisites.rst index 11792e6f56a..b126ab090f5 100644 --- a/doc/sphinx-guides/source/installation/prerequisites.rst +++ b/doc/sphinx-guides/source/installation/prerequisites.rst @@ -188,6 +188,11 @@ Solr The Dataverse search index is powered by Solr. +Supported Versions +================== + +Dataverse has been tested with Solr version 7.7.2. Future releases in the 7.x series are likely to be compatible; however, this cannot be confirmed until they are officially tested. Major releases above 7.x (eg. 8.x) are not supported. + Installing Solr =============== From 31451981638bba779b2302111d002435a7d5b568 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Wed, 26 Feb 2020 10:42:09 -0500 Subject: [PATCH 344/475] typo --- doc/sphinx-guides/source/installation/prerequisites.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/installation/prerequisites.rst b/doc/sphinx-guides/source/installation/prerequisites.rst index b126ab090f5..bfa8e11e6fc 100644 --- a/doc/sphinx-guides/source/installation/prerequisites.rst +++ b/doc/sphinx-guides/source/installation/prerequisites.rst @@ -191,7 +191,7 @@ The Dataverse search index is powered by Solr. Supported Versions ================== -Dataverse has been tested with Solr version 7.7.2. Future releases in the 7.x series are likely to be compatible; however, this cannot be confirmed until they are officially tested. Major releases above 7.x (eg. 8.x) are not supported. +Dataverse has been tested with Solr version 7.7.2. Future releases in the 7.x series are likely to be compatible; however, this cannot be confirmed until they are officially tested. Major releases above 7.x (e.g. 8.x) are not supported. Installing Solr =============== From 11b42783a51afe08add8a8e950fa8974187368df Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Wed, 26 Feb 2020 10:42:23 -0500 Subject: [PATCH 345/475] typo From eb063f2e76b5ce47c2c2daf392ca29785f975c9e Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Wed, 26 Feb 2020 10:53:55 -0500 Subject: [PATCH 346/475] minor cleanup of the code in OaiHandler - was supposed to be part of the PR. (#4964) --- .../iq/dataverse/harvest/client/oai/OaiHandler.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java b/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java index e5fd1300c5e..2f2df5491f2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java +++ b/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java @@ -176,20 +176,14 @@ public List runListSets() throws OaiHandlerException { } */ - Date now = new Date(); - long seconds = (now.getTime() - startMilSec) / 1000; - if (count >= 100) { // Have we been waiting more than 30 seconds? if (new Date().getTime() - startMilSec > 30000) { - System.out.println("EXITING on set " + count + ", name: " + setSpec + "seconds: "+seconds); setListTruncated = true; break; } } - - System.out.println("on set " + count + ", name: " + setSpec + "seconds: "+seconds); - + if (!StringUtils.isEmpty(setSpec)) { sets.add(setSpec); } From 19c17e5e51459e4b3a3b9514280bcc6d772ed211 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 26 Feb 2020 10:58:17 -0500 Subject: [PATCH 347/475] public not needed --- .../java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java index a961c3a9e32..d7a405d63c7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java @@ -529,7 +529,7 @@ public FileOutputStream openLocalFileAsOutputStream () { return out; } - public String getDatasetDirectory() throws IOException { + private String getDatasetDirectory() throws IOException { if (dvObject == null) { throw new IOException("No DvObject defined in the Data Access Object"); } From 299b5b7377a7cd9fc882d8e016f2001bcd9ec5ab Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Wed, 26 Feb 2020 12:20:27 -0500 Subject: [PATCH 348/475] Added some warnings and TODOs to the code that handles package files, about the need to address how they handle storage locations. (#6666) --- src/main/java/edu/harvard/iq/dataverse/Dataset.java | 3 ++- .../importer/filesystem/FileRecordJobListener.java | 10 ++++++++++ .../jobs/importer/filesystem/FileRecordReader.java | 10 ++++++++++ .../command/impl/ImportFromFileSystemCommand.java | 12 ++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataset.java b/src/main/java/edu/harvard/iq/dataverse/Dataset.java index 9e71ff56085..92ebc82df9a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataset.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataset.java @@ -504,7 +504,8 @@ private Collection getCategoryNames() { } } - /*Only used with packageFiles after the implementation of multi-store in #6488 + /* Only used with packageFiles after the implementation of multi-store in #6488 + * DO NOT USE THIS METHOD FOR ANY OTHER PURPOSES - it's @Deprecated for a reason. * */ @Deprecated diff --git a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordJobListener.java b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordJobListener.java index 4a6f48f1600..d6713a42e12 100644 --- a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordJobListener.java +++ b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordJobListener.java @@ -439,6 +439,16 @@ private void loadChecksumManifest() { + SEP + dataset.getIdentifier() + SEP + uploadFolder + SEP + manifest; + // TODO: + // The above goes directly to the filesystem directory configured by the + // old "dataverse.files.directory" JVM option (otherwise used for temp + // files only, after the Multistore implementatoin (#6488). + // We probably want package files to be able to use specific stores instead. + // More importantly perhaps, the approach above does not take into account + // if the dataset may have an AlternativePersistentIdentifier, that may be + // designated isStorageLocationDesignator() - i.e., if a different identifer + // needs to be used to name the storage directory, instead of the main/current + // persistent identifier above. getJobLogger().log(Level.INFO, "Reading checksum manifest: " + manifestAbsolutePath); Scanner scanner = null; try { diff --git a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordReader.java b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordReader.java index 023b0876be4..724ef5795ff 100644 --- a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordReader.java +++ b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordReader.java @@ -99,6 +99,16 @@ public void open(Serializable checkpoint) throws Exception { directory = new File(System.getProperty("dataverse.files.directory") + SEP + dataset.getAuthority() + SEP + dataset.getIdentifier() + SEP + uploadFolder); + // TODO: + // The above goes directly to the filesystem directory configured by the + // old "dataverse.files.directory" JVM option (otherwise used for temp + // files only, after the Multistore implementatoin (#6488). + // We probably want package files to be able to use specific stores instead. + // More importantly perhaps, the approach above does not take into account + // if the dataset may have an AlternativePersistentIdentifier, that may be + // designated isStorageLocationDesignator() - i.e., if a different identifer + // needs to be used to name the storage directory, instead of the main/current + // persistent identifier above. getJobLogger().log(Level.INFO, "Reading dataset directory: " + directory.getAbsolutePath() + " (excluding: " + excludes + ")"); if (isValidDirectory(directory)) { diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportFromFileSystemCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportFromFileSystemCommand.java index fc0d9362545..5f38cd8d224 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportFromFileSystemCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportFromFileSystemCommand.java @@ -71,6 +71,16 @@ public JsonObject execute(CommandContext ctxt) throws CommandException { } File directory = new File(System.getProperty("dataverse.files.directory") + File.separator + dataset.getAuthority() + File.separator + dataset.getIdentifier()); + // TODO: + // The above goes directly to the filesystem directory configured by the + // old "dataverse.files.directory" JVM option (otherwise used for temp + // files only, after the Multistore implementatoin (#6488). + // We probably want package files to be able to use specific stores instead. + // More importantly perhaps, the approach above does not take into account + // if the dataset may have an AlternativePersistentIdentifier, that may be + // designated isStorageLocationDesignator() - i.e., if a different identifer + // needs to be used to name the storage directory, instead of the main/current + // persistent identifier above. if (!isValidDirectory(directory)) { String error = "Dataset directory is invalid. " + directory; logger.info(error); @@ -86,6 +96,8 @@ public JsonObject execute(CommandContext ctxt) throws CommandException { File uploadDirectory = new File(System.getProperty("dataverse.files.directory") + File.separator + dataset.getAuthority() + File.separator + dataset.getIdentifier() + File.separator + uploadFolder); + // TODO: + // see the comment above. if (!isValidDirectory(uploadDirectory)) { String error = "Upload folder is not a valid directory."; logger.info(error); From 90166ddca3e288ff354f22e4dd4729525af21145 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 26 Feb 2020 12:28:44 -0500 Subject: [PATCH 349/475] typo --- .../batch/jobs/importer/filesystem/FileRecordJobListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordJobListener.java b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordJobListener.java index d6713a42e12..6b82a665c17 100644 --- a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordJobListener.java +++ b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordJobListener.java @@ -442,7 +442,7 @@ private void loadChecksumManifest() { // TODO: // The above goes directly to the filesystem directory configured by the // old "dataverse.files.directory" JVM option (otherwise used for temp - // files only, after the Multistore implementatoin (#6488). + // files only, after the Multistore implementation (#6488). // We probably want package files to be able to use specific stores instead. // More importantly perhaps, the approach above does not take into account // if the dataset may have an AlternativePersistentIdentifier, that may be From 688c7a69fc0750419ddf6e86d11d03928ebf59c2 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 26 Feb 2020 12:29:15 -0500 Subject: [PATCH 350/475] typo --- .../batch/jobs/importer/filesystem/FileRecordReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordReader.java b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordReader.java index 724ef5795ff..b3d3a7107a6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordReader.java +++ b/src/main/java/edu/harvard/iq/dataverse/batch/jobs/importer/filesystem/FileRecordReader.java @@ -102,7 +102,7 @@ public void open(Serializable checkpoint) throws Exception { // TODO: // The above goes directly to the filesystem directory configured by the // old "dataverse.files.directory" JVM option (otherwise used for temp - // files only, after the Multistore implementatoin (#6488). + // files only, after the Multistore implementation (#6488). // We probably want package files to be able to use specific stores instead. // More importantly perhaps, the approach above does not take into account // if the dataset may have an AlternativePersistentIdentifier, that may be From 55ad201700bc4d03e1fcc38c0d85a5b40fb0d127 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 26 Feb 2020 12:29:49 -0500 Subject: [PATCH 351/475] same typo --- .../engine/command/impl/ImportFromFileSystemCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportFromFileSystemCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportFromFileSystemCommand.java index 5f38cd8d224..64beba82450 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportFromFileSystemCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ImportFromFileSystemCommand.java @@ -74,7 +74,7 @@ public JsonObject execute(CommandContext ctxt) throws CommandException { // TODO: // The above goes directly to the filesystem directory configured by the // old "dataverse.files.directory" JVM option (otherwise used for temp - // files only, after the Multistore implementatoin (#6488). + // files only, after the Multistore implementation (#6488). // We probably want package files to be able to use specific stores instead. // More importantly perhaps, the approach above does not take into account // if the dataset may have an AlternativePersistentIdentifier, that may be From 230609cad42ab16bf37d87b1b35e39ff7ad7ba50 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Wed, 26 Feb 2020 18:29:23 -0500 Subject: [PATCH 352/475] another minor improvement, for an OAI server with a tricky list of sets. (#4964) I'm done, for reals. --- .../iq/dataverse/HarvestingClientsPage.java | 26 +++++++++++++++---- .../harvest/client/oai/OaiHandler.java | 4 +-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java index 44b33e807ac..77aed692556 100644 --- a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java @@ -20,6 +20,7 @@ import edu.harvard.iq.dataverse.util.BundleUtil; import edu.harvard.iq.dataverse.util.JsfHelper; import static edu.harvard.iq.dataverse.util.JsfHelper.JH; +import edu.harvard.iq.dataverse.util.StringUtil; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -250,7 +251,7 @@ public void editClient(HarvestingClient harvestingClient) { // and if not, what do we do? // alternatively, should we make these 2 fields not editable at all? - this.newOaiSet = !StringUtils.isEmpty(harvestingClient.getHarvestingSet()) ? harvestingClient.getHarvestingSet() : "none"; + this.newOaiSet = !StringUtils.isEmpty(harvestingClient.getHarvestingSet()) ? harvestingClient.getHarvestingSet() : ""; this.newMetadataFormat = harvestingClient.getMetadataPrefix(); this.newHarvestingStyle = harvestingClient.getHarvestStyle(); @@ -580,10 +581,10 @@ public boolean validateServerUrlOAI() { } // And if that worked, the list of sets provided: + ArrayList sets = null; if (success) { try { - List sets = oaiHandler.runListSets(); - createOaiSetsSelectItems(sets); + sets = oaiHandler.runListSets(); } catch (Exception ex) { //success = false; // ok - we'll try and live without sets for now... @@ -597,8 +598,23 @@ public boolean validateServerUrlOAI() { } if (success) { - if (oaiHandler.isSetListTruncated()) { - setListTruncated = true; + if (sets != null) { + if (oaiHandler.isSetListTruncated()) { + // If it was taking too long to retrieve the full list + // of sets (oai.datacite.org/oai - looking at you! - + // and we had to truncate it: + setListTruncated = true; + + // And if we are re-configuring an existing client, with + // a specific set in place - let's make sure it's on the pull down + // menu list; even if we have failed to retrieve it from the server. + if (StringUtil.nonEmpty(this.newOaiSet)) { + if (!sets.contains(this.newOaiSet)) { + sets.add(0, this.newOaiSet); + } + } + } + createOaiSetsSelectItems(sets); } return true; } diff --git a/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java b/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java index 2f2df5491f2..7119e625044 100644 --- a/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java +++ b/src/main/java/edu/harvard/iq/dataverse/harvest/client/oai/OaiHandler.java @@ -145,7 +145,7 @@ private ServiceProvider getServiceProvider() throws OaiHandlerException { return serviceProvider; } - public List runListSets() throws OaiHandlerException { + public ArrayList runListSets() throws OaiHandlerException { ServiceProvider sp = getServiceProvider(); @@ -161,7 +161,7 @@ public List runListSets() throws OaiHandlerException { throw new OaiHandlerException("No valid response received from the OAI server."); } - List sets = new ArrayList<>(); + ArrayList sets = new ArrayList<>(); int count = 0; From 3cd1575c85ca89e8e6f7092575c14cc268b1f7d0 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Wed, 26 Feb 2020 18:38:36 -0500 Subject: [PATCH 353/475] ok, now I'm done (#4964) --- .../java/edu/harvard/iq/dataverse/HarvestingClientsPage.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java index 77aed692556..3cc581ee93c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/HarvestingClientsPage.java @@ -582,6 +582,11 @@ public boolean validateServerUrlOAI() { // And if that worked, the list of sets provided: ArrayList sets = null; + + // reset the sets menu: + setOaiSetsSelectItems(null); + setListTruncated = false; + if (success) { try { sets = oaiHandler.runListSets(); From f1436a9b82938392b5894a24cee032f01acec564 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 26 Feb 2020 21:04:26 -0500 Subject: [PATCH 354/475] updated sql filename --- ...ole-alias.sql => V4.19.1.0__6644-update-editor-role-alias.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V4.20.0.0__6644-update-editor-role-alias.sql => V4.19.1.0__6644-update-editor-role-alias.sql} (100%) diff --git a/src/main/resources/db/migration/V4.20.0.0__6644-update-editor-role-alias.sql b/src/main/resources/db/migration/V4.19.1.0__6644-update-editor-role-alias.sql similarity index 100% rename from src/main/resources/db/migration/V4.20.0.0__6644-update-editor-role-alias.sql rename to src/main/resources/db/migration/V4.19.1.0__6644-update-editor-role-alias.sql From 8e14da3cddf5e73150a031306ede0b783b4db1f7 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 26 Feb 2020 22:06:12 -0500 Subject: [PATCH 355/475] update name based on code review feedback --- ...ole-alias.sql => V4.19.0.2__6644-update-editor-role-alias.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V4.19.1.0__6644-update-editor-role-alias.sql => V4.19.0.2__6644-update-editor-role-alias.sql} (100%) diff --git a/src/main/resources/db/migration/V4.19.1.0__6644-update-editor-role-alias.sql b/src/main/resources/db/migration/V4.19.0.2__6644-update-editor-role-alias.sql similarity index 100% rename from src/main/resources/db/migration/V4.19.1.0__6644-update-editor-role-alias.sql rename to src/main/resources/db/migration/V4.19.0.2__6644-update-editor-role-alias.sql From 2e8ded9e6517d5f9667d323b28f376e630657997 Mon Sep 17 00:00:00 2001 From: Don Sizemore Date: Thu, 27 Feb 2020 09:58:47 -0500 Subject: [PATCH 356/475] #6682 add API Test Coverage shield --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2bdc0e8edde..f52a6e20f83 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Dataverse is a trademark of President and Fellows of Harvard College and is regi [![Dataverse Project logo](src/main/webapp/resources/images/dataverseproject_logo.jpg?raw=true "Dataverse Project")](http://dataverse.org) [![API Test Status](https://jenkins.dataverse.org/buildStatus/icon?job=IQSS-dataverse-develop&subject=API%20Test%20Status)](https://jenkins.dataverse.org/job/IQSS-dataverse-develop/) +[![API Test Coverage](https://img.shields.io/jenkins/coverage/jacoco?jobUrl=https%3A%2F%2Fjenkins.dataverse.org%2Fjob%2FIQSS-dataverse-develop&label=API%20Test%20Coverage)](https://jenkins.dataverse.org/job/IQSS-dataverse-develop/) [![Unit Test Status](https://img.shields.io/travis/IQSS/dataverse?label=Unit%20Test%20Status)](https://travis-ci.org/IQSS/dataverse) [![Unit Test Coverage](https://img.shields.io/coveralls/github/IQSS/dataverse?label=Unit%20Test%20Coverage)](https://coveralls.io/github/IQSS/dataverse?branch=develop) From 66633947a37bf0e7e5c69aaa94b578e69190ab18 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 27 Feb 2020 11:42:37 -0500 Subject: [PATCH 357/475] #6665 update ds solr docs directly --- .../iq/dataverse/search/IndexServiceBean.java | 99 +++++++++++++------ .../edu/harvard/iq/dataverse/api/UtilIT.java | 6 ++ 2 files changed, 74 insertions(+), 31 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java index 5afd6cd5dd4..c4dd30d2216 100644 --- a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java @@ -27,6 +27,7 @@ import edu.harvard.iq.dataverse.datavariable.VariableMetadataUtil; import edu.harvard.iq.dataverse.datavariable.VariableServiceBean; import edu.harvard.iq.dataverse.harvest.client.HarvestingClient; +import edu.harvard.iq.dataverse.harvest.server.OaiSetException; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.FileUtil; import edu.harvard.iq.dataverse.util.StringUtil; @@ -41,6 +42,7 @@ import java.util.Collection; import java.util.Date; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; @@ -258,21 +260,23 @@ public Future indexDataverse(Dataverse dataverse) throws SolrServerExcep for (String dvPath : linkingDataversePaths) { dataversePaths.add(dvPath); } - //Get Linking Dataverses to see if I need to reindex my children - if (hasAnyLinkingDataverses(dataverse)) { - for (Dataset dv : datasetService.findPublishedByOwnerId(dataverse.getId())) { - //if this dataverse or any of its ancestors is linked and contains datasets then - // the datasets must be reindexed to get the new paths added - indexDataset(dv, true); - } + if (hasAnyLinkingDataverses(dataverse)) { for (Dataverse dv : dataverseService.findPublishedByOwnerId(dataverse.getId())) { //if this dataverse or any of its ancestors is linked and contains dataverses then // the dataverses must be reindexed to get the new paths added + //We're sticking with the re-index here so that the dataverses datasets will also + //get their paths updated indexDataverse(dv); } + + for (Dataset dv : datasetService.findPublishedByOwnerId(dataverse.getId())) { + //if this dataverse or any of its ancestors is linked and contains datasets then + // the datasets must get the new paths added + // changed from a full re-index for efficiency wrt issue 6665 + updatePathForExistingSolrDocs(dv); + } } - solrInputDocument.addField(SearchFields.SUBTREE, dataversePaths); docs.add(solrInputDocument); @@ -694,29 +698,6 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d Dataset dataset = indexableDataset.getDatasetVersion().getDataset(); logger.fine("adding or updating Solr document for dataset id " + dataset.getId()); Collection docs = new ArrayList<>(); - List dataversePathSegmentsAccumulator = new ArrayList<>(); - List dataverseSegments = new ArrayList<>(); - try { - dataverseSegments = findPathSegments(dataset.getOwner(), dataversePathSegmentsAccumulator); - } catch (Exception ex) { - logger.info("failed to find dataverseSegments for dataversePaths for " + SearchFields.SUBTREE + ": " + ex); - } - List dataversePaths = getDataversePathsFromSegments(dataverseSegments); - // Add Paths for linking dataverses - for (Dataverse linkingDataverse : dsLinkingService.findLinkingDataverses(dataset.getId())) { - List linkingDataversePathSegmentsAccumulator = new ArrayList<>(); - List linkingdataverseSegments = findPathSegments(linkingDataverse, linkingDataversePathSegmentsAccumulator); - List linkingDataversePaths = getDataversePathsFromSegments(linkingdataverseSegments); - for (String dvPath : linkingDataversePaths) { - dataversePaths.add(dvPath); - } - } - - //Add paths for my linking dataverses - List linkingDataversePaths = findLinkingDataversePaths(dataset.getOwner()); - for (String dvPath : linkingDataversePaths) { - dataversePaths.add(dvPath); - } SolrInputDocument solrInputDocument = new SolrInputDocument(); String datasetSolrDocId = indexableDataset.getSolrDocId(); @@ -898,6 +879,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d } } + List dataversePaths = retrieveDatasetPaths(dataset); solrInputDocument.addField(SearchFields.SUBTREE, dataversePaths); // solrInputDocument.addField(SearchFields.HOST_DATAVERSE, // dataset.getOwner().getName()); @@ -1417,6 +1399,61 @@ public static String getIN_REVIEW_STRING() { public static String getDEACCESSIONED_STRING() { return DEACCESSIONED_STRING; } + + + + private void updatePathForExistingSolrDocs(DvObject object) throws SolrServerException, IOException { + SolrQuery solrQuery = new SolrQuery(); + + solrQuery.setQuery(SearchUtil.constructQuery(SearchFields.ENTITY_ID, object.getId().toString())); + + QueryResponse res = solrClientService.getSolrClient().query(solrQuery); + + if (res.getResults().isEmpty()) { + //nothing to update - + } else { + SolrDocument doc = res.getResults().get(0); + SolrInputDocument tmp = new SolrInputDocument(); + + for (String fieldName : doc.getFieldNames()) { + tmp.addField(fieldName, doc.getFieldValue(fieldName)); + } + Dataset ds = datasetService.find(object.getId()); + tmp.removeField(SearchFields.SUBTREE); + tmp.addField(SearchFields.SUBTREE, retrieveDatasetPaths(ds)); + UpdateResponse addResponse = solrClientService.getSolrClient().add(tmp); + UpdateResponse commitResponse = solrClientService.getSolrClient().commit(); + } + + } + + + private List retrieveDatasetPaths(Dataset dataset) { + List dataversePathSegmentsAccumulator = new ArrayList<>(); + List dataverseSegments = new ArrayList<>(); + try { + dataverseSegments = findPathSegments(dataset.getOwner(), dataversePathSegmentsAccumulator); + } catch (Exception ex) { + logger.info("failed to find dataverseSegments for dataversePaths for " + SearchFields.SUBTREE + ": " + ex); + } + List dataversePaths = getDataversePathsFromSegments(dataverseSegments); + // Add Paths for linking dataverses + for (Dataverse linkingDataverse : dsLinkingService.findLinkingDataverses(dataset.getId())) { + List linkingDataversePathSegmentsAccumulator = new ArrayList<>(); + List linkingdataverseSegments = findPathSegments(linkingDataverse, linkingDataversePathSegmentsAccumulator); + List linkingDataversePaths = getDataversePathsFromSegments(linkingdataverseSegments); + for (String dvPath : linkingDataversePaths) { + dataversePaths.add(dvPath); + } + } + + //Add paths for my linking dataverses + List linkingDataversePaths = findLinkingDataversePaths(dataset.getOwner()); + for (String dvPath : linkingDataversePaths) { + dataversePaths.add(dvPath); + } + return dataversePaths; + } public String delete(Dataverse doomed) { logger.fine("deleting Solr document for dataverse " + doomed.getId()); diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index c609b400f7e..4507c18eb89 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -1059,6 +1059,12 @@ static Response reindexDataset(String persistentId) { .get("/api/admin/index/dataset?persistentId=" + persistentId); return response; } + + static Response reindexDataverse(String dvId) { + Response response = given() + .get("/api/admin/index/dataverses/" + dvId); + return response; + } static Response listAuthenticatedUsers(String apiToken) { Response response = given() From 641c73fd68a7f294a37c541fec12a6d3f4dacc69 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Thu, 27 Feb 2020 12:30:50 -0500 Subject: [PATCH 358/475] couple of cosmetic/punctuation changes to the messages in the bundle. (#4964) --- src/main/java/propertyFiles/Bundle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 067a4f22ba9..35229c5162d 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -482,7 +482,7 @@ harvestclients.newClientDialog.oaiSets.tip=Harvesting sets offered by this OAI s harvestclients.newClientDialog.oaiSets.noset=None harvestclients.newClientDialog.oaiSets.helptext=Selecting "none" will harvest the default set, as defined by the server. Often this will be the entire body of content across all sub-sets. harvestclients.newClientDialog.oaiSets.helptext.noset=This OAI server does not support named sets. The entire body of content offered by the server will be harvested. -harvestclients.newClientDialog.oaiSets.listTruncated=Please note that the remote server was taking too long to return the full list of available OAI sets, so the list was truncated! Please select a set from the current list (or select the "no set" option), and try again later if you need to change it. +harvestclients.newClientDialog.oaiSets.listTruncated=Please note that the remote server was taking too long to return the full list of available OAI sets, so the list was truncated. Please select a set from the current list (or select the "no set" option), and try again later, if you need to change it. harvestclients.newClientDialog.oaiMetadataFormat=Metadata Format harvestclients.newClientDialog.oaiMetadataFormat.tip=Metadata formats offered by the remote server. harvestclients.newClientDialog.oaiMetadataFormat.required=Please select the metadata format to harvest from this archive. @@ -504,7 +504,7 @@ harvestclients.newClientDialog.step4=Step 4 of 4 - Display harvestclients.newClientDialog.harvestingStyle=Archive Type harvestclients.newClientDialog.harvestingStyle.tip=Type of remote archive. harvestclients.newClientDialog.harvestingStyle.helptext=Select the archive type that best describes this remote server in order to properly apply formatting rules and styles to the harvested metadata as they are shown in the search results. Note that improperly selecting the type of the remote archive can result in incomplete entries in the search results, and a failure to redirect the user to the archival source of the data. -harvestclients.newClientDialog.harvestingStyle.required=Please select one of the values from the menu +harvestclients.newClientDialog.harvestingStyle.required=Please select one of the values from the menu. harvestclients.viewEditDialog.title=Edit Harvesting Client harvestclients.viewEditDialog.archiveUrl=Archive URL harvestclients.viewEditDialog.archiveUrl.tip=The URL of the archive that serves the data harvested by this client, which is used in search results for links to the original sources of the harvested content. From ce2d2aaa3ffe127ba0b25ca00958612376e3b225 Mon Sep 17 00:00:00 2001 From: Michael Heppler Date: Thu, 27 Feb 2020 14:24:43 -0500 Subject: [PATCH 359/475] Added missing ui:param components to guestbook-responses to fix header [ref #6284] --- src/main/webapp/guestbook-responses.xhtml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/guestbook-responses.xhtml b/src/main/webapp/guestbook-responses.xhtml index d09de393bf5..aab177a98e1 100644 --- a/src/main/webapp/guestbook-responses.xhtml +++ b/src/main/webapp/guestbook-responses.xhtml @@ -20,7 +20,8 @@ - + + From 919c579aa6860b01da99f6fe09dff9519b1a2842 Mon Sep 17 00:00:00 2001 From: Don Sizemore Date: Fri, 28 Feb 2020 13:57:27 -0500 Subject: [PATCH 360/475] #6703 update Citation Date Field Type stanzas --- doc/sphinx-guides/source/api/native-api.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 5cc5cefc2ab..f3264678825 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -977,19 +977,18 @@ The fully expanded example above (without environment variables) looks like this curl -H "X-Dataverse-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X DELETE https://demo.dataverse.org/api/datasets/24/versions/:draft -Set Citation Date Field for a Dataset -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Set Citation Date Field Type for a Dataset +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Sets the dataset field type to be used as the citation date for the given dataset (if the dataset does not include the dataset field type, the default logic is used). The name of the dataset field type should be sent in the body of the request. -To revert to the default logic, use ``:publicationDate`` as the ``$DATASET_FIELD_TYPE_NAME``. -Note that the dataset field used has to be a date field. +Sets the dataset citation date field type for a given dataset. ``:publicationDate`` is the default. +Note that the dataset citation date field type must be a date field. .. code-block:: bash export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx export SERVER_URL=https://demo.dataverse.org export ID=24 - export DATASET_FIELD_TYPE_NAME=:publicationDate + export DATASET_FIELD_TYPE_NAME=:dateOfDeposit curl -H "X-Dataverse-key: $API_TOKEN" -X PUT $SERVER_URL/api/datasets/$ID/citationdate --data "$DATASET_FIELD_TYPE_NAME" @@ -997,12 +996,12 @@ The fully expanded example above (without environment variables) looks like this .. code-block:: bash - curl -H "X-Dataverse-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X PUT https://demo.dataverse.org/api/datasets/24/citationdate --data ":publicationDate" + curl -H "X-Dataverse-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X PUT https://demo.dataverse.org/api/datasets/24/citationdate --data ":dateOfDeposit" -Revert Citation Date Field to Default for Dataset -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Revert Citation Date Field Type to Default for Dataset +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Restores the default logic of the field type to be used as the citation date. Same as ``PUT`` with ``:publicationDate`` body: +Restores the default citation date field type, ``:publicationDate``, for a given dataset. .. code-block:: bash From 6265a4f90e0626b8035dfd2d3d77d6e1033186e4 Mon Sep 17 00:00:00 2001 From: Peter Kiraly Date: Mon, 2 Mar 2020 17:04:53 +0100 Subject: [PATCH 361/475] #6083 update examples in File part of Native API: 'Provenance' section. --- doc/sphinx-guides/source/api/native-api.rst | 184 ++++++++++++++++++-- 1 file changed, 174 insertions(+), 10 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 5cc5cefc2ab..28a8db51560 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2042,25 +2042,189 @@ You can download :download:`dct.xml <../../../../src/test/resources/xml/dct.xml> Provenance ~~~~~~~~~~ -Get Provenance JSON for an uploaded file:: - GET http://$SERVER/api/files/{id}/prov-json?key=$apiKey +Get Provenance JSON for an uploaded file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A curl example using an ``ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=24 + + curl -H "X-Dataverse-key:$API_TOKEN" $SERVER_URL/api/files/$ID/prov-json + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" https://demo.dataverse.org/api/files/24/prov-json + +A curl example using a ``PERSISTENT_ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export PERSISTENT_ID=doi:10.5072/FK2/AAA000 + + curl -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/files/:persistentId/prov-json?persistentId=$PERSISTENT_ID" + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/files/:persistentId/prov-json?persistentId=doi:10.5072/FK2/AAA000" + +Get Provenance Description for an uploaded file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A curl example using an ``ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=24 + + curl -H "X-Dataverse-key:$API_TOKEN" $SERVER_URL/api/files/$ID/prov-freeform + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" https://demo.dataverse.org/api/files/24/prov-freeform + +A curl example using a ``PERSISTENT_ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export PERSISTENT_ID=doi:10.5072/FK2/AAA000 + + curl -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/files/:persistentId/prov-freeform?persistentId=$PERSISTENT_ID" + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/files/:persistentId/prov-freeform?persistentId=doi:10.5072/FK2/AAA000" + +Create/Update Provenance JSON and provide related entity name for an uploaded file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A curl example using an ``ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=24 + export ENTITY_NAME="..." + export FILE_PATH=provenance.json + + curl -H "X-Dataverse-key:$API_TOKEN" -X POST $SERVER_URL/api/files/$ID/prov-json?entityName=$ENTITY_NAME -H "Content-type:application/json" --upload-file $FILE_PATH + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST "https://demo.dataverse.org/api/files/24/prov-json?entityName=..." -H "Content-type:application/json" --upload-file provenance.json + +A curl example using a ``PERSISTENT_ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export PERSISTENT_ID=doi:10.5072/FK2/AAA000 + export ENTITY_NAME="..." + export FILE_PATH=provenance.json -Get Provenance Description for an uploaded file:: + curl -H "X-Dataverse-key:$API_TOKEN" -X POST "$SERVER_URL/api/files/:persistentId/prov-json?persistentId=$PERSISTENT_ID&entityName=$ENTITY_NAME" -H "Content-type:application/json" --upload-file $FILE_PATH - GET http://$SERVER/api/files/{id}/prov-freeform?key=$apiKey +The fully expanded example above (without environment variables) looks like this: -Create/Update Provenance JSON and provide related entity name for an uploaded file:: +.. code-block:: bash - POST http://$SERVER/api/files/{id}/prov-json?key=$apiKey&entityName=$entity -H "Content-type:application/json" --upload-file $filePath + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST "https://demo.dataverse.org/api/files/:persistentId/prov-json?persistentId=doi:10.5072/FK2/AAA000&entityName=..." -H "Content-type:application/json" --upload-file provenance.json -Create/Update Provenance Description for an uploaded file. Requires a JSON file with the description connected to a key named "text":: +Create/Update Provenance Description for an uploaded file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - POST http://$SERVER/api/files/{id}/prov-freeform?key=$apiKey -H "Content-type:application/json" --upload-file $filePath +Requires a JSON file with the description connected to a key named "text" + +A curl example using an ``ID`` + +.. code-block:: bash -Delete Provenance JSON for an uploaded file:: + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=24 + export FILE_PATH=provenance.json + + curl -H "X-Dataverse-key:$API_TOKEN" -X POST $SERVER_URL/api/files/$ID/prov-freeform -H "Content-type:application/json" --upload-file $FILE_PATH + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST https://demo.dataverse.org/api/files/24/prov-freeform -H "Content-type:application/json" --upload-file provenance.json + +A curl example using a ``PERSISTENT_ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export PERSISTENT_ID=doi:10.5072/FK2/AAA000 + export FILE_PATH=provenance.json + + curl -H "X-Dataverse-key:$API_TOKEN" -X POST "$SERVER_URL/api/files/:persistentId/prov-freeform?persistentId=$PERSISTENT_ID" -H "Content-type:application/json" --upload-file $FILE_PATH + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST "https://demo.dataverse.org/api/files/:persistentId/prov-freeform?persistentId=doi:10.5072/FK2/AAA000" -H "Content-type:application/json" --upload-file provenance.json + +Delete Provenance JSON for an uploaded file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A curl example using an ``ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=24 + + curl -H "X-Dataverse-key:$API_TOKEN" -X DELETE $SERVER_URL/api/files/$ID/prov-json + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X DELETE https://demo.dataverse.org/api/files/24/prov-json + +A curl example using a ``PERSISTENT_ID`` + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export PERSISTENT_ID=doi:10.5072/FK2/AAA000 + + curl -H "X-Dataverse-key:$API_TOKEN" -X DELETE "$SERVER_URL/api/files/:persistentId/prov-json?persistentId=$PERSISTENT_ID" + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash - DELETE http://$SERVER/api/files/{id}/prov-json?key=$apiKey + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X DELETE "https://demo.dataverse.org/api/files/:persistentId/prov-json?persistentId=doi:10.5072/FK2/AAA000" Datafile Integrity ~~~~~~~~~~~~~~~~~~ From 72bf99bf37ae0e268ae8d4f15e81f53cbae34bda Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Mon, 2 Mar 2020 12:46:17 -0500 Subject: [PATCH 362/475] add text for coverage badge --- doc/release-notes/6711-coverage-badge | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/release-notes/6711-coverage-badge diff --git a/doc/release-notes/6711-coverage-badge b/doc/release-notes/6711-coverage-badge new file mode 100644 index 00000000000..fc90da68742 --- /dev/null +++ b/doc/release-notes/6711-coverage-badge @@ -0,0 +1,3 @@ +Integration Test Coverage Reporting + +API-based integration tests are run every time a branch is merged to develop and the percentage of code covered by these integration tests is now shown on a badge at the bottom of the README.md file that serves as the homepage of Dataverse Github Repository. \ No newline at end of file From 91f42755ba488ae73155b4321a53635b59377058 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 2 Mar 2020 14:39:41 -0500 Subject: [PATCH 363/475] don't wrap file --- src/main/webapp/resources/js/fileupload.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index c3da541414a..83d42b9f417 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -45,16 +45,14 @@ function queueFileForDirectUpload(file, datasetId) { } function uploadFileDirectly(url, storageId) { - var data = new FormData(); //Pick a pending file var file = fileList.pop(); - data.append('file',file); $('.ui-fileupload-progress').html(''); $('.ui-fileupload-progress').append($('').attr('class', 'ui-progressbar ui-widget ui-widget-content ui-corner-all')); $.ajax({ url: url, type: 'PUT', - data: data, + data: file, cache: false, processData: false, success: function () { From a94b391b5010f45df8f783a9cd00002781b46994 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 2 Mar 2020 16:56:32 -0500 Subject: [PATCH 364/475] #6665 add paths to files on index dataverse --- .../iq/dataverse/search/IndexServiceBean.java | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java index c4dd30d2216..b381efbda52 100644 --- a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java @@ -1409,22 +1409,35 @@ private void updatePathForExistingSolrDocs(DvObject object) throws SolrServerExc QueryResponse res = solrClientService.getSolrClient().query(solrQuery); - if (res.getResults().isEmpty()) { - //nothing to update - - } else { + if (!res.getResults().isEmpty()) { SolrDocument doc = res.getResults().get(0); - SolrInputDocument tmp = new SolrInputDocument(); + SolrInputDocument sid = new SolrInputDocument(); for (String fieldName : doc.getFieldNames()) { - tmp.addField(fieldName, doc.getFieldValue(fieldName)); + sid.addField(fieldName, doc.getFieldValue(fieldName)); } Dataset ds = datasetService.find(object.getId()); - tmp.removeField(SearchFields.SUBTREE); - tmp.addField(SearchFields.SUBTREE, retrieveDatasetPaths(ds)); - UpdateResponse addResponse = solrClientService.getSolrClient().add(tmp); + sid.removeField(SearchFields.SUBTREE); + List paths = retrieveDatasetPaths(ds); + sid.addField(SearchFields.SUBTREE, paths); + UpdateResponse addResponse = solrClientService.getSolrClient().add(sid); UpdateResponse commitResponse = solrClientService.getSolrClient().commit(); + for (DataFile df : ds.getFiles()) { + solrQuery.setQuery(SearchUtil.constructQuery(SearchFields.ENTITY_ID, df.getId().toString())); + res = solrClientService.getSolrClient().query(solrQuery); + if (!res.getResults().isEmpty()) { + doc = res.getResults().get(0); + sid = new SolrInputDocument(); + for (String fieldName : doc.getFieldNames()) { + sid.addField(fieldName, doc.getFieldValue(fieldName)); + } + sid.removeField(SearchFields.SUBTREE); + sid.addField(SearchFields.SUBTREE, paths); + addResponse = solrClientService.getSolrClient().add(sid); + commitResponse = solrClientService.getSolrClient().commit(); + } + } } - } From 8446bfb5deae3ae2e106801f5786ace907462198 Mon Sep 17 00:00:00 2001 From: Victoria Lubitch Date: Tue, 3 Mar 2020 12:41:22 -0500 Subject: [PATCH 365/475] fix export import ddi --- .../api/imports/ImportDDIServiceBean.java | 131 ++++++++++++------ .../dataverse/export/ddi/DdiExportUtil.java | 94 ++++++++++--- .../dataset-create-new-all-ddi-fields.json | 84 +++++++++++ .../dataverse/export/ddi/dataset-finch1.xml | 1 + .../iq/dataverse/export/ddi/exportfull.xml | 46 +++++- 5 files changed, 288 insertions(+), 68 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java index 03179f1e29d..ce2f646322c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportDDIServiceBean.java @@ -10,6 +10,8 @@ import edu.harvard.iq.dataverse.api.dto.MetadataBlockDTO; import edu.harvard.iq.dataverse.api.imports.ImportUtil.ImportType; import static edu.harvard.iq.dataverse.export.ddi.DdiExportUtil.NOTE_TYPE_CONTENTTYPE; +import static edu.harvard.iq.dataverse.export.ddi.DdiExportUtil.NOTE_TYPE_TERMS_OF_ACCESS; + import edu.harvard.iq.dataverse.util.StringUtil; import java.io.File; import java.io.FileInputStream; @@ -267,18 +269,18 @@ private void processCodeBook(ImportType importType, XMLStreamReader xmlr, Datase } } } - + private void processDocDscr(XMLStreamReader xmlr, DatasetDTO datasetDTO) throws XMLStreamException { for (int event = xmlr.next(); event != XMLStreamConstants.END_DOCUMENT; event = xmlr.next()) { if (event == XMLStreamConstants.START_ELEMENT) { - + if (xmlr.getLocalName().equals("IDNo") && StringUtil.isEmpty(datasetDTO.getIdentifier()) ) { // this will set a StudyId if it has not yet been set; it will get overridden by a metadata // id in the StudyDscr section, if one exists if ( AGENCY_HANDLE.equals( xmlr.getAttributeValue(null, "agency") ) ) { parseStudyIdHandle( parseText(xmlr), datasetDTO ); - } - // EMK TODO: we need to save this somewhere when we add harvesting infrastructure + } + // EMK TODO: we need to save this somewhere when we add harvesting infrastructure } /*else if ( xmlr.getLocalName().equals("holdings") && StringUtil.isEmpty(datasetDTO..getHarvestHoldings()) ) { metadata.setHarvestHoldings( xmlr.getAttributeValue(null, "URI") ); }*/ @@ -286,7 +288,7 @@ private void processDocDscr(XMLStreamReader xmlr, DatasetDTO datasetDTO) throws if (xmlr.getLocalName().equals("docDscr")) return; } } - } + } private String parseText(XMLStreamReader xmlr) throws XMLStreamException { return parseText(xmlr,true); } @@ -393,41 +395,12 @@ else if (xmlr.getLocalName().equals("relStdy")) { relStudy.add(parseText(xmlr, "relStdy")); getCitation(dvDTO).addField(FieldDTO.createMultiplePrimitiveFieldDTO(DatasetFieldConstant.relatedDatasets, relStudy)); } else if (xmlr.getLocalName().equals("relPubl")) { - HashSet set = new HashSet<>(); - - // call new parse text logic - Object rpFromDDI = parseTextNew(xmlr, "relPubl"); - if (rpFromDDI instanceof Map) { - Map rpMap = (Map) rpFromDDI; - addToSet(set, DatasetFieldConstant.publicationCitation, rpMap.get("text")); - addToSet(set, DatasetFieldConstant.publicationIDNumber, rpMap.get("idNumber")); - addToSet(set, DatasetFieldConstant.publicationURL, rpMap.get("url")); - if (rpMap.get("idType")!=null) { - set.add(FieldDTO.createVocabFieldDTO(DatasetFieldConstant.publicationIDType, rpMap.get("idType").toLowerCase())); - } - // rp.setText((String) rpMap.get("text")); - // rp.setIdType((String) rpMap.get("idType")); - // rp.setIdNumber((String) rpMap.get("idNumber")); - // rp.setUrl((String) rpMap.get("url")); - // TODO: ask about where/whether we want to save this - // if (!replicationForFound && rpMap.get("replicationData") != null) { - // rp.setReplicationData(true); - /// replicationForFound = true; - // } - } else { - addToSet(set, DatasetFieldConstant.publicationCitation, (String) rpFromDDI); - // rp.setText( (String) rpFromDDI ); - } - publications.add(set); - - - } else if (xmlr.getLocalName().equals("othRefs")) { - + processRelPubl(xmlr, dvDTO, publications); + } else if (xmlr.getLocalName().equals("othRefs")) { List otherRefs = new ArrayList<>(); otherRefs.add(parseText(xmlr, "othRefs")); getCitation(dvDTO).addField(FieldDTO.createMultiplePrimitiveFieldDTO(DatasetFieldConstant.otherReferences, otherRefs)); - - } + } } else if (event == XMLStreamConstants.END_ELEMENT) { if (publications.size()>0) { getCitation(dvDTO).addField(FieldDTO.createMultipleCompoundFieldDTO(DatasetFieldConstant.publication, publications)); @@ -438,6 +411,49 @@ else if (xmlr.getLocalName().equals("relStdy")) { } } } + private void processRelPubl(XMLStreamReader xmlr, DatasetVersionDTO dvDTO, List> publications) throws XMLStreamException { + HashSet set = new HashSet<>(); + for (int event = xmlr.next(); event != XMLStreamConstants.END_DOCUMENT; event = xmlr.next()) { + if (event == XMLStreamConstants.START_ELEMENT) { + if (xmlr.getLocalName().equals("citation")) { + for (int event2 = xmlr.next(); event2 != XMLStreamConstants.END_DOCUMENT; event2 = xmlr.next()) { + if (event2 == XMLStreamConstants.START_ELEMENT) { + if (xmlr.getLocalName().equals("titlStmt")) { + int event3 = xmlr.next(); + if (event3 == XMLStreamConstants.START_ELEMENT) { + if (xmlr.getLocalName().equals("IDNo")) { + set.add(FieldDTO.createVocabFieldDTO(DatasetFieldConstant.publicationIDType, xmlr.getAttributeValue(null, "agency"))); + addToSet(set, DatasetFieldConstant.publicationIDNumber, parseText(xmlr)); + } + } + } else if (xmlr.getLocalName().equals("biblCit")) { + if (event2 == XMLStreamConstants.START_ELEMENT) { + if (xmlr.getLocalName().equals("biblCit")) { + addToSet(set, DatasetFieldConstant.publicationCitation, parseText(xmlr)); + } + } + } + } else if (event2 == XMLStreamConstants.END_ELEMENT) { + if (xmlr.getLocalName().equals("citation")) { + break; + } + } + + } + } else if (xmlr.getLocalName().equals("ExtLink")) { + addToSet(set, DatasetFieldConstant.publicationURL, xmlr.getAttributeValue(null, "URI")); + } + } else if (event == XMLStreamConstants.END_ELEMENT) { + if (xmlr.getLocalName().equals("relPubl")) { + if (set.size() > 0) { + publications.add(set); + } + return; + } + } + } + } + private void processCitation(ImportType importType, XMLStreamReader xmlr, DatasetDTO datasetDTO) throws XMLStreamException, ImportException { DatasetVersionDTO dvDTO = datasetDTO.getDatasetVersion(); MetadataBlockDTO citation=datasetDTO.getDatasetVersion().getMetadataBlocks().get("citation"); @@ -1159,7 +1175,16 @@ private void processDataAccs(XMLStreamReader xmlr, DatasetVersionDTO dvDTO) thro String noteType = xmlr.getAttributeValue(null, "type"); if (NOTE_TYPE_TERMS_OF_USE.equalsIgnoreCase(noteType) ) { if ( LEVEL_DV.equalsIgnoreCase(xmlr.getAttributeValue(null, "level"))) { - dvDTO.setTermsOfUse(parseText(xmlr, "notes")); + String termOfUse = parseText(xmlr, "notes"); + if (termOfUse != null && termOfUse.trim().equals("CC0 Waiver") ) { + dvDTO.setLicense("CC0"); + } else if (termOfUse != null && !termOfUse.trim().equals("")){ + dvDTO.setTermsOfUse(termOfUse); + } + } + } else if (NOTE_TYPE_TERMS_OF_ACCESS.equalsIgnoreCase(noteType) ) { + if (LEVEL_DV.equalsIgnoreCase(xmlr.getAttributeValue(null, "level"))) { + dvDTO.setTermsOfAccess(parseText(xmlr, "notes")); } } else { processNotes(xmlr, dvDTO); @@ -1266,13 +1291,16 @@ private void processDistStmt(XMLStreamReader xmlr, MetadataBlockDTO citation) th for (int event = xmlr.next(); event != XMLStreamConstants.END_DOCUMENT; event = xmlr.next()) { if (event == XMLStreamConstants.START_ELEMENT) { if (xmlr.getLocalName().equals("distrbtr")) { - HashSet set = new HashSet<>(); - addToSet(set, "distributorAbbreviation", xmlr.getAttributeValue(null, "abbr")); - addToSet(set, "distributorAffiliation", xmlr.getAttributeValue(null, "affiliation")); - addToSet(set, "distributorURL", xmlr.getAttributeValue(null, "URI")); - addToSet(set, "distributorLogoURL", xmlr.getAttributeValue(null, "role")); - addToSet(set, "distributorName", xmlr.getElementText()); - distributors.add(set); + String source = xmlr.getAttributeValue(null, "source"); + if (source == null || !source.equals("archive")) { + HashSet set = new HashSet<>(); + addToSet(set, "distributorAbbreviation", xmlr.getAttributeValue(null, "abbr")); + addToSet(set, "distributorAffiliation", xmlr.getAttributeValue(null, "affiliation")); + addToSet(set, "distributorURL", xmlr.getAttributeValue(null, "URI")); + addToSet(set, "distributorLogoURL", xmlr.getAttributeValue(null, "role")); + addToSet(set, "distributorName", xmlr.getElementText()); + distributors.add(set); + } } else if (xmlr.getLocalName().equals("contact")) { HashSet set = new HashSet<>(); @@ -1414,6 +1442,7 @@ private void processTitlStmt(XMLStreamReader xmlr, DatasetDTO datasetDTO) throws private void processRspStmt(XMLStreamReader xmlr, MetadataBlockDTO citation) throws XMLStreamException { List> authors = new ArrayList<>(); + List> contributors = new ArrayList<>(); for (int event = xmlr.next(); event != XMLStreamConstants.END_DOCUMENT; event = xmlr.next()) { if (event == XMLStreamConstants.START_ELEMENT) { if (xmlr.getLocalName().equals("AuthEnty")) { @@ -1424,12 +1453,24 @@ private void processRspStmt(XMLStreamReader xmlr, MetadataBlockDTO citation) thr authors.add(set); } } + if (xmlr.getLocalName().equals("othId")) { + HashSet set = new HashSet<>(); + set.add(FieldDTO.createVocabFieldDTO("contributorType", xmlr.getAttributeValue(null, "role") )); + addToSet(set,"contributorName", parseText(xmlr)); + if (!set.isEmpty()) { + contributors.add(set); + } + } } else if (event == XMLStreamConstants.END_ELEMENT) { if (xmlr.getLocalName().equals("rspStmt")) { if (authors.size()>0) { FieldDTO author = FieldDTO.createMultipleCompoundFieldDTO("author", authors); citation.getFields().add(author); } + if (contributors.size() > 0) { + FieldDTO contributor = FieldDTO.createMultipleCompoundFieldDTO("contributor", contributors); + citation.getFields().add(contributor); + } return; } diff --git a/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java b/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java index db019d5a39a..a29d6ac7fbc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java @@ -73,7 +73,9 @@ public class DdiExportUtil { private static final Logger logger = Logger.getLogger(DdiExportUtil.class.getCanonicalName()); public static final String NOTE_TYPE_TERMS_OF_USE = "DVN:TOU"; - public static final String NOTE_SUBJECT_TERMS_OF_USE = "Terms Of Use"; + public static final String NOTE_TYPE_TERMS_OF_ACCESS = "DVN:TOA"; + public static final String NOTE_TYPE_DATA_ACCESS_PLACE = "DVN:DAP"; + public static final String LEVEL_DV = "dv"; @@ -186,13 +188,19 @@ private static void createStdyDscr(XMLStreamWriter xmlw, DatasetDTO datasetDto) writeAttribute(xmlw, "agency", persistentAgency); xmlw.writeCharacters(persistentProtocol + ":" + persistentAuthority + "/" + persistentId); xmlw.writeEndElement(); // IDNo - + writeOtherIdElement(xmlw, version); xmlw.writeEndElement(); // titlStmt writeAuthorsElement(xmlw, version); writeProducersElement(xmlw, version); xmlw.writeStartElement("distStmt"); + if (datasetDto.getPublisher() != null && !datasetDto.getPublisher().equals("")) { + xmlw.writeStartElement("distrbtr"); + writeAttribute(xmlw, "source", "archive"); + xmlw.writeCharacters(datasetDto.getPublisher()); + xmlw.writeEndElement(); //distrbtr + } writeDistributorsElement(xmlw, version); writeContactsElement(xmlw, version); writeFullElement(xmlw, "distDate", dto2Primitive(version, DatasetFieldConstant.distributionDate)); @@ -245,23 +253,27 @@ private static void writeDataAccess(XMLStreamWriter xmlw , DatasetVersionDTO ver xmlw.writeCharacters(version.getTermsOfUse()); xmlw.writeEndElement(); //notes } - /*else if (xmlr.getLocalName().equals("notes")) { - String noteType = xmlr.getAttributeValue(null, "type"); - if (NOTE_TYPE_TERMS_OF_USE.equalsIgnoreCase(noteType) ) { - if ( LEVEL_DV.equalsIgnoreCase(xmlr.getAttributeValue(null, "level"))) { - dvDTO.setTermsOfUse(parseText(xmlr, "notes")); - }*/ + if (version.getTermsOfAccess() != null && !version.getTermsOfAccess().trim().equals("")) { + xmlw.writeStartElement("notes"); + writeAttribute(xmlw, "type", NOTE_TYPE_TERMS_OF_ACCESS); + writeAttribute(xmlw, "level", LEVEL_DV); + xmlw.writeCharacters(version.getTermsOfAccess()); + xmlw.writeEndElement(); //notes + } + + xmlw.writeStartElement("setAvail"); writeFullElement(xmlw, "accsPlac", version.getDataAccessPlace()); writeFullElement(xmlw, "origArch", version.getOriginalArchive()); writeFullElement(xmlw, "avlStatus", version.getAvailabilityStatus()); writeFullElement(xmlw, "collSize", version.getSizeOfCollection()); writeFullElement(xmlw, "complete", version.getStudyCompletion()); + xmlw.writeEndElement(); //setAvail xmlw.writeStartElement("useStmt"); writeFullElement(xmlw, "confDec", version.getConfidentialityDeclaration()); writeFullElement(xmlw, "specPerm", version.getSpecialPermissions()); writeFullElement(xmlw, "restrctn", version.getRestrictions()); writeFullElement(xmlw, "contact", version.getContactForAccess()); - writeFullElement(xmlw, "citeReq", version.getCitationRequirements()); + writeFullElement(xmlw, "citReq", version.getCitationRequirements()); writeFullElement(xmlw, "deposReq", version.getDepositorRequirements()); writeFullElement(xmlw, "conditions", version.getConditions()); writeFullElement(xmlw, "disclaimer", version.getDisclaimer()); @@ -293,10 +305,15 @@ private static void writeDocDescElement (XMLStreamWriter xmlw, DatasetDTO datase xmlw.writeStartElement("IDNo"); writeAttribute(xmlw, "agency", persistentAgency); xmlw.writeCharacters(persistentProtocol + ":" + persistentAuthority + "/" + persistentId); - xmlw.writeEndElement(); // IDNo + xmlw.writeEndElement(); // IDNo xmlw.writeEndElement(); // titlStmt xmlw.writeStartElement("distStmt"); - writeFullElement(xmlw, "distrbtr", datasetDto.getPublisher()); + if (datasetDto.getPublisher() != null && !datasetDto.getPublisher().equals("")) { + xmlw.writeStartElement("distrbtr"); + writeAttribute(xmlw, "source", "archive"); + xmlw.writeCharacters(datasetDto.getPublisher()); + xmlw.writeEndElement(); // distrbtr + } writeFullElement(xmlw, "distDate", datasetDto.getPublicationDate()); xmlw.writeEndElement(); // diststmt @@ -606,9 +623,9 @@ private static void writeAuthorsElement(XMLStreamWriter xmlw, DatasetVersionDTO String key = entry.getKey(); MetadataBlockDTO value = entry.getValue(); if ("citation".equals(key)) { + xmlw.writeStartElement("rspStmt"); for (FieldDTO fieldDTO : value.getFields()) { if (DatasetFieldConstant.author.equals(fieldDTO.getTypeName())) { - xmlw.writeStartElement("rspStmt"); String authorName = ""; String authorAffiliation = ""; for (HashSet foo : fieldDTO.getMultipleCompound()) { @@ -630,10 +647,34 @@ private static void writeAuthorsElement(XMLStreamWriter xmlw, DatasetVersionDTO xmlw.writeEndElement(); //AuthEnty } } - xmlw.writeEndElement(); //rspStmt + + } else if (DatasetFieldConstant.contributor.equals(fieldDTO.getTypeName())) { + String contributorName = ""; + String contributorType = ""; + for (HashSet foo : fieldDTO.getMultipleCompound()) { + for (Iterator iterator = foo.iterator(); iterator.hasNext();) { + FieldDTO next = iterator.next(); + if (DatasetFieldConstant.contributorName.equals(next.getTypeName())) { + contributorName = next.getSinglePrimitive(); + } + if (DatasetFieldConstant.contributorType.equals(next.getTypeName())) { + contributorType = next.getSinglePrimitive(); + } + } + if (!contributorName.isEmpty()){ + xmlw.writeStartElement("othId"); + if(!contributorType.isEmpty()){ + writeAttribute(xmlw,"role", contributorType); + } + xmlw.writeCharacters(contributorName); + xmlw.writeEndElement(); //othId + } + } } } + xmlw.writeEndElement(); //rspStmt } + } } @@ -832,12 +873,27 @@ private static void writeRelPublElement(XMLStreamWriter xmlw, DatasetVersionDTO url = next.getSinglePrimitive(); } } - pubString = appendCommaSeparatedValue(citation, IDType); - pubString = appendCommaSeparatedValue(pubString, IDNo); - pubString = appendCommaSeparatedValue(pubString, url); - if (!pubString.isEmpty()){ - xmlw.writeStartElement("relPubl"); - xmlw.writeCharacters(pubString); + if (citation != null && !citation.trim().equals("")) { + xmlw.writeStartElement("relPubl"); + xmlw.writeStartElement("citation"); + if (IDNo != null && !IDNo.trim().equals("")) { + xmlw.writeStartElement("titlStmt"); + xmlw.writeStartElement("IDNo"); + if (IDType != null && !IDType.trim().equals("")) { + xmlw.writeAttribute("agency", IDType ); + } + xmlw.writeCharacters(IDNo); + xmlw.writeEndElement(); //IDNo + xmlw.writeEndElement(); // titlStmt + } + + writeFullElement(xmlw,"biblCit",citation); + xmlw.writeEndElement(); //citation + if (url != null && !url.trim().equals("") ) { + xmlw.writeStartElement("ExtLink"); + xmlw.writeAttribute("URI", url); + xmlw.writeEndElement(); //ExtLink + } xmlw.writeEndElement(); //relPubl } } diff --git a/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-create-new-all-ddi-fields.json b/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-create-new-all-ddi-fields.json index 31d43eb5377..8930938d1af 100644 --- a/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-create-new-all-ddi-fields.json +++ b/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-create-new-all-ddi-fields.json @@ -17,6 +17,20 @@ "createTime": "2015-09-24T16:47:51Z", "license": "CC0", "termsOfUse": "CC0 Waiver", + "termsOfAccess": "Terms of Access", + "dataAccessPlace": "Data Access Place", + "originalArchive": "Original Archive", + "availabilityStatus": "Availability Status", + "sizeOfCollection": "Size of Collection", + "studyCompletion": "Study Completion", + "confidentialityDeclaration": "Confidentiality Declaration", + "specialPermissions": "Special Permissions", + "restrictions": "Restrictions", + "contactForAccess": "Contact for Access", + "citationRequirements": "Citation Requirements", + "depositorRequirements": "Depositor Requirements", + "conditions": "Conditions ", + "disclaimer": "Disclaimer", "metadataBlocks": { "citation": { "displayName": "Citation Metadata", @@ -39,6 +53,41 @@ "typeClass": "primitive", "value": "Alternative Title" }, + { + "typeName": "otherId", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "otherIdAgency": { + "typeName": "otherIdAgency", + "multiple": false, + "typeClass": "primitive", + "value": "OtherIDAgency1" + }, + "otherIdValue": { + "typeName": "otherIdValue", + "multiple": false, + "typeClass": "primitive", + "value": "OtherIDIdentifier1" + } + }, + { + "otherIdAgency": { + "typeName": "otherIdAgency", + "multiple": false, + "typeClass": "primitive", + "value": "OtherIDAgency2" + }, + "otherIdValue": { + "typeName": "otherIdValue", + "multiple": false, + "typeClass": "primitive", + "value": "OtherIDIdentifier2" + } + } + ] + }, { "typeName": "author", "multiple": true, @@ -362,6 +411,41 @@ "typeClass": "primitive", "value": "ProductionPlace" }, + { + "typeName": "contributor", + "multiple": true, + "typeClass": "compound", + "value": [ + { + "contributorType": { + "typeName": "contributorType", + "multiple": false, + "typeClass": "controlledVocabulary", + "value": "Data Collector" + }, + "contributorName": { + "typeName": "contributorName", + "multiple": false, + "typeClass": "primitive", + "value": "LastContributor1, FirstContributor1" + } + }, + { + "contributorType": { + "typeName": "contributorType", + "multiple": false, + "typeClass": "controlledVocabulary", + "value": "Data Curator" + }, + "contributorName": { + "typeName": "contributorName", + "multiple": false, + "typeClass": "primitive", + "value": "LastContributor2, FirstContributor2" + } + } + ] + }, { "typeName": "grantNumber", "multiple": true, diff --git a/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-finch1.xml b/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-finch1.xml index 3e9fa6b0561..79e9e363994 100644 --- a/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-finch1.xml +++ b/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-finch1.xml @@ -64,6 +64,7 @@ + diff --git a/src/test/java/edu/harvard/iq/dataverse/export/ddi/exportfull.xml b/src/test/java/edu/harvard/iq/dataverse/export/ddi/exportfull.xml index 390f1968d9a..d9be1217fc9 100644 --- a/src/test/java/edu/harvard/iq/dataverse/export/ddi/exportfull.xml +++ b/src/test/java/edu/harvard/iq/dataverse/export/ddi/exportfull.xml @@ -7,7 +7,7 @@ doi:10.5072/FK2/WKUKGV - Root + Root 2020-02-19 @@ -23,10 +23,14 @@ Subtitle Alternative Title doi:10.5072/FK2/WKUKGV + OtherIDIdentifier1 + OtherIDIdentifier2 LastAuthor1, FirstAuthor1 LastAuthor2, FirstAuthor2 + LastContributor1, FirstContributor1 + LastContributor2, FirstContributor2 LastProducer1, FirstProducer1 @@ -39,6 +43,7 @@ GrantInformationGrantNumber2 + Root LastDistributor1, FirstDistributor1 LastDistributor2, FirstDistributor2 LastContact1, FirstContact1 @@ -139,15 +144,48 @@ CC0 Waiver - + Terms of Access + + Data Access Place + Original Archive + Availability Status + Size of Collection + Study Completion + + + Confidentiality Declaration + Special Permissions + Restrictions + Contact for Access + Citation Requirements + Depositor Requirements + Conditions + Disclaimer + RelatedMaterial1 RelatedMaterial2 RelatedDatasets1 RelatedDatasets2 - RelatedPublicationCitation1, ark, RelatedPublicationIDNumber1, http://RelatedPublicationURL1.org - RelatedPublicationCitation2, arXiv, RelatedPublicationIDNumber2, http://RelatedPublicationURL2.org + + + + RelatedPublicationIDNumber1 + + RelatedPublicationCitation1 + + + + + + + RelatedPublicationIDNumber2 + + RelatedPublicationCitation2 + + + OtherReferences1 OtherReferences2 From 0052eeff66ef7008bdf9ce98a35c4275bb95720a Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 3 Mar 2020 10:28:25 -0500 Subject: [PATCH 366/475] give default selection a value Conflicts: src/main/webapp/dataverse.xhtml --- src/main/java/edu/harvard/iq/dataverse/Dataverse.java | 6 +++++- src/main/java/edu/harvard/iq/dataverse/DataversePage.java | 2 +- src/main/webapp/dataverse.xhtml | 3 +-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java index 4b53937a87f..3774e7576d6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java @@ -778,6 +778,10 @@ public String getStorageDriverId() { } public void setStorageDriverId(String storageDriver) { - this.storageDriver = storageDriver; + if(storageDriver!=null&&storageDriver.equals("default")) { + this.storageDriver=null; + } else { + this.storageDriver = storageDriver; + } } } diff --git a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java index 12f398c9c7d..9684071fe1e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java @@ -1214,7 +1214,7 @@ public Set> getStorageDriverOptions() { HashMap drivers =new HashMap(); drivers.putAll(DataAccess.getStorageDriverLabels()); //Add an entry for the default (inherited from an ancestor or the system default) - drivers.put(getDefaultStorageDriverLabel(), ""); + drivers.put(getDefaultStorageDriverLabel(), "default"); return drivers.entrySet(); } diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index e42630bb07b..323d501ed82 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -147,8 +147,7 @@ data-toggle="tooltip" data-placement="auto right" data-original-title="#{bundle['dataverse.storage.title']}">
- - + From 48d176ea9142858e76f5970e44427dc8aeb7d4c0 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 3 Mar 2020 10:48:39 -0500 Subject: [PATCH 367/475] typo --- src/main/webapp/dataverse.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index 323d501ed82..8530b149001 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -147,7 +147,7 @@ data-toggle="tooltip" data-placement="auto right" data-original-title="#{bundle['dataverse.storage.title']}">
- + From 94abdda08298476a38936ea8592a06495971ddfc Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 3 Mar 2020 11:39:14 -0500 Subject: [PATCH 368/475] use non-null indicator for default for reported dataverse.storageIdentifier value Also fix fromAncestor logic Conflicts: src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java --- .../java/edu/harvard/iq/dataverse/Dataverse.java | 5 ++++- .../edu/harvard/iq/dataverse/DataversePage.java | 15 ++++++++++----- .../java/edu/harvard/iq/dataverse/api/Admin.java | 2 +- .../iq/dataverse/dataaccess/DataAccess.java | 5 +++-- src/main/webapp/dataverse.xhtml | 2 +- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java index 3774e7576d6..0eea108c461 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java @@ -774,11 +774,14 @@ public String getEffectiveStorageDriverId() { public String getStorageDriverId() { + if(storageDriver==null) { + return DataAccess.UNDEFINED_STORAGE_DRIVER_IDENTIFIER; + } return storageDriver; } public void setStorageDriverId(String storageDriver) { - if(storageDriver!=null&&storageDriver.equals("default")) { + if(storageDriver!=null&&storageDriver.equals(DataAccess.UNDEFINED_STORAGE_DRIVER_IDENTIFIER)) { this.storageDriver=null; } else { this.storageDriver = storageDriver; diff --git a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java index 9684071fe1e..165c1759b5e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataversePage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataversePage.java @@ -1214,19 +1214,24 @@ public Set> getStorageDriverOptions() { HashMap drivers =new HashMap(); drivers.putAll(DataAccess.getStorageDriverLabels()); //Add an entry for the default (inherited from an ancestor or the system default) - drivers.put(getDefaultStorageDriverLabel(), "default"); + drivers.put(getDefaultStorageDriverLabel(), DataAccess.UNDEFINED_STORAGE_DRIVER_IDENTIFIER); return drivers.entrySet(); } public String getDefaultStorageDriverLabel() { String storageDriverId = DataAccess.DEFAULT_STORAGE_DRIVER_IDENTIFIER; Dataverse parent = dataverse.getOwner(); + boolean fromAncestor=false; if(parent != null) { storageDriverId = parent.getEffectiveStorageDriverId(); - } - boolean fromAncestor=false; - if(!storageDriverId.equals(DataAccess.DEFAULT_STORAGE_DRIVER_IDENTIFIER)) { - fromAncestor = true; + //recurse dataverse chain to root and if any have a storagedriver set, fromAncestor is true + while(parent!=null) { + if(!parent.getStorageDriverId().equals(DataAccess.UNDEFINED_STORAGE_DRIVER_IDENTIFIER)) { + fromAncestor=true; + break; + } + parent=parent.getOwner(); + } } String label = DataAccess.getStorageDriverLabelFor(storageDriverId); if(fromAncestor) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index c5f358e8f71..1474104d379 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -1665,7 +1665,7 @@ public Response getStorageDriver(@PathParam("alias") String alias) throws Wrappe } catch (WrappedResponse wr) { return wr.getResponse(); } - //Note that this returns what's set directly on this dataverse. If null, the user would have to recurse the chain of parents to find the effective storageDriver + //Note that this returns what's set directly on this dataverse. If null/DataAccess.UNDEFINED_STORAGE_DRIVER_IDENTIFIER, the user would have to recurse the chain of parents to find the effective storageDriver return ok(dataverse.getStorageDriverId()); } diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index ed4fc24742a..4955f404e40 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -41,9 +41,10 @@ public DataAccess() { }; - //Default is only for tests - public static final String DEFAULT_STORAGE_DRIVER_IDENTIFIER = System.getProperty("dataverse.files.storage-driver-id", "file"); + public static final String DEFAULT_STORAGE_DRIVER_IDENTIFIER = System.getProperty("dataverse.files.storage-driver-id"); + public static final String UNDEFINED_STORAGE_DRIVER_IDENTIFIER = "undefined"; //Used in dataverse.xhtml as a non-null selection option value (indicating a null driver/inheriting the default) + // The getStorageIO() methods initialize StorageIO objects for // datafiles that are already saved using one of the supported Dataverse // DataAccess IO drivers. diff --git a/src/main/webapp/dataverse.xhtml b/src/main/webapp/dataverse.xhtml index 8530b149001..06edc64f1a6 100644 --- a/src/main/webapp/dataverse.xhtml +++ b/src/main/webapp/dataverse.xhtml @@ -147,7 +147,7 @@ data-toggle="tooltip" data-placement="auto right" data-original-title="#{bundle['dataverse.storage.title']}">
- + From 17936daf787bac9dfd0db4b40a0cf82ab5e9b5fb Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 3 Mar 2020 12:30:07 -0500 Subject: [PATCH 369/475] using S3 tag for temp files --- .../iq/dataverse/dataaccess/S3AccessIO.java | 28 +++++++++++++++++++ .../dataverse/ingest/IngestServiceBean.java | 4 +++ src/main/webapp/resources/js/fileupload.js | 1 + 3 files changed, 33 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index 9180eb502d2..bb4c6c9a078 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -7,10 +7,12 @@ import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.Headers; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.CopyObjectRequest; import com.amazonaws.services.s3.model.DeleteObjectRequest; +import com.amazonaws.services.s3.model.DeleteObjectTaggingRequest; import com.amazonaws.services.s3.model.DeleteObjectsRequest; import com.amazonaws.services.s3.model.DeleteObjectsRequest.KeyVersion; import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; @@ -851,6 +853,9 @@ public String generateTemporaryS3UploadUrl() throws IOException { GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key).withMethod(HttpMethod.PUT).withExpiration(expiration); + //Require user to add this header to indicate a temporary file + generatePresignedUrlRequest.putCustomRequestHeader(Headers.S3_TAGGING, "dv-state=temp"); + URL presignedUrl; try { presignedUrl = s3.generatePresignedUrl(generatePresignedUrlRequest); @@ -925,4 +930,27 @@ private void readSettings() { bucketName = System.getProperty("dataverse.files." + this.driverId + ".bucket-name"); } + + public void removeTempTag() throws IOException { + if (!(dvObject instanceof DataFile)) { + logger.warning("Attempt to remove tag from non-file DVObject id: " + dvObject.getId()); + throw new IOException("Attempt to remove temp tag from non-file S3 Object"); + } + try { + + key = getMainFileKey(); + DeleteObjectTaggingRequest deleteObjectTaggingRequest = new DeleteObjectTaggingRequest(bucketName, key); + //NOte - currently we only use one tag so delete is the fastest and cheapest way to get rid of that one tag + //Otherwise you have to get tags, remove the one you don't want and post new tags and get charged for the operations + s3.deleteObjectTagging(deleteObjectTaggingRequest); + } catch (SdkClientException sce) { + logger.severe("Unable to remove temp tag from : " + bucketName + " : " + key); + throw new IOException("Cannot remove temp tag from S3 object " + bucketName + " : " + key + " ("+sce.getMessage()+")"); + } catch (IOException e) { + logger.warning("Could not create key for S3 object." ); + e.printStackTrace(); + } + + } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java index c50257956f4..b9573b4aade 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java @@ -44,6 +44,7 @@ import edu.harvard.iq.dataverse.dataaccess.DataAccessOption; import edu.harvard.iq.dataverse.dataaccess.StorageIO; import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter; +import edu.harvard.iq.dataverse.dataaccess.S3AccessIO; import edu.harvard.iq.dataverse.dataaccess.TabularSubsetGenerator; import edu.harvard.iq.dataverse.datavariable.SummaryStatistic; import edu.harvard.iq.dataverse.datavariable.DataVariable; @@ -301,6 +302,9 @@ public List saveAndAddFilesToDataset(DatasetVersion version, List)dataAccess).removeTempTag(); + } } catch (IOException ioex) { logger.warning("Failed to get file size, storage id " + dataFile.getStorageIdentifier() + " (" + ioex.getMessage() + ")"); diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index 83d42b9f417..b177fed7df7 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -51,6 +51,7 @@ function uploadFileDirectly(url, storageId) { $('.ui-fileupload-progress').append($('').attr('class', 'ui-progressbar ui-widget ui-widget-content ui-corner-all')); $.ajax({ url: url, + headers: {"x-amz-tagging":"dv-state=temp"}, type: 'PUT', data: file, cache: false, From 34c8ee2377428db1b89cfac80e07d649bd62dda3 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 3 Mar 2020 14:03:55 -0500 Subject: [PATCH 370/475] ignore tag issues on Minio --- .../edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java | 9 +++++++-- .../harvard/iq/dataverse/ingest/IngestServiceBean.java | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index bb4c6c9a078..7b6979ff1a7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -944,8 +944,13 @@ public void removeTempTag() throws IOException { //Otherwise you have to get tags, remove the one you don't want and post new tags and get charged for the operations s3.deleteObjectTagging(deleteObjectTaggingRequest); } catch (SdkClientException sce) { - logger.severe("Unable to remove temp tag from : " + bucketName + " : " + key); - throw new IOException("Cannot remove temp tag from S3 object " + bucketName + " : " + key + " ("+sce.getMessage()+")"); + if(sce.getMessage().contains("Status Code: 501")) { + // In this case, it's likely that tags are not implemented at all (e.g. by Minio) so no tag was set either and it's just something to be aware of + logger.warning("Temp tag not deleted: Object tags not supported by storage: " + driverId); + } else { + // In this case, the assumption is that adding tags has worked, so not removing it is a problem that should be looked into. + logger.severe("Unable to remove temp tag from : " + bucketName + " : " + key); + } } catch (IOException e) { logger.warning("Could not create key for S3 object." ); e.printStackTrace(); diff --git a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java index b9573b4aade..c2a2a13c272 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java @@ -303,7 +303,7 @@ public List saveAndAddFilesToDataset(DatasetVersion version, List)dataAccess).removeTempTag(); + ((S3AccessIO)dataAccess).removeTempTag(); } } catch (IOException ioex) { logger.warning("Failed to get file size, storage id " + dataFile.getStorageIdentifier() + " (" From 5c721ff24512bb2b8036f74d3ffd6b6b0e1a82f6 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 3 Mar 2020 14:04:05 -0500 Subject: [PATCH 371/475] new progress color --- src/main/webapp/resources/css/structure.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/resources/css/structure.css b/src/main/webapp/resources/css/structure.css index 44ee913c385..e6fd0a110b6 100644 --- a/src/main/webapp/resources/css/structure.css +++ b/src/main/webapp/resources/css/structure.css @@ -979,5 +979,5 @@ progress::-webkit-progress-bar { } progress::-webkit-progress-value { - background-color:#0e90d2; + background-color:green; } From 2a78a68e9125fd28915bf42f088af9cb14364dd5 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 3 Mar 2020 17:35:03 -0500 Subject: [PATCH 372/475] remove obsolete storage default string --- src/main/java/propertyFiles/Bundle.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index ae4dcab6a57..504f3bd3dec 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -693,7 +693,6 @@ dataverse.host.autocomplete.nomatches=No matches dataverse.identifier.title=Short name used for the URL of this dataverse. dataverse.affiliation.title=The organization with which this dataverse is affiliated. dataverse.storage.title=A storage service to be used for datasets in this dataverse. -dataverse.storage.usedefault=Use Default dataverse.category=Category dataverse.category.title=The type that most closely reflects this dataverse. dataverse.type.selectTab.top=Select one... From dcc62f379a6389643dbc900ba70005257617e456 Mon Sep 17 00:00:00 2001 From: Pete Meyer Date: Tue, 3 Mar 2020 17:54:10 -0500 Subject: [PATCH 373/475] match the start and end dataverse specific comment blocks in solr schema --- conf/solr/7.7.2/schema.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/solr/7.7.2/schema.xml b/conf/solr/7.7.2/schema.xml index 6c377d2e92c..da40a8e99fa 100644 --- a/conf/solr/7.7.2/schema.xml +++ b/conf/solr/7.7.2/schema.xml @@ -293,7 +293,7 @@ - + From 66a48ee2cfa98454989751dca7d1a49e6f708169 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 3 Mar 2020 19:07:48 -0500 Subject: [PATCH 374/475] remove unused methods and tests of them --- .../datasetutility/FileSizeChecker.java | 111 +++--------------- .../datasetutility/FileSizeCheckerTest.java | 67 ----------- 2 files changed, 19 insertions(+), 159 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileSizeChecker.java b/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileSizeChecker.java index 8d24270c76c..06b3f467867 100644 --- a/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileSizeChecker.java +++ b/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileSizeChecker.java @@ -6,9 +6,6 @@ package edu.harvard.iq.dataverse.datasetutility; import edu.harvard.iq.dataverse.util.BundleUtil; -import edu.harvard.iq.dataverse.util.SystemConfig; -import java.util.Collections; -import java.util.logging.Logger; /** * Convenience methods for checking max. file size @@ -16,94 +13,24 @@ */ public class FileSizeChecker { - private static final Logger logger = Logger.getLogger(FileSizeChecker.class.getCanonicalName()); + /* This method turns a number of bytes into a human readable version + */ + public static String bytesToHumanReadable(long v) { + return bytesToHumanReadable(v, 1); + } + + /* This method turns a number of bytes into a human readable version + * with figs decimal places + */ + public static String bytesToHumanReadable(long v, int figs) { + if (v < 1024) { + return v + " " + BundleUtil.getStringFromBundle("file.addreplace.error.byte_abrev"); + } + // 63 - because long has 63 binary digits + int trailingBin0s = (63 - Long.numberOfLeadingZeros(v))/10; + //String base = "%."+figs+"f %s"+ BundleUtil.getStringFromBundle("file.addreplace.error.byte_abrev"); + return String.format("%."+figs+"f %s"+ BundleUtil.getStringFromBundle("file.addreplace.error.byte_abrev"), (double)v / (1L << (trailingBin0s*10)), + " KMGTPE".charAt(trailingBin0s)); + } - SystemConfig systemConfig; - - /** - * constructor - */ - public FileSizeChecker(SystemConfig systemConfig){ - if (systemConfig == null){ - throw new NullPointerException("systemConfig cannot be null"); - } - this.systemConfig = systemConfig; - } - - public FileSizeResponse isAllowedFileSize(Long filesize){ - - if (filesize == null){ - throw new NullPointerException("filesize cannot be null"); - //return new FileSizeResponse(false, "The file size could not be found!"); - } - - Long maxFileSize = systemConfig.getMaxFileUploadSize(); - - // If no maxFileSize in the database, set it to unlimited! - // - if (maxFileSize == null){ - return new FileSizeResponse(true, - BundleUtil.getStringFromBundle("file.addreplace.file_size_ok") - ); - } - - // Good size! - // - if (filesize <= maxFileSize){ - return new FileSizeResponse(true, - BundleUtil.getStringFromBundle("file.addreplace.file_size_ok") - ); - } - - // Nope! Sorry! File is too big - // - String errMsg = BundleUtil.getStringFromBundle("file.addreplace.error.file_exceeds_limit", Collections.singletonList(bytesToHumanReadable(maxFileSize))); - - return new FileSizeResponse(false, errMsg); - - } - - /* This method turns a number of bytes into a human readable version - */ - public static String bytesToHumanReadable(long v) { - return bytesToHumanReadable(v, 1); - } - - /* This method turns a number of bytes into a human readable version - * with figs decimal places - */ - public static String bytesToHumanReadable(long v, int figs) { - if (v < 1024) { - return v + " " + BundleUtil.getStringFromBundle("file.addreplace.error.byte_abrev"); - } - // 63 - because long has 63 binary digits - int trailingBin0s = (63 - Long.numberOfLeadingZeros(v))/10; - //String base = "%."+figs+"f %s"+ BundleUtil.getStringFromBundle("file.addreplace.error.byte_abrev"); - return String.format("%."+figs+"f %s"+ BundleUtil.getStringFromBundle("file.addreplace.error.byte_abrev"), (double)v / (1L << (trailingBin0s*10)), - " KMGTPE".charAt(trailingBin0s)); - } - - /** - * Inner class that can also return an error message - */ - public class FileSizeResponse{ - - public boolean fileSizeOK; - public String userMsg; - - public FileSizeResponse(boolean isOk, String msg){ - - fileSizeOK = isOk; - userMsg = msg; - } - - public boolean isFileSizeOK(){ - return fileSizeOK; - } - - public String getUserMessage(){ - return userMsg; - } - - } // end inner class } diff --git a/src/test/java/edu/harvard/iq/dataverse/datasetutility/FileSizeCheckerTest.java b/src/test/java/edu/harvard/iq/dataverse/datasetutility/FileSizeCheckerTest.java index e562e3f9e0c..824dc6794fe 100644 --- a/src/test/java/edu/harvard/iq/dataverse/datasetutility/FileSizeCheckerTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/datasetutility/FileSizeCheckerTest.java @@ -7,22 +7,13 @@ import static edu.harvard.iq.dataverse.datasetutility.FileSizeChecker.bytesToHumanReadable; -import edu.harvard.iq.dataverse.datasetutility.FileSizeChecker.FileSizeResponse; import edu.harvard.iq.dataverse.util.BundleUtil; -import edu.harvard.iq.dataverse.util.SystemConfig; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; /** * @@ -44,62 +35,4 @@ public void testBytesToHumanReadable() { assertEquals(expAns, ans); assertEquals(expLongAns, longAns); } - - @Test - public void testIsAllowedFileSize_throwsOnNull() { - FileSizeChecker fileSizeChecker = new FileSizeChecker(new SystemConfig() { - @Override - public Long getMaxFileUploadSize() { - return 1000L; - } - }); - assertThrows(NullPointerException.class, () -> { - fileSizeChecker.isAllowedFileSize(null); - }); - } - - @ParameterizedTest - @ValueSource(longs = { 0L, 999L, 1000L }) - public void testIsAllowedFileSize_allowsSmallerOrEqualFileSize(Long fileSize) { - // initialize a system config and instantiate a file size checker - // override the max file upload side to allow for testing - FileSizeChecker fileSizeChecker = new FileSizeChecker(new SystemConfig() { - @Override - public Long getMaxFileUploadSize() { - return 1000L; - } - }); - FileSizeResponse response = fileSizeChecker.isAllowedFileSize(fileSize); - assertTrue(response.fileSizeOK); - } - - @ParameterizedTest - @ValueSource(longs = { 1001L, Long.MAX_VALUE }) - public void testIsAllowedFileSize_rejectsBiggerFileSize(Long fileSize) { - // initialize a system config and instantiate a file size checker - // override the max file upload side to allow for testing - FileSizeChecker fileSizeChecker = new FileSizeChecker(new SystemConfig() { - @Override - public Long getMaxFileUploadSize() { - return 1000L; - } - }); - FileSizeResponse response = fileSizeChecker.isAllowedFileSize(fileSize); - assertFalse(response.fileSizeOK); - } - - @ParameterizedTest - @ValueSource(longs = { 0L, 1000L, Long.MAX_VALUE }) - public void testIsAllowedFileSize_allowsOnUnboundedFileSize(Long fileSize) { - // initialize a system config and instantiate a file size checker - // ensure that a max filesize is not set - FileSizeChecker unboundedFileSizeChecker = new FileSizeChecker(new SystemConfig() { - @Override - public Long getMaxFileUploadSize() { - return null; - } - }); - FileSizeResponse response = unboundedFileSizeChecker.isAllowedFileSize(fileSize); - assertTrue(response.fileSizeOK); - } } From 560c97338a9a9e7d94fc7547221a1efebc19d7d3 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 3 Mar 2020 19:08:29 -0500 Subject: [PATCH 375/475] make max file size limit per store --- .../edu/harvard/iq/dataverse/DatasetPage.java | 2 +- .../iq/dataverse/EditDatafilesPage.java | 16 +++---- .../datadeposit/SwordConfigurationImpl.java | 7 ++- .../settings/SettingsServiceBean.java | 46 ++++++++++++++++++- .../harvard/iq/dataverse/util/FileUtil.java | 2 +- .../iq/dataverse/util/SystemConfig.java | 8 ++-- 6 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index 690443d4def..67a09a9a62a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -1774,7 +1774,7 @@ public void updateOwnerDataverse() { private String init(boolean initFull) { //System.out.println("_YE_OLDE_QUERY_COUNTER_"); // for debug purposes - this.maxFileUploadSizeInBytes = systemConfig.getMaxFileUploadSize(); + this.maxFileUploadSizeInBytes = systemConfig.getMaxFileUploadSizeForStore(dataset.getOwner().getEffectiveStorageDriverId()); setDataverseSiteUrl(systemConfig.getDataverseSiteUrl()); guestbookResponse = new GuestbookResponse(); diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 681c9c15dd9..971a62666f2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -450,10 +450,7 @@ public String initCreateMode(String modeToken, DatasetVersion version, List(); selectedFiles = selectedFileMetadatasList; + this.maxFileUploadSizeInBytes = systemConfig.getMaxFileUploadSizeForStore(dataset.getOwner().getEffectiveStorageDriverId()); + this.multipleUploadFilesLimit = systemConfig.getMultipleUploadFilesLimit(); + logger.fine("done"); saveEnabled = true; @@ -473,9 +473,6 @@ public String init() { newFiles = new ArrayList<>(); uploadedFiles = new ArrayList<>(); - this.maxFileUploadSizeInBytes = systemConfig.getMaxFileUploadSize(); - this.multipleUploadFilesLimit = systemConfig.getMultipleUploadFilesLimit(); - if (dataset.getId() != null){ // Set Working Version and Dataset by Datasaet Id and Version //retrieveDatasetVersionResponse = datasetVersionService.retrieveDatasetVersionById(dataset.getId(), null); @@ -490,7 +487,10 @@ public String init() { // that the dataset id is mandatory... But 404 will do for now. return permissionsWrapper.notFound(); } - + + this.maxFileUploadSizeInBytes = systemConfig.getMaxFileUploadSizeForStore(dataset.getOwner().getEffectiveStorageDriverId()); + this.multipleUploadFilesLimit = systemConfig.getMultipleUploadFilesLimit(); + workingVersion = dataset.getEditVersion(); clone = workingVersion.cloneDatasetVersion(); if (workingVersion == null || !workingVersion.isDraft()) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordConfigurationImpl.java b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordConfigurationImpl.java index 4eb6e77fe21..ce5f9415fcc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordConfigurationImpl.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordConfigurationImpl.java @@ -124,8 +124,11 @@ public String getTempDirectory() { public int getMaxUploadSize() { int unlimited = -1; - - Long maxUploadInBytes = systemConfig.getMaxFileUploadSize(); + /* It doesn't look like we can determine which store will be used here, so we'll go with the default + * (It looks like the collection or study involved is available where this method is called, but the SwordConfiguration.getMaxUploadSize() + * doesn't allow a parameter) + */ + Long maxUploadInBytes = systemConfig.getMaxFileUploadSizeForStore("default"); if (maxUploadInBytes == null){ // (a) No setting, return unlimited diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java index 473bea561b4..75b604eb440 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java @@ -1,9 +1,13 @@ package edu.harvard.iq.dataverse.settings; +import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.actionlogging.ActionLogRecord; import edu.harvard.iq.dataverse.actionlogging.ActionLogServiceBean; import edu.harvard.iq.dataverse.api.ApiBlockingFilter; +import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.util.StringUtil; + +import java.io.StringReader; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -12,6 +16,8 @@ import javax.ejb.EJB; import javax.ejb.Stateless; import javax.inject.Named; +import javax.json.Json; +import javax.json.JsonObject; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @@ -162,7 +168,7 @@ public enum Key { /** Enable full-text indexing in solr up to max file size */ SolrFullTextIndexing, //true or false (default) SolrMaxFileSizeForFullTextIndexing, //long - size in bytes (default unset/no limit) - /** Key for limiting the number of bytes uploaded via the Data Deposit API, UI (web site and . */ + /** Default Key for limiting the number of bytes uploaded via the Data Deposit API, UI (web site and . */ MaxFileUploadSizeInBytes, /** Key for if ScrubMigrationData is enabled or disabled. */ ScrubMigrationData, @@ -477,6 +483,44 @@ public Long getValueForKeyAsLong(Key key){ } + /** + * Attempt to convert a value in a compound key to a long + * - Applicable for keys such as MaxFileUploadSizeInBytes after multistore capabilities were added in ~v4.20 + * backward compatible with a single value. For multi values, the key's value must be an object with param:value pairs. + * A "default":value pair is allowed and will be returned for any param that doesn't have a defined value. + * + * On failure (key not found or string not convertible to a long), returns null + * @param key + * @return + */ + public Long getValueForCompoundKeyAsLong(Key key, String param){ + + String val = this.getValueForKey(key); + + if (val == null){ + return null; + } + + try { + return Long.parseLong(val); + } catch (NumberFormatException ex) { + try ( StringReader rdr = new StringReader(val) ) { + JsonObject settings = Json.createReader(rdr).readObject(); + if(settings.containsKey(param)) { + return Long.parseLong(settings.getString(param)); + } else if(settings.containsKey("default")) { + return Long.parseLong(settings.getString("default")); + } else { + return null; + } + + } catch (Exception e) { + logger.log(Level.WARNING, "Incorrect setting. Could not convert \"{0}\" from setting {1} to long.", new Object[]{val, key.toString()}); + return null; + } + } + + } /** * Return the value stored, or the default value, in case no setting by that diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index 820a7037605..f272e3ff884 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -714,7 +714,7 @@ public static List createDataFiles(DatasetVersion version, InputStream // save the file, in the temporary location for now: Path tempFile = null; - Long fileSizeLimit = systemConfig.getMaxFileUploadSize(); + Long fileSizeLimit = systemConfig.getMaxFileUploadSizeForStore(version.getDataset().getOwner().getEffectiveStorageDriverId()); String finalType = null; if (newStorageIdentifier == null) { if (getFilesTempDirectory() != null) { diff --git a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java index 8d0cb276a93..161493fa13f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java @@ -539,12 +539,12 @@ public boolean isFilesOnDatasetPageFromSolr() { return settingsService.isTrueForKey(SettingsServiceBean.Key.FilesOnDatasetPageFromSolr, safeDefaultIfKeyNotFound); } - public Long getMaxFileUploadSize(){ - return settingsService.getValueForKeyAsLong(SettingsServiceBean.Key.MaxFileUploadSizeInBytes); + public Long getMaxFileUploadSizeForStore(String driverId){ + return settingsService.getValueForCompoundKeyAsLong(SettingsServiceBean.Key.MaxFileUploadSizeInBytes, driverId); } - public String getHumanMaxFileUploadSize(){ - return bytesToHumanReadable(getMaxFileUploadSize()); + public String getHumanMaxFileUploadSizeForStore(String driverId){ + return bytesToHumanReadable(getMaxFileUploadSizeForStore(driverId)); } public Integer getSearchHighlightFragmentSize() { From 84f57a31196f04c7a72462aa6403814cd31ee53e Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 4 Mar 2020 10:37:43 -0500 Subject: [PATCH 376/475] get max file size after dataset is initialized --- src/main/java/edu/harvard/iq/dataverse/DatasetPage.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index 67a09a9a62a..ae89602e045 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -1774,7 +1774,6 @@ public void updateOwnerDataverse() { private String init(boolean initFull) { //System.out.println("_YE_OLDE_QUERY_COUNTER_"); // for debug purposes - this.maxFileUploadSizeInBytes = systemConfig.getMaxFileUploadSizeForStore(dataset.getOwner().getEffectiveStorageDriverId()); setDataverseSiteUrl(systemConfig.getDataverseSiteUrl()); guestbookResponse = new GuestbookResponse(); @@ -1821,7 +1820,10 @@ private String init(boolean initFull) { // Set Working Version and Dataset by DatasaetVersion Id //retrieveDatasetVersionResponse = datasetVersionService.retrieveDatasetVersionByVersionId(versionId); - } + } + + this.maxFileUploadSizeInBytes = systemConfig.getMaxFileUploadSizeForStore(dataset.getOwner().getEffectiveStorageDriverId()); + if (retrieveDatasetVersionResponse == null) { return permissionsWrapper.notFound(); From 500094ff15df0499fc4b08c70abc10dff8e2a539 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 4 Mar 2020 14:10:41 -0500 Subject: [PATCH 377/475] remove systemconfig default methods --- src/main/java/edu/harvard/iq/dataverse/DatasetPage.java | 1 - .../java/edu/harvard/iq/dataverse/EditDatafilesPage.java | 5 +++++ .../harvard/iq/dataverse/settings/SettingsServiceBean.java | 2 +- .../java/edu/harvard/iq/dataverse/util/SystemConfig.java | 4 ---- src/main/webapp/editFilesFragment.xhtml | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index ae89602e045..b13200b0dde 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -1821,7 +1821,6 @@ private String init(boolean initFull) { //retrieveDatasetVersionResponse = datasetVersionService.retrieveDatasetVersionByVersionId(versionId); } - this.maxFileUploadSizeInBytes = systemConfig.getMaxFileUploadSizeForStore(dataset.getOwner().getEffectiveStorageDriverId()); diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 971a62666f2..71b74ddc7ae 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -7,6 +7,7 @@ import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.branding.BrandingUtil; import edu.harvard.iq.dataverse.datasetutility.AddReplaceFileHelper; +import edu.harvard.iq.dataverse.datasetutility.FileSizeChecker; import edu.harvard.iq.dataverse.datasetutility.FileReplaceException; import edu.harvard.iq.dataverse.datasetutility.FileReplacePageHelper; import edu.harvard.iq.dataverse.dataaccess.DataAccess; @@ -313,6 +314,10 @@ public Long getMaxFileUploadSizeInBytes() { return this.maxFileUploadSizeInBytes; } + public String getHumanMaxFileUploadSizeInBytes() { + return FileSizeChecker.bytesToHumanReadable(this.maxFileUploadSizeInBytes); + } + public boolean isUnlimitedUploadFileSize() { return this.maxFileUploadSizeInBytes == null; diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java index 75b604eb440..ece5eff2843 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java @@ -515,7 +515,7 @@ public Long getValueForCompoundKeyAsLong(Key key, String param){ } } catch (Exception e) { - logger.log(Level.WARNING, "Incorrect setting. Could not convert \"{0}\" from setting {1} to long.", new Object[]{val, key.toString()}); + logger.log(Level.WARNING, "Incorrect setting. Could not convert \"{0}\" from setting {1} to long: {2}", new Object[]{val, key.toString(), e.getMessage()}); return null; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java index 161493fa13f..aefb01992f4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java @@ -543,10 +543,6 @@ public Long getMaxFileUploadSizeForStore(String driverId){ return settingsService.getValueForCompoundKeyAsLong(SettingsServiceBean.Key.MaxFileUploadSizeInBytes, driverId); } - public String getHumanMaxFileUploadSizeForStore(String driverId){ - return bytesToHumanReadable(getMaxFileUploadSizeForStore(driverId)); - } - public Integer getSearchHighlightFragmentSize() { String fragSize = settingsService.getValueForKey(SettingsServiceBean.Key.SearchHighlightFragmentSize); if (fragSize != null) { diff --git a/src/main/webapp/editFilesFragment.xhtml b/src/main/webapp/editFilesFragment.xhtml index 5f3b14d92b5..57d760f6a56 100644 --- a/src/main/webapp/editFilesFragment.xhtml +++ b/src/main/webapp/editFilesFragment.xhtml @@ -73,8 +73,8 @@ - + rendered="#{!EditDatafilesPage.isUnlimitedUploadFileSize()}"> +

From 91136126c9cbcbbe4b25a68803c87103a1694d9e Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 4 Mar 2020 14:29:18 -0500 Subject: [PATCH 378/475] restore test fix --- .../java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index 4955f404e40..db87b1751c6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -41,8 +41,8 @@ public DataAccess() { }; - - public static final String DEFAULT_STORAGE_DRIVER_IDENTIFIER = System.getProperty("dataverse.files.storage-driver-id"); + //Default to "file" is for tests only + public static final String DEFAULT_STORAGE_DRIVER_IDENTIFIER = System.getProperty("dataverse.files.storage-driver-id", "file"); public static final String UNDEFINED_STORAGE_DRIVER_IDENTIFIER = "undefined"; //Used in dataverse.xhtml as a non-null selection option value (indicating a null driver/inheriting the default) // The getStorageIO() methods initialize StorageIO objects for From d3c2539f2a699725bbc8bbe546dd9700bd0a4311 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 4 Mar 2020 14:49:37 -0500 Subject: [PATCH 379/475] document per store file upload size limits --- doc/sphinx-guides/source/installation/config.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index 7920661378b..ec82b035a32 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -244,6 +244,8 @@ If you wish to change which store is used by default, you'll need to delete the ./asadmin $ASADMIN_OPTS delete-jvm-options "-Ddataverse.files.storage-driver-id=file" ./asadmin $ASADMIN_OPTS create-jvm-options "-Ddataverse.files.storage-driver-id=" + + It is also possible to set maximum file upload size limits per store. See the :ref:`:MaxFileUploadSizeInBytes` setting below. File Storage ++++++++++++ @@ -1476,7 +1478,14 @@ Alongside the ``:StatusMessageHeader`` you need to add StatusMessageText for the :MaxFileUploadSizeInBytes +++++++++++++++++++++++++ -Set `MaxFileUploadSizeInBytes` to "2147483648", for example, to limit the size of files uploaded to 2 GB. +This setting controls the maximum size of uploaded files. +- To have one limit for all stores, set `MaxFileUploadSizeInBytes` to "2147483648", for example, to limit the size of files uploaded to 2 GB: + +``curl -X PUT -d 2147483648 http://localhost:8080/api/admin/settings/:MaxFileUploadSizeInBytes`` + +- To have limits per store with an optional default, use a serialized json object for the value of `MaxFileUploadSizeInBytes` with an entry per store, as in the following exmaple, which maintains a 2 GB default and adds higher limits for stores with ids "fileOne" and "s3". + +``curl -X PUT -d '{"default":"2147483648","fileOne":"4000000000","s3":"8000000000"}' http://localhost:8080/api/admin/settings/:MaxFileUploadSizeInBytes`` Notes: @@ -1486,7 +1495,7 @@ Notes: - For larger file upload sizes, you may need to configure your reverse proxy timeout. If using apache2 (httpd) with Shibboleth, add a timeout to the ProxyPass defined in etc/httpd/conf.d/ssl.conf (which is described in the :doc:`/installation/shibboleth` setup). -``curl -X PUT -d 2147483648 http://localhost:8080/api/admin/settings/:MaxFileUploadSizeInBytes`` + :ZipDownloadLimit +++++++++++++++++ From abbebd8a3167dc6b99350c667871ae626846dd82 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 4 Mar 2020 15:06:37 -0500 Subject: [PATCH 380/475] doc of new features --- doc/sphinx-guides/source/developers/big-data-support.rst | 4 ++++ doc/sphinx-guides/source/installation/config.rst | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/developers/big-data-support.rst b/doc/sphinx-guides/source/developers/big-data-support.rst index 8f1103cf720..a64dbb07ea1 100644 --- a/doc/sphinx-guides/source/developers/big-data-support.rst +++ b/doc/sphinx-guides/source/developers/big-data-support.rst @@ -23,6 +23,8 @@ To configure these options, an administrator must set two JVM options for the Da With multiple stores configured, it is possible to configure one S3 store with direct upload and/or download to support large files (in general or for specific dataverses) while configuring only direct download, or no direct access for another store. +It is also possible to set file upload size limits per store. See the :MaxFileUploadSizeInBytes setting described in the :doc:`/installation/config` guide. + At present, one potential drawback for direct-upload is that files are only partially 'ingested', tabular and FITS files are processed, but zip files are not unzipped, and the file contents are not inspected to evaluate their mimetype. This could be appropriate for large files, or it may be useful to completely turn off ingest processing for performance reasons (ingest processing requires a copy of the file to be retrieved by Dataverse from the S3 store). A store using direct upload can be configured to disable all ingest processing for files above a given size limit: ``./asadmin create-jvm-options "-Ddataverse.files..ingestsizelimit="`` @@ -30,6 +32,8 @@ At present, one potential drawback for direct-upload is that files are only part One additional step that is required to enable direct download to work with previewers is to allow cross site (CORS) requests on your S3 store. +Since the direct upload mechanism creates the final file rather than an intermediate temporary file, user actions, such as neither saving or canceling an upload session before closing the browser page, can leave an abandoned file in the store. The direct upload mechanism attempts to use S3 Tags to aid in identifying/removing such files. Upon upload, files are given a "dv-status":"temp" tag which is removed when the dataset changes are saved and the new file(s) are added in Dataverse. Note that not all S3 implementations support Tags: Minio does not. WIth such stores, direct upload works, but Tags are not used. + Data Capture Module (DCM) ------------------------- diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index ec82b035a32..bb2f5702899 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -1483,7 +1483,7 @@ This setting controls the maximum size of uploaded files. ``curl -X PUT -d 2147483648 http://localhost:8080/api/admin/settings/:MaxFileUploadSizeInBytes`` -- To have limits per store with an optional default, use a serialized json object for the value of `MaxFileUploadSizeInBytes` with an entry per store, as in the following exmaple, which maintains a 2 GB default and adds higher limits for stores with ids "fileOne" and "s3". +- To have limits per store with an optional default, use a serialized json object for the value of `MaxFileUploadSizeInBytes` with an entry per store, as in the following example, which maintains a 2 GB default and adds higher limits for stores with ids "fileOne" and "s3". ``curl -X PUT -d '{"default":"2147483648","fileOne":"4000000000","s3":"8000000000"}' http://localhost:8080/api/admin/settings/:MaxFileUploadSizeInBytes`` From e476c077e6c2d1a5e088584a07ef664390c5d9dc Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Wed, 4 Mar 2020 16:32:19 -0500 Subject: [PATCH 381/475] bug fix for changed UI --- .../files/var/www/dataverse/branding/analytics-code.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/_static/installation/files/var/www/dataverse/branding/analytics-code.html b/doc/sphinx-guides/source/_static/installation/files/var/www/dataverse/branding/analytics-code.html index 4e6a01f2d5d..c8b1a3e945a 100644 --- a/doc/sphinx-guides/source/_static/installation/files/var/www/dataverse/branding/analytics-code.html +++ b/doc/sphinx-guides/source/_static/installation/files/var/www/dataverse/branding/analytics-code.html @@ -117,7 +117,7 @@ var row = target.parents('tr')[0]; if(row != null) { //finds the file id/DOI in the Dataset page - label = $(row).find('td.col-file-metadata > a').attr('href'); + label = $(row).find('td.col-file-metadata a').attr('href'); } else { //finds the file id/DOI in the file page label = $('#fileForm').attr('action'); From eb38f4dcad3f5cbacd64129add0ab4e74812ffe2 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Wed, 4 Mar 2020 16:57:50 -0500 Subject: [PATCH 382/475] release note --- doc/release-notes/6725-analytics-bug.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/release-notes/6725-analytics-bug.md diff --git a/doc/release-notes/6725-analytics-bug.md b/doc/release-notes/6725-analytics-bug.md new file mode 100644 index 00000000000..bbb703fcb58 --- /dev/null +++ b/doc/release-notes/6725-analytics-bug.md @@ -0,0 +1,3 @@ +# Google Analytics Download Tracking Bug + +The button tracking capability discussed in the installation guide (http://guides.dataverse.org/en/4.20/installation/config.html#id88) relies on an analytics-code.html file that must be configured using the :WebAnalyticsCode setting. The example file provided in the installation guide is no longer compatible with recent Dataverse releases (>v4.16). Installations using this feature should update their analytics-code.html file by following the installation instructions using the updated example file. (Alternately, sites can modify their existing files to include the one-line change made in the example file at line 120.) \ No newline at end of file From 5cd8744bb30e64d471a125a3fc48d644d853728d Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 5 Mar 2020 15:40:40 -0500 Subject: [PATCH 383/475] avoid resetting mimetype for normal upload --- src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java index f272e3ff884..a4370c7b38f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/FileUtil.java @@ -1084,10 +1084,7 @@ public static List createDataFiles(DatasetVersion version, InputStream } return null; - } else { - // ToDo what subset of checks from determineFileType makes sense? - finalType = suppliedContentType; - } + } } else { //Remote file, trust supplier finalType = suppliedContentType; From bce3c33ec3f40a89bb3d7529b4bc97e57a2c1bb2 Mon Sep 17 00:00:00 2001 From: Peter Kiraly Date: Fri, 6 Mar 2020 14:51:35 +0100 Subject: [PATCH 384/475] Issue #6514: Implement affiliation reading from Shibboleth attribute. --- .../source/installation/config.rst | 17 +++++++++++++++++ .../java/edu/harvard/iq/dataverse/Shib.java | 11 ++++++++++- .../dataverse/settings/SettingsServiceBean.java | 8 +++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index bfa66b97eb1..154f0bbff3e 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -1777,6 +1777,23 @@ You can set the value of "#THIS PAGE#" to the URL of your Dataverse homepage, or ``curl -X PUT -d true http://localhost:8080/api/admin/settings/:ShibPassiveLoginEnabled`` +:ShibAffiliationAttribute ++++++++++++++++++++++++++ + +Shibboleth affiliation attribute which holds information about the affiliation of the user (e.g. "ou"). In case of Shibboleth affiliation string is read from the DiscoFeed at each login. ``:ShibAffiliationAttribute`` is a name of a Shibboleth attribute, which takes place in Shibboleth header, and Dataverse will read the affiliation string from that. If this value is not set or empty, Dataverse uses the DiscoFeed. + +To set ``:ShibAffiliationAttribute``: + +``curl -X PUT -d "ou" http://localhost:8080/api/admin/settings/:ShibAffiliationAttribute`` + +To delete ``:ShibAffiliationAttribute``: + +``curl -X DELETE http://localhost:8080/api/admin/settings/:ShibAffiliationAttribute`` + +To check the current value of ``:ShibAffiliationAttribute``: + +``curl -X GET http://localhost:8080/api/admin/settings/:ShibAffiliationAttribute`` + .. _:ComputeBaseUrl: :ComputeBaseUrl diff --git a/src/main/java/edu/harvard/iq/dataverse/Shib.java b/src/main/java/edu/harvard/iq/dataverse/Shib.java index 8af9a22d783..d5ff8d88de5 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Shib.java +++ b/src/main/java/edu/harvard/iq/dataverse/Shib.java @@ -11,9 +11,12 @@ import edu.harvard.iq.dataverse.authorization.providers.shib.ShibUserNameFields; import edu.harvard.iq.dataverse.authorization.providers.shib.ShibUtil; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; +import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import edu.harvard.iq.dataverse.util.JsfHelper; import edu.harvard.iq.dataverse.util.SystemConfig; +import org.apache.commons.lang.StringUtils; + import java.io.IOException; import java.sql.Timestamp; import java.util.ArrayList; @@ -50,6 +53,8 @@ public class Shib implements java.io.Serializable { GroupServiceBean groupService; @EJB UserNotificationServiceBean userNotificationService; + @EJB + SettingsServiceBean settingsService; HttpServletRequest request; @@ -205,7 +210,11 @@ public void init() { internalUserIdentifer = ShibUtil.generateFriendlyLookingUserIdentifer(usernameAssertion, emailAddress); logger.fine("friendly looking identifer (backend will enforce uniqueness):" + internalUserIdentifer); - String affiliation = shibService.getAffiliation(shibIdp, shibService.getDevShibAccountType()); + String shibAffiliationAttribute = settingsService.getValueForKey(SettingsServiceBean.Key.ShibAffiliationAttribute); + String affiliation = (StringUtils.isNotBlank(shibAffiliationAttribute)) + ? getValueFromAssertion(shibAffiliationAttribute) + : shibService.getAffiliation(shibIdp, shibService.getDevShibAccountType()); + if (affiliation != null) { affiliationToDisplayAtConfirmation = affiliation; friendlyNameForInstitution = affiliation; diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java index 473bea561b4..165944acfdb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java @@ -411,7 +411,13 @@ Whether Harvesting (OAI) service is enabled * Lifespan, in minutes, of a login user session  * (both DataverseSession and the underlying HttpSession) */ - LoginSessionTimeout; + LoginSessionTimeout, + + /** + * Shibboleth affiliation attribute which holds information about the affiliation of the user (e.g. ou) + */ + ShibAffiliationAttribute + ; @Override public String toString() { From bd3f1d6803c36115976fcade9fb4d3a1bd1cd1b1 Mon Sep 17 00:00:00 2001 From: Peter Kiraly Date: Fri, 6 Mar 2020 15:35:11 +0100 Subject: [PATCH 385/475] #6514: extend documentation. --- .../source/installation/config.rst | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index 154f0bbff3e..95cedf8ca32 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -1782,6 +1782,36 @@ You can set the value of "#THIS PAGE#" to the URL of your Dataverse homepage, or Shibboleth affiliation attribute which holds information about the affiliation of the user (e.g. "ou"). In case of Shibboleth affiliation string is read from the DiscoFeed at each login. ``:ShibAffiliationAttribute`` is a name of a Shibboleth attribute, which takes place in Shibboleth header, and Dataverse will read the affiliation string from that. If this value is not set or empty, Dataverse uses the DiscoFeed. +If the attribute is not yet set for the Shibboleth, please consult the Shibboleth administrators how o set it. Typically it requires changing of `/etc/shibboleth/attribute-map.xml` file by adding an attribute request, e.g. + +``` + + + +``` + +In order to take place the change, you should restart Shibboleth and Apache2 services: + +``` +sudo service shibd restart +sudo service apache2 restart +``` + +To check if the attribute is sent, you should log in again to Dataverse and check Shibboleth's transaction log. You should see something like this: + +``` +INFO Shibboleth-TRANSACTION [25]: Cached the following attributes with session (ID: _9d1f34c0733b61c0feb0ca7596ef43b2) for (applicationId: default) { +INFO Shibboleth-TRANSACTION [25]: givenName (1 values) +INFO Shibboleth-TRANSACTION [25]: ou (1 values) +INFO Shibboleth-TRANSACTION [25]: sn (1 values) +INFO Shibboleth-TRANSACTION [25]: eppn (1 values) +INFO Shibboleth-TRANSACTION [25]: mail (1 values) +INFO Shibboleth-TRANSACTION [25]: displayName (1 values) +INFO Shibboleth-TRANSACTION [25]: } +``` + +If you see the attribue you requested in this list, you can set the attribute in Dataverse. + To set ``:ShibAffiliationAttribute``: ``curl -X PUT -d "ou" http://localhost:8080/api/admin/settings/:ShibAffiliationAttribute`` From 1e5951fe35257dc0d0a110590475fa54ae55db36 Mon Sep 17 00:00:00 2001 From: Michael Heppler Date: Fri, 6 Mar 2020 10:08:04 -0500 Subject: [PATCH 386/475] Changed selector in analytics exmaple to be more precise [ref #6725] --- .../files/var/www/dataverse/branding/analytics-code.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/_static/installation/files/var/www/dataverse/branding/analytics-code.html b/doc/sphinx-guides/source/_static/installation/files/var/www/dataverse/branding/analytics-code.html index c8b1a3e945a..ca703dddf11 100644 --- a/doc/sphinx-guides/source/_static/installation/files/var/www/dataverse/branding/analytics-code.html +++ b/doc/sphinx-guides/source/_static/installation/files/var/www/dataverse/branding/analytics-code.html @@ -117,7 +117,7 @@ var row = target.parents('tr')[0]; if(row != null) { //finds the file id/DOI in the Dataset page - label = $(row).find('td.col-file-metadata a').attr('href'); + label = $(row).find('div.file-metadata-block > a').attr('href'); } else { //finds the file id/DOI in the file page label = $('#fileForm').attr('action'); From b67125ba2282f58db0a238e6b824ae09f90f8f5f Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Fri, 6 Mar 2020 10:10:30 -0500 Subject: [PATCH 387/475] adding release note file, some basic doc updates --- doc/release-notes/6514-shib-updates | 0 doc/sphinx-guides/source/installation/config.rst | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 doc/release-notes/6514-shib-updates diff --git a/doc/release-notes/6514-shib-updates b/doc/release-notes/6514-shib-updates new file mode 100644 index 00000000000..e69de29bb2d diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index 95cedf8ca32..9fc2cf3cd11 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -1780,9 +1780,9 @@ You can set the value of "#THIS PAGE#" to the URL of your Dataverse homepage, or :ShibAffiliationAttribute +++++++++++++++++++++++++ -Shibboleth affiliation attribute which holds information about the affiliation of the user (e.g. "ou"). In case of Shibboleth affiliation string is read from the DiscoFeed at each login. ``:ShibAffiliationAttribute`` is a name of a Shibboleth attribute, which takes place in Shibboleth header, and Dataverse will read the affiliation string from that. If this value is not set or empty, Dataverse uses the DiscoFeed. +The Shibboleth affiliation attribute holds information about the affiliation of the user (e.g. "ou"). The Shibboleth affiliation string is read from the DiscoFeed at each login. ``:ShibAffiliationAttribute`` is a name of a Shibboleth attribute, which takes place in Shibboleth header, and Dataverse will read the affiliation string from that. If this value is not set or empty, Dataverse uses the DiscoFeed. -If the attribute is not yet set for the Shibboleth, please consult the Shibboleth administrators how o set it. Typically it requires changing of `/etc/shibboleth/attribute-map.xml` file by adding an attribute request, e.g. +If the attribute is not yet set for the Shibboleth, please consult the Shibboleth administrators how to set it. Typically it requires changing of the `/etc/shibboleth/attribute-map.xml` file by adding an attribute request, e.g. ``` @@ -1790,7 +1790,7 @@ If the attribute is not yet set for the Shibboleth, please consult the Shibbolet ``` -In order to take place the change, you should restart Shibboleth and Apache2 services: +In order to implement the change, you should restart Shibboleth and Apache2 services: ``` sudo service shibd restart From d600593d6263c090f80e31ced576e0454febbac9 Mon Sep 17 00:00:00 2001 From: Kevin Condon Date: Fri, 6 Mar 2020 10:22:02 -0500 Subject: [PATCH 388/475] Update 6489-release-notes.md --- doc/release-notes/6489-release-notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release-notes/6489-release-notes.md b/doc/release-notes/6489-release-notes.md index 3c21cd52bdb..5f38bd61d55 100644 --- a/doc/release-notes/6489-release-notes.md +++ b/doc/release-notes/6489-release-notes.md @@ -10,8 +10,8 @@ Direct upload to S3 is enabled per store by one new jvm option: ./asadmin create-jvm-options "\-Ddataverse.files..upload-redirect=true" -The existing :MaxFileUploadSizeInBytes property and dataverse.files..url-expiration-minutes jvm option for the same store also apply to direct upload. +The existing :MaxFileUploadSizeInBytes property and "dataverse.files..url-expiration-minutes" jvm option for the same store also apply to direct upload. Direct upload via the Dataverse web interface is transparent to the user and handled automatically by the browser. Some minor differences in file upload exist: directly uploaded files are not unzipped and Dataverse does not scan their content to help in assigning a MIME type. Ingest of tabular files and metadata extraction from FITS files will occur, but can be turned off for files above a specified size limit through the new dataverse.files..ingestsizelimit jvm option. -API calls to support direct upload also exist, and, if direct upload is enabled for a store in Dataverse, the latest DVUploader (v1.0.8) provides a'-directupload' flag that enables its use. \ No newline at end of file +API calls to support direct upload also exist, and, if direct upload is enabled for a store in Dataverse, the latest DVUploader (v1.0.8) provides a'-directupload' flag that enables its use. From 0f4b5f0266f9d46f395387c5617ddadb8bfc6029 Mon Sep 17 00:00:00 2001 From: Kevin Condon Date: Fri, 6 Mar 2020 10:27:06 -0500 Subject: [PATCH 389/475] Update 6489-release-notes.md --- doc/release-notes/6489-release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/6489-release-notes.md b/doc/release-notes/6489-release-notes.md index 5f38bd61d55..b28174c9a74 100644 --- a/doc/release-notes/6489-release-notes.md +++ b/doc/release-notes/6489-release-notes.md @@ -10,7 +10,7 @@ Direct upload to S3 is enabled per store by one new jvm option: ./asadmin create-jvm-options "\-Ddataverse.files..upload-redirect=true" -The existing :MaxFileUploadSizeInBytes property and "dataverse.files..url-expiration-minutes" jvm option for the same store also apply to direct upload. +The existing :MaxFileUploadSizeInBytes property and ```dataverse.files..url-expiration-minutes``` jvm option for the same store also apply to direct upload. Direct upload via the Dataverse web interface is transparent to the user and handled automatically by the browser. Some minor differences in file upload exist: directly uploaded files are not unzipped and Dataverse does not scan their content to help in assigning a MIME type. Ingest of tabular files and metadata extraction from FITS files will occur, but can be turned off for files above a specified size limit through the new dataverse.files..ingestsizelimit jvm option. From e235d8c9854e64fdb44ebe5606f5c1ae90a4616b Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 6 Mar 2020 14:55:32 -0500 Subject: [PATCH 390/475] initialize storageDriver to null affects root dataverse also checking isBlank on storagedriver rather than ==null as backward compatibility for devs. --- src/main/java/edu/harvard/iq/dataverse/Dataverse.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java index 0eea108c461..75dbb39e2ca 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java @@ -32,6 +32,8 @@ import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; + +import org.apache.commons.lang.StringUtils; import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotEmpty; @@ -149,7 +151,7 @@ public String getIndexableCategoryName() { private String affiliation; - private String storageDriver=""; + private String storageDriver=null; // Note: We can't have "Remove" here, as there are role assignments that refer // to this role. So, adding it would mean violating a forign key contstraint. @@ -762,7 +764,7 @@ public boolean isAncestorOf( DvObject other ) { public String getEffectiveStorageDriverId() { String id = storageDriver; - if(id == null) { + if(StringUtils.isBlank(id)) { if(this.getOwner() != null) { id = this.getOwner().getEffectiveStorageDriverId(); } else { From a8c8e008c135c5d5a5d5aaf2fbec7d94e8416709 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 6 Mar 2020 14:56:50 -0500 Subject: [PATCH 391/475] set alreadyExists(DVObject) false to allow direct upload during create mode with directupload, this will get called, and true would cause a failure --- .../dataverse/pidproviders/FakePidProviderServiceBean.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakePidProviderServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakePidProviderServiceBean.java index ce9e281e986..eb313631077 100644 --- a/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakePidProviderServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/pidproviders/FakePidProviderServiceBean.java @@ -15,7 +15,11 @@ public class FakePidProviderServiceBean extends AbstractGlobalIdServiceBean { @Override public boolean alreadyExists(DvObject dvo) throws Exception { - return true; + /* Direct upload creates an identifier prior to calling the CreateNewDatasetCommand - if this is true, that call fails. + * In that case, the local test (DatasetServiceBean.isIdentifierLocallyUnique()) correctly returns false since it tests the database. + * This provider could do the same check or use some other method to test alreadyExists(DvObject) =true failures. (no tests found currently) + */ + return false; } @Override From 5584adcbd672ffc4e04cf2487329d446056b170d Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 6 Mar 2020 15:11:17 -0500 Subject: [PATCH 392/475] remove debug logging --- .../java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index 7b6979ff1a7..96ce92754a4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -866,9 +866,7 @@ public String generateTemporaryS3UploadUrl() throws IOException { String urlString = null; if (presignedUrl != null) { String endpoint = System.getProperty("dataverse.files." + driverId + ".custom-endpoint-url"); - logger.info("endpoint: " + endpoint); String proxy = System.getProperty("dataverse.files." + driverId + ".proxy-url"); - logger.info("proxy: " + proxy); if(proxy!=null) { urlString = presignedUrl.toString().replace(endpoint, proxy); } else { From 1085a152a0cbac2b5a613ea3639f9c8cb6a4564b Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 9 Mar 2020 09:57:03 -0400 Subject: [PATCH 393/475] #6665 remove path update from index all --- .../iq/dataverse/search/IndexServiceBean.java | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java index b381efbda52..a636615d189 100644 --- a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java @@ -163,10 +163,14 @@ public void close() { @TransactionAttribute(REQUIRES_NEW) public Future indexDataverseInNewTransaction(Dataverse dataverse) throws SolrServerException, IOException{ - return indexDataverse(dataverse); + return indexDataverse(dataverse, false); } - + public Future indexDataverse(Dataverse dataverse) throws SolrServerException, IOException { + return indexDataverse(dataverse, true); + } + + public Future indexDataverse(Dataverse dataverse, boolean processPaths) throws SolrServerException, IOException { logger.fine("indexDataverse called on dataverse id " + dataverse.getId() + "(" + dataverse.getAlias() + ")"); if (dataverse.getId() == null) { // TODO: Investigate the root cause of this "unable to index dataverse" @@ -260,23 +264,30 @@ public Future indexDataverse(Dataverse dataverse) throws SolrServerExcep for (String dvPath : linkingDataversePaths) { dataversePaths.add(dvPath); } - //Get Linking Dataverses to see if I need to reindex my children - if (hasAnyLinkingDataverses(dataverse)) { - for (Dataverse dv : dataverseService.findPublishedByOwnerId(dataverse.getId())) { - //if this dataverse or any of its ancestors is linked and contains dataverses then - // the dataverses must be reindexed to get the new paths added - //We're sticking with the re-index here so that the dataverses datasets will also - //get their paths updated - indexDataverse(dv); - } - - for (Dataset dv : datasetService.findPublishedByOwnerId(dataverse.getId())) { - //if this dataverse or any of its ancestors is linked and contains datasets then - // the datasets must get the new paths added - // changed from a full re-index for efficiency wrt issue 6665 - updatePathForExistingSolrDocs(dv); + //only do this if we're indexing an individual dataverse ie not full re-index + if (processPaths) { + //Get Linking Dataverses to see if I need to reindex my children + if (hasAnyLinkingDataverses(dataverse)) { + List found = dataverseService.findByOwnerId(dataverse.getId()); + if (!found.isEmpty()) { + for (Dataverse dv : found) { + //if this dataverse or any of its ancestors is linked and contains dataverses then + // the dataverses must be reindexed to get the new paths added + //We're sticking with the re-index here so that the dataverses datasets will also + //get their paths updated + indexDataverseInNewTransaction(dv); + } + } + List datasets = datasetService.findByOwnerId(dataverse.getId()); + for (Dataset ds : datasets) { + //if this dataverse or any of its ancestors is linked and contains datasets then + // the datasets must get the new paths added + // changed from a full re-index for efficiency wrt issue 6665 + updatePathForExistingSolrDocs(ds); + } } } + solrInputDocument.addField(SearchFields.SUBTREE, dataversePaths); docs.add(solrInputDocument); @@ -306,7 +317,7 @@ public Future indexDataverse(Dataverse dataverse) throws SolrServerExcep return new AsyncResult<>(msg); } - + @TransactionAttribute(REQUIRES_NEW) public Future indexDatasetInNewTransaction(Long datasetId) throws SolrServerException, IOException{ //Dataset dataset) { boolean doNormalSolrDocCleanUp = false; @@ -1404,7 +1415,6 @@ public static String getDEACCESSIONED_STRING() { private void updatePathForExistingSolrDocs(DvObject object) throws SolrServerException, IOException { SolrQuery solrQuery = new SolrQuery(); - solrQuery.setQuery(SearchUtil.constructQuery(SearchFields.ENTITY_ID, object.getId().toString())); QueryResponse res = solrClientService.getSolrClient().query(solrQuery); @@ -1437,6 +1447,8 @@ private void updatePathForExistingSolrDocs(DvObject object) throws SolrServerExc commitResponse = solrClientService.getSolrClient().commit(); } } + } else { + indexDatasetInNewTransaction(object.getId()); } } From 83218c92b7dfe51b5a6cd718ee08a3504e74ff3f Mon Sep 17 00:00:00 2001 From: Peter Kiraly Date: Mon, 9 Mar 2020 17:37:41 +0100 Subject: [PATCH 394/475] #6083 update examples in File part of Native API: 'Datafile Integrity' section. --- doc/sphinx-guides/source/api/native-api.rst | 31 +++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index fae9fc088c1..c86aa0f568d 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2228,12 +2228,39 @@ The fully expanded example above (without environment variables) looks like this Datafile Integrity ~~~~~~~~~~~~~~~~~~ -Starting the release 4.10 the size of the saved original file (for an ingested tabular datafile) is stored in the database. The following API will retrieve and permanently store the sizes for any already existing saved originals:: +Starting the release 4.10 the size of the saved original file (for an ingested tabular datafile) is stored in the database. The following API will retrieve and permanently store the sizes for any already existing saved originals: - GET http://$SERVER/api/admin/datafiles/integrity/fixmissingoriginalsizes{?limit=N} +.. code-block:: bash + + export SERVER_URL=https://localhost + + curl $SERVER_URL/api/admin/datafiles/integrity/fixmissingoriginalsizes + +with limit parameter: + +.. code-block:: bash + + export SERVER_URL=https://localhost + export LIMIT=10 + + curl "$SERVER_URL/api/admin/datafiles/integrity/fixmissingoriginalsizes?limit=$LIMIT" + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl https://localhost/api/admin/datafiles/integrity/fixmissingoriginalsizes" + +with limit parameter: + +.. code-block:: bash + + curl https://localhost/api/admin/datafiles/integrity/fixmissingoriginalsizes?limit=10" Note the optional "limit" parameter. Without it, the API will attempt to populate the sizes for all the saved originals that don't have them in the database yet. Otherwise it will do so for the first N such datafiles. +By default the admin API calls are restricted to be called from the localhost. See more details in :ref:`:BlockedApiEndpoints <:BlockedApiEndpoints>` and :ref:`:BlockedApiPolicy <:BlockedApiPolicy>` settings in :doc:`/installation/config`. + Users Token Management ---------------------- From cf237af1a2a0d526f32ccbdfb16a552a123a378c Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Mon, 9 Mar 2020 21:44:50 -0400 Subject: [PATCH 395/475] doc edits --- doc/sphinx-guides/source/installation/config.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index 9fc2cf3cd11..6bf03cef215 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -1780,9 +1780,9 @@ You can set the value of "#THIS PAGE#" to the URL of your Dataverse homepage, or :ShibAffiliationAttribute +++++++++++++++++++++++++ -The Shibboleth affiliation attribute holds information about the affiliation of the user (e.g. "ou"). The Shibboleth affiliation string is read from the DiscoFeed at each login. ``:ShibAffiliationAttribute`` is a name of a Shibboleth attribute, which takes place in Shibboleth header, and Dataverse will read the affiliation string from that. If this value is not set or empty, Dataverse uses the DiscoFeed. +The Shibboleth affiliation attribute holds information about the affiliation of the user (e.g. "OU") and is read from the DiscoFeed at each login. ``:ShibAffiliationAttribute`` is a name of a Shibboleth attribute in the Shibboleth header which Dataverse will read from instead of DiscoFeed. If this value is not set or empty, Dataverse uses the DiscoFeed. -If the attribute is not yet set for the Shibboleth, please consult the Shibboleth administrators how to set it. Typically it requires changing of the `/etc/shibboleth/attribute-map.xml` file by adding an attribute request, e.g. +If the attribute is not yet set for the Shibboleth, please consult the Shibboleth Administrators at your institution. Typically it requires changing of the `/etc/shibboleth/attribute-map.xml` file by adding an attribute request, e.g. ``` From c2133b10bcf9919e4c2557a87171f597891e2c7d Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Mon, 9 Mar 2020 21:45:48 -0400 Subject: [PATCH 396/475] add release note --- doc/release-notes/6514-shib-updates | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release-notes/6514-shib-updates b/doc/release-notes/6514-shib-updates index e69de29bb2d..6935fd1fc99 100644 --- a/doc/release-notes/6514-shib-updates +++ b/doc/release-notes/6514-shib-updates @@ -0,0 +1 @@ +New JVM option :ShibAffiliationAttribute \ No newline at end of file From 239ccdc1876df6691e980d18797beacdfb550850 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Mon, 9 Mar 2020 21:54:41 -0400 Subject: [PATCH 397/475] rewording one section --- doc/sphinx-guides/source/api/native-api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index c86aa0f568d..fac4957bfb3 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2259,7 +2259,7 @@ with limit parameter: Note the optional "limit" parameter. Without it, the API will attempt to populate the sizes for all the saved originals that don't have them in the database yet. Otherwise it will do so for the first N such datafiles. -By default the admin API calls are restricted to be called from the localhost. See more details in :ref:`:BlockedApiEndpoints <:BlockedApiEndpoints>` and :ref:`:BlockedApiPolicy <:BlockedApiPolicy>` settings in :doc:`/installation/config`. +By default, the admin API calls are blocked and can only be called from localhost. See more details in :ref:`:BlockedApiEndpoints <:BlockedApiEndpoints>` and :ref:`:BlockedApiPolicy <:BlockedApiPolicy>` settings in :doc:`/installation/config`. Users Token Management ---------------------- From 5a27cdf4d599fb1ad08b5ed1ab537dc54d430df1 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Tue, 10 Mar 2020 09:54:15 -0400 Subject: [PATCH 398/475] changing JVM option to DB option --- doc/release-notes/6514-shib-updates | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/6514-shib-updates b/doc/release-notes/6514-shib-updates index 6935fd1fc99..561358c6b8d 100644 --- a/doc/release-notes/6514-shib-updates +++ b/doc/release-notes/6514-shib-updates @@ -1 +1 @@ -New JVM option :ShibAffiliationAttribute \ No newline at end of file +New DB option :ShibAffiliationAttribute \ No newline at end of file From fdbf8db07d4cb5e381d253e7706f9d29b479662a Mon Sep 17 00:00:00 2001 From: Oliver Bertuch Date: Tue, 10 Mar 2020 15:29:51 +0100 Subject: [PATCH 399/475] Make BundleUtil.getDefaultLocale() respect sane system defaults. #6734 --- .../harvard/iq/dataverse/util/BundleUtil.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/util/BundleUtil.java b/src/main/java/edu/harvard/iq/dataverse/util/BundleUtil.java index 98a2d84aee6..5ceff6b35ae 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/BundleUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/BundleUtil.java @@ -159,19 +159,20 @@ public static String getStringFromDefaultPropertyFile(String key, String propert } return getStringFromBundleNoMissingCheck(key, null, bundle); } - + + /** + * Return JVM default locale. + * + * For now, this simply forwards default system behaviour. + * That means on JDK8 the system property user.language will be set on startup + * from environment variables like LANG or via Maven arguments (which is important for testing). + * (See also pom.xml for an example how we pinpoint this for reproducible tests!) + * (You should also be aware that good IDEs are honoring settings from pom.xml.) + * + * Nonetheless, someday we might want to have more influence on how this is determined, thus this wrapper. + * @return Dataverse default locale + */ public static Locale getDefaultLocale() { - String localeEnvVar = System.getenv().get("LANG"); - if (localeEnvVar != null) { - if (localeEnvVar.indexOf('.') > 0) { - localeEnvVar = localeEnvVar.substring(0, localeEnvVar.indexOf('.')); - } - if (!"en_US".equals(localeEnvVar)) { - logger.fine("BundleUtil: LOCALE code from the environmental variable is "+localeEnvVar); - return new Locale(localeEnvVar); - } - } - - return new Locale("en"); + return Locale.getDefault(); } } From 4f321b88043e574c98f681fe45bfb9281b9dce47 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 10 Mar 2020 11:31:14 -0400 Subject: [PATCH 400/475] #6665 removing variable metadata process for benchmarking --- .../iq/dataverse/search/IndexServiceBean.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java index a636615d189..8d68b3d2282 100644 --- a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java @@ -890,7 +890,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d } } - List dataversePaths = retrieveDatasetPaths(dataset); + List dataversePaths = retrieveDatasetPaths(dataset); solrInputDocument.addField(SearchFields.SUBTREE, dataversePaths); // solrInputDocument.addField(SearchFields.HOST_DATAVERSE, // dataset.getOwner().getName()); @@ -938,7 +938,9 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d * whether full text indexing is on now. */ if ((fileMetadata.getDataFile().isRestricted() == releasedFileMetadata.getDataFile().isRestricted())) { - if (fileMetadata.contentEquals(releasedFileMetadata) && variableMetadataUtil.compareVariableMetadata(releasedFileMetadata,fileMetadata)) { + if (fileMetadata.contentEquals(releasedFileMetadata) + // && variableMetadataUtil.compareVariableMetadata(releasedFileMetadata,fileMetadata) + ) { indexThisMetadata = false; logger.fine("This file metadata hasn't changed since the released version; skipping indexing."); } else { @@ -1170,7 +1172,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d datafileSolrInputDocument.addField(SearchFields.VARIABLE_NAME, var.getName()); } - +/* List vmList = variableService.findByDataVarIdAndFileMetaId(var.getId(), fileMetadata.getId()); VariableMetadata vm = null; if (vmList != null && vmList.size() >0) { @@ -1204,8 +1206,9 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d } } - +*/ } + // TABULAR DATA TAGS: // (not to be confused with the file categories, indexed above!) for (DataFileTag tag : fileMetadata.getDataFile().getTags()) { @@ -1447,8 +1450,8 @@ private void updatePathForExistingSolrDocs(DvObject object) throws SolrServerExc commitResponse = solrClientService.getSolrClient().commit(); } } - } else { - indexDatasetInNewTransaction(object.getId()); + } else { + indexDataset((Dataset) object, true); } } From 770194d3d0701742856bd86bcb287f50c1e372ba Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Tue, 10 Mar 2020 14:32:28 -0400 Subject: [PATCH 401/475] adding release note --- doc/release-notes/6650-export-import-mismatch | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/release-notes/6650-export-import-mismatch diff --git a/doc/release-notes/6650-export-import-mismatch b/doc/release-notes/6650-export-import-mismatch new file mode 100644 index 00000000000..0ab2999a603 --- /dev/null +++ b/doc/release-notes/6650-export-import-mismatch @@ -0,0 +1,3 @@ +Run ReExportall to update JSON Exports + +http://guides.dataverse.org/en/4.19/admin/metadataexport.html?highlight=export#batch-exports-through-the-api \ No newline at end of file From 567d4d4c74d5a832075801509125da9da8d7485f Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 10 Mar 2020 15:05:39 -0400 Subject: [PATCH 402/475] #6697 delete user api update --- .../iq/dataverse/api/AbstractApiBean.java | 4 ++ .../edu/harvard/iq/dataverse/api/Admin.java | 49 +++++++++++-------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java b/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java index b8616809adc..cbf536fe069 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java @@ -15,6 +15,7 @@ import edu.harvard.iq.dataverse.DataverseRoleServiceBean; import edu.harvard.iq.dataverse.DataverseServiceBean; import edu.harvard.iq.dataverse.DvObject; +import edu.harvard.iq.dataverse.DvObjectServiceBean; import edu.harvard.iq.dataverse.EjbDataverseEngine; import edu.harvard.iq.dataverse.MapLayerMetadataServiceBean; import edu.harvard.iq.dataverse.MetadataBlock; @@ -238,6 +239,9 @@ String getWrappedMessageWhenJson() { @EJB MetricsServiceBean metricsSvc; + + @EJB + DvObjectServiceBean dvObjSvc; @PersistenceContext(unitName = "VDCNet-ejbPU") protected EntityManager em; diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index c5f358e8f71..94d34a232e4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -324,16 +324,21 @@ public Response getAuthenticatedUser(@PathParam("identifier") String identifier) return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found."); } - @DELETE - @Path("authenticatedUsers/{identifier}/") - public Response deleteAuthenticatedUser(@PathParam("identifier") String identifier) { - AuthenticatedUser user = authSvc.getAuthenticatedUser(identifier); - if (user != null) { - authSvc.deleteAuthenticatedUser(user.getId()); - return ok("AuthenticatedUser " + identifier + " deleted. "); - } - return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found."); - } + @DELETE + @Path("authenticatedUsers/{identifier}/") + public Response deleteAuthenticatedUser(@PathParam("identifier") String identifier) { + AuthenticatedUser user = authSvc.getAuthenticatedUser(identifier); + if (user != null) { + + if (!dvObjSvc.findByAuthenticatedUserId(user).isEmpty()){ + return error(Status.BAD_REQUEST, "Could not delete AuthenticatedUser " + identifier + " because the user has created Dataverse object(s). " ); + } + + authSvc.deleteAuthenticatedUser(user.getId()); + return ok("AuthenticatedUser " + identifier + " deleted. "); + } + return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found."); + } @@ -811,16 +816,20 @@ public Response builtin2oauth(String content) { return ok(response); } - @DELETE - @Path("authenticatedUsers/id/{id}/") - public Response deleteAuthenticatedUserById(@PathParam("id") Long id) { - AuthenticatedUser user = authSvc.findByID(id); - if (user != null) { - authSvc.deleteAuthenticatedUser(user.getId()); - return ok("AuthenticatedUser " + id + " deleted. "); - } - return error(Response.Status.BAD_REQUEST, "User " + id + " not found."); - } + @DELETE + @Path("authenticatedUsers/id/{id}/") + public Response deleteAuthenticatedUserById(@PathParam("id") Long id) { + AuthenticatedUser user = authSvc.findByID(id); + if (user != null) { + if (!dvObjSvc.findByAuthenticatedUserId(user).isEmpty()) { + return error(Status.BAD_REQUEST, "Could not delete AuthenticatedUser " + user.getIdentifier() + " because the user has created Dataverse object(s). "); + } + + authSvc.deleteAuthenticatedUser(user.getId()); + return ok("AuthenticatedUser " + id + " deleted. "); + } + return error(Response.Status.BAD_REQUEST, "User " + id + " not found."); + } @Path("roles") @POST From 022306d178841a375983c7f0b7518f6f83be9d36 Mon Sep 17 00:00:00 2001 From: Peter Kiraly Date: Wed, 11 Mar 2020 17:43:44 +0100 Subject: [PATCH 403/475] #6736 Add Provenance Example File to Documentation. --- doc/sphinx-guides/source/_static/api/file-provenance.json | 1 + doc/sphinx-guides/source/api/native-api.rst | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 doc/sphinx-guides/source/_static/api/file-provenance.json diff --git a/doc/sphinx-guides/source/_static/api/file-provenance.json b/doc/sphinx-guides/source/_static/api/file-provenance.json new file mode 100644 index 00000000000..6c823cdb5f3 --- /dev/null +++ b/doc/sphinx-guides/source/_static/api/file-provenance.json @@ -0,0 +1 @@ +{"prefix": {"pre_0": "http://www.w3.org/2001/XMLSchema", "s-prov": "http://s-prov/ns/#", "provone": "http://purl.dataone.org/provone/2015/01/15/ontology#", "vargen": "http://openprovenance.org/vargen#", "foaf": "http://xmlns.com/foaf/0.1/", "dcterms": "http://purl.org/dc/terms/", "tmpl": "http://openprovenance.org/tmpl#", "var": "http://openprovenance.org/var#", "vcard": "http://www.w3.org/2006/vcard/ns#", "swirrl": "http://project-dare.eu/ns#"}, "bundle": {"vargen:SessionSnapshot": {"prefix": {"s-prov": "http://s-prov/ns/#", "provone": "http://purl.dataone.org/provone/2015/01/15/ontology#", "vargen": "http://openprovenance.org/vargen#", "tmpl": "http://openprovenance.org/tmpl#", "var": "http://openprovenance.org/var#", "vcard": "http://www.w3.org/2006/vcard/ns#", "swirrl": "http://project-dare.eu/ns#"}, "entity": {"vargen:inData": {"swirrl:volumeId": {"$": "var:rawVolumeId", "type": "prov:QUALIFIED_NAME"}, "prov:type": {"$": "provone:Data", "type": "prov:QUALIFIED_NAME"}}, "vargen:inFile": {"prov:atLocation": {"$": "var:atLocation", "type": "prov:QUALIFIED_NAME"}, "s-prov:format": {"$": "var:format", "type": "prov:QUALIFIED_NAME"}, "s-prov:checksum": {"$": "var:checksum", "type": "prov:QUALIFIED_NAME"}}, "vargen:WorkData": {"swirrl:volumeId": {"$": "var:workVolumeId", "type": "prov:QUALIFIED_NAME"}, "prov:type": {"$": "provone:Data", "type": "prov:QUALIFIED_NAME"}}, "var:JupSnapshot": {"prov:generatedAt": {"$": "var:generatedAt", "type": "prov:QUALIFIED_NAME"}, "prov:atLocation": {"$": "var:repoUrl", "type": "prov:QUALIFIED_NAME"}, "s-prov:description": {"$": "var:description", "type": "prov:QUALIFIED_NAME"}, "prov:type": {"$": "swirrl:NotebookSnapshot", "type": "prov:QUALIFIED_NAME"}, "swirrl:sessionId": {"$": "var:sessionId", "type": "prov:QUALIFIED_NAME"}}}, "used": {"_:id1": {"prov:activity": "vargen:snapshot", "prov:entity": "var:Jupyter"}, "_:id2": {"prov:activity": "vargen:snapshot", "prov:entity": "vargen:WorkData"}, "_:id3": {"prov:activity": "vargen:snapshot", "prov:entity": "vargen:inData"}}, "wasDerivedFrom": {"_:id4": {"prov:usedEntity": "var:Jupyter", "prov:generatedEntity": "var:JupSnapshot"}}, "wasAssociatedWith": {"_:id5": {"prov:activity": "vargen:snapshot", "prov:agent": "var:snapAgent"}}, "actedOnBehalfOf": {"_:id6": {"prov:delegate": "var:snapAgent", "prov:responsible": "var:user"}}, "activity": {"vargen:snapshot": {"prov:atLocation": {"$": "var:method_path", "type": "prov:QUALIFIED_NAME"}, "tmpl:startTime": {"$": "var:startTime", "type": "prov:QUALIFIED_NAME"}, "tmpl:endTime": {"$": "var:endTime", "type": "prov:QUALIFIED_NAME"}}}, "wasGeneratedBy": {"_:id7": {"prov:activity": "vargen:snapshot", "prov:entity": "var:JupSnapshot"}}, "agent": {"var:user": {"vcard:uid": {"$": "var:name", "type": "prov:QUALIFIED_NAME"}, "swirrl:authMode": {"$": "var:authmode", "type": "prov:QUALIFIED_NAME"}, "swirrl:group": {"$": "var:group", "type": "prov:QUALIFIED_NAME"}, "prov:type": {"$": "prov:Person", "type": "prov:QUALIFIED_NAME"}}, "var:snapAgent": {"vcard:uid": {"$": "var:name_api", "type": "prov:QUALIFIED_NAME"}, "prov:type": {"$": "prov:SoftwareAgent", "type": "prov:QUALIFIED_NAME"}}}, "hadMember": {"_:id8": {"prov:collection": "vargen:inData", "prov:entity": "vargen:inFile"}}}}} \ No newline at end of file diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index fac4957bfb3..79ecdbad0b8 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2190,6 +2190,8 @@ The fully expanded example above (without environment variables) looks like this curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST "https://demo.dataverse.org/api/files/:persistentId/prov-freeform?persistentId=doi:10.5072/FK2/AAA000" -H "Content-type:application/json" --upload-file provenance.json +See a sample JSON file :download:`file-provenance.json <../_static/api/file-provenance.json>` from http://openprovenance.org (c.f. Huynh, Trung Dong and Moreau, Luc (2014) ProvStore: a public provenance repository. At 5th International Provenance and Annotation Workshop (IPAW'14), Cologne, Germany, 09-13 Jun 2014. pp. 275-277). + Delete Provenance JSON for an uploaded file ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From df4a2430120390b18e2a9f9d1e978613cd67722c Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 11 Mar 2020 13:44:50 -0400 Subject: [PATCH 404/475] initial copy of release notes content --- doc/release-notes/4.20-release-notes | 125 +++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 doc/release-notes/4.20-release-notes diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes new file mode 100644 index 00000000000..70c8711582c --- /dev/null +++ b/doc/release-notes/4.20-release-notes @@ -0,0 +1,125 @@ +# Dataverse 4.19 + +This release brings new features, enhancements, and bug fixes to Dataverse. Thank you to all of the community members who contributed code, suggestions, bug reports, and other assistance across the project. + +## Release Highlights + +### Open ID Connect Support + +Dataverse now provides basic support for any OpenID Connect (OIDC) compliant authentication provider. + +Prior to supporting this standard, new authentication methods needed to be added by pull request. OIDC support provides a standardized way for authentication, sharing user information, and more. You are able to use any compliant provider just by loading a configuration file, without touching the codebase. While the usual prominent providers like Google and others feature OIDC support there are plenty of other options to easily attach your installation to a custom authentication provider, using enterprise grade software. + +See the [OpenID Connect Login Options documentation](http://guides.dataverse.org/en/4.19/installation/oidc.html) in the Installation Guide for more details. + +This is to be extended with support for attribute mapping, group syncing and more in future versions of the code. + +### Python Installer + +We are introducing a new installer script, written in Python. It is intended to eventually replace the old installer (written in Perl). For now it is being offered as an (experimental) alternative. + +See [README_python.txt](https://github.com/IQSS/dataverse/blob/v4.19/scripts/installer/README_python.txt) in scripts/installer and/or in the installer bundle for more information. + +## Major Use Cases + +Newly-supported use cases in this release include: + +- Dataverse installation administrators will be able to experiment with a Python Installer (Issue #3937, PR #6484) +- Dataverse installation administrators will be able to set up an OIDC-compliant login options by editing a configuration file and with no need for a code change (Issue #6432, PR #6433) +- Following setup by a Dataverse administration, users will be able to log in using OIDC-compliant methods (Issue #6432, PR #6433) +- Users of the Search API will see additional fields in the JSON output (Issues #6300, #6396, PR #6441) +- Users loading the support form will now be presented with the math challenge as expected and will be able to successfully send an email to support (Issue #6307, PR #6462) +- Users of https://mybinder.org can now spin up Jupyter Notebooks and other computational environments from Dataverse DOIs (Issue #4714, PR #6453) + +## Notes for Dataverse Installation Administrators + +### Security vulnerability in Solr + +A serious security issue has recently been identified in multiple versions of Solr search engine, including v.7.3 that Dataverse is currently using. Follow the instructions below to verify that your installation is safe from a potential attack. You can also consult the following link for a detailed description of the issue: + +RCE in Solr via Velocity Template. + +The vulnerability allows an intruder to execute arbitrary code on the system running Solr. Fortunately, it can only be exploited if Solr API access point is open to direct access from public networks (aka, "the outside world"), which is NOT needed in a Dataverse installation. + +We have always recommended having Solr (port 8983) firewalled off from public access in our installation guides. But we recommend that you double-check your firewall settings and verify that the port is not accessible from outside networks. The simplest quick test is to try the following URL in your browser: + + `http://:8983` + +and confirm that you get "access denied" or that it times out, etc. + +In most cases, when Solr runs on the same server as the Dataverse web application, you will only want the port accessible from localhost. We also recommend that you add the following arguments to the Solr startup command: `-j jetty.host=127.0.0.1`. This will make Solr accept connections from localhost only; adding redundancy, in case of the firewall failure. + +In a case where Solr needs to run on a different host, make sure that the firewall limits access to the port only to the Dataverse web host(s), by specific ip address(es). + +We would also like to reiterate that it is simply never a good idea to run Solr as root! Running the process as a non-privileged user would substantially minimize any potential damage even in the event that the instance is compromised. + +### Citation and Geospatial Metadata Block Updates + +We updated two metadata blocks in this release. Updating these metadata blocks is mentioned in the step-by-step upgrade instructions below. + +### Run ReExportall + +We made changes to the JSON Export in this release (#6246). If you'd like these changes to reflected in your JSON exports, you should run ReExportall as part of the upgrade process. We've included this in the step-by-step instructions below. + +### BinderHub + +https://mybinder.org now supports spinning up Jupyter Notebooks and other computational environments from Dataverse DOIs. + +### Widgets update for OpenScholar + +We updated the code for widgets so that they will keep working in OpenScholar sites after the upcoming upgrade OpenScholar upgrade to Drupal 8. If users of your dataverse have embedded widgets on an Openscholar site that upgrades to Drupal 8, you will need to run this Dataverse version (or later) for the widgets to keep working. + +### Payara tech preview + +Dataverse 4 has always run on Glassfish 4.1 but changes in this release (PR #6523) should open the door to upgrading to Payara 5 eventually. Production installations of Dataverse should remain on Glassfish 4.1 but feedback from any experiments running Dataverse on Payara 5 is welcome via the [usual channels](https://dataverse.org/contact). + +## Notes for Tool Developers and Integrators + +### Search API + +The boolean parameter `query_entities` has been removed from the Search API. The former "true" behavior of "whether entities are queried via direct database calls (for developer use)" is now always true. + +Additional fields are now available via the Search API, mostly related to information about specific dataset versions. + +## Complete List of Changes + +For the complete list of code changes in this release, see the 4.19 milestone in Github. + +For help with upgrading, installing, or general questions please post to the Dataverse Google Group or email support@dataverse.org. + +## Installation + +If this is a new installation, please see our Installation Guide. + +## Upgrade + +1. Undeploy the previous version. + +- <glassfish install path>/glassfish4/bin/asadmin list-applications +- <glassfish install path>/glassfish4/bin/asadmin undeploy dataverse + +2. Stop glassfish and remove the generated directory, start. + +- service glassfish stop +- remove the generated directory: rm -rf <glassfish install path>glassfish4/glassfish/domains/domain1/generated +- service glassfish start + +3. Deploy this version. + +- <glassfish install path>/glassfish4/bin/asadmin deploy <path>dataverse-4.19.war + +4. Restart glassfish. + +5. Update Citation Metadata Block + +- `wget https://github.com/IQSS/dataverse/releases/download/v4.19/citation.tsv` +- `curl http://localhost:8080/api/admin/datasetfield/load -X POST --data-binary @citation.tsv -H "Content-type: text/tab-separated-values"` + +6. Update Geospatial Metadata Block + +- `wget https://github.com/IQSS/dataverse/releases/download/v4.19/geospatial.tsv` +- `curl http://localhost:8080/api/admin/datasetfield/load -X POST --data-binary @geospatial.tsv -H "Content-type: text/tab-separated-values"` + +7. (Optional) Run ReExportall to update JSON Exports + + From 8993b867614b8dee1b16760af845f06b0612405d Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 11 Mar 2020 13:51:54 -0400 Subject: [PATCH 405/475] Initial updates --- doc/release-notes/4.20-release-notes | 85 +++++----------------------- 1 file changed, 13 insertions(+), 72 deletions(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 70c8711582c..0b86b2d3c2d 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -1,95 +1,46 @@ -# Dataverse 4.19 +# Dataverse 4.20 This release brings new features, enhancements, and bug fixes to Dataverse. Thank you to all of the community members who contributed code, suggestions, bug reports, and other assistance across the project. ## Release Highlights -### Open ID Connect Support +### Multiple Stores -Dataverse now provides basic support for any OpenID Connect (OIDC) compliant authentication provider. +xxx -Prior to supporting this standard, new authentication methods needed to be added by pull request. OIDC support provides a standardized way for authentication, sharing user information, and more. You are able to use any compliant provider just by loading a configuration file, without touching the codebase. While the usual prominent providers like Google and others feature OIDC support there are plenty of other options to easily attach your installation to a custom authentication provider, using enterprise grade software. +### Direct Upload to S3 -See the [OpenID Connect Login Options documentation](http://guides.dataverse.org/en/4.19/installation/oidc.html) in the Installation Guide for more details. - -This is to be extended with support for attribute mapping, group syncing and more in future versions of the code. - -### Python Installer - -We are introducing a new installer script, written in Python. It is intended to eventually replace the old installer (written in Perl). For now it is being offered as an (experimental) alternative. - -See [README_python.txt](https://github.com/IQSS/dataverse/blob/v4.19/scripts/installer/README_python.txt) in scripts/installer and/or in the installer bundle for more information. +xxx ## Major Use Cases Newly-supported use cases in this release include: -- Dataverse installation administrators will be able to experiment with a Python Installer (Issue #3937, PR #6484) -- Dataverse installation administrators will be able to set up an OIDC-compliant login options by editing a configuration file and with no need for a code change (Issue #6432, PR #6433) -- Following setup by a Dataverse administration, users will be able to log in using OIDC-compliant methods (Issue #6432, PR #6433) -- Users of the Search API will see additional fields in the JSON output (Issues #6300, #6396, PR #6441) -- Users loading the support form will now be presented with the math challenge as expected and will be able to successfully send an email to support (Issue #6307, PR #6462) -- Users of https://mybinder.org can now spin up Jupyter Notebooks and other computational environments from Dataverse DOIs (Issue #4714, PR #6453) +- Case 1 (Issue #xxx, PR #xxx) ## Notes for Dataverse Installation Administrators -### Security vulnerability in Solr - -A serious security issue has recently been identified in multiple versions of Solr search engine, including v.7.3 that Dataverse is currently using. Follow the instructions below to verify that your installation is safe from a potential attack. You can also consult the following link for a detailed description of the issue: - -RCE in Solr via Velocity Template. - -The vulnerability allows an intruder to execute arbitrary code on the system running Solr. Fortunately, it can only be exploited if Solr API access point is open to direct access from public networks (aka, "the outside world"), which is NOT needed in a Dataverse installation. - -We have always recommended having Solr (port 8983) firewalled off from public access in our installation guides. But we recommend that you double-check your firewall settings and verify that the port is not accessible from outside networks. The simplest quick test is to try the following URL in your browser: - - `http://:8983` - -and confirm that you get "access denied" or that it times out, etc. - -In most cases, when Solr runs on the same server as the Dataverse web application, you will only want the port accessible from localhost. We also recommend that you add the following arguments to the Solr startup command: `-j jetty.host=127.0.0.1`. This will make Solr accept connections from localhost only; adding redundancy, in case of the firewall failure. - -In a case where Solr needs to run on a different host, make sure that the firewall limits access to the port only to the Dataverse web host(s), by specific ip address(es). - -We would also like to reiterate that it is simply never a good idea to run Solr as root! Running the process as a non-privileged user would substantially minimize any potential damage even in the event that the instance is compromised. - -### Citation and Geospatial Metadata Block Updates +### Note 1 -We updated two metadata blocks in this release. Updating these metadata blocks is mentioned in the step-by-step upgrade instructions below. +### ... Metadata Block Updates ### Run ReExportall -We made changes to the JSON Export in this release (#6246). If you'd like these changes to reflected in your JSON exports, you should run ReExportall as part of the upgrade process. We've included this in the step-by-step instructions below. - -### BinderHub - -https://mybinder.org now supports spinning up Jupyter Notebooks and other computational environments from Dataverse DOIs. - -### Widgets update for OpenScholar - -We updated the code for widgets so that they will keep working in OpenScholar sites after the upcoming upgrade OpenScholar upgrade to Drupal 8. If users of your dataverse have embedded widgets on an Openscholar site that upgrades to Drupal 8, you will need to run this Dataverse version (or later) for the widgets to keep working. - -### Payara tech preview - -Dataverse 4 has always run on Glassfish 4.1 but changes in this release (PR #6523) should open the door to upgrading to Payara 5 eventually. Production installations of Dataverse should remain on Glassfish 4.1 but feedback from any experiments running Dataverse on Payara 5 is welcome via the [usual channels](https://dataverse.org/contact). +We made changes to the JSON Export in this release (#xxx). If you'd like these changes to reflected in your JSON exports, you should run ReExportall as part of the upgrade process. We've included this in the step-by-step instructions below. ## Notes for Tool Developers and Integrators -### Search API - -The boolean parameter `query_entities` has been removed from the Search API. The former "true" behavior of "whether entities are queried via direct database calls (for developer use)" is now always true. - -Additional fields are now available via the Search API, mostly related to information about specific dataset versions. +### API Changes... ## Complete List of Changes -For the complete list of code changes in this release, see the 4.19 milestone in Github. +For the complete list of code changes in this release, see the 4.20 milestone in Github. For help with upgrading, installing, or general questions please post to the Dataverse Google Group or email support@dataverse.org. ## Installation -If this is a new installation, please see our Installation Guide. +If this is a new installation, please see our Installation Guide. ## Upgrade @@ -110,16 +61,6 @@ If this is a new installation, please see our From a50262aad328eccc64737b2bd26df928d323885f Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 11 Mar 2020 14:12:28 -0400 Subject: [PATCH 406/475] some more updates... --- doc/release-notes/4.20-release-notes | 12 +++++++--- doc/release-notes/6262-release-notes.md | 4 ---- ...6510-duplicate-datafiles-and-datatables.md | 22 ------------------- .../6534-new-guestbook-columns.md | 2 +- 4 files changed, 10 insertions(+), 30 deletions(-) delete mode 100644 doc/release-notes/6262-release-notes.md delete mode 100644 doc/release-notes/6510-duplicate-datafiles-and-datatables.md diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 0b86b2d3c2d..736dea1f994 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -16,11 +16,13 @@ xxx Newly-supported use cases in this release include: -- Case 1 (Issue #xxx, PR #xxx) +- Users will now be able to see the number of linked datasets and dataverses accurately reflected in the facet counts on the Dataverse search page. (Issue #6564, PR #6262) ## Notes for Dataverse Installation Administrators -### Note 1 +### Dataverse Linking Fix + +The fix implemented for #6262 will display the datasets contained in linked dataverses in the linking dataverse. An index in place is recommended for these counts to be updated. This is mentioned in the step by step instructions below. Going forward, this will happen automatically whenever a dataverse is linked. ### ... Metadata Block Updates @@ -61,6 +63,10 @@ If this is a new installation, please see our Date: Wed, 11 Mar 2020 15:10:15 -0400 Subject: [PATCH 407/475] more updates... --- doc/release-notes/4.20-release-notes | 55 +++++++++++++++++-- .../6534-new-guestbook-columns.md | 10 ---- .../6570-search-api-contact-affiliation.md | 1 - doc/release-notes/6590-citation-reload.md | 4 -- doc/release-notes/6599-update-solr-772.md | 9 --- doc/release-notes/6644-role-name-change.md | 1 - 6 files changed, 51 insertions(+), 29 deletions(-) delete mode 100644 doc/release-notes/6534-new-guestbook-columns.md delete mode 100644 doc/release-notes/6570-search-api-contact-affiliation.md delete mode 100644 doc/release-notes/6590-citation-reload.md delete mode 100644 doc/release-notes/6599-update-solr-772.md delete mode 100644 doc/release-notes/6644-role-name-change.md diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 736dea1f994..160ae94feb2 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -20,9 +20,32 @@ Newly-supported use cases in this release include: ## Notes for Dataverse Installation Administrators +### Potential Data Integrity Issue + +We recently discovered a *potential* data integrity issue in Dataverse databases. One manifests itself as duplicate DataFile objects created for the same uploaded file (https://github.com/IQSS/dataverse/issues/6522); the other as duplicate DataTable (tabular metadata) objects linked to the same DataFile (https://github.com/IQSS/dataverse/issues/6510). This issue impacted approximately .03% of datasets in Harvard's Dataverse. + +To see if any datasets in your installation have been impacted by this data integrity issue, we've provided a diagnostic script here: + +https://github.com/IQSS/dataverse/raw/develop/scripts/issues/6510/check_datafiles_6522_6510.sh + +The script relies on the PostgreSQL utility psql to access the database. You will need to edit the credentials at the top of the script to match your database configuration. + +If neither of the two issues is present in your database, you will see a message "... no duplicate DataFile objects in your database" and "no tabular files affected by this issue in your database". + +If either, or both kinds of duplicates are detected, the script will provide further instructions. We will need you to send us the produced output. We will then assist you in resolving the issues in your database. + +### Solr Update + +With this release we upgrade to the latest available stable release in the Solr 7.x branch. We recommend a fresh installation of Solr 7.7.2 (the index will be empty) +followed by an "index all". + +Before you start the "index all", Dataverse will appear to be empty because +the search results come from Solr. As indexing progresses, results will appear +until indexing is complete. + ### Dataverse Linking Fix -The fix implemented for #6262 will display the datasets contained in linked dataverses in the linking dataverse. An index in place is recommended for these counts to be updated. This is mentioned in the step by step instructions below. Going forward, this will happen automatically whenever a dataverse is linked. +The fix implemented for #6262 will display the datasets contained in linked dataverses in the linking dataverse. The full reindex described above will correct these counts. Going forward, this will happen automatically whenever a dataverse is linked. ### ... Metadata Block Updates @@ -32,7 +55,22 @@ We made changes to the JSON Export in this release (#xxx). If you'd like these c ## Notes for Tool Developers and Integrators -### API Changes... +### Guestbook Column Changes + +Users of downloaded guestbooks should note that two new columns have been added: + +- Dataset PID +- File PID + +If you are expecting column in the CSV file to be in a particular order, you will need to make adjustments. + +Old columns: Guestbook, Dataset, Date, Type, File Name, File Id, User Name, Email, Institution, Position, Custom Questions + +New columns: Guestbook, Dataset, Dataset PID, Date, Type, File Name, File Id, File PID, User Name, Email, Institution, Position, Custom Questions + +### API Changes + +As reported in #6570, the affiliation for dataset contacts has been wrapped in parentheses in the JSON output from the Search API. These parentheses have now been removed. This is a backward incompatible change but it's expected that this will not cause issues for integrators. ## Complete List of Changes @@ -57,15 +95,24 @@ If this is a new installation, please see our Date: Wed, 11 Mar 2020 15:15:28 -0400 Subject: [PATCH 408/475] and yet more updates. --- doc/release-notes/4.20-release-notes | 12 +++++++++++- doc/release-notes/6711-coverage-badge | 3 --- doc/release-notes/6725-analytics-bug.md | 3 --- 3 files changed, 11 insertions(+), 7 deletions(-) delete mode 100644 doc/release-notes/6711-coverage-badge delete mode 100644 doc/release-notes/6725-analytics-bug.md diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 160ae94feb2..52f525826c5 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -47,7 +47,9 @@ until indexing is complete. The fix implemented for #6262 will display the datasets contained in linked dataverses in the linking dataverse. The full reindex described above will correct these counts. Going forward, this will happen automatically whenever a dataverse is linked. -### ... Metadata Block Updates +### Google Analytics Download Tracking Bug + +The button tracking capability discussed in the installation guide (http://guides.dataverse.org/en/4.20/installation/config.html#id88) relies on an analytics-code.html file that must be configured using the :WebAnalyticsCode setting. The example file provided in the installation guide is no longer compatible with recent Dataverse releases (>v4.16). Installations using this feature should update their analytics-code.html file by following the installation instructions using the updated example file. Alternately, sites can modify their existing files to include the one-line change made in the example file at line 120. ### Run ReExportall @@ -55,6 +57,10 @@ We made changes to the JSON Export in this release (#xxx). If you'd like these c ## Notes for Tool Developers and Integrators +### Integration Test Coverage Reporting + +API-based integration tests are run every time a branch is merged to develop and the percentage of code covered by these integration tests is now shown on a badge at the bottom of the README.md file that serves as the homepage of Dataverse Github Repository. + ### Guestbook Column Changes Users of downloaded guestbooks should note that two new columns have been added: @@ -72,6 +78,10 @@ New columns: Guestbook, Dataset, Dataset PID, Date, Type, File Name, File Id, Fi As reported in #6570, the affiliation for dataset contacts has been wrapped in parentheses in the JSON output from the Search API. These parentheses have now been removed. This is a backward incompatible change but it's expected that this will not cause issues for integrators. +### Role Name Change + +The role alias provided in API responses has changed, so if anything was hard-coded to "editor" instead of "contributor" it will need to be updated. + ## Complete List of Changes For the complete list of code changes in this release, see the 4.20 milestone in Github. diff --git a/doc/release-notes/6711-coverage-badge b/doc/release-notes/6711-coverage-badge deleted file mode 100644 index fc90da68742..00000000000 --- a/doc/release-notes/6711-coverage-badge +++ /dev/null @@ -1,3 +0,0 @@ -Integration Test Coverage Reporting - -API-based integration tests are run every time a branch is merged to develop and the percentage of code covered by these integration tests is now shown on a badge at the bottom of the README.md file that serves as the homepage of Dataverse Github Repository. \ No newline at end of file diff --git a/doc/release-notes/6725-analytics-bug.md b/doc/release-notes/6725-analytics-bug.md deleted file mode 100644 index bbb703fcb58..00000000000 --- a/doc/release-notes/6725-analytics-bug.md +++ /dev/null @@ -1,3 +0,0 @@ -# Google Analytics Download Tracking Bug - -The button tracking capability discussed in the installation guide (http://guides.dataverse.org/en/4.20/installation/config.html#id88) relies on an analytics-code.html file that must be configured using the :WebAnalyticsCode setting. The example file provided in the installation guide is no longer compatible with recent Dataverse releases (>v4.16). Installations using this feature should update their analytics-code.html file by following the installation instructions using the updated example file. (Alternately, sites can modify their existing files to include the one-line change made in the example file at line 120.) \ No newline at end of file From 1809eb047afc07da8f5913a043cb700b2408b94c Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 11 Mar 2020 15:16:26 -0400 Subject: [PATCH 409/475] #6665 add debug lines for benchmarking with var metadata processing --- .../iq/dataverse/search/IndexServiceBean.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java index 8d68b3d2282..e75381df155 100644 --- a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java @@ -37,6 +37,7 @@ import java.sql.Timestamp; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.time.Instant; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; @@ -705,6 +706,8 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset) throws Sol } private String addOrUpdateDataset(IndexableDataset indexableDataset, Set datafilesInDraftVersion) throws SolrServerException, IOException { + System.out.print("start index: " + Instant.now()); + String startTime = Instant.now().toString(); IndexableDataset.DatasetState state = indexableDataset.getDatasetState(); Dataset dataset = indexableDataset.getDatasetVersion().getDataset(); logger.fine("adding or updating Solr document for dataset id " + dataset.getId()); @@ -922,10 +925,13 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d logger.fine( "We are indexing a draft version of a dataset that has a released version. We'll be checking file metadatas if they are exact clones of the released versions."); } - + System.out.print("before files: " + Instant.now()); for (FileMetadata fileMetadata : fileMetadatas) { + boolean indexThisMetadata = true; if (checkForDuplicateMetadata) { + System.out.print("check for duplticates"); + logger.fine("Checking if this file metadata is a duplicate."); for (FileMetadata releasedFileMetadata : dataset.getReleasedVersion().getFileMetadatas()) { if (fileMetadata.getDataFile() != null && fileMetadata.getDataFile().equals(releasedFileMetadata.getDataFile())) { @@ -939,7 +945,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d */ if ((fileMetadata.getDataFile().isRestricted() == releasedFileMetadata.getDataFile().isRestricted())) { if (fileMetadata.contentEquals(releasedFileMetadata) - // && variableMetadataUtil.compareVariableMetadata(releasedFileMetadata,fileMetadata) + && variableMetadataUtil.compareVariableMetadata(releasedFileMetadata,fileMetadata) ) { indexThisMetadata = false; logger.fine("This file metadata hasn't changed since the released version; skipping indexing."); @@ -954,8 +960,11 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d } } if (indexThisMetadata) { + + SolrInputDocument datafileSolrInputDocument = new SolrInputDocument(); Long fileEntityId = fileMetadata.getDataFile().getId(); + System.out.print("Indexing file: " + fileEntityId + " " + Instant.now()); datafileSolrInputDocument.addField(SearchFields.ENTITY_ID, fileEntityId); datafileSolrInputDocument.addField(SearchFields.DATAVERSE_VERSION_INDEXED_BY, dataverseVersion); datafileSolrInputDocument.addField(SearchFields.IDENTIFIER, fileEntityId); @@ -1172,7 +1181,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d datafileSolrInputDocument.addField(SearchFields.VARIABLE_NAME, var.getName()); } -/* + List vmList = variableService.findByDataVarIdAndFileMetaId(var.getId(), fileMetadata.getId()); VariableMetadata vm = null; if (vmList != null && vmList.size() >0) { @@ -1206,7 +1215,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d } } -*/ + } // TABULAR DATA TAGS: @@ -1224,7 +1233,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d } } } - +System.out.print("After files: " + Instant.now()); try { solrClientService.getSolrClient().add(docs); solrClientService.getSolrClient().commit(); @@ -1249,6 +1258,9 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d // return "indexed dataset " + dataset.getId() + " as " + solrDocId + // "\nindexFilesResults for " + solrDocId + ":" + fileInfo.toString(); + System.out.print("Started: " + startTime); + System.out.print("Finished: " + Instant.now()); + System.out.print("indexed dataset " + dsId + " as " + datasetSolrDocId + ". filesIndexed: " + filesIndexed.size()); return "indexed dataset " + dsId + " as " + datasetSolrDocId + ". filesIndexed: " + filesIndexed; } From 4adf0ce76b9283af82fb0cd6cb54938542b6993b Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 11 Mar 2020 15:33:07 -0400 Subject: [PATCH 410/475] added multiple store content --- doc/release-notes/4.20-release-notes | 48 +++++++++++++++++++---- doc/release-notes/6485-multiple-stores.md | 36 ----------------- 2 files changed, 40 insertions(+), 44 deletions(-) delete mode 100644 doc/release-notes/6485-multiple-stores.md diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 52f525826c5..8bcd3d15806 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -4,9 +4,11 @@ This release brings new features, enhancements, and bug fixes to Dataverse. Than ## Release Highlights -### Multiple Stores +### Multiple Store Support -xxx +Dataverse can now be configured to store files in more than one place at the same time (multiple file, s3, and/or swift stores). + +General information about this capability can be found in the Configuration Guide - File Storage section. ### Direct Upload to S3 @@ -34,6 +36,34 @@ If neither of the two issues is present in your database, you will see a message If either, or both kinds of duplicates are detected, the script will provide further instructions. We will need you to send us the produced output. We will then assist you in resolving the issues in your database. +### Multiple Store Support Changes + +**Existing installations will need to make configuration changes to adopt this version, regardless of whether additional stores are to be added or not.** + +Multistore support requires that each store be assigned a label, id, and type - see the Configuration Guide for a more complete explanation. For an existing store, the recommended upgrade path is to assign the store id based on it's type, i.e. a 'file' store would get id 'file', an 's3' store would have the id 's3'. + +With this choice, no manual changes to datafile 'storageidentifier' entries are needed in the database. If you do not name your existing store using this convention, you will need to edit the database to maintain access to existing files. + +The following set of commands to change the Glassfish JVM options will adapt an existing file or s3 store for this upgrade: +For a file store: + + ./asadmin create-jvm-options "\-Ddataverse.files.file.type=file" + ./asadmin create-jvm-options "\-Ddataverse.files.file.label=file" + ./asadmin create-jvm-options "\-Ddataverse.files.file.directory=" + +For a s3 store: + + ./asadmin create-jvm-options "\-Ddataverse.files.s3.type=s3" + ./asadmin create-jvm-options "\-Ddataverse.files.s3.label=s3" + ./asadmin delete-jvm-options "-Ddataverse.files.s3-bucket-name=" + ./asadmin create-jvm-options "-Ddataverse.files.s3.bucket-name=" + +Any additional S3 options you have set will need to be replaced as well, following the pattern in the last two lines above - delete the option including a '-' after 's3' and creating the same option with the '-' replaced by a '.', using the same value you currently have configured. + +Once these options are set, restarting the glassfish service is all that is needed to complete the change. + +Note that the "\-Ddataverse.files.directory", if defined, continues to control where temporary files are stored (in the /temp subdir of that directory), independent of the location of any 'file' store defined above. + ### Solr Update With this release we upgrade to the latest available stable release in the Solr 7.x branch. We recommend a fresh installation of Solr 7.7.2 (the index will be empty) @@ -109,21 +139,23 @@ If this is a new installation, please see our diff --git a/doc/release-notes/6485-multiple-stores.md b/doc/release-notes/6485-multiple-stores.md deleted file mode 100644 index ea2d224d612..00000000000 --- a/doc/release-notes/6485-multiple-stores.md +++ /dev/null @@ -1,36 +0,0 @@ -# Multiple Store Support -Dataverse can now be configured to store files in more than one place at the same time (multiple file, s3, and/or swift stores). - -General information about this capability can be found in the Configuration Guide - File Storage section. - -**Upgrade Information:** - -**Existing installations will need to make configuration changes to adopt this version, regardless of whether additional stores are to be added or not.** - -Multistore support requires that each store be assigned a label, id, and type - see the documentation for a more complete explanation. For an existing store, the recommended upgrade path is to assign the store id based on it's type, i.e. a 'file' store would get id 'file', an 's3' store would have the id 's3'. - -With this choice, no manual changes to datafile 'storageidentifier' entries are needed in the database. (If you do not name your existing store using this convention, you will need to edit the database to maintain access to existing files!). - -The following set of commands to change the Glassfish JVM options will adapt an existing file or s3 store for this upgrade: -For a file store: - - ./asadmin create-jvm-options "\-Ddataverse.files.file.type=file" - ./asadmin create-jvm-options "\-Ddataverse.files.file.label=file" - ./asadmin create-jvm-options "\-Ddataverse.files.file.directory=" - -For an s3 store: - - ./asadmin create-jvm-options "\-Ddataverse.files.s3.type=s3" - ./asadmin create-jvm-options "\-Ddataverse.files.s3.label=s3" - ./asadmin delete-jvm-options "-Ddataverse.files.s3-bucket-name=" - ./asadmin create-jvm-options "-Ddataverse.files.s3.bucket-name=" - -Any additional S3 options you have set will need to be replaced as well, following the pattern in the last two lines above - delete the option including a '-' after 's3' and creating the same option with the '-' replaced by a '.', using the same value you currently have configured. - -Once these options are set, restarting the glassfish service is all that is needed to complete the change. - -<<<<<<< HEAD -Note that the "\-Ddataverse.files.directory", if defined, continues to control where temporary files are stored (in the /temp subdir of that directory), independent of the location of any 'file' store defined above. -======= -Note that the "\-Ddataverse.files.directory", if defined, continues to control where temporary files are stored (in the /temp subdir of that directory), independent of the location of any 'file' store defined above. ->>>>>>> branch 'IQSS/6485' of https://github.com/TexasDigitalLibrary/dataverse.git From 78565389b54b7ee68defbb7d9f3760f718379629 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 12 Mar 2020 09:28:19 -0400 Subject: [PATCH 411/475] #6665 remove variable metadata indexing and debug statements --- .../iq/dataverse/search/IndexServiceBean.java | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java index e75381df155..b6b7df2887a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java @@ -706,8 +706,6 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset) throws Sol } private String addOrUpdateDataset(IndexableDataset indexableDataset, Set datafilesInDraftVersion) throws SolrServerException, IOException { - System.out.print("start index: " + Instant.now()); - String startTime = Instant.now().toString(); IndexableDataset.DatasetState state = indexableDataset.getDatasetState(); Dataset dataset = indexableDataset.getDatasetVersion().getDataset(); logger.fine("adding or updating Solr document for dataset id " + dataset.getId()); @@ -925,12 +923,10 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d logger.fine( "We are indexing a draft version of a dataset that has a released version. We'll be checking file metadatas if they are exact clones of the released versions."); } - System.out.print("before files: " + Instant.now()); for (FileMetadata fileMetadata : fileMetadatas) { boolean indexThisMetadata = true; if (checkForDuplicateMetadata) { - System.out.print("check for duplticates"); logger.fine("Checking if this file metadata is a duplicate."); for (FileMetadata releasedFileMetadata : dataset.getReleasedVersion().getFileMetadatas()) { @@ -945,7 +941,8 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d */ if ((fileMetadata.getDataFile().isRestricted() == releasedFileMetadata.getDataFile().isRestricted())) { if (fileMetadata.contentEquals(releasedFileMetadata) - && variableMetadataUtil.compareVariableMetadata(releasedFileMetadata,fileMetadata) + /* SEK 3/12/2020 remove variable metadata indexing*/ + // && variableMetadataUtil.compareVariableMetadata(releasedFileMetadata,fileMetadata) ) { indexThisMetadata = false; logger.fine("This file metadata hasn't changed since the released version; skipping indexing."); @@ -964,7 +961,6 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d SolrInputDocument datafileSolrInputDocument = new SolrInputDocument(); Long fileEntityId = fileMetadata.getDataFile().getId(); - System.out.print("Indexing file: " + fileEntityId + " " + Instant.now()); datafileSolrInputDocument.addField(SearchFields.ENTITY_ID, fileEntityId); datafileSolrInputDocument.addField(SearchFields.DATAVERSE_VERSION_INDEXED_BY, dataverseVersion); datafileSolrInputDocument.addField(SearchFields.IDENTIFIER, fileEntityId); @@ -1181,7 +1177,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d datafileSolrInputDocument.addField(SearchFields.VARIABLE_NAME, var.getName()); } - +/* SEK 3/12/2020 remove variable metadata indexing List vmList = variableService.findByDataVarIdAndFileMetaId(var.getId(), fileMetadata.getId()); VariableMetadata vm = null; if (vmList != null && vmList.size() >0) { @@ -1215,7 +1211,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d } } - +*/ } // TABULAR DATA TAGS: @@ -1233,7 +1229,7 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d } } } -System.out.print("After files: " + Instant.now()); + try { solrClientService.getSolrClient().add(docs); solrClientService.getSolrClient().commit(); @@ -1256,11 +1252,6 @@ private String addOrUpdateDataset(IndexableDataset indexableDataset, Set d dvObjectToModify = em.merge(dvObjectToModify); dvObjectToModify = null; - // return "indexed dataset " + dataset.getId() + " as " + solrDocId + - // "\nindexFilesResults for " + solrDocId + ":" + fileInfo.toString(); - System.out.print("Started: " + startTime); - System.out.print("Finished: " + Instant.now()); - System.out.print("indexed dataset " + dsId + " as " + datasetSolrDocId + ". filesIndexed: " + filesIndexed.size()); return "indexed dataset " + dsId + " as " + datasetSolrDocId + ". filesIndexed: " + filesIndexed; } From 00c62d20d7d5aa2d80d7897693b544c7bf2d7f1b Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 12 Mar 2020 09:48:01 -0400 Subject: [PATCH 412/475] retry to give S3 time to 'index' new objects eventual consistency... --- .../iq/dataverse/dataaccess/S3AccessIO.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index 96ce92754a4..b65739915eb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -213,14 +213,29 @@ public void open(DataAccessOption... options) throws IOException { } else if (dvObject instanceof Dataverse) { throw new IOException("Data Access: Storage driver does not support dvObject type Dataverse yet"); } else { - //Direct access, e.g. for external upload - no associated DVobject yet, but we want to be abel to get the size + // Direct access, e.g. for external upload - no associated DVobject yet, but we want to be able to get the size + // With small files, it looks like we may call before S3 says it exists, so try some retries before failing if(key!=null) { ObjectMetadata objectMetadata = null; - try { - objectMetadata = s3.getObjectMetadata(bucketName, key); - } catch (SdkClientException sce) { - throw new IOException("Cannot get S3 object " + key + " ("+sce.getMessage()+")"); - } + int retries = 3; + while(retries > 0) { + try { + objectMetadata = s3.getObjectMetadata(bucketName, key); + retries = 0; + } catch (SdkClientException sce) { + if(retries > 1) { + retries--; + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + logger.warning("Retrying after: " + sce.getMessage()); + } else { + throw new IOException("Cannot get S3 object " + key + " ("+sce.getMessage()+")"); + } + } + } this.setSize(objectMetadata.getContentLength()); }else { throw new IOException("Data Access: Invalid DvObject type"); From d0f3e4ceb7ea41b1456ec69325f09ae817edbeef Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Thu, 12 Mar 2020 12:04:28 -0400 Subject: [PATCH 413/475] Update 4.16-release-notes.md --- doc/release-notes/4.16-release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release-notes/4.16-release-notes.md b/doc/release-notes/4.16-release-notes.md index 66241a42777..8feb263d2ab 100644 --- a/doc/release-notes/4.16-release-notes.md +++ b/doc/release-notes/4.16-release-notes.md @@ -91,6 +91,7 @@ If this is a new installation, please see our Date: Thu, 12 Mar 2020 21:36:40 -0400 Subject: [PATCH 414/475] adding step 5 from stores doc --- doc/release-notes/4.20-release-notes | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 8bcd3d15806..8c246e4dad1 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -143,7 +143,21 @@ See http://guides.dataverse.org/en/4.20/installation/prerequisites.html#installi - <glassfish install path>/glassfish4/bin/asadmin deploy <path>dataverse-4.20.war -5. Update JVM options for multiple stores...? +5. The following set of commands to change the Glassfish JVM options will adapt an existing file or s3 store for this upgrade: +For a file store: + + ./asadmin create-jvm-options "\-Ddataverse.files.file.type=file" + ./asadmin create-jvm-options "\-Ddataverse.files.file.label=file" + ./asadmin create-jvm-options "\-Ddataverse.files.file.directory=" + +For a s3 store: + + ./asadmin create-jvm-options "\-Ddataverse.files.s3.type=s3" + ./asadmin create-jvm-options "\-Ddataverse.files.s3.label=s3" + ./asadmin delete-jvm-options "-Ddataverse.files.s3-bucket-name=" + ./asadmin create-jvm-options "-Ddataverse.files.s3.bucket-name=" + +Any additional S3 options you have set will need to be replaced as well, following the pattern in the last two lines above - delete the option including a '-' after 's3' and creating the same option with the '-' replaced by a '.', using the same value you currently have configured. 6. Restart glassfish. From 83a47c9e1b4387248abad6ddb633a3e0e6bae2c1 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Fri, 13 Mar 2020 11:38:01 -0400 Subject: [PATCH 415/475] #6697 add test for roles, refactor --- .../iq/dataverse/api/AbstractApiBean.java | 4 ++ .../edu/harvard/iq/dataverse/api/Admin.java | 48 +++++++++++-------- src/main/java/propertyFiles/Bundle.properties | 4 ++ 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java b/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java index cbf536fe069..94613100b16 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java @@ -17,6 +17,7 @@ import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.DvObjectServiceBean; import edu.harvard.iq.dataverse.EjbDataverseEngine; +import edu.harvard.iq.dataverse.GuestbookResponseServiceBean; import edu.harvard.iq.dataverse.MapLayerMetadataServiceBean; import edu.harvard.iq.dataverse.MetadataBlock; import edu.harvard.iq.dataverse.MetadataBlockServiceBean; @@ -242,6 +243,9 @@ String getWrappedMessageWhenJson() { @EJB DvObjectServiceBean dvObjSvc; + + @EJB + GuestbookResponseServiceBean gbRespSvc; @PersistenceContext(unitName = "VDCNet-ejbPU") protected EntityManager em; diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 94d34a232e4..763641f3774 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -329,18 +329,38 @@ public Response getAuthenticatedUser(@PathParam("identifier") String identifier) public Response deleteAuthenticatedUser(@PathParam("identifier") String identifier) { AuthenticatedUser user = authSvc.getAuthenticatedUser(identifier); if (user != null) { - - if (!dvObjSvc.findByAuthenticatedUserId(user).isEmpty()){ - return error(Status.BAD_REQUEST, "Could not delete AuthenticatedUser " + identifier + " because the user has created Dataverse object(s). " ); - } - - authSvc.deleteAuthenticatedUser(user.getId()); - return ok("AuthenticatedUser " + identifier + " deleted. "); + return deleteAuthenticatedUser(user); } return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found."); } + + @Path("authenticatedUsers/id/{id}/") + public Response deleteAuthenticatedUserById(@PathParam("id") Long id) { + AuthenticatedUser user = authSvc.findByID(id); + if (user != null) { + return deleteAuthenticatedUser(user); + } + return error(Response.Status.BAD_REQUEST, "User " + id + " not found."); + } + + private Response deleteAuthenticatedUser(AuthenticatedUser au) { + + if (!roleAssigneeSvc.getAssignmentsFor(au.getIdentifier()).isEmpty()) { + return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.roleAssignments", Arrays.asList(au.getIdentifier()))); + } - + if (!dvObjSvc.findByAuthenticatedUserId(au).isEmpty()) { + return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.dvobjects", Arrays.asList(au.getIdentifier()))); + } + + if (!gbRespSvc.findByAuthenticatedUserId(au).isEmpty()) { + return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.gbResps", Arrays.asList(au.getIdentifier()))); + } + + authSvc.deleteAuthenticatedUser(au.getId()); + return ok("AuthenticatedUser " + au.getIdentifier() + " deleted. "); + + } @POST @Path("publishDataverseAsCreator/{id}") @@ -817,19 +837,7 @@ public Response builtin2oauth(String content) { } @DELETE - @Path("authenticatedUsers/id/{id}/") - public Response deleteAuthenticatedUserById(@PathParam("id") Long id) { - AuthenticatedUser user = authSvc.findByID(id); - if (user != null) { - if (!dvObjSvc.findByAuthenticatedUserId(user).isEmpty()) { - return error(Status.BAD_REQUEST, "Could not delete AuthenticatedUser " + user.getIdentifier() + " because the user has created Dataverse object(s). "); - } - authSvc.deleteAuthenticatedUser(user.getId()); - return ok("AuthenticatedUser " + id + " deleted. "); - } - return error(Response.Status.BAD_REQUEST, "User " + id + " not found."); - } @Path("roles") @POST diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 35229c5162d..7308cdd16c8 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -2223,6 +2223,10 @@ admin.api.migrateHDL.failure.must.be.hdl.dataset=Dataset was not registered as a admin.api.migrateHDL.success=Dataset migrate HDL registration complete. Dataset re-registered successfully. admin.api.migrateHDL.failure=Failed to migrate Dataset Handle id: {0} admin.api.migrateHDL.failureWithException=Failed to migrate Dataset Handle id: {0} Unexpected exception: {1} +admin.api.deleteUser.failure.dvobjects=Could not delete AuthenticatedUser {0} because the user has created Dataverse object(s). +admin.api.deleteUser.failure.gbResps=Could not delete AuthenticatedUser {0} because the user is associated with file download (Guestbook Response) record(s). +admin.api.deleteUser.failure.roleAssignments=Could not delete AuthenticatedUser {0} because the user is associated with role assignment record(s). + #Datasets.java datasets.api.updatePIDMetadata.failure.dataset.must.be.released=Modify Registration Metadata must be run on a published dataset. From 2d28a71d7ca1a2afeec3359e553a01001d38e970 Mon Sep 17 00:00:00 2001 From: landreev Date: Fri, 13 Mar 2020 11:44:37 -0400 Subject: [PATCH 416/475] cors configuration example Added an example of an S3 bucket CORS configuration. Mostly to emphasize that it is required. --- .../source/developers/big-data-support.rst | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/developers/big-data-support.rst b/doc/sphinx-guides/source/developers/big-data-support.rst index a64dbb07ea1..c1c2969a60a 100644 --- a/doc/sphinx-guides/source/developers/big-data-support.rst +++ b/doc/sphinx-guides/source/developers/big-data-support.rst @@ -30,7 +30,26 @@ At present, one potential drawback for direct-upload is that files are only part ``./asadmin create-jvm-options "-Ddataverse.files..ingestsizelimit="`` -One additional step that is required to enable direct download to work with previewers is to allow cross site (CORS) requests on your S3 store. +**IMPORTANT:** One additional step that is required to enable direct download to work with previewers is to allow cross site (CORS) requests on your S3 store. +The example below shows how to enable the minimum needed CORS rules on a bucket using the AWS CLI command line tool. Note that you may need to add more methods and/or locations, if you also need to support certain previewers and external tools. + +``aws s3api put-bucket-cors --bucket --cors-configuration file://cors.json`` + +with the contents of the file cors.json as follows: + +.. code-block:: json + + { + "CORSRules": [ + { + "AllowedOrigins": ["https://"], + "AllowedHeaders": ["*"], + "AllowedMethods": ["PUT", "GET"] + } + ] + } + +Alternatively, you can enable CORS using the AWS S3 web interface, using json-encoded rules as in the example above. Since the direct upload mechanism creates the final file rather than an intermediate temporary file, user actions, such as neither saving or canceling an upload session before closing the browser page, can leave an abandoned file in the store. The direct upload mechanism attempts to use S3 Tags to aid in identifying/removing such files. Upon upload, files are given a "dv-status":"temp" tag which is removed when the dataset changes are saved and the new file(s) are added in Dataverse. Note that not all S3 implementations support Tags: Minio does not. WIth such stores, direct upload works, but Tags are not used. From 0f718a162fa6f22fcdecb6414869dde2ebcadc1a Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Fri, 13 Mar 2020 12:39:52 -0400 Subject: [PATCH 417/475] Update 4.20-release-notes --- doc/release-notes/4.20-release-notes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 8c246e4dad1..6b5fbe8f6c6 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -60,7 +60,7 @@ For a s3 store: Any additional S3 options you have set will need to be replaced as well, following the pattern in the last two lines above - delete the option including a '-' after 's3' and creating the same option with the '-' replaced by a '.', using the same value you currently have configured. -Once these options are set, restarting the glassfish service is all that is needed to complete the change. +Once these options are set, restarting the Glassfish service is all that is needed to complete the change. Note that the "\-Ddataverse.files.directory", if defined, continues to control where temporary files are stored (in the /temp subdir of that directory), independent of the location of any 'file' store defined above. From ab4f6c9fb40fbeb0d7c62527313437dd58714d05 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 13 Mar 2020 14:38:01 -0400 Subject: [PATCH 418/475] fix duplicate id issue with direct upload --- .../java/edu/harvard/iq/dataverse/DatasetPage.java | 10 ---------- src/main/webapp/dataset.xhtml | 1 - 2 files changed, 11 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index b13200b0dde..0ece7e9c4c2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -2982,16 +2982,6 @@ public void setLinkingDataverseErrorMessage(String linkingDataverseErrorMessage) this.linkingDataverseErrorMessage = linkingDataverseErrorMessage; } - UIInput selectedLinkingDataverseMenu; - - public UIInput getSelectedDataverseMenu() { - return selectedLinkingDataverseMenu; - } - - public void setSelectedDataverseMenu(UIInput selectedDataverseMenu) { - this.selectedLinkingDataverseMenu = selectedDataverseMenu; - } - private Boolean saveLink(Dataverse dataverse){ boolean retVal = true; if (readOnly) { diff --git a/src/main/webapp/dataset.xhtml b/src/main/webapp/dataset.xhtml index db7620bab71..d907aa5aceb 100644 --- a/src/main/webapp/dataset.xhtml +++ b/src/main/webapp/dataset.xhtml @@ -1363,7 +1363,6 @@
Date: Fri, 13 Mar 2020 15:34:41 -0400 Subject: [PATCH 419/475] #6697 fix delete user endpoint --- src/main/java/edu/harvard/iq/dataverse/api/Admin.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 763641f3774..c9890d21306 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -333,7 +333,8 @@ public Response deleteAuthenticatedUser(@PathParam("identifier") String identifi } return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found."); } - + + @DELETE @Path("authenticatedUsers/id/{id}/") public Response deleteAuthenticatedUserById(@PathParam("id") Long id) { AuthenticatedUser user = authSvc.findByID(id); @@ -836,7 +837,7 @@ public Response builtin2oauth(String content) { return ok(response); } - @DELETE + @Path("roles") From 40eafcf69c46518e8498b6ca6311f2eac4e7533d Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Mon, 16 Mar 2020 09:22:49 -0400 Subject: [PATCH 420/475] A *very* simple solution for the undetected database save fail in ingest. (is it too simple? am I missing something??) #6660 --- .../harvard/iq/dataverse/DataFileServiceBean.java | 13 +++++++++++++ .../iq/dataverse/ingest/IngestServiceBean.java | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java index 54a88c27d91..448218c93cd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java @@ -29,6 +29,8 @@ import java.util.logging.Logger; import javax.ejb.EJB; import javax.ejb.Stateless; +import javax.ejb.TransactionAttribute; +import javax.ejb.TransactionAttributeType; import javax.inject.Named; import javax.persistence.EntityManager; import javax.persistence.NoResultException; @@ -942,6 +944,17 @@ public DataFile save(DataFile dataFile) { } } + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public DataFile saveInTransaction(DataFile dataFile) { + + if (dataFile.isMergeable()) { + DataFile savedDataFile = em.merge(dataFile); + return savedDataFile; + } else { + throw new IllegalArgumentException("This DataFile object has been set to NOT MERGEABLE; please ensure a MERGEABLE object is passed to the save method."); + } + } + private void msg(String m){ System.out.println(m); } diff --git a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java index b06877df2ae..7922bcdd452 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java @@ -955,7 +955,7 @@ public boolean ingestAsTabular(Long datafile_id) { throw new EJBException("Deliberate database save failure"); } */ - dataFile = fileService.save(dataFile); + dataFile = fileService.saveInTransaction(dataFile); databaseSaveSuccessful = true; logger.fine("Ingest (" + dataFile.getFileMetadata().getLabel() + "."); From 4d64f85b26d131a68d8ff46b04eeba7619a311b9 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 16 Mar 2020 11:25:47 -0400 Subject: [PATCH 421/475] #6697 more delete user tests bundle update --- .../edu/harvard/iq/dataverse/api/Admin.java | 30 +++++++++++++++++-- src/main/java/propertyFiles/Bundle.properties | 11 ++++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index c9890d21306..4b498fb53a3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -74,6 +74,7 @@ import edu.harvard.iq.dataverse.authorization.AuthTestDataServiceBean; import edu.harvard.iq.dataverse.authorization.RoleAssignee; import edu.harvard.iq.dataverse.authorization.UserRecordIdentifier; +import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupServiceBean; import edu.harvard.iq.dataverse.authorization.users.User; import edu.harvard.iq.dataverse.dataset.DatasetThumbnail; import edu.harvard.iq.dataverse.dataset.DatasetUtil; @@ -136,6 +137,11 @@ public class Admin extends AbstractApiBean { GroupServiceBean groupService; @EJB SettingsServiceBean settingsService; + @EJB + DatasetVersionServiceBean datasetVersionService; + @EJB + ExplicitGroupServiceBean explicitGroupService; + // Make the session available @Inject @@ -348,8 +354,8 @@ private Response deleteAuthenticatedUser(AuthenticatedUser au) { if (!roleAssigneeSvc.getAssignmentsFor(au.getIdentifier()).isEmpty()) { return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.roleAssignments", Arrays.asList(au.getIdentifier()))); - } - + } + if (!dvObjSvc.findByAuthenticatedUserId(au).isEmpty()) { return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.dvobjects", Arrays.asList(au.getIdentifier()))); } @@ -358,10 +364,28 @@ private Response deleteAuthenticatedUser(AuthenticatedUser au) { return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.gbResps", Arrays.asList(au.getIdentifier()))); } + if (!datasetVersionService.getDatasetVersionUsersByAuthenticatedUser(au).isEmpty()) { + return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.versionUser", Arrays.asList(au.getIdentifier()))); + } + + if (!explicitGroupService.findGroups(au).isEmpty()) { + return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.groupMember", Arrays.asList(au.getIdentifier()))); + } + + if (userHasPendingAccessRequests(au)) { + return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.pendingRequests", Arrays.asList(au.getIdentifier()))); + } + authSvc.deleteAuthenticatedUser(au.getId()); return ok("AuthenticatedUser " + au.getIdentifier() + " deleted. "); - } + } + + private boolean userHasPendingAccessRequests(AuthenticatedUser au){ + + return !em.createNativeQuery("select datafile_id from fileaccessrequests where authenticated_user_id = "+au.getId()).getResultList().isEmpty(); + + } @POST @Path("publishDataverseAsCreator/{id}") diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 7308cdd16c8..4918e35127e 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -2223,10 +2223,13 @@ admin.api.migrateHDL.failure.must.be.hdl.dataset=Dataset was not registered as a admin.api.migrateHDL.success=Dataset migrate HDL registration complete. Dataset re-registered successfully. admin.api.migrateHDL.failure=Failed to migrate Dataset Handle id: {0} admin.api.migrateHDL.failureWithException=Failed to migrate Dataset Handle id: {0} Unexpected exception: {1} -admin.api.deleteUser.failure.dvobjects=Could not delete AuthenticatedUser {0} because the user has created Dataverse object(s). -admin.api.deleteUser.failure.gbResps=Could not delete AuthenticatedUser {0} because the user is associated with file download (Guestbook Response) record(s). -admin.api.deleteUser.failure.roleAssignments=Could not delete AuthenticatedUser {0} because the user is associated with role assignment record(s). - +admin.api.deleteUser.failure.dvobjects=Could not delete Authenticated User {0} because the user has created Dataverse object(s). +admin.api.deleteUser.failure.gbResps=Could not delete Authenticated User {0} because the user is associated with file download (Guestbook Response) record(s). +admin.api.deleteUser.failure.roleAssignments=Could not delete Authenticated User {0} because the user is associated with role assignment record(s). +admin.api.deleteUser.failure.versionUser=Could not delete Authenticated User {0} because the user has contributed to dataset version(s). +admin.api.deleteUser.failure.groupMember=Could not delete Authenticated User {0} because the user is a member of Explicit Group(s). +admin.api.deleteUser.failure.pendingRequests=Could not delete Authenticated User {0} because the user has pending File Access Request(s). +admin.api.deleteUser.success=Authenticated User {0} deleted. #Datasets.java datasets.api.updatePIDMetadata.failure.dataset.must.be.released=Modify Registration Metadata must be run on a published dataset. From 34df93c195dc7274a5bcb9540424d4282b3ac9a3 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Mon, 16 Mar 2020 14:06:15 -0400 Subject: [PATCH 422/475] One extra dataFileService.save(), to ensure there's no optimistic lock after a successful update. (#6660) --- .../edu/harvard/iq/dataverse/ingest/IngestServiceBean.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java index 7922bcdd452..c6ca819f4fd 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java @@ -958,7 +958,7 @@ public boolean ingestAsTabular(Long datafile_id) { dataFile = fileService.saveInTransaction(dataFile); databaseSaveSuccessful = true; - logger.fine("Ingest (" + dataFile.getFileMetadata().getLabel() + "."); + logger.info("Ingest (" + dataFile.getFileMetadata().getLabel() + "."); if (additionalData != null) { // remove the extra tempfile, if there was one: @@ -996,7 +996,7 @@ public boolean ingestAsTabular(Long datafile_id) { // and we want to save the original of the ingested file: try { dataAccess.backupAsAux(FileUtil.SAVED_ORIGINAL_FILENAME_EXTENSION); - logger.fine("Saved the ingested original as a backup aux file "+FileUtil.SAVED_ORIGINAL_FILENAME_EXTENSION); + logger.info("Saved the ingested original as a backup aux file "+FileUtil.SAVED_ORIGINAL_FILENAME_EXTENSION); } catch (IOException iox) { logger.warning("Failed to save the ingested original! " + iox.getMessage()); } @@ -1005,6 +1005,9 @@ public boolean ingestAsTabular(Long datafile_id) { dataAccess.savePath(Paths.get(tabFile.getAbsolutePath())); // Reset the file size: dataFile.setFilesize(dataAccess.getSize()); + + dataFile = fileService.save(dataFile); + logger.info("saved data file after updating the size"); // delete the temp tab-file: tabFile.delete(); From 4e70dd6ffa8a9ef6618a0ce4e60e44336ff90a09 Mon Sep 17 00:00:00 2001 From: Don Sizemore Date: Mon, 16 Mar 2020 14:22:15 -0400 Subject: [PATCH 423/475] #6742 update EC2 documentation --- .../source/developers/deployment.rst | 15 ++- .../source/developers/testing.rst | 29 +++-- scripts/installer/ec2-create-instance.sh | 107 ++++++++++++++---- 3 files changed, 111 insertions(+), 40 deletions(-) diff --git a/doc/sphinx-guides/source/developers/deployment.rst b/doc/sphinx-guides/source/developers/deployment.rst index 9532e7c769f..5e830bfde5b 100755 --- a/doc/sphinx-guides/source/developers/deployment.rst +++ b/doc/sphinx-guides/source/developers/deployment.rst @@ -82,23 +82,26 @@ Download and Run the "Create Instance" Script Once you have done the configuration above, you are ready to try running the "ec2-create-instance.sh" script to spin up Dataverse in AWS. -Download :download:`ec2-create-instance.sh <../../../../scripts/installer/ec2-create-instance.sh>` and put it somewhere reasonable. For the purpose of these instructions we'll assume it's in the "Downloads" directory in your home directory. +Download :download:`ec2-create-instance.sh` and put it somewhere reasonable. For the purpose of these instructions we'll assume it's in the "Downloads" directory in your home directory. -ec2-create-instance accepts a number few command-line switches: +To run it with default values you just need the script, but you may also want a current copy of the ansible :download:`group vars`_ file. + +ec2-create-instance accepts a number of command-line switches, including: * -r: GitHub Repository URL (defaults to https://github.com/IQSS/dataverse.git) * -b: branch to build (defaults to develop) * -p: pemfile directory (defaults to $HOME) * -g: Ansible GroupVars file (if you wish to override role defaults) +* -h: help (displays usage for each available option) ``bash ~/Downloads/ec2-create-instance.sh -b develop -r https://github.com/scholarsportal/dataverse.git -g main.yml`` -Now you will need to wait around 15 minutes until the deployment is finished. Eventually, the output should tell you how to access the installation of Dataverse in a web browser or via ssh. It will also provide instructions on how to delete the instance when you are finished with it. Please be aware that AWS charges per minute for a running instance. You can also delete your instance from https://console.aws.amazon.com/console/home?region=us-east-1 . +You will need to wait for 15 minutes or so until the deployment is finished, longer if you've enabled sample data and/or the API test suite. Eventually, the output should tell you how to access the installation of Dataverse in a web browser or via SSH. It will also provide instructions on how to delete the instance when you are finished with it. Please be aware that AWS charges per minute for a running instance. You may also delete your instance from https://console.aws.amazon.com/console/home?region=us-east-1 . -Caveats -~~~~~~~ +Caveat Recipiens +~~~~~~~~~~~~~~~~ -Please note that while the script should work fine on newish branches, older branches that have different dependencies such as an older version of Solr may not produce a working Dataverse installation. Your mileage may vary. +Please note that while the script should work well on new-ish branches, older branches that have different dependencies such as an older version of Solr may not produce a working Dataverse installation. Your mileage may vary. ---- diff --git a/doc/sphinx-guides/source/developers/testing.rst b/doc/sphinx-guides/source/developers/testing.rst index 82a4e22ebed..2894c457d85 100755 --- a/doc/sphinx-guides/source/developers/testing.rst +++ b/doc/sphinx-guides/source/developers/testing.rst @@ -108,22 +108,33 @@ Unfortunately, the term "integration tests" can mean different things to differe Running the Full API Test Suite Using EC2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To run the API test suite on EC2 you should first follow the steps in the :doc:`deployment` section to get set up for AWS in general and EC2 in particular. +To run the API test suite in an EC2 instance you should first follow the steps in the :doc:`deployment` section to get set up for AWS in general and EC2 in particular. -Then read the instructions in https://github.com/IQSS/dataverse-sample-data for EC2 but be sure to make the adjustments below. +You may always retrieve a current copy of the ec2-create-instance.sh script and accompanying group_var.yml file from the `dataverse-ansible repo`_: -Edit ``ec2config.yaml`` to change ``test_suite`` to ``true``. +- `ec2-create-instance.sh`_ +- `main.yml`_ -Pass in the repo and branch you are testing. You should also specify a local directory where server.log and other useful information will be written so you can start debugging any failures. +Edit ``main.yml`` to set the desired GitHub repo, branch, and to ensure that the API test suite is enabled: + +- ``dataverse_repo: https://github.com/IQSS/dataverse.git`` +- ``dataverse_branch: develop`` +- ``dataverse.api.test_suite: true`` +- ``dataverse.sampledata.enabled: true`` + +If you wish, you may pass the local path of a logging directory, which will tell ec2-create-instance.sh to `grab glassfish, maven and other logs`_ for your review. + +Finally, run the script: .. code-block:: bash - export REPO=https://github.com/IQSS/dataverse.git - export BRANCH=123-my-branch - export LOGS=/tmp/123 + $ ./ec2-create-instance.sh -g main.yml -l log_dir + +Near the beginning and at the end of the ec2-create-instance.sh output you will see instructions for connecting to the instance via SSH. If you are actively working on a branch and want to refresh the warfile after each commit, you may wish to call a `redeploy.sh`_ script placed by the Ansible role, which will do a "git pull" against your branch, build the warfile, deploy the warfile, then restart glassfish. By default this script is written to /tmp/dataverse/redeploy.sh. You may invoke the script by appending it to the SSH command in ec2-create's output: + +.. code-block:: bash - mkdir $LOGS - ./ec2-create-instance.sh -g ec2config.yaml -r $REPO -b $BRANCH -l $LOGS + $ ssh -i your_pem.pem user@ec2-host.aws.com /tmp/dataverse/redeploy.sh Running the full API test suite using Docker ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/scripts/installer/ec2-create-instance.sh b/scripts/installer/ec2-create-instance.sh index 63e9ac21bc6..81fdd5940c1 100755 --- a/scripts/installer/ec2-create-instance.sh +++ b/scripts/installer/ec2-create-instance.sh @@ -3,21 +3,28 @@ # For docs, see the "Deployment" page in the Dev Guide. # repo and branch defaults -REPO_URL='https://github.com/IQSS/dataverse.git' -BRANCH='develop' +REPO_URL_DEFAULT='https://github.com/IQSS/dataverse.git' +BRANCH_DEFAULT='develop' PEM_DEFAULT=${HOME} +AWS_AMI_DEFAULT='ami-9887c6e7' usage() { - echo "Usage: $0 -b -r -p -g " 1>&2 + echo "Usage: $0 -b -r -p -g -a -i aws_image -s aws_size -t aws_tag -l local_log_path" 1>&2 echo "default branch is develop" echo "default repo is https://github.com/IQSS/dataverse" echo "default .pem location is ${HOME}" echo "example group_vars may be retrieved from https://raw.githubusercontent.com/IQSS/dataverse-ansible/master/defaults/main.yml" + echo "default AWS AMI ID is $AWS_AMI_DEFAULT" + echo "default AWS size is t2.medium" + echo "local log path" exit 1 } -while getopts ":r:b:g:p:" o; do +while getopts ":a:r:b:g:p:i:s:t:l:" o; do case "${o}" in + a) + DA_BRANCH=${OPTARG} + ;; r) REPO_URL=${OPTARG} ;; @@ -30,32 +37,74 @@ while getopts ":r:b:g:p:" o; do p) PEM_DIR=${OPTARG} ;; + i) + AWS_IMAGE=${OPTARG} + ;; + s) + AWS_SIZE=${OPTARG} + ;; + t) + TAG=${OPTARG} + ;; + l) + LOCAL_LOG_PATH=${OPTARG} + ;; *) usage ;; esac done -# test for user-supplied conf files +# test for ansible group_vars if [ ! -z "$GRPVRS" ]; then GVFILE=$(basename "$GRPVRS") GVARG="-e @$GVFILE" echo "using $GRPVRS for extra vars" fi +# test for CLI args if [ ! -z "$REPO_URL" ]; then GVARG+=" -e dataverse_repo=$REPO_URL" - echo "using $REPO_URL" + echo "using repo $REPO_URL" fi if [ ! -z "$BRANCH" ]; then GVARG+=" -e dataverse_branch=$BRANCH" - echo "building $BRANCH" + echo "building branch $BRANCH" fi +# The AMI ID may change in the future and the way to look it up is with the following command, which takes a long time to run: +# aws ec2 describe-images --owners 'aws-marketplace' --filters 'Name=product-code,Values=aw0evgkw8e5c1q413zgy5pjce' --query 'sort_by(Images, &CreationDate)[-1].[ImageId]' --output 'text' +# To use an AMI, one must subscribe to it via the AWS GUI. +# AMI IDs are specific to the region. + +if [ ! -z "$AWS_IMAGE" ]; then + AMI_ID=$AWS_IMAGE +else + AMI_ID="$AWS_AMI_DEFAULT" +fi +echo "using $AMI_ID" + +if [ ! -z "$AWS_SIZE" ]; then + SIZE=$AWS_SIZE +else + SIZE="t2.medium" +fi +echo "using $SIZE" + +if [ ! -z "$TAG" ]; then + TAGARG="--tag-specifications ResourceType=instance,Tags=[{Key=name,Value=$TAG}]" + echo "using tag $TAG" +fi + +# default to dataverse-ansible/master +if [ -z "$DA_BRANCH" ]; then + DA_BRANCH="master" +fi + +# ansible doesn't care about pem_dir (yet) if [ -z "$PEM_DIR" ]; then PEM_DIR="$PEM_DEFAULT" - echo "using $PEM_DIR" fi AWS_CLI_VERSION=$(aws --version) @@ -95,22 +144,12 @@ else exit 1 fi -# The AMI ID may change in the future and the way to look it up is with the -# following command, which takes a long time to run: -# -# aws ec2 describe-images --owners 'aws-marketplace' --filters 'Name=product-code,Values=aw0evgkw8e5c1q413zgy5pjce' --query 'sort_by(Images, &CreationDate)[-1].[ImageId]' --output 'text' -# -# To use this AMI, we subscribed to it from the AWS GUI. -# AMI IDs are specific to the region. -AMI_ID='ami-9887c6e7' -# Smaller than medium lead to Maven and Solr problems. -SIZE='t2.medium' echo "Creating EC2 instance" # TODO: Add some error checking for "ec2 run-instances". -INSTANCE_ID=$(aws ec2 run-instances --image-id $AMI_ID --security-groups $SECURITY_GROUP --count 1 --instance-type $SIZE --key-name $PEM_DIR/$KEY_NAME --query 'Instances[0].InstanceId' --block-device-mappings '[ { "DeviceName": "/dev/sda1", "Ebs": { "DeleteOnTermination": true } } ]' | tr -d \") +INSTANCE_ID=$(aws ec2 run-instances --image-id $AMI_ID --security-groups $SECURITY_GROUP $TAGARG --count 1 --instance-type $SIZE --key-name $PEM_DIR/$KEY_NAME --query 'Instances[0].InstanceId' --block-device-mappings '[ { "DeviceName": "/dev/sda1", "Ebs": { "DeleteOnTermination": true } } ]' | tr -d \") echo "Instance ID: "$INSTANCE_ID -echo "giving instance 30 seconds to wake up..." -sleep 30 +echo "giving instance 60 seconds to wake up..." +sleep 60 echo "End creating EC2 instance" PUBLIC_DNS=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID --query "Reservations[*].Instances[*].[PublicDnsName]" --output text) @@ -132,18 +171,36 @@ ssh -T -i $PEM_FILE -o 'StrictHostKeyChecking no' -o 'UserKnownHostsFile=/dev/nu sudo yum -y install epel-release sudo yum -y install https://releases.ansible.com/ansible/rpm/release/epel-7-x86_64/ansible-2.7.9-1.el7.ans.noarch.rpm sudo yum -y install git nano -git clone https://github.com/IQSS/dataverse-ansible.git dataverse +git clone -b $DA_BRANCH https://github.com/IQSS/dataverse-ansible.git dataverse export ANSIBLE_ROLES_PATH=. -echo $extra_vars ansible-playbook -v -i dataverse/inventory dataverse/dataverse.pb --connection=local $GVARG EOF +if [ ! -z "$LOCAL_LOG_PATH" ]; then + echo "copying logs to $LOCAL_LOG_PATH." + # 1 accept SSH keys + ssh-keyscan ${PUBLIC_DNS} >> ~/.ssh/known_hosts + # 2 logdir should exist + mkdir -p $LOCAL_LOG_PATH + # 3 grab logs for local processing in jenkins + rsync -av -e "ssh -i $PEM_FILE" --ignore-missing-args centos@$PUBLIC_DNS:/tmp/dataverse/target/site $LOCAL_LOG_PATH/ + rsync -av -e "ssh -i $PEM_FILE" --ignore-missing-args centos@$PUBLIC_DNS:/tmp/dataverse/target/surefire-reports $LOCAL_LOG_PATH/ + rsync -av -e "ssh -i $PEM_FILE" centos@$PUBLIC_DNS:/usr/local/glassfish4/glassfish/domains/domain1/logs/server* $LOCAL_LOG_PATH/ + # 4 grab mvn.out + rsync -av -e "ssh -i $PEM_FILE" --ignore-missing-args centos@$PUBLIC_DNS:/tmp/dataverse/mvn.out $LOCAL_LOG_PATH/ + # 5 jacoco + rsync -av -e "ssh -i $PEM_FILE" --ignore-missing-args centos@$PUBLIC_DNS:/tmp/dataverse/target/coverage-it $LOCAL_LOG_PATH/ + rsync -av -e "ssh -i $PEM_FILE" --ignore-missing-args centos@$PUBLIC_DNS:/tmp/dataverse/target/*.exec $LOCAL_LOG_PATH/ + rsync -av -e "ssh -i $PEM_FILE" --ignore-missing-args centos@$PUBLIC_DNS:/tmp/dataverse/target/classes $LOCAL_LOG_PATH/ + rsync -av -e "ssh -i $PEM_FILE" --ignore-missing-args centos@$PUBLIC_DNS:/tmp/dataverse/src $LOCAL_LOG_PATH/ +fi + # Port 8080 has been added because Ansible puts a redirect in place # from HTTP to HTTPS and the cert is invalid (self-signed), forcing # the user to click through browser warnings. -CLICKABLE_LINK="http://${PUBLIC_DNS}:8080" +CLICKABLE_LINK="http://${PUBLIC_DNS}" echo "To ssh into the new instance:" echo "ssh -i $PEM_FILE $USER_AT_HOST" -echo "Branch \"$BRANCH\" from $REPO_URL has been deployed to $CLICKABLE_LINK" +echo "Branch $BRANCH from $REPO_URL has been deployed to $CLICKABLE_LINK" echo "When you are done, please terminate your instance with:" echo "aws ec2 terminate-instances --instance-ids $INSTANCE_ID" From d4bfae0d5373f690290003012100f276b69bc084 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Mon, 16 Mar 2020 18:39:17 -0400 Subject: [PATCH 424/475] cleaned up logging messages (#6660) --- .../harvard/iq/dataverse/ingest/IngestServiceBean.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java index c6ca819f4fd..5e84ecb0155 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java @@ -958,7 +958,7 @@ public boolean ingestAsTabular(Long datafile_id) { dataFile = fileService.saveInTransaction(dataFile); databaseSaveSuccessful = true; - logger.info("Ingest (" + dataFile.getFileMetadata().getLabel() + "."); + logger.fine("Ingest (" + dataFile.getFileMetadata().getLabel() + "."); if (additionalData != null) { // remove the extra tempfile, if there was one: @@ -982,7 +982,7 @@ public boolean ingestAsTabular(Long datafile_id) { } if (!databaseSaveSuccessful) { - logger.warning("Ingest failure (!databaseSaveSuccessful)."); + logger.warning("Ingest failure (failed to save the tabular data in the database; file left intact as uploaded)."); return false; } @@ -996,7 +996,7 @@ public boolean ingestAsTabular(Long datafile_id) { // and we want to save the original of the ingested file: try { dataAccess.backupAsAux(FileUtil.SAVED_ORIGINAL_FILENAME_EXTENSION); - logger.info("Saved the ingested original as a backup aux file "+FileUtil.SAVED_ORIGINAL_FILENAME_EXTENSION); + logger.fine("Saved the ingested original as a backup aux file "+FileUtil.SAVED_ORIGINAL_FILENAME_EXTENSION); } catch (IOException iox) { logger.warning("Failed to save the ingested original! " + iox.getMessage()); } @@ -1007,7 +1007,7 @@ public boolean ingestAsTabular(Long datafile_id) { dataFile.setFilesize(dataAccess.getSize()); dataFile = fileService.save(dataFile); - logger.info("saved data file after updating the size"); + logger.fine("saved data file after updating the size"); // delete the temp tab-file: tabFile.delete(); From ac67f2c1b0dcae4d241cc1fd13aea62f8cec33ae Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 17 Mar 2020 11:32:35 -0400 Subject: [PATCH 425/475] #6697 add integration tests --- .../edu/harvard/iq/dataverse/api/Admin.java | 7 +-- .../edu/harvard/iq/dataverse/api/UsersIT.java | 50 ++++++++++++++++++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 4b498fb53a3..f48fb7ad068 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -352,13 +352,14 @@ public Response deleteAuthenticatedUserById(@PathParam("id") Long id) { private Response deleteAuthenticatedUser(AuthenticatedUser au) { - if (!roleAssigneeSvc.getAssignmentsFor(au.getIdentifier()).isEmpty()) { - return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.roleAssignments", Arrays.asList(au.getIdentifier()))); - } if (!dvObjSvc.findByAuthenticatedUserId(au).isEmpty()) { return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.dvobjects", Arrays.asList(au.getIdentifier()))); } + + if (!roleAssigneeSvc.getAssignmentsFor(au.getIdentifier()).isEmpty()) { + return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.roleAssignments", Arrays.asList(au.getIdentifier()))); + } if (!gbRespSvc.findByAuthenticatedUserId(au).isEmpty()) { return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.gbResps", Arrays.asList(au.getIdentifier()))); diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java index 35799add309..588d6f6e7f0 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java @@ -19,6 +19,7 @@ import static junit.framework.Assert.assertEquals; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertTrue; import org.junit.BeforeClass; import org.junit.Test; @@ -28,11 +29,11 @@ public class UsersIT { @BeforeClass public static void setUp() { RestAssured.baseURI = UtilIT.getRestAssuredBaseUri(); - + /* Response removeAllowApiTokenLookupViaApi = UtilIT.deleteSetting(SettingsServiceBean.Key.AllowApiTokenLookupViaApi); removeAllowApiTokenLookupViaApi.then().assertThat() .statusCode(200); - +*/ } @Test @@ -430,6 +431,51 @@ public void testAPITokenEndpoints() { getExpiration.then().assertThat() .statusCode(UNAUTHORIZED.getStatusCode()); + } + + @Test + public void testDeleteAuthenticatedUser() { + + Response createSuperuser = UtilIT.createRandomUser(); + String superuserUsername = UtilIT.getUsernameFromResponse(createSuperuser); + String superuserApiToken = UtilIT.getApiTokenFromResponse(createSuperuser); + Response toggleSuperuser = UtilIT.makeSuperUser(superuserUsername); + toggleSuperuser.then().assertThat() + .statusCode(OK.getStatusCode()); + + Response createUser = UtilIT.createRandomUser(); + createUser.prettyPrint(); + String usernameForCreateDV = UtilIT.getUsernameFromResponse(createUser); + String normalApiToken = UtilIT.getApiTokenFromResponse(createUser); + + Response createDataverse = UtilIT.createRandomDataverse(normalApiToken); + createDataverse.prettyPrint(); + createDataverse.then().assertThat() + .statusCode(CREATED.getStatusCode()); + String dataverseAlias = UtilIT.getAliasFromResponse(createDataverse); + + //if this fails likely one of the converts that said they failed actually didn't! + Response deleteUserCreateDV = UtilIT.deleteUser(usernameForCreateDV); + + deleteUserCreateDV.prettyPrint(); + deleteUserCreateDV.then().assertThat() + .statusCode(BAD_REQUEST.getStatusCode()) + .body("message", contains("Could not delete Authenticated User @" + usernameForCreateDV + " because the user has created Dataverse object(s).")); + + Response deleteDataverse = UtilIT.deleteDataverse(dataverseAlias, normalApiToken); + deleteDataverse.prettyPrint(); + deleteDataverse.then().assertThat() + .statusCode(OK.getStatusCode()); + + Response deleteUserAfterDeleteDV = UtilIT.deleteUser(usernameForCreateDV); + //Should be able to delete user after dv is deleted + deleteUserAfterDeleteDV.prettyPrint(); + deleteUserAfterDeleteDV.then().assertThat() + .statusCode(OK.getStatusCode()); + Response deleteSuperuser = UtilIT.deleteUser(superuserUsername); + assertEquals(200, deleteSuperuser.getStatusCode()); + + } private Response convertUserFromBcryptToSha1(long idOfBcryptUserToConvert, String password) { From 9ecc40c719aafa2877b5a352c68d8d0bebd17bf5 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 17 Mar 2020 16:26:43 -0400 Subject: [PATCH 426/475] #6697 fix failing test --- src/main/java/propertyFiles/Bundle.properties | 2 +- src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 4918e35127e..7f382e3f43a 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -2223,7 +2223,7 @@ admin.api.migrateHDL.failure.must.be.hdl.dataset=Dataset was not registered as a admin.api.migrateHDL.success=Dataset migrate HDL registration complete. Dataset re-registered successfully. admin.api.migrateHDL.failure=Failed to migrate Dataset Handle id: {0} admin.api.migrateHDL.failureWithException=Failed to migrate Dataset Handle id: {0} Unexpected exception: {1} -admin.api.deleteUser.failure.dvobjects=Could not delete Authenticated User {0} because the user has created Dataverse object(s). +admin.api.deleteUser.failure.dvobjects=Could not delete Authenticated User {0} because the user has created Dataverse object(s). admin.api.deleteUser.failure.gbResps=Could not delete Authenticated User {0} because the user is associated with file download (Guestbook Response) record(s). admin.api.deleteUser.failure.roleAssignments=Could not delete Authenticated User {0} because the user is associated with role assignment record(s). admin.api.deleteUser.failure.versionUser=Could not delete Authenticated User {0} because the user has contributed to dataset version(s). diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java index 588d6f6e7f0..e71edf174b7 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java @@ -460,7 +460,7 @@ public void testDeleteAuthenticatedUser() { deleteUserCreateDV.prettyPrint(); deleteUserCreateDV.then().assertThat() .statusCode(BAD_REQUEST.getStatusCode()) - .body("message", contains("Could not delete Authenticated User @" + usernameForCreateDV + " because the user has created Dataverse object(s).")); + .body("message", equalTo("Could not delete Authenticated User @" + usernameForCreateDV + " because the user has created Dataverse object(s).")); Response deleteDataverse = UtilIT.deleteDataverse(dataverseAlias, normalApiToken); deleteDataverse.prettyPrint(); From 89f5d8e71bb651355dee18d69c4836265610312e Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 17 Mar 2020 17:15:23 -0400 Subject: [PATCH 427/475] #6697 add test for user has role assigned --- .../edu/harvard/iq/dataverse/api/UsersIT.java | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java index e71edf174b7..f2d67a80693 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java @@ -5,6 +5,7 @@ import com.jayway.restassured.http.ContentType; import com.jayway.restassured.path.json.JsonPath; import com.jayway.restassured.response.Response; +import edu.harvard.iq.dataverse.authorization.DataverseRole; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import java.util.ArrayList; import java.util.List; @@ -454,7 +455,23 @@ public void testDeleteAuthenticatedUser() { .statusCode(CREATED.getStatusCode()); String dataverseAlias = UtilIT.getAliasFromResponse(createDataverse); - //if this fails likely one of the converts that said they failed actually didn't! + createUser = UtilIT.createRandomUser(); + createUser.prettyPrint(); + String usernameForAssignedRole = UtilIT.getUsernameFromResponse(createUser); + String roleApiToken = UtilIT.getApiTokenFromResponse(createUser); + + Response assignRole = UtilIT.grantRoleOnDataverse(dataverseAlias, DataverseRole.EDITOR.toString(), + "@" + usernameForAssignedRole, superuserApiToken); + + //Shouldn't be able to delete user with a role + Response deleteUserRole = UtilIT.deleteUser(usernameForAssignedRole); + + deleteUserRole.prettyPrint(); + deleteUserRole.then().assertThat() + .statusCode(BAD_REQUEST.getStatusCode()) + .body("message", equalTo("Could not delete Authenticated User @" + usernameForAssignedRole + " because the user is associated with role assignment record(s).")); + + //Shouldn't be able to delete a user who has created a DV Response deleteUserCreateDV = UtilIT.deleteUser(usernameForCreateDV); deleteUserCreateDV.prettyPrint(); @@ -466,16 +483,22 @@ public void testDeleteAuthenticatedUser() { deleteDataverse.prettyPrint(); deleteDataverse.then().assertThat() .statusCode(OK.getStatusCode()); - + Response deleteUserAfterDeleteDV = UtilIT.deleteUser(usernameForCreateDV); //Should be able to delete user after dv is deleted deleteUserAfterDeleteDV.prettyPrint(); deleteUserAfterDeleteDV.then().assertThat() .statusCode(OK.getStatusCode()); + + deleteUserAfterDeleteDV = UtilIT.deleteUser(usernameForAssignedRole); + //Should be able to delete user after dv is deleted role should be gone as well + deleteUserAfterDeleteDV.prettyPrint(); + deleteUserAfterDeleteDV.then().assertThat() + .statusCode(OK.getStatusCode()); + Response deleteSuperuser = UtilIT.deleteUser(superuserUsername); assertEquals(200, deleteSuperuser.getStatusCode()); - } private Response convertUserFromBcryptToSha1(long idOfBcryptUserToConvert, String password) { From a909444f7a22ea19a5752e93d465df71abcb422f Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 18 Mar 2020 10:04:41 -0400 Subject: [PATCH 428/475] #6697 refactor error messages --- .../edu/harvard/iq/dataverse/api/Admin.java | 33 +------ .../AuthenticationServiceBean.java | 86 +++++++++++++++++++ src/main/java/propertyFiles/Bundle.properties | 13 +-- .../edu/harvard/iq/dataverse/api/UsersIT.java | 2 +- 4 files changed, 98 insertions(+), 36 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index f48fb7ad068..aa76381ed56 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -351,30 +351,9 @@ public Response deleteAuthenticatedUserById(@PathParam("id") Long id) { } private Response deleteAuthenticatedUser(AuthenticatedUser au) { - - - if (!dvObjSvc.findByAuthenticatedUserId(au).isEmpty()) { - return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.dvobjects", Arrays.asList(au.getIdentifier()))); - } - - if (!roleAssigneeSvc.getAssignmentsFor(au.getIdentifier()).isEmpty()) { - return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.roleAssignments", Arrays.asList(au.getIdentifier()))); - } - - if (!gbRespSvc.findByAuthenticatedUserId(au).isEmpty()) { - return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.gbResps", Arrays.asList(au.getIdentifier()))); - } - - if (!datasetVersionService.getDatasetVersionUsersByAuthenticatedUser(au).isEmpty()) { - return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.versionUser", Arrays.asList(au.getIdentifier()))); - } - - if (!explicitGroupService.findGroups(au).isEmpty()) { - return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.groupMember", Arrays.asList(au.getIdentifier()))); - } - - if (userHasPendingAccessRequests(au)) { - return badRequest(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.pendingRequests", Arrays.asList(au.getIdentifier()))); + String errorMessages = authSvc.getDeleteUserErrorMessages(au); + if (!errorMessages.isEmpty()) { + return badRequest(errorMessages); } authSvc.deleteAuthenticatedUser(au.getId()); @@ -382,11 +361,7 @@ private Response deleteAuthenticatedUser(AuthenticatedUser au) { } - private boolean userHasPendingAccessRequests(AuthenticatedUser au){ - - return !em.createNativeQuery("select datafile_id from fileaccessrequests where authenticated_user_id = "+au.getId()).getResultList().isEmpty(); - - } + @POST @Path("publishDataverseAsCreator/{id}") diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java index f5d4b015fc7..e734f34142d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java @@ -1,5 +1,9 @@ package edu.harvard.iq.dataverse.authorization; +import edu.harvard.iq.dataverse.DatasetVersionServiceBean; +import edu.harvard.iq.dataverse.DvObjectServiceBean; +import edu.harvard.iq.dataverse.GuestbookResponseServiceBean; +import edu.harvard.iq.dataverse.RoleAssigneeServiceBean; import edu.harvard.iq.dataverse.UserNotificationServiceBean; import edu.harvard.iq.dataverse.UserServiceBean; import edu.harvard.iq.dataverse.authorization.providers.oauth2.oidc.OIDCAuthenticationProviderFactory; @@ -9,6 +13,7 @@ import edu.harvard.iq.dataverse.authorization.exceptions.AuthenticationFailedException; import edu.harvard.iq.dataverse.authorization.exceptions.AuthenticationProviderFactoryNotFoundException; import edu.harvard.iq.dataverse.authorization.exceptions.AuthorizationSetupException; +import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupServiceBean; import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderFactory; import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderRow; import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinAuthenticationProvider; @@ -26,9 +31,11 @@ import edu.harvard.iq.dataverse.confirmemail.ConfirmEmailServiceBean; import edu.harvard.iq.dataverse.passwordreset.PasswordResetData; import edu.harvard.iq.dataverse.passwordreset.PasswordResetServiceBean; +import edu.harvard.iq.dataverse.util.BundleUtil; import edu.harvard.iq.dataverse.validation.PasswordValidatorServiceBean; import edu.harvard.iq.dataverse.workflows.WorkflowComment; import java.sql.Timestamp; +import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Date; @@ -102,6 +109,21 @@ public class AuthenticationServiceBean { @EJB PasswordValidatorServiceBean passwordValidatorService; + + @EJB + DvObjectServiceBean dvObjSvc; + + @EJB + RoleAssigneeServiceBean roleAssigneeSvc; + + @EJB + GuestbookResponseServiceBean gbRespSvc; + + @EJB + DatasetVersionServiceBean datasetVersionService; + + @EJB + ExplicitGroupServiceBean explicitGroupService; @PersistenceContext(unitName = "VDCNet-ejbPU") private EntityManager em; @@ -511,6 +533,70 @@ public AuthenticatedUser lookupUser( String apiToken ) { return tkn.getAuthenticatedUser(); } + /* + getDeleteUserErrorMessages( AuthenticatedUser au ) + method which checks for reasons that a user may not be deleted + -has created dvObjects + -has roles + -has guestbook records + -etc. + An empty string is returned if the user is 'deletable' + */ + + public String getDeleteUserErrorMessages(AuthenticatedUser au) { + String retVal = ""; + if (!dvObjSvc.findByAuthenticatedUserId(au).isEmpty()) { + retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.dvobjects"); + } + + if (!roleAssigneeSvc.getAssignmentsFor(au.getIdentifier()).isEmpty()) { + if (!retVal.isEmpty()) { + retVal += "; "; + } + retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.roleAssignments"); + } + + if (!gbRespSvc.findByAuthenticatedUserId(au).isEmpty()) { + if (!retVal.isEmpty()) { + retVal += "; "; + } + retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.gbResps"); + } + + if (!datasetVersionService.getDatasetVersionUsersByAuthenticatedUser(au).isEmpty()) { + if (!retVal.isEmpty()) { + retVal += "; "; + } + retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.versionUser"); + } + + if (!explicitGroupService.findGroups(au).isEmpty()) { + if (!retVal.isEmpty()) { + retVal += "; "; + } + retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.groupMember"); + } + + if (userHasPendingAccessRequests(au)) { + if (!retVal.isEmpty()) { + retVal += "; "; + } + retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.pendingRequests"); + } + if (!retVal.isEmpty()) { + // + retVal = BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.prefix", Arrays.asList(au.getIdentifier())) + " " + retVal + "."; + } + + return retVal; + } + + private boolean userHasPendingAccessRequests(AuthenticatedUser au){ + + return !em.createNativeQuery("select datafile_id from fileaccessrequests where authenticated_user_id = "+au.getId()).getResultList().isEmpty(); + + } + public AuthenticatedUser save( AuthenticatedUser user ) { em.persist(user); em.flush(); diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 7f382e3f43a..34401b323bc 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -2223,12 +2223,13 @@ admin.api.migrateHDL.failure.must.be.hdl.dataset=Dataset was not registered as a admin.api.migrateHDL.success=Dataset migrate HDL registration complete. Dataset re-registered successfully. admin.api.migrateHDL.failure=Failed to migrate Dataset Handle id: {0} admin.api.migrateHDL.failureWithException=Failed to migrate Dataset Handle id: {0} Unexpected exception: {1} -admin.api.deleteUser.failure.dvobjects=Could not delete Authenticated User {0} because the user has created Dataverse object(s). -admin.api.deleteUser.failure.gbResps=Could not delete Authenticated User {0} because the user is associated with file download (Guestbook Response) record(s). -admin.api.deleteUser.failure.roleAssignments=Could not delete Authenticated User {0} because the user is associated with role assignment record(s). -admin.api.deleteUser.failure.versionUser=Could not delete Authenticated User {0} because the user has contributed to dataset version(s). -admin.api.deleteUser.failure.groupMember=Could not delete Authenticated User {0} because the user is a member of Explicit Group(s). -admin.api.deleteUser.failure.pendingRequests=Could not delete Authenticated User {0} because the user has pending File Access Request(s). +admin.api.deleteUser.failure.prefix=Could not delete Authenticated User {0} because +admin.api.deleteUser.failure.dvobjects= the user has created Dataverse object(s) +admin.api.deleteUser.failure.gbResps= the user is associated with file download (Guestbook Response) record(s) +admin.api.deleteUser.failure.roleAssignments=the user is associated with role assignment record(s) +admin.api.deleteUser.failure.versionUser=the user has contributed to dataset version(s) +admin.api.deleteUser.failure.groupMember=the user is a member of Explicit Group(s) +admin.api.deleteUser.failure.pendingRequests=the user has pending File Access Request(s) admin.api.deleteUser.success=Authenticated User {0} deleted. #Datasets.java diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java index f2d67a80693..83dfc5fd889 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java @@ -477,7 +477,7 @@ public void testDeleteAuthenticatedUser() { deleteUserCreateDV.prettyPrint(); deleteUserCreateDV.then().assertThat() .statusCode(BAD_REQUEST.getStatusCode()) - .body("message", equalTo("Could not delete Authenticated User @" + usernameForCreateDV + " because the user has created Dataverse object(s).")); + .body("message", equalTo("Could not delete Authenticated User @" + usernameForCreateDV + " because the user has created Dataverse object(s); the user is associated with role assignment record(s).")); Response deleteDataverse = UtilIT.deleteDataverse(dataverseAlias, normalApiToken); deleteDataverse.prettyPrint(); From 44df633f85be8411d48757551004aed4667105f8 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 18 Mar 2020 10:12:15 -0400 Subject: [PATCH 429/475] #6697 add comments --- src/main/java/edu/harvard/iq/dataverse/api/Admin.java | 6 ++++++ .../dataverse/authorization/AuthenticationServiceBean.java | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index aa76381ed56..e91e4ed0c7d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -351,7 +351,13 @@ public Response deleteAuthenticatedUserById(@PathParam("id") Long id) { } private Response deleteAuthenticatedUser(AuthenticatedUser au) { + + //getDeleteUserErrorMessages does all of the tests to see + //if the user is 'deletable' if it returns an empty string the user + //can be safely deleted. + String errorMessages = authSvc.getDeleteUserErrorMessages(au); + if (!errorMessages.isEmpty()) { return badRequest(errorMessages); } diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java index e734f34142d..f6217856034 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java @@ -584,7 +584,6 @@ public String getDeleteUserErrorMessages(AuthenticatedUser au) { retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.pendingRequests"); } if (!retVal.isEmpty()) { - // retVal = BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.prefix", Arrays.asList(au.getIdentifier())) + " " + retVal + "."; } From 73cce6805e66f54108d442af5d97d0798901e04f Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 18 Mar 2020 11:09:12 -0400 Subject: [PATCH 430/475] #6697 add doc for delete user --- doc/sphinx-guides/source/api/native-api.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index fac4957bfb3..8ac14f92628 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2804,6 +2804,21 @@ Make User a SuperUser Toggles superuser mode on the ``AuthenticatedUser`` whose ``identifier`` (without the ``@`` sign) is passed. :: POST http://$SERVER/api/admin/superuser/$identifier + +Delete a User +~~~~~~~~~~~~~ + +Deletes an ``AuthenticatedUser`` whose ``identifier`` (without the ``@`` sign) is passed. :: + + DELETE http://$SERVER/api/admin/authenticatedUsers/$identifier + +Deletes an ``AuthenticatedUser`` whose ``id`` is passed. :: + + DELETE http://$SERVER/api/admin/authenticatedUsers/id/$id + +Note: If the user has performed certain actions such as creating or contributing to a Dataset they may not be deleted. + + List Role Assignments of a Role Assignee ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From b1221c1cd03b19f258df70acde1370e49392a98d Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 18 Mar 2020 15:03:04 -0400 Subject: [PATCH 431/475] update script with version changes (per discussion) --- src/main/webapp/editFilesFragment.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/editFilesFragment.xhtml b/src/main/webapp/editFilesFragment.xhtml index 57d760f6a56..5d431ecbac7 100644 --- a/src/main/webapp/editFilesFragment.xhtml +++ b/src/main/webapp/editFilesFragment.xhtml @@ -11,7 +11,7 @@ xmlns:o="http://omnifaces.org/ui" xmlns:iqbs="http://xmlns.jcp.org/jsf/composite/iqbs"> - + From be03eadb0f705d07d0c37ab57026b7d12d171356 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 18 Mar 2020 15:58:49 -0400 Subject: [PATCH 432/475] limit parallel requests (to 4 at the moment) --- src/main/webapp/resources/js/fileupload.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index b177fed7df7..5a18b8b7662 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -1,6 +1,7 @@ var fileList = []; var observer2=null; var datasetId=null; +var filesInProgress=0; function setupDirectUpload(enabled, theDatasetId) { if(enabled) { @@ -40,13 +41,17 @@ function setupDirectUpload(enabled, theDatasetId) { function queueFileForDirectUpload(file, datasetId) { if(fileList.length === 0) {uploadWidgetDropRemoveMsg();} fileList.push(file); - - requestDirectUploadUrl(); + if(filesInProgress <5 ) { + filesInProgress= filesInProgress+1; + requestDirectUploadUrl(); + + } } function uploadFileDirectly(url, storageId) { //Pick a pending file var file = fileList.pop(); + filesInProgress=filesInProgress-1; $('.ui-fileupload-progress').html(''); $('.ui-fileupload-progress').append($('').attr('class', 'ui-progressbar ui-widget ui-widget-content ui-corner-all')); $.ajax({ @@ -165,6 +170,11 @@ function directUploadFinished() { observer.disconnect(); observer=null; } + } else { + if(filesInProgress <5 ) { + filesInProgress= filesInProgress+1; + requestDirectUploadUrl(); + } } } From bf2175a2867bf039e4e6bf9ad49a6be06353a529 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Thu, 19 Mar 2020 09:31:11 -0400 Subject: [PATCH 433/475] adding highlights --- doc/release-notes/4.20-release-notes | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 6b5fbe8f6c6..a7919e53ac8 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -8,11 +8,21 @@ This release brings new features, enhancements, and bug fixes to Dataverse. Than Dataverse can now be configured to store files in more than one place at the same time (multiple file, s3, and/or swift stores). -General information about this capability can be found in the Configuration Guide - File Storage section. +General information about this capability can be found below and in the Configuration Guide - File Storage section. ### Direct Upload to S3 -xxx +To support large data uploads, installations can now configure direct upload to S3, bypassing the application server. This will allow for larger uploads (10+ GB) over a more resilient transfer method. + +General information about this capability can be found below and in the Configuration Guide. + +### API Test Coverage + +### New APIs + +New APIs for Role Management and Dataset Size have been added. Previously, managing roles at the dataset and file level was only possible through UI. API users can now also retrieve the size of a dataset through an API call, with specific parameters depending on the type of information needed. + +More information can be found in the API Guide. ## Major Use Cases From c2cf2759f999d97533c92c3013a9a97601b126a8 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 19 Mar 2020 16:57:16 -0400 Subject: [PATCH 434/475] handle progress bars, avoid calling AllUploadsFinished more than once --- src/main/webapp/resources/js/fileupload.js | 114 +++++++++++++-------- 1 file changed, 71 insertions(+), 43 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index 5a18b8b7662..cdc9af6d660 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -1,7 +1,14 @@ var fileList = []; var observer2=null; var datasetId=null; +//How many files have started being processed but aren't yet being uploaded var filesInProgress=0; +//The # of the current file being processed (total number of files for which upload has at least started) +var curFile=0; +//The number of upload ids that have been assigned in the files table +var fileUpId=0; +//How many files are completely done +var filesFinished=0; function setupDirectUpload(enabled, theDatasetId) { if(enabled) { @@ -41,19 +48,37 @@ function setupDirectUpload(enabled, theDatasetId) { function queueFileForDirectUpload(file, datasetId) { if(fileList.length === 0) {uploadWidgetDropRemoveMsg();} fileList.push(file); - if(filesInProgress <5 ) { + //Fire off the first 4 to start (0,1,2,3) + if(filesInProgress < 4 ) { filesInProgress= filesInProgress+1; requestDirectUploadUrl(); - } } function uploadFileDirectly(url, storageId) { - //Pick a pending file - var file = fileList.pop(); + //Pick the 'first-in' pending file + var file = fileList.shift(); + //This appears to be the earliest point when the file table has been populated, and, since we don't know how many table entries have had ids added already, we check + var filerows = $('.ui-fileupload-files .ui-fileupload-row'); + //Add an id attribute to each entry so we can later match progress and errors with the right entry + for(i=0;i< filerows.length;i++) { + var upid=filerows[i].getAttribute('upid'); + if(typeof upid === "undefined" || upid === null || upid === '') { + filerows[i].setAttribute('upid', fileUpId); + fileUpId = fileUpId+1; + } + } + //Get the list of files to upload + var files = $('.ui-fileupload-files'); + //Find the corresponding row (assumes that the file order and the order of rows is the same) + var fileNode = files.find("[upid='"+curFile+"']"); + //Increment count of files being processed + curFile=curFile+1; + //Decrement number queued for processing filesInProgress=filesInProgress-1; - $('.ui-fileupload-progress').html(''); - $('.ui-fileupload-progress').append($('').attr('class', 'ui-progressbar ui-widget ui-widget-content ui-corner-all')); + var progBar = fileNode.find('.ui-fileupload-progress'); + progBar.html(''); + progBar.append($('').attr('class', 'ui-progressbar ui-widget ui-widget-content ui-corner-all')); $.ajax({ url: url, headers: {"x-amz-tagging":"dv-state=temp"}, @@ -62,7 +87,7 @@ function uploadFileDirectly(url, storageId) { cache: false, processData: false, success: function () { - reportUpload(storageId, file) + reportUpload(storageId, file) }, error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); @@ -74,7 +99,7 @@ function uploadFileDirectly(url, storageId) { myXhr.upload.addEventListener('progress', function(e) { if(e.lengthComputable) { var doublelength = 2 * e.total; - $('progress').attr({ + progBar.children('progress').attr({ value:e.loaded, max:doublelength }); @@ -87,11 +112,11 @@ function uploadFileDirectly(url, storageId) { } function reportUpload(storageId, file){ - + getMD5( file, prog => {console.log("Progress: " + prog); - + var current = 1 + prog; $('progress').attr({ value:current, @@ -119,36 +144,36 @@ function removeErrors() { var observer=null; function uploadStarted() { - // If this is not the first upload, remove error messages since - // the upload of any files that failed will be tried again. - removeErrors(); - var curId=0; - //Find the upload table body - var files = $('.ui-fileupload-files .ui-fileupload-row'); - //Add an id attribute to each entry so we can later match errors with the right entry - for(i=0;i< files.length;i++) { - files[i].setAttribute('upid', curId); - curId = curId+1; - } - //Setup an observer to watch for additional rows being added - var config={childList: true}; - var callback = function(mutations) { - //Add an id attribute to all new entries - mutations.forEach(function(mutation) { - for(i=0; i Date: Thu, 19 Mar 2020 17:38:58 -0400 Subject: [PATCH 435/475] Add support for drag and drop --- src/main/webapp/resources/js/fileupload.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index cdc9af6d660..1f27f0717f0 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -15,17 +15,26 @@ function setupDirectUpload(enabled, theDatasetId) { datasetId=theDatasetId; $('.ui-fileupload-upload').hide(); $('.ui-fileupload-cancel').hide(); + //Catch files entered via upload dialog box. Since this 'select' widget is replaced by PF, we need to add a listener again when it is replaced var fileInput=document.getElementById('datasetForm:fileUpload_input'); fileInput.addEventListener('change', function(event) { - fileList=[]; - for(var i=0;i Date: Fri, 20 Mar 2020 10:16:42 -0400 Subject: [PATCH 436/475] cut/paste error and adding an error handler --- src/main/webapp/resources/js/fileupload.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index 1f27f0717f0..c6d2ad0d302 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -24,10 +24,12 @@ function setupDirectUpload(enabled, theDatasetId) { } }, {once:false}); //Add support for drag and drop. Since the fileUploadForm is not replaced by PF, catching changes with a mutationobserver isn't needed - var fileDropWidget=document.getElementById('datasetForm:fileUpload'); fileDropWidget.addEventListener('drop', function(event) { console.log('Drop!'); - fileDropWidget.addEventListener('drop', function(event) { console.log('Drop!'); - fileList=[]; - for(var i=0;i Date: Fri, 20 Mar 2020 10:19:50 -0400 Subject: [PATCH 437/475] more error handling --- src/main/webapp/editFilesFragment.xhtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/editFilesFragment.xhtml b/src/main/webapp/editFilesFragment.xhtml index 5d431ecbac7..7f7d3e5c594 100644 --- a/src/main/webapp/editFilesFragment.xhtml +++ b/src/main/webapp/editFilesFragment.xhtml @@ -521,8 +521,8 @@
- - + + From 9668c5f3fafc5acd07d2eb2b70cff6bf8fb2b9b8 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 20 Mar 2020 12:40:43 -0400 Subject: [PATCH 438/475] increasing retries and adding logging for testing --- .../java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index b65739915eb..9ebed03dc67 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -217,16 +217,17 @@ public void open(DataAccessOption... options) throws IOException { // With small files, it looks like we may call before S3 says it exists, so try some retries before failing if(key!=null) { ObjectMetadata objectMetadata = null; - int retries = 3; + int retries = 20; while(retries > 0) { try { objectMetadata = s3.getObjectMetadata(bucketName, key); + logger.warning("Success for key: " + key + " after " + ((20-retries)*3) + " seconds"); retries = 0; } catch (SdkClientException sce) { if(retries > 1) { retries--; try { - Thread.sleep(1000); + Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } From 21f736122438e98562bc6e998d41785d424533e1 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 20 Mar 2020 15:24:06 -0400 Subject: [PATCH 439/475] add error handling and pre/post S3 logging --- src/main/webapp/resources/js/fileupload.js | 46 +++++++++++++++------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index c6d2ad0d302..7e2622c54fa 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -69,6 +69,7 @@ function queueFileForDirectUpload(file, datasetId) { function uploadFileDirectly(url, storageId) { //Pick the 'first-in' pending file var file = fileList.shift(); + console.log('Uploading ' + file.name + ' as ' +storageId + ' to ' + url); //This appears to be the earliest point when the file table has been populated, and, since we don't know how many table entries have had ids added already, we check var filerows = $('.ui-fileupload-files .ui-fileupload-row'); //Add an id attribute to each entry so we can later match progress and errors with the right entry @@ -84,6 +85,7 @@ function uploadFileDirectly(url, storageId) { //Find the corresponding row (assumes that the file order and the order of rows is the same) var fileNode = files.find("[upid='"+curFile+"']"); //Increment count of files being processed + var thisFile=curFile; curFile=curFile+1; //Decrement number queued for processing filesInProgress=filesInProgress-1; @@ -101,7 +103,7 @@ function uploadFileDirectly(url, storageId) { reportUpload(storageId, file) }, error: function(jqXHR, textStatus, errorThrown) { - uploadFailure(); + uploadFailure(jqXHR, thisFile); }, xhr: function() { var myXhr = $.ajaxSettings.xhr(); @@ -122,10 +124,10 @@ function uploadFileDirectly(url, storageId) { } function reportUpload(storageId, file){ - + console.log('S3 Upload complete for ' + file.name + ' : ' + storageId); getMD5( file, - prog => {console.log("Progress: " + prog); + prog => { var current = 1 + prog; $('progress').attr({ @@ -216,7 +218,7 @@ function directUploadFinished() { } } -function uploadFailure(fileUpload) { +function uploadFailure(jqXHR, upid, filename) { // This handles HTTP errors (non-20x reponses) such as 0 (no connection at all), 413 (Request too large), // and 504 (Gateway timeout) where the upload call to the server fails (the server doesn't receive the request) // It notifies the user and provides info about the error (status, statusText) @@ -225,20 +227,34 @@ function uploadFailure(fileUpload) { // from the call stack instead (arguments to the fail() method that calls onerror() that calls this function //Retrieve the error number (status) and related explanation (statusText) - var status = arguments.callee.caller.caller.arguments[1].jqXHR.status; - var statusText = arguments.callee.caller.caller.arguments[1].jqXHR.statusText; + var status = null; + var statusText =null; + + // There are various metadata available about which file the error pertains to + // including the name and size. + // However, since the table rows created by PrimeFaces only show name and approximate size, + // these may not uniquely identify the affected file. Therefore, we set a unique upid attribute + // in uploadStarted (and the MutationObserver there) and look for that here. The files array has + // only one element and that element includes a description of the row involved, including it's upid. + + var name = null; + var id=null; + + if(!(typeof jqXHR !=='undefined')) { + status = jqXHR.status; + statusText=jqXHR.statusText; + id = upid; + name=filename; + } else { + status=arguments.callee.caller.caller.arguments[1].jqXHR.status; + statusText = arguments.callee.caller.caller.arguments[1].jqXHR.statusText; + name = arguments.callee.caller.caller.arguments[1].files[0].name; + id = arguments.callee.caller.caller.arguments[1].files[0].row[0].attributes.upid.value; + } + //statusText for error 0 is the unhelpful 'error' if(status == 0) statusText='Network Error'; - // There are various metadata available about which file the error pertains to - // including the name and size. - // However, since the table rows created by PrimeFaces only show name and approximate size, - // these may not uniquely identify the affected file. Therefore, we set a unique upid attribute - // in uploadStarted (and the MutationObserver there) and look for that here. The files array has - // only one element and that element includes a description of the row involved, including it's upid. - - var name = arguments.callee.caller.caller.arguments[1].files[0].name; - var id = arguments.callee.caller.caller.arguments[1].files[0].row[0].attributes.upid.value; //Log the error console.log('Upload error:' + name + ' upid=' + id + ', Error ' + status + ': ' + statusText ); //Find the table From 8eba2c1db53c310b2ae832b747e2eb5e70315546 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Fri, 20 Mar 2020 16:55:44 -0400 Subject: [PATCH 440/475] fixes the issue where the dataset directory is only created when a datafile is saved, but not when saving dataset-level files. (#6739) --- .../iq/dataverse/dataaccess/FileAccessIO.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java index d7a405d63c7..2b1a8d30918 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java @@ -147,7 +147,6 @@ public void open (DataAccessOption... options) throws IOException { } else if (dvObject instanceof Dataset) { //This case is for uploading a dataset related auxiliary file //e.g. image thumbnails/metadata exports - //TODO: do we really need to do anything here? should we return the dataset directory? dataset = this.getDataset(); if (isReadAccess) { //TODO: Not necessary for dataset as there is no files associated with this @@ -229,10 +228,19 @@ public void saveInputStream(InputStream inputStream) throws IOException { @Override public Channel openAuxChannel(String auxItemTag, DataAccessOption... options) throws IOException { - + Path auxPath = getAuxObjectAsPath(auxItemTag); if (isWriteAccessRequested(options)) { + if (dvObject instanceof Dataset && !this.canWrite()) { + // If this is a dataset-level auxilary file (a cached metadata export, + // dataset logo, etc.) there's a chance that no "real" files + // have been saved for this dataset yet, and thus the filesystem + // directory does not exist yet. Let's force a proper .open() on + // this StorageIO, that will ensure it is created: + open(DataAccessOption.WRITE_ACCESS); + } + FileOutputStream auxOut = new FileOutputStream(auxPath.toFile()); if (auxOut == null) { @@ -287,7 +295,7 @@ public Path getAuxObjectAsPath(String auxItemTag) throws IOException { } String datasetDirectory = getDatasetDirectory(); - + if (dvObject.getStorageIdentifier() == null || "".equals(dvObject.getStorageIdentifier())) { throw new IOException("Data Access: No local storage identifier defined for this datafile."); } @@ -325,6 +333,10 @@ public void revertBackupAsAux(String auxItemTag) throws IOException { // this method copies a local filesystem Path into this DataAccess Auxiliary location: @Override public void savePathAsAux(Path fileSystemPath, String auxItemTag) throws IOException { + if (dvObject instanceof Dataset && !this.canWrite()) { + // see the comment in openAuxChannel() + open(DataAccessOption.WRITE_ACCESS); + } // quick Files.copy method: try { Path auxPath = getAuxObjectAsPath(auxItemTag); @@ -340,7 +352,10 @@ public void saveInputStreamAsAux(InputStream inputStream, String auxItemTag, Lon @Override public void saveInputStreamAsAux(InputStream inputStream, String auxItemTag) throws IOException { - + if (dvObject instanceof Dataset && !this.canWrite()) { + // see the comment in openAuxChannel() + open(DataAccessOption.WRITE_ACCESS); + } // Since this is a local fileystem file, we can use the // quick NIO Files.copy method: From a15b83d84d022c42af64f6fec2f9308556992959 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 20 Mar 2020 17:44:06 -0400 Subject: [PATCH 441/475] tighten up on async issues create local vars from global ones so that value isn't changed by another async callback before we use it. --- src/main/webapp/resources/js/fileupload.js | 103 ++++++++++++--------- 1 file changed, 57 insertions(+), 46 deletions(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index 7e2622c54fa..c47ce524dc7 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -6,9 +6,16 @@ var filesInProgress=0; //The # of the current file being processed (total number of files for which upload has at least started) var curFile=0; //The number of upload ids that have been assigned in the files table -var fileUpId=0; +var getUpId = (function () { + var counter = -1; + return function () {counter += 1; return counter} +})(); //How many files are completely done -var filesFinished=0; +var finishFile = (function () { + var counter = 0; + return function () {counter += 1; return counter} +})(); + function setupDirectUpload(enabled, theDatasetId) { if(enabled) { @@ -23,10 +30,10 @@ function setupDirectUpload(enabled, theDatasetId) { queueFileForDirectUpload(fileInput.files[i], datasetId); } }, {once:false}); - //Add support for drag and drop. Since the fileUploadForm is not replaced by PF, catching changes with a mutationobserver isn't needed + //Add support for drag and drop. Since the fileUploadForm is not replaced by PF, catching changes with a mutationobserver isn't needed var fileDropWidget=document.getElementById('datasetForm:fileUpload'); fileDropWidget.addEventListener('drop', function(event) { - fileList=[]; + fileList=[]; for(var i=0;i= fileSize) { endCallback(null); return; @@ -336,5 +349,3 @@ function getMD5(blob, cbProgress) { }); }); } - - From 3a9e8117282c1e01338d4e39fa19500ae0551259 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 20 Mar 2020 18:44:53 -0400 Subject: [PATCH 442/475] remove debug log message --- .../edu/harvard/iq/dataverse/ingest/IngestServiceBean.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java index c2a2a13c272..e7ccc7bf1b4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/ingest/IngestServiceBean.java @@ -310,8 +310,7 @@ public List saveAndAddFilesToDataset(DatasetVersion version, List Date: Mon, 23 Mar 2020 10:39:40 -0400 Subject: [PATCH 443/475] #6697 delete items that can be deleted --- .../edu/harvard/iq/dataverse/api/Admin.java | 5 +- .../AuthenticationServiceBean.java | 70 +++++++++++-------- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index e91e4ed0c7d..fe6d7f34885 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -361,7 +361,10 @@ private Response deleteAuthenticatedUser(AuthenticatedUser au) { if (!errorMessages.isEmpty()) { return badRequest(errorMessages); } - + + //if the user is deletable we will delete access requests, group membership and world map tokens + authSvc.removeAuthentictedUserItems(au); + authSvc.deleteAuthenticatedUser(au.getId()); return ok("AuthenticatedUser " + au.getIdentifier() + " deleted. "); diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java index f6217856034..a1519b08bee 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java @@ -13,6 +13,7 @@ import edu.harvard.iq.dataverse.authorization.exceptions.AuthenticationFailedException; import edu.harvard.iq.dataverse.authorization.exceptions.AuthenticationProviderFactoryNotFoundException; import edu.harvard.iq.dataverse.authorization.exceptions.AuthorizationSetupException; +import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroup; import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupServiceBean; import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderFactory; import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderRow; @@ -35,6 +36,7 @@ import edu.harvard.iq.dataverse.validation.PasswordValidatorServiceBean; import edu.harvard.iq.dataverse.workflows.WorkflowComment; import java.sql.Timestamp; +import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; @@ -47,6 +49,7 @@ import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; import javax.ejb.EJB; import javax.ejb.EJBException; @@ -539,60 +542,65 @@ public AuthenticatedUser lookupUser( String apiToken ) { -has created dvObjects -has roles -has guestbook records - -etc. + An empty string is returned if the user is 'deletable' */ public String getDeleteUserErrorMessages(AuthenticatedUser au) { String retVal = ""; + List reasons= new ArrayList(); if (!dvObjSvc.findByAuthenticatedUserId(au).isEmpty()) { - retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.dvobjects"); + reasons.add(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.dvobjects")); } if (!roleAssigneeSvc.getAssignmentsFor(au.getIdentifier()).isEmpty()) { - if (!retVal.isEmpty()) { - retVal += "; "; - } - retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.roleAssignments"); + reasons.add(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.roleAssignments")); } if (!gbRespSvc.findByAuthenticatedUserId(au).isEmpty()) { - if (!retVal.isEmpty()) { - retVal += "; "; - } - retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.gbResps"); + reasons.add( BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.gbResps")); } if (!datasetVersionService.getDatasetVersionUsersByAuthenticatedUser(au).isEmpty()) { - if (!retVal.isEmpty()) { - retVal += "; "; - } - retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.versionUser"); + reasons.add(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.versionUser")); } - - if (!explicitGroupService.findGroups(au).isEmpty()) { - if (!retVal.isEmpty()) { - retVal += "; "; - } - retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.groupMember"); + + if (!reasons.isEmpty()) { + retVal = BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.prefix", Arrays.asList(au.getIdentifier())); + retVal += " " + reasons.stream().collect(Collectors.joining("; ")) + "."; } + - if (userHasPendingAccessRequests(au)) { - if (!retVal.isEmpty()) { - retVal += "; "; - } - retVal += BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.pendingRequests"); - } - if (!retVal.isEmpty()) { - retVal = BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.prefix", Arrays.asList(au.getIdentifier())) + " " + retVal + "."; - } return retVal; } - private boolean userHasPendingAccessRequests(AuthenticatedUser au){ + public void removeAuthentictedUserItems(AuthenticatedUser au){ + /* if the user has pending access requests, is the member of a group or has a world map token + we will delete them here + */ + + deletePendingAccessRequests(au); + + deleteWorldMapToken(au); + + if (!explicitGroupService.findGroups(au).isEmpty()) { + for(ExplicitGroup explicitGroup: explicitGroupService.findGroups(au)){ + explicitGroup.removeByRoleAssgineeIdentifier(au.getIdentifier()); + } + } + + } + + private void deletePendingAccessRequests(AuthenticatedUser au){ + + em.createNativeQuery("delete from fileaccessrequests where authenticated_user_id = "+au.getId()); + + } + + private void deleteWorldMapToken(AuthenticatedUser au){ - return !em.createNativeQuery("select datafile_id from fileaccessrequests where authenticated_user_id = "+au.getId()).getResultList().isEmpty(); + em.createNativeQuery("delete from worldmapauth_token where dataverseuser_id = "+au.getId()); } From ea4d8862d120228b724a0113b62beb7aa374c2f6 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 23 Mar 2020 10:50:24 -0400 Subject: [PATCH 444/475] #6697 update doc wording --- doc/sphinx-guides/source/api/native-api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 9e3d3ca7ee5..271ed49176f 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2818,7 +2818,7 @@ Deletes an ``AuthenticatedUser`` whose ``id`` is passed. :: DELETE http://$SERVER/api/admin/authenticatedUsers/id/$id -Note: If the user has performed certain actions such as creating or contributing to a Dataset they may not be deleted. +Note: If the user has performed certain actions such as creating or contributing to a Dataset they cannot be deleted. From 7043a0a08cbaf1ffceb1889fe201ec5a4d0f91dc Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 23 Mar 2020 11:53:54 -0400 Subject: [PATCH 445/475] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 271ed49176f..67b4317e1de 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2818,7 +2818,7 @@ Deletes an ``AuthenticatedUser`` whose ``id`` is passed. :: DELETE http://$SERVER/api/admin/authenticatedUsers/id/$id -Note: If the user has performed certain actions such as creating or contributing to a Dataset they cannot be deleted. +Note: If the user has performed certain actions such as creating or contributing to a Dataset or downloading a file they cannot be deleted. From 29ac8541c1af756f2f2073d469726d7f25ec1133 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Mon, 23 Mar 2020 15:56:11 -0400 Subject: [PATCH 446/475] only warn if a retry occurred --- .../java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index 9ebed03dc67..973fa8ee42a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -221,7 +221,9 @@ public void open(DataAccessOption... options) throws IOException { while(retries > 0) { try { objectMetadata = s3.getObjectMetadata(bucketName, key); - logger.warning("Success for key: " + key + " after " + ((20-retries)*3) + " seconds"); + if(retries != 20) { + logger.warning("Success for key: " + key + " after " + ((20-retries)*3) + " seconds"); + } retries = 0; } catch (SdkClientException sce) { if(retries > 1) { From 7ab532327c1b5ab87e2f8f1ef778ee303a24436b Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Mon, 23 Mar 2020 17:34:43 -0400 Subject: [PATCH 447/475] APIs and API test notes --- doc/release-notes/4.20-release-notes | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index a7919e53ac8..3cd8a52a212 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -16,11 +16,13 @@ To support large data uploads, installations can now configure direct upload to General information about this capability can be found below and in the Configuration Guide. -### API Test Coverage +### Integration Test Coverage Reporting + +The percentage of code covered by the API-based integration tests is now shown on a badge at the bottom of the README.md file that serves as the homepage of Dataverse Github Repository. ### New APIs -New APIs for Role Management and Dataset Size have been added. Previously, managing roles at the dataset and file level was only possible through UI. API users can now also retrieve the size of a dataset through an API call, with specific parameters depending on the type of information needed. +New APIs for Role Management and Dataset Size have been added. Previously, managing roles at the dataset and file level was only possible through the UI. API users can now also retrieve the size of a dataset through an API call, with specific parameters depending on the type of information needed. More information can be found in the API Guide. From 67675039cb2b4d61ea178ead1d2441080b303a53 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Mon, 23 Mar 2020 17:46:31 -0400 Subject: [PATCH 448/475] adding docs for S3 direct upload support --- doc/release-notes/4.20-release-notes | 25 +++++++++++++++++++++++-- doc/release-notes/6514-shib-updates | 1 - 2 files changed, 23 insertions(+), 3 deletions(-) delete mode 100644 doc/release-notes/6514-shib-updates diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 3cd8a52a212..bfbde91ddd6 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -10,9 +10,13 @@ Dataverse can now be configured to store files in more than one place at the sam General information about this capability can be found below and in the Configuration Guide - File Storage section. -### Direct Upload to S3 +### S3 Direct Upload support -To support large data uploads, installations can now configure direct upload to S3, bypassing the application server. This will allow for larger uploads (10+ GB) over a more resilient transfer method. +S3 stores can now optionally be configured to support direct upload of files, as one option for supporting upload of larger files. This will allow for uploads of up to five GB for installations using AWS and more than five GB for installations using Minio or another S3 driver. + +General information about this capability can be found in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. + +To support large data uploads, installations can now configure direct upload to S3, bypassing the application server. This will allow for larger uploads over a more resilient transfer method. General information about this capability can be found below and in the Configuration Guide. @@ -76,6 +80,18 @@ Once these options are set, restarting the Glassfish service is all that is need Note that the "\-Ddataverse.files.directory", if defined, continues to control where temporary files are stored (in the /temp subdir of that directory), independent of the location of any 'file' store defined above. +### Direct S3 Upload Changes + +Direct upload to S3 is enabled per store by one new jvm option: + + ./asadmin create-jvm-options "\-Ddataverse.files..upload-redirect=true" + +The existing :MaxFileUploadSizeInBytes property and ```dataverse.files..url-expiration-minutes``` jvm option for the same store also apply to direct upload. + +Direct upload via the Dataverse web interface is transparent to the user and handled automatically by the browser. Some minor differences in file upload exist: directly uploaded files are not unzipped and Dataverse does not scan their content to help in assigning a MIME type. Ingest of tabular files and metadata extraction from FITS files will occur, but can be turned off for files above a specified size limit through the new dataverse.files..ingestsizelimit jvm option. + +API calls to support direct upload also exist, and, if direct upload is enabled for a store in Dataverse, the latest DVUploader (v1.0.8) provides a'-directupload' flag that enables its use. + ### Solr Update With this release we upgrade to the latest available stable release in the Solr 7.x branch. We recommend a fresh installation of Solr 7.7.2 (the index will be empty) @@ -97,6 +113,11 @@ The button tracking capability discussed in the installation guide (http://guide We made changes to the JSON Export in this release (#xxx). If you'd like these changes to reflected in your JSON exports, you should run ReExportall as part of the upgrade process. We've included this in the step-by-step instructions below. +### New Database Settings and JVM options + +- The database setting :ShibAffiliationAttribute can now be set to prevent affiliations for Shibboleth users from being reset upon each log in. +- + ## Notes for Tool Developers and Integrators ### Integration Test Coverage Reporting diff --git a/doc/release-notes/6514-shib-updates b/doc/release-notes/6514-shib-updates deleted file mode 100644 index 561358c6b8d..00000000000 --- a/doc/release-notes/6514-shib-updates +++ /dev/null @@ -1 +0,0 @@ -New DB option :ShibAffiliationAttribute \ No newline at end of file From 8639918b89880618034df673c5e7cfb87c83f5fa Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Tue, 24 Mar 2020 11:42:25 -0400 Subject: [PATCH 449/475] deleting file after adding content to 420 notes --- doc/release-notes/6489-release-notes.md | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 doc/release-notes/6489-release-notes.md diff --git a/doc/release-notes/6489-release-notes.md b/doc/release-notes/6489-release-notes.md deleted file mode 100644 index b28174c9a74..00000000000 --- a/doc/release-notes/6489-release-notes.md +++ /dev/null @@ -1,17 +0,0 @@ -# S3 Direct Upload support - -S3 stores can now optionally be configured to support direct upload of files, as one option for supporting upload of larger files. - -General information about this capability can be found in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. - -**Upgrade Information:** - -Direct upload to S3 is enabled per store by one new jvm option: - - ./asadmin create-jvm-options "\-Ddataverse.files..upload-redirect=true" - -The existing :MaxFileUploadSizeInBytes property and ```dataverse.files..url-expiration-minutes``` jvm option for the same store also apply to direct upload. - -Direct upload via the Dataverse web interface is transparent to the user and handled automatically by the browser. Some minor differences in file upload exist: directly uploaded files are not unzipped and Dataverse does not scan their content to help in assigning a MIME type. Ingest of tabular files and metadata extraction from FITS files will occur, but can be turned off for files above a specified size limit through the new dataverse.files..ingestsizelimit jvm option. - -API calls to support direct upload also exist, and, if direct upload is enabled for a store in Dataverse, the latest DVUploader (v1.0.8) provides a'-directupload' flag that enables its use. From 953ef621e3ae8ac663d06abe7d77df4be1120149 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 24 Mar 2020 18:17:04 -0400 Subject: [PATCH 450/475] don't assume optionalParams exists - not true in replace --- .../iq/dataverse/datasetutility/AddReplaceFileHelper.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java index 6716cb15327..a470dbcb8e0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java +++ b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java @@ -502,10 +502,12 @@ private boolean runAddReplacePhase1(Dataset dataset, return false; } - - if(optionalFileParams.hasCheckSum()) { - newCheckSum = optionalFileParams.getCheckSum(); + if(optionalFileParams != null) { + if(optionalFileParams.hasCheckSum()) { + newCheckSum = optionalFileParams.getCheckSum(); + } } + msgt("step_030_createNewFilesViaIngest"); if (!this.step_030_createNewFilesViaIngest()){ return false; From a60110894096bfe81c0ce8ee5f8533747f5e2673 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 25 Mar 2020 09:24:53 -0400 Subject: [PATCH 451/475] new jvm options for direct to s3 --- doc/release-notes/4.20-release-notes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index bfbde91ddd6..fe9f0419d11 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -116,7 +116,8 @@ We made changes to the JSON Export in this release (#xxx). If you'd like these c ### New Database Settings and JVM options - The database setting :ShibAffiliationAttribute can now be set to prevent affiliations for Shibboleth users from being reset upon each log in. -- +- The new JVM option + ## Notes for Tool Developers and Integrators From e17004449f906a02694f0f1fe3acd43aa42cbd61 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 25 Mar 2020 10:04:08 -0400 Subject: [PATCH 452/475] adding JVM Options --- doc/release-notes/4.20-release-notes | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index fe9f0419d11..47968dadb43 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -113,11 +113,29 @@ The button tracking capability discussed in the installation guide (http://guide We made changes to the JSON Export in this release (#xxx). If you'd like these changes to reflected in your JSON exports, you should run ReExportall as part of the upgrade process. We've included this in the step-by-step instructions below. -### New Database Settings and JVM options - -- The database setting :ShibAffiliationAttribute can now be set to prevent affiliations for Shibboleth users from being reset upon each log in. -- The new JVM option - +### New JVM Options and Database Settings + +## New JVM Options for S3 storage + +========================================= ================== ================================================================== ============= +JVM Option Value Description Default value +========================================= ================== ================================================================== ============= +dataverse.files.storage-driver-id Enable as the default storage driver. ``file`` +dataverse.files..bucket-name The bucket name. See above. (none) +dataverse.files..download-redirect ``true``/``false`` Enable direct download or proxy through Dataverse. ``false`` +dataverse.files..upload-redirect ``true``/``false`` Enable direct upload of files added to a dataset to the S3 store. ``false`` +dataverse.files..ingestsizelimit Maximum size of directupload files that should be ingested (none) +dataverse.files..url-expiration-minutes If direct uploads/downloads: time until links expire. Optional. 60 +dataverse.files..custom-endpoint-url Use custom S3 endpoint. Needs URL either with or without protocol. (none) +dataverse.files..custom-endpoint-region Only used when using custom endpoint. Optional. ``dataverse`` +dataverse.files..path-style-access ``true``/``false`` Use path style buckets instead of subdomains. Optional. ``false`` +dataverse.files..payload-signing ``true``/``false`` Enable payload signing. Optional ``false`` +dataverse.files..chunked-encoding ``true``/``false`` Disable chunked encoding. Optional ``true`` +========================================= ================== ================================================================== ============= + +## New Database Settings for Shibboleth + +The database setting :ShibAffiliationAttribute can now be set to prevent affiliations for Shibboleth users from being reset upon each log in. ## Notes for Tool Developers and Integrators From b000c78df6082aa9e99891df3320553fc5b288d5 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 25 Mar 2020 10:45:32 -0400 Subject: [PATCH 453/475] #6697 make world map token cascade delete --- .../AuthenticationServiceBean.java | 3 +-- .../users/AuthenticatedUser.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java index a1519b08bee..9fb575ec5f0 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java @@ -576,13 +576,12 @@ public String getDeleteUserErrorMessages(AuthenticatedUser au) { } public void removeAuthentictedUserItems(AuthenticatedUser au){ - /* if the user has pending access requests, is the member of a group or has a world map token + /* if the user has pending access requests, is the member of a group or we will delete them here */ deletePendingAccessRequests(au); - deleteWorldMapToken(au); if (!explicitGroupService.findGroups(au).isEmpty()) { for(ExplicitGroup explicitGroup: explicitGroupService.findGroups(au)){ diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java b/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java index 449ca56e89e..18b5e94e62f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java @@ -3,6 +3,7 @@ import edu.harvard.iq.dataverse.Cart; import edu.harvard.iq.dataverse.DatasetLock; import edu.harvard.iq.dataverse.ValidateEmail; +import edu.harvard.iq.dataverse.authorization.AccessRequest; import edu.harvard.iq.dataverse.authorization.AuthenticatedUserDisplayInfo; import edu.harvard.iq.dataverse.authorization.AuthenticatedUserLookup; import edu.harvard.iq.dataverse.userdata.UserUtil; @@ -10,6 +11,7 @@ import edu.harvard.iq.dataverse.util.BundleUtil; import static edu.harvard.iq.dataverse.util.StringUtil.nonEmpty; import edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder; +import edu.harvard.iq.dataverse.worldmapauth.WorldMapToken; import java.io.Serializable; import java.sql.Timestamp; import java.util.List; @@ -124,6 +126,31 @@ public String getIdentifier() { return IDENTIFIER_PREFIX + userIdentifier; } + @OneToMany(mappedBy = "dataverseUser", cascade={CascadeType.REMOVE}) + private List worldMapTokens; + + public List getWorldMapTokens() { + return worldMapTokens; + } + + public void setWorldMapTokens(List worldMapTokens) { + this.worldMapTokens = worldMapTokens; + } + + /* + + @OneToMany(mappedBy = "authenticatedUser", cascade={CascadeType.REMOVE}) + private List fileAccessRequests; + + public List getAccessRequests() { + return fileAccessRequests; + } + + public void setFileAccessRequests(List fileAccessRequests) { + this.fileAccessRequests = fileAccessRequests; + } + */ + @OneToMany(mappedBy = "user", cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST}) private List datasetLocks; From c7695fb9f7a342c5308d8ac156a31cb2bd8e5216 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 25 Mar 2020 11:24:19 -0400 Subject: [PATCH 454/475] #6697 add notifications to cascade delete --- .../AuthenticationServiceBean.java | 7 +---- .../users/AuthenticatedUser.java | 26 +++++++++++++------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java index 9fb575ec5f0..59e79d41841 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java @@ -593,15 +593,10 @@ public void removeAuthentictedUserItems(AuthenticatedUser au){ private void deletePendingAccessRequests(AuthenticatedUser au){ - em.createNativeQuery("delete from fileaccessrequests where authenticated_user_id = "+au.getId()); + em.createNativeQuery("delete from fileaccessrequests where authenticated_user_id = "+au.getId()).executeUpdate(); } - private void deleteWorldMapToken(AuthenticatedUser au){ - - em.createNativeQuery("delete from worldmapauth_token where dataverseuser_id = "+au.getId()); - - } public AuthenticatedUser save( AuthenticatedUser user ) { em.persist(user); diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java b/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java index 18b5e94e62f..175e5743e93 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java @@ -2,6 +2,7 @@ import edu.harvard.iq.dataverse.Cart; import edu.harvard.iq.dataverse.DatasetLock; +import edu.harvard.iq.dataverse.UserNotification; import edu.harvard.iq.dataverse.ValidateEmail; import edu.harvard.iq.dataverse.authorization.AccessRequest; import edu.harvard.iq.dataverse.authorization.AuthenticatedUserDisplayInfo; @@ -137,19 +138,28 @@ public void setWorldMapTokens(List worldMapTokens) { this.worldMapTokens = worldMapTokens; } - /* + @OneToMany(mappedBy = "user", cascade={CascadeType.REMOVE}) + private List notifications; + + public List getUserNotifications() { + return notifications; + } + + public void setUserNotifications(List notifications) { + this.notifications = notifications; + } - @OneToMany(mappedBy = "authenticatedUser", cascade={CascadeType.REMOVE}) - private List fileAccessRequests; + @OneToMany(mappedBy = "requestor", cascade={CascadeType.REMOVE}) + private List requests; - public List getAccessRequests() { - return fileAccessRequests; + public List getUserRequests() { + return requests; } - public void setFileAccessRequests(List fileAccessRequests) { - this.fileAccessRequests = fileAccessRequests; + public void setUserRequestss(List requests) { + this.requests = requests; } - */ + @OneToMany(mappedBy = "user", cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST}) private List datasetLocks; From 3e686b57d56a2fb31596f7bf01206fb67737bff2 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 25 Mar 2020 14:46:06 -0400 Subject: [PATCH 455/475] use cases, JVM options --- doc/release-notes/4.20-release-notes | 30 ++++++++++++---------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 47968dadb43..077cd89ce84 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -16,7 +16,7 @@ S3 stores can now optionally be configured to support direct upload of files, as General information about this capability can be found in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. -To support large data uploads, installations can now configure direct upload to S3, bypassing the application server. This will allow for larger uploads over a more resilient transfer method. +To support large data uploads, installations can now configure direct upload to S3, bypassing the application server. This will allow for larger uploads over a more resilient transfer method. General information about this capability can be found below and in the Configuration Guide. @@ -35,6 +35,12 @@ More information can be found in the Enable as the default storage driver. ``file`` -dataverse.files..bucket-name The bucket name. See above. (none) -dataverse.files..download-redirect ``true``/``false`` Enable direct download or proxy through Dataverse. ``false`` -dataverse.files..upload-redirect ``true``/``false`` Enable direct upload of files added to a dataset to the S3 store. ``false`` -dataverse.files..ingestsizelimit Maximum size of directupload files that should be ingested (none) -dataverse.files..url-expiration-minutes If direct uploads/downloads: time until links expire. Optional. 60 -dataverse.files..custom-endpoint-url Use custom S3 endpoint. Needs URL either with or without protocol. (none) -dataverse.files..custom-endpoint-region Only used when using custom endpoint. Optional. ``dataverse`` -dataverse.files..path-style-access ``true``/``false`` Use path style buckets instead of subdomains. Optional. ``false`` -dataverse.files..payload-signing ``true``/``false`` Enable payload signing. Optional ``false`` -dataverse.files..chunked-encoding ``true``/``false`` Disable chunked encoding. Optional ``true`` -========================================= ================== ================================================================== ============= +- The JVM option dataverse.files.file.directory= controls where temporary files are stored (in the /temp subdir of the defined directory), independent of the location of any 'file' store defined above. +- The JVM option dataverse.files..upload-redirect enables direct upload of files added to a dataset to the S3 store. +- The JVM option dataverse.files..ingestsizelimit controls the maximum size of files (uploaded via directupload) for which ingest will be attempted. ## New Database Settings for Shibboleth -The database setting :ShibAffiliationAttribute can now be set to prevent affiliations for Shibboleth users from being reset upon each log in. +- The database setting :ShibAffiliationAttribute can now be set to prevent affiliations for Shibboleth users from being reset upon each log in. ## Notes for Tool Developers and Integrators From 9f76eba82cd3e997756a9cae784a09c0c1c0d756 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 25 Mar 2020 14:56:49 -0400 Subject: [PATCH 456/475] Always fix DataFile storageidentifier if needed Not just for write mode --- .../iq/dataverse/dataaccess/S3AccessIO.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index 973fa8ee42a..aa62e605c3c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -165,7 +165,31 @@ public void open(DataAccessOption... options) throws IOException { if (storageIdentifier == null || "".equals(storageIdentifier)) { throw new FileNotFoundException("Data Access: No local storage identifier defined for this datafile."); } + + + //Fix new DataFiles: DataFiles that have not yet been saved may use this method when they don't have their storageidentifier in the final ://: form + // So we fix it up here. ToDo: refactor so that storageidentifier is generated by the appropriate StorageIO class and is final from the start. + String newStorageIdentifier = null; + if (storageIdentifier.startsWith(this.driverId + "://")) { + if(!storageIdentifier.substring((this.driverId + "://").length()).contains(":")) { + //Driver id but no bucket + if(bucketName!=null) { + newStorageIdentifier=this.driverId + "://" + bucketName + ":" + storageIdentifier.substring((this.driverId + "://").length()); + } else { + throw new IOException("S3AccessIO: DataFile (storage identifier " + storageIdentifier + ") is not associated with a bucket."); + } + } // else we're OK (assumes bucket name in storageidentifier matches the driver's bucketname) + } else { + //No driver id or bucket (presumably - we don't expect cases where there's no driver id but a bucket is listed - could add a check) + newStorageIdentifier= this.driverId + "://" + bucketName + ":" + storageIdentifier; + } + if(newStorageIdentifier != null) { + //Fixup needed: + storageIdentifier = newStorageIdentifier; + dvObject.setStorageIdentifier(newStorageIdentifier); + } + if (isReadAccess) { key = getMainFileKey(); ObjectMetadata objectMetadata = null; @@ -189,14 +213,7 @@ public void open(DataAccessOption... options) throws IOException { } else if (isWriteAccess) { key = dataFile.getOwner().getAuthorityForFileStorage() + "/" + this.getDataFile().getOwner().getIdentifierForFileStorage(); - - if (storageIdentifier.startsWith(this.driverId + "://")) { - key += "/" + storageIdentifier.substring(storageIdentifier.lastIndexOf(":") + 1); - } else { - key += "/" + storageIdentifier; - dvObject.setStorageIdentifier(this.driverId + "://" + bucketName + ":" + storageIdentifier); - } - + key += "/" + storageIdentifier.substring(storageIdentifier.lastIndexOf(":") + 1); } this.setMimeType(dataFile.getContentType()); @@ -784,7 +801,7 @@ String getMainFileKey() throws IOException { if (storageIdentifier.startsWith(this.driverId + "://")) { bucketName = storageIdentifier.substring((this.driverId + "://").length(), storageIdentifier.lastIndexOf(":")); - key = baseKey + "/" + storageIdentifier.substring(storageIdentifier.lastIndexOf(":") + 1); + key = baseKey + "/" + storageIdentifier.substring(storageIdentifier.lastIndexOf(":") + 1); } else { throw new IOException("S3AccessIO: DataFile (storage identifier " + storageIdentifier + ") does not appear to be an S3 object."); } From 445dd89b0febe6c12c963f38df2a6f358917bcaf Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 25 Mar 2020 14:57:18 -0400 Subject: [PATCH 457/475] cleanup - newStorageIdentifier is always set below --- .../iq/dataverse/datasetutility/AddReplaceFileHelper.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java index a470dbcb8e0..53af964fc14 100644 --- a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java +++ b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java @@ -952,9 +952,7 @@ private boolean step_020_loadNewFile(String fileName, String fileContentType, St if (storageIdentifier == null) { this.addErrorSevere(getBundleErr("file_upload_failed")); return false; - } else { - newStorageIdentifier = storageIdentifier; - } + } } newFileName = fileName; From d0a0caaae887e6991ea94a2e2e2769d34c824c00 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 25 Mar 2020 15:12:12 -0400 Subject: [PATCH 458/475] add 4th case -only bucket --- .../edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java index aa62e605c3c..b12013b8f8f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/S3AccessIO.java @@ -180,8 +180,13 @@ public void open(DataAccessOption... options) throws IOException { } } // else we're OK (assumes bucket name in storageidentifier matches the driver's bucketname) } else { - //No driver id or bucket (presumably - we don't expect cases where there's no driver id but a bucket is listed - could add a check) - newStorageIdentifier= this.driverId + "://" + bucketName + ":" + storageIdentifier; + if(!storageIdentifier.substring((this.driverId + "://").length()).contains(":")) { + //No driver id or bucket + newStorageIdentifier= this.driverId + "://" + bucketName + ":" + storageIdentifier; + } else { + //Just the bucketname + newStorageIdentifier= this.driverId + "://" + storageIdentifier; + } } if(newStorageIdentifier != null) { //Fixup needed: From 385e68d8cbde4916cf78dbf392ffd78dac769f85 Mon Sep 17 00:00:00 2001 From: landreev Date: Wed, 25 Mar 2020 16:05:23 -0400 Subject: [PATCH 459/475] changed "driver" to "S3 service provider" (in the context of "minio" as opposed to s3 from aws) --- doc/release-notes/4.20-release-notes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 077cd89ce84..826339d3cf7 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -12,7 +12,7 @@ General information about this capability can be found below and in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. From 8a1cc8a78ebf9844a442a88e2b35c74bb1f3023c Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 25 Mar 2020 16:39:07 -0400 Subject: [PATCH 460/475] #6697 fix comment --- src/main/java/edu/harvard/iq/dataverse/api/Admin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 170b64e1aac..82181568510 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -362,7 +362,8 @@ private Response deleteAuthenticatedUser(AuthenticatedUser au) { return badRequest(errorMessages); } - //if the user is deletable we will delete access requests, group membership and world map tokens + //if the user is deletable we will delete access requests and group membership + // many-to-many relationships that couldn't be cascade deleted authSvc.removeAuthentictedUserItems(au); authSvc.deleteAuthenticatedUser(au.getId()); From 6dba7017c8c430f8b07ff6e19ac6790e9f722b63 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 25 Mar 2020 17:01:55 -0400 Subject: [PATCH 461/475] use cases --- doc/release-notes/4.20-release-notes | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 077cd89ce84..5ef229b3bc9 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -8,17 +8,17 @@ This release brings new features, enhancements, and bug fixes to Dataverse. Than Dataverse can now be configured to store files in more than one place at the same time (multiple file, s3, and/or swift stores). -General information about this capability can be found below and in the Configuration Guide - File Storage section. +General information about this capability can be found below and in the Configuration Guide - File Storage section. ### S3 Direct Upload support S3 stores can now optionally be configured to support direct upload of files, as one option for supporting upload of larger files. This will allow for uploads of up to five GB for installations using AWS and more than five GB for installations using Minio or another S3 driver. -General information about this capability can be found in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. +General information about this capability can be found in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. To support large data uploads, installations can now configure direct upload to S3, bypassing the application server. This will allow for larger uploads over a more resilient transfer method. -General information about this capability can be found below and in the Configuration Guide. +General information about this capability can be found below and in the Configuration Guide. ### Integration Test Coverage Reporting @@ -28,19 +28,19 @@ The percentage of code covered by the API-based integration tests is now shown o New APIs for Role Management and Dataset Size have been added. Previously, managing roles at the dataset and file level was only possible through the UI. API users can now also retrieve the size of a dataset through an API call, with specific parameters depending on the type of information needed. -More information can be found in the API Guide. +More information can be found in the API Guide. ## Major Use Cases Newly-supported use cases in this release include: - Users will now be able to see the number of linked datasets and dataverses accurately reflected in the facet counts on the Dataverse search page. (Issue #6564, PR #6262) +- Users will be able to upload large files directly to S3. (Issue #6489, PR #6490) +- Users will be able to see the PIDs of datasets and files in the Guestbook export. (Issue #6534, PR #6628) - Administrators will be able to configure multiple stores per Dataverse installation, which allow dataverse-level setting of storage location, upload size limits, and supported data transfer methods (Issue #6485, PR #6488) -- Direct upload... (Issue #6489, PR #6490) -- Administrators and integrators will be able to manage roles using a new API. -- Administrators and integrators will be able to determine a dataset's size. -- Integrators will now be able to retrieve the number of files in a dataset as part of a single API call instead of needing to count the number of files in the response. () -- Users will be able to see the PIDs of datasets and files in the Guestbook export. +- Administrators and integrators will be able to manage roles using a new API. (Issue #6290, PR #6622) +- Administrators and integrators will be able to determine a dataset's size. (Issue #6524, PR #6609) +- Integrators will now be able to retrieve the number of files in a dataset as part of a single API call instead of needing to count the number of files in the response. (Issue #6601, PR #6623) ## Notes for Dataverse Installation Administrators @@ -62,7 +62,7 @@ If either, or both kinds of duplicates are detected, the script will provide fur **Existing installations will need to make configuration changes to adopt this version, regardless of whether additional stores are to be added or not.** -Multistore support requires that each store be assigned a label, id, and type - see the Configuration Guide for a more complete explanation. For an existing store, the recommended upgrade path is to assign the store id based on it's type, i.e. a 'file' store would get id 'file', an 's3' store would have the id 's3'. +Multistore support requires that each store be assigned a label, id, and type - see the Configuration Guide for a more complete explanation. For an existing store, the recommended upgrade path is to assign the store id based on it's type, i.e. a 'file' store would get id 'file', an 's3' store would have the id 's3'. With this choice, no manual changes to datafile 'storageidentifier' entries are needed in the database. If you do not name your existing store using this convention, you will need to edit the database to maintain access to existing files. From f2afd55b7362ab9d0c1aff504ac8fd3aeaebd313 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 25 Mar 2020 17:04:42 -0400 Subject: [PATCH 462/475] leonid recommended change --- doc/release-notes/4.20-release-notes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 5ef229b3bc9..264e023dbb5 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -12,7 +12,7 @@ General information about this capability can be found below and in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. From e68263828917c78cfa6ec50c6e01240c0a561234 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 25 Mar 2020 17:11:34 -0400 Subject: [PATCH 463/475] linking to correct issue and PR for export --- doc/release-notes/4.20-release-notes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 264e023dbb5..aea536acaf0 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -119,7 +119,7 @@ The button tracking capability discussed in the installation guide (http://guide ### Run ReExportall -We made changes to the JSON Export in this release (#xxx). If you'd like these changes to reflected in your JSON exports, you should run ReExportall as part of the upgrade process. We've included this in the step-by-step instructions below. +We made changes to the JSON Export in this release (Issue 6650, PR #6669). If you'd like these changes to reflected in your JSON exports, you should run ReExportall as part of the upgrade process. We've included this in the step-by-step instructions below. ### New JVM Options and Database Settings From 8a26934b9317dfc77dee795fc7eb52bdf4515277 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 25 Mar 2020 17:22:23 -0400 Subject: [PATCH 464/475] avoid null error when select option is removed e.g. for replace file where only one file upload is allowed and the select button goes away after one upload --- src/main/webapp/resources/js/fileupload.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/resources/js/fileupload.js b/src/main/webapp/resources/js/fileupload.js index c47ce524dc7..126d5d47c87 100644 --- a/src/main/webapp/resources/js/fileupload.js +++ b/src/main/webapp/resources/js/fileupload.js @@ -24,12 +24,14 @@ function setupDirectUpload(enabled, theDatasetId) { $('.ui-fileupload-cancel').hide(); //Catch files entered via upload dialog box. Since this 'select' widget is replaced by PF, we need to add a listener again when it is replaced var fileInput=document.getElementById('datasetForm:fileUpload_input'); - fileInput.addEventListener('change', function(event) { + if(fileInput !==null) { + fileInput.addEventListener('change', function(event) { fileList=[]; for(var i=0;i Date: Wed, 25 Mar 2020 17:23:10 -0400 Subject: [PATCH 465/475] propagate checksum --- .../datasetutility/FileReplacePageHelper.java | 17 ++++++++++++++--- .../datasetutility/OptionalFileParams.java | 4 ++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileReplacePageHelper.java b/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileReplacePageHelper.java index 94f247e6419..24ba8b663bc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileReplacePageHelper.java +++ b/src/main/java/edu/harvard/iq/dataverse/datasetutility/FileReplacePageHelper.java @@ -94,9 +94,10 @@ public boolean resetReplaceFileHelper(){ /** * Handle native file replace + * @param checkSum * @param event */ - public boolean handleNativeFileUpload(InputStream inputStream, String fullStorageId, String fileName, String fileContentType) { + public boolean handleNativeFileUpload(InputStream inputStream, String fullStorageId, String fileName, String fileContentType, String checkSum) { phase1Success = false; @@ -111,7 +112,17 @@ public boolean handleNativeFileUpload(InputStream inputStream, String fullStorag if (fileContentType == null){ throw new NullPointerException("fileContentType cannot be null"); } - + + OptionalFileParams ofp = null; + if(checkSum != null) { + try { + ofp = new OptionalFileParams(null); + } catch (DataFileTagException e) { + //Shouldn't happen with null input + e.printStackTrace(); + } + ofp.setCheckSum(checkSum); + } // Run 1st phase of replace // replaceFileHelper.runReplaceFromUI_Phase1(fileToReplace.getId(), @@ -119,7 +130,7 @@ public boolean handleNativeFileUpload(InputStream inputStream, String fullStorag fileContentType, inputStream, fullStorageId, - null + ofp ); // Did it work? diff --git a/src/main/java/edu/harvard/iq/dataverse/datasetutility/OptionalFileParams.java b/src/main/java/edu/harvard/iq/dataverse/datasetutility/OptionalFileParams.java index 11787d25a7e..e48d96e355d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/datasetutility/OptionalFileParams.java +++ b/src/main/java/edu/harvard/iq/dataverse/datasetutility/OptionalFileParams.java @@ -217,6 +217,10 @@ public String getMimeType() { return mimeType; } + public void setCheckSum(String checkSum) { + this.checkSum = checkSum; + } + public boolean hasCheckSum() { return ((checkSum!=null)&&(!checkSum.isEmpty())); } From bc6b07495f3c44b2819bda3d076ee053888b2c44 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Wed, 25 Mar 2020 17:23:36 -0400 Subject: [PATCH 466/475] convert location to storageId and pass checksum --- .../iq/dataverse/EditDatafilesPage.java | 30 ++++++++++++------- .../iq/dataverse/dataaccess/DataAccess.java | 5 ++++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java index 71b74ddc7ae..8fe7651fe85 100644 --- a/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java @@ -1873,7 +1873,8 @@ private void handleReplaceFileUpload(FacesEvent event, InputStream inputStream, if (fileReplacePageHelper.handleNativeFileUpload(inputStream,null, fileName, - contentType + contentType, + null )){ saveEnabled = true; @@ -1932,11 +1933,13 @@ the uploadFinished() method, triggered next, after the upload event private void handleReplaceFileUpload(String fullStorageLocation, String fileName, - String contentType){ + String contentType, + String checkSum){ fileReplacePageHelper.resetReplaceFileHelper(); saveEnabled = false; - if (fileReplacePageHelper.handleNativeFileUpload(null, fullStorageLocation, fileName, contentType)){ + String storageIdentifier = DataAccess.getStorarageIdFromLocation(fullStorageLocation); + if (fileReplacePageHelper.handleNativeFileUpload(null, storageIdentifier, fileName, contentType, checkSum)){ saveEnabled = true; /** @@ -2069,6 +2072,16 @@ public void handleExternalUpload() { //get file size long fileSize = sio.getSize(); + if(StringUtils.isEmpty(contentType)) { + contentType = FileUtil.MIME_TYPE_UNDETERMINED_DEFAULT; + } + + if(DataFile.ChecksumType.fromString(checksumType) != DataFile.ChecksumType.MD5 ) { + String warningMessage = "Non-MD5 checksums not yet supported in external uploads"; + localWarningMessage = warningMessage; + //ToDo - methods like handleReplaceFileUpload and classes like OptionalFileParams will need to track the algorithm in addition to the value to enable this + } + /* ---------------------------- Check file size - Max size NOT specified in db: default is unlimited @@ -2083,7 +2096,7 @@ public void handleExternalUpload() { // Is this a FileReplaceOperation? If so, then diverge! // ----------------------------------------------------------- if (this.isFileReplaceOperation()){ - this.handleReplaceFileUpload(storageLocation, fileName, FileUtil.MIME_TYPE_UNDETERMINED_DEFAULT); + this.handleReplaceFileUpload(storageLocation, fileName, contentType, checksumValue); this.setFileMetadataSelectedForTagsPopup(fileReplacePageHelper.getNewFileMetadatasBeforeSave().get(0)); return; } @@ -2099,13 +2112,8 @@ public void handleExternalUpload() { // for example, multiple files can be extracted from an uncompressed // zip file. //datafiles = ingestService.createDataFiles(workingVersion, dropBoxStream, fileName, "application/octet-stream"); - if(StringUtils.isEmpty(contentType)) { - contentType = "application/octet-stream"; - } - if(DataFile.ChecksumType.fromString(checksumType) != DataFile.ChecksumType.MD5 ) { - String warningMessage = "Non-MD5 checksums not yet supported in external uploads"; - localWarningMessage = warningMessage; - } + + datafiles = FileUtil.createDataFiles(workingVersion, null, fileName, contentType, fullStorageIdentifier, checksumValue, systemConfig); } catch (IOException ex) { logger.log(Level.SEVERE, "Error during ingest of file {0}", new Object[]{fileName}); diff --git a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java index db87b1751c6..0cf9883b240 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataaccess/DataAccess.java @@ -122,6 +122,11 @@ public static String[] getDriverIdAndStorageLocation(String storageLocation) { } public static String getStorarageIdFromLocation(String location) { + if(location.contains("://")) { + //It's a full location with a driverId, so strip and reapply the driver id + //NOte that this will strip the bucketname out (which s3 uses) but the S3IOStorage class knows to look at re-insert it + return location.substring(0,location.indexOf("://") +3) + location.substring(location.lastIndexOf('/')+1); + } return location.substring(location.lastIndexOf('/')+1); } From 16d520456754b7516e1a44dc2333494c8767d80f Mon Sep 17 00:00:00 2001 From: landreev Date: Thu, 26 Mar 2020 14:14:20 -0400 Subject: [PATCH 467/475] couple of small changes to the storage JVM section --- doc/release-notes/4.20-release-notes | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index aea536acaf0..06cceb6a38e 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -123,11 +123,12 @@ We made changes to the JSON Export in this release (Issue 6650, PR #6669). If yo ### New JVM Options and Database Settings -## New JVM Options for S3 storage +## New JVM Options for file storage drivers - The JVM option dataverse.files.file.directory= controls where temporary files are stored (in the /temp subdir of the defined directory), independent of the location of any 'file' store defined above. -- The JVM option dataverse.files..upload-redirect enables direct upload of files added to a dataset to the S3 store. -- The JVM option dataverse.files..ingestsizelimit controls the maximum size of files (uploaded via directupload) for which ingest will be attempted. +- The JVM option dataverse.files..upload-redirect enables direct upload of files added to a dataset to the S3 bucket. (S3 stores only!) +- The JVM option dataverse.files..MaxFileUploadSizeInBytes controls the maximum size of file uploads allowed for the given file store. +- The JVM option dataverse.files..ingestsizelimit controls the maximum size of files for which ingest will be attempted, for the given file store. ## New Database Settings for Shibboleth From 9f398cba9be33c2ab448c0d5e62cab210e540988 Mon Sep 17 00:00:00 2001 From: landreev Date: Thu, 26 Mar 2020 14:32:16 -0400 Subject: [PATCH 468/475] changed the direct upload file size section again --- doc/release-notes/4.20-release-notes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index 06cceb6a38e..c81e820060b 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -12,7 +12,7 @@ General information about this capability can be found below and in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. From 6ccd4b5025a1c13a918f8745dea18a7289b99ecc Mon Sep 17 00:00:00 2001 From: qqmyers Date: Thu, 26 Mar 2020 14:52:46 -0400 Subject: [PATCH 469/475] modifying direct upload info --- doc/release-notes/4.20-release-notes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/4.20-release-notes b/doc/release-notes/4.20-release-notes index c81e820060b..e29953db101 100644 --- a/doc/release-notes/4.20-release-notes +++ b/doc/release-notes/4.20-release-notes @@ -12,7 +12,7 @@ General information about this capability can be found below and in the Big Data Support Guide with specific information about how to enable it in the Configuration Guide - File Storage section. From b2996b81a88ea38aa215ca1f5a7a8f6ad9e483d6 Mon Sep 17 00:00:00 2001 From: Gustavo Durand Date: Fri, 27 Mar 2020 15:59:04 -0400 Subject: [PATCH 470/475] changed editor to contributor --- src/main/webapp/permissions-configure.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/permissions-configure.xhtml b/src/main/webapp/permissions-configure.xhtml index 3e8f55ba0a6..dc42e928a3b 100644 --- a/src/main/webapp/permissions-configure.xhtml +++ b/src/main/webapp/permissions-configure.xhtml @@ -26,7 +26,7 @@
- + #{managePermissionsPage.customDefaultContributorRoleAlias} From 0951452146a1b38afd8f645196f0058512b88880 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 27 Mar 2020 16:54:25 -0400 Subject: [PATCH 471/475] don't use class dataset - typo --- .../datasetutility/AddReplaceFileHelper.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java index 53af964fc14..d318428c454 100644 --- a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java +++ b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java @@ -367,7 +367,7 @@ public boolean runReplaceFile(Long oldFileId, if (!this.step_005_loadFileToReplaceById(oldFileId)){ return false; } - + logger.info("owner id " + fileToReplace.getOwner().getId()); return this.runAddReplaceFile(fileToReplace.getOwner(), newFileName, newFileContentType, newFileInputStream, optionalFileParams); } @@ -394,10 +394,10 @@ public boolean runReplaceFile(Long oldFileId, */ private boolean runAddReplaceFile(Dataset owner, String newFileName, String newFileContentType, InputStream newFileInputStream, OptionalFileParams optionalFileParams) { - return runAddReplaceFile(dataset,newFileName, newFileContentType, null, newFileInputStream, optionalFileParams); + return runAddReplaceFile(owner,newFileName, newFileContentType, null, newFileInputStream, optionalFileParams); } - private boolean runAddReplaceFile(Dataset dataset, + private boolean runAddReplaceFile(Dataset owner, String newFileName, String newFileContentType, String newStorageIdentifier, InputStream newFileInputStream, OptionalFileParams optionalFileParams){ @@ -405,14 +405,13 @@ private boolean runAddReplaceFile(Dataset dataset, // Run "Phase 1" - Initial ingest of file + error check // But don't save the dataset version yet // - boolean phase1Success = runAddReplacePhase1(dataset, + boolean phase1Success = runAddReplacePhase1(owner, newFileName, newFileContentType, newStorageIdentifier, newFileInputStream, optionalFileParams ); - if (!phase1Success){ return false; } @@ -476,7 +475,7 @@ public boolean runReplaceFromUI_Phase1(Long oldFileId, * * @return */ - private boolean runAddReplacePhase1(Dataset dataset, + private boolean runAddReplacePhase1(Dataset owner, String newFileName, String newFileContentType, String newStorageIdentifier, InputStream newFileInputStream, @@ -487,7 +486,7 @@ private boolean runAddReplacePhase1(Dataset dataset, } msgt("step_001_loadDataset"); - if (!this.step_001_loadDataset(dataset)){ + if (!this.step_001_loadDataset(owner)){ return false; } @@ -988,7 +987,7 @@ private boolean step_005_loadFileToReplaceById(Long dataFileId){ // Does the file exist? // DataFile existingFile = fileService.find(dataFileId); - + if (existingFile == null){ this.addError(BundleUtil.getStringFromBundle("file.addreplace.error.existing_file_to_replace_not_found_by_id", Collections.singletonList(dataFileId.toString()))); return false; From ce4b9d6de4698e361b7c8bbea8f8a4b213159ae7 Mon Sep 17 00:00:00 2001 From: qqmyers Date: Fri, 27 Mar 2020 16:57:15 -0400 Subject: [PATCH 472/475] remove debug logging --- .../iq/dataverse/datasetutility/AddReplaceFileHelper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java index d318428c454..18bf172f5d3 100644 --- a/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java +++ b/src/main/java/edu/harvard/iq/dataverse/datasetutility/AddReplaceFileHelper.java @@ -367,7 +367,6 @@ public boolean runReplaceFile(Long oldFileId, if (!this.step_005_loadFileToReplaceById(oldFileId)){ return false; } - logger.info("owner id " + fileToReplace.getOwner().getId()); return this.runAddReplaceFile(fileToReplace.getOwner(), newFileName, newFileContentType, newFileInputStream, optionalFileParams); } From 862dfe4cde15e74f0557cdcfba62aa5ca968d3ad Mon Sep 17 00:00:00 2001 From: Kevin Condon Date: Wed, 1 Apr 2020 14:38:16 -0400 Subject: [PATCH 473/475] Update pom.xml Update version to 4.20 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f96382397f4..f25bc86be7c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ --> edu.harvard.iq dataverse - 4.19 + 4.20 war dataverse From 734f84f033366b10325474bbf2918df9caaff4da Mon Sep 17 00:00:00 2001 From: Kevin Condon Date: Wed, 1 Apr 2020 14:40:16 -0400 Subject: [PATCH 474/475] Update conf.py Update version to 4.20 --- doc/sphinx-guides/source/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/conf.py b/doc/sphinx-guides/source/conf.py index bb27f7610d6..6ca7856c063 100755 --- a/doc/sphinx-guides/source/conf.py +++ b/doc/sphinx-guides/source/conf.py @@ -65,9 +65,9 @@ # built documents. # # The short X.Y version. -version = '4.19' +version = '4.20' # The full version, including alpha/beta/rc tags. -release = '4.19' +release = '4.20' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 9a2159d3bf504ba8aea897107659532523f60f51 Mon Sep 17 00:00:00 2001 From: Kevin Condon Date: Wed, 1 Apr 2020 14:41:34 -0400 Subject: [PATCH 475/475] Update versions.rst Update version to 4.20 --- doc/sphinx-guides/source/versions.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/versions.rst b/doc/sphinx-guides/source/versions.rst index 580dd0bcb14..3c670096efe 100755 --- a/doc/sphinx-guides/source/versions.rst +++ b/doc/sphinx-guides/source/versions.rst @@ -6,8 +6,9 @@ Dataverse Documentation Versions This list provides a way to refer to the documentation for previous versions of Dataverse. In order to learn more about the updates delivered from one version to another, visit the `Releases `__ page in our GitHub repo. -- 4.19 +- 4.20 +- `4.19 `__ - `4.18.1 `__ - `4.18 `__ - `4.17 `__

BI6>-i_=A*6z=~)!Ef#+;b(>+8FB- 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 literal 0 HcmV?d00001 diff --git a/tests/jenkins/groupvars.yml b/tests/jenkins/groupvars.yml index d028b6f8ade..a32be3e5d41 100644 --- a/tests/jenkins/groupvars.yml +++ b/tests/jenkins/groupvars.yml @@ -89,7 +89,7 @@ dataverse: postgres: reporpm: https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm version: 9.6 - jdbcurl: https://jdbc.postgresql.org/download/postgresql-42.2.8.jar + jdbcurl: https://jdbc.postgresql.org/download/postgresql-42.2.9.jar log_lock_waits: true previewers: enabled: true From d54206f4f5a5194165b3123b0ad7cca09cb99c36 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 6 Feb 2020 10:52:50 -0500 Subject: [PATCH 210/475] remove parentheses from dataset contact affiliation #6570 --- .../6570-search-api-contact-affiliation.md | 1 + .../harvard/iq/dataverse/DatasetVersion.java | 37 ++++++++++++++++++- .../iq/dataverse/search/SolrSearchResult.java | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 doc/release-notes/6570-search-api-contact-affiliation.md diff --git a/doc/release-notes/6570-search-api-contact-affiliation.md b/doc/release-notes/6570-search-api-contact-affiliation.md new file mode 100644 index 00000000000..a7cab0a5ef5 --- /dev/null +++ b/doc/release-notes/6570-search-api-contact-affiliation.md @@ -0,0 +1 @@ +As reported in https://github.com/IQSS/dataverse/issues/6570 the affiliation for dataset contacts has been wrapped in parentheses in the JSON output from the Search API. These parentheses have now been removed. This is a backward incompatible change but it is hoped that it won't cause any problems for integrations and API users. diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetVersion.java b/src/main/java/edu/harvard/iq/dataverse/DatasetVersion.java index 0f9654c0a5f..51c9be4bc1f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetVersion.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetVersion.java @@ -783,7 +783,42 @@ public List getDatasetContacts(){ } return retList; } - + + /** + * This method is the same as getDatasetContacts above but the actual value + * is returned for affiliation instead of the "display" value, which as of + * this writing wraps the value in parentheses. + */ + public List getDatasetContactsNonDisplay() { + List retList = new ArrayList<>(); + for (DatasetField dsf : this.getDatasetFields()) { + Boolean addContributor = true; + String contributorName = ""; + String contributorAffiliation = ""; + if (dsf.getDatasetFieldType().getName().equals(DatasetFieldConstant.datasetContact)) { + for (DatasetFieldCompoundValue authorValue : dsf.getDatasetFieldCompoundValues()) { + for (DatasetField subField : authorValue.getChildDatasetFields()) { + if (subField.getDatasetFieldType().getName().equals(DatasetFieldConstant.datasetContactName)) { + if (subField.isEmptyForDisplay()) { + addContributor = false; + } + contributorName = subField.getDisplayValue(); + } + if (subField.getDatasetFieldType().getName().equals(DatasetFieldConstant.datasetContactAffiliation)) { + contributorAffiliation = subField.getValue(); + } + + } + if (addContributor) { + String[] datasetContributor = new String[]{contributorName, contributorAffiliation}; + retList.add(datasetContributor); + } + } + } + } + return retList; + } + public List getDatasetProducers(){ List retList = new ArrayList<>(); for (DatasetField dsf : this.getDatasetFields()) { diff --git a/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java b/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java index 595c9962dd4..8abea55b1e7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java +++ b/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java @@ -596,7 +596,7 @@ public JsonObjectBuilder json(boolean showRelevance, boolean showEntityIds, bool if (!dv.getDatasetContacts().isEmpty()) { JsonArrayBuilder contacts = Json.createArrayBuilder(); NullSafeJsonBuilder nullSafeJsonBuilderInner = jsonObjectBuilder(); - for (String contact[] : dv.getDatasetContacts()) { + for (String contact[] : dv.getDatasetContactsNonDisplay()) { nullSafeJsonBuilderInner.add("name", contact[0]); nullSafeJsonBuilderInner.add("affiliation", contact[1]); contacts.add(nullSafeJsonBuilderInner); From dac1ad19f76bbb083e1f9668f2e20abf86009336 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 6 Feb 2020 11:11:49 -0500 Subject: [PATCH 211/475] #6290 cannot add role without permission --- src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java index 69712914b63..bfda75a465a 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -1144,8 +1144,12 @@ public void testAddRoles(){ //Give that random user permission //(String definitionPoint, String role, String roleAssignee, String apiToken) + //Can't give yourself permission + Response giveRandoPermission = UtilIT.grantRoleOnDataset(datasetPersistentId, "fileDownloader", "@" + randomUsername, randomUserApiToken); + giveRandoPermission.prettyPrint(); + assertEquals(401, giveRandoPermission.getStatusCode()); - Response giveRandoPermission = UtilIT.grantRoleOnDataset(datasetPersistentId, "fileDownloader", "@" + randomUsername, apiToken); + giveRandoPermission = UtilIT.grantRoleOnDataset(datasetPersistentId, "fileDownloader", "@" + randomUsername, apiToken); giveRandoPermission.prettyPrint(); assertEquals(200, giveRandoPermission.getStatusCode()); From aeebf04bbeafb740c2a91b5c4079a6c7f23acdd2 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 6 Feb 2020 13:00:53 -0500 Subject: [PATCH 212/475] add note: info exposed in restricted tabular files #6474 --- .../source/user/dataset-management.rst | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/doc/sphinx-guides/source/user/dataset-management.rst b/doc/sphinx-guides/source/user/dataset-management.rst index 9d5360786ce..31665a41a63 100755 --- a/doc/sphinx-guides/source/user/dataset-management.rst +++ b/doc/sphinx-guides/source/user/dataset-management.rst @@ -166,6 +166,7 @@ Additional download options available for tabular data (found in the same drop-d - Data File Citation (currently in either RIS, EndNote XML, or BibTeX format); - All of the above, as a zipped bundle. +See also :ref:`restricted-tabular-files`. Geospatial ---------- @@ -219,6 +220,28 @@ There are several advanced options available for certain file types. - Image files: .jpg, .png, and .tif files are able to be selected as the default thumbnail for a dataset. The selected thumbnail will appear on the search result card for that dataset. - SPSS files: SPSS files can be tagged with the language they were originally coded in. This is found by clicking on Advanced Options and selecting the language from the list provided. +.. _restricted-files: + +Restricted Files +================ + +When you restrict a file in Dataverse it cannot be downloaded unless permission has been granted. + +See also :ref:`terms-of-access` and :ref:`permissions`. + +.. _restricted-tabular-files: + +Restricted Tabular Files +------------------------ + +Restricted tabular files are treated differently than other file types in that the following information is exposed when the files are published: + +- The name of columns (variables) +- The "label" (description) of columns. +- Summary statistics (max, min, mean, etc.) of columns. + +This information can been seen from the file landing page if you click "Export Metada" and then "DDI". Depending on your installation, the information above may also be available from :doc:`/admin/external-tools`. + Edit Files ========== @@ -298,6 +321,8 @@ If you are unable to use the CC0 Public Domain Dedication for your datasets, you Here is an `example of a Data Usage Agreement `_ for datasets that have de-identified human subject data. +.. _terms-of-access: + Restricted Files + Terms of Access ---------------------------------- @@ -305,6 +330,8 @@ If you restrict any files in your dataset, you will be prompted by a pop-up to e **Note:** Some Dataverse installations do not allow for file restriction. +See also :ref:`restricted-files`. + Guestbook --------- From 17011e8e8aef607f2724e78ee67e1258bf179eae Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 6 Feb 2020 14:03:46 -0500 Subject: [PATCH 213/475] typo, forgot a period to match the other bullets #6474 --- doc/sphinx-guides/source/user/dataset-management.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/user/dataset-management.rst b/doc/sphinx-guides/source/user/dataset-management.rst index 31665a41a63..7eb0477d02b 100755 --- a/doc/sphinx-guides/source/user/dataset-management.rst +++ b/doc/sphinx-guides/source/user/dataset-management.rst @@ -236,7 +236,7 @@ Restricted Tabular Files Restricted tabular files are treated differently than other file types in that the following information is exposed when the files are published: -- The name of columns (variables) +- The name of columns (variables). - The "label" (description) of columns. - Summary statistics (max, min, mean, etc.) of columns. From e3a25faeddcfe21db02e9ba432e427893ec7c90d Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 6 Feb 2020 14:21:38 -0500 Subject: [PATCH 214/475] reduce code duplication #6570 --- .../harvard/iq/dataverse/DatasetVersion.java | 49 +++++-------------- .../iq/dataverse/search/SolrSearchResult.java | 2 +- 2 files changed, 13 insertions(+), 38 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetVersion.java b/src/main/java/edu/harvard/iq/dataverse/DatasetVersion.java index 51c9be4bc1f..83152d1a75f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetVersion.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetVersion.java @@ -754,43 +754,17 @@ public String getDescriptionHtmlEscaped() { return MarkupChecker.escapeHtml(getDescription()); } - public List getDatasetContacts(){ - List retList = new ArrayList<>(); - for (DatasetField dsf : this.getDatasetFields()) { - Boolean addContributor = true; - String contributorName = ""; - String contributorAffiliation = ""; - if (dsf.getDatasetFieldType().getName().equals(DatasetFieldConstant.datasetContact)) { - for (DatasetFieldCompoundValue authorValue : dsf.getDatasetFieldCompoundValues()) { - for (DatasetField subField : authorValue.getChildDatasetFields()) { - if (subField.getDatasetFieldType().getName().equals(DatasetFieldConstant.datasetContactName)) { - if (subField.isEmptyForDisplay()) { - addContributor = false; - } - contributorName = subField.getDisplayValue(); - } - if (subField.getDatasetFieldType().getName().equals(DatasetFieldConstant.datasetContactAffiliation)) { - contributorAffiliation = subField.getDisplayValue(); - } - - } - if (addContributor) { - String[] datasetContributor = new String[] {contributorName, contributorAffiliation}; - retList.add(datasetContributor); - } - } - } - } - return retList; + public List getDatasetContacts() { + boolean getDisplayValues = true; + return getDatasetContacts(getDisplayValues); } /** - * This method is the same as getDatasetContacts above but the actual value - * is returned for affiliation instead of the "display" value, which as of - * this writing wraps the value in parentheses. + * @param getDisplayValues Instead of the retrieving pristine value in the + * database, run the value through special formatting. */ - public List getDatasetContactsNonDisplay() { - List retList = new ArrayList<>(); + public List getDatasetContacts(boolean getDisplayValues) { + List retList = new ArrayList<>(); for (DatasetField dsf : this.getDatasetFields()) { Boolean addContributor = true; String contributorName = ""; @@ -802,21 +776,22 @@ public List getDatasetContactsNonDisplay() { if (subField.isEmptyForDisplay()) { addContributor = false; } + // There is no use case yet for getting the non-display value for contributorName. contributorName = subField.getDisplayValue(); } if (subField.getDatasetFieldType().getName().equals(DatasetFieldConstant.datasetContactAffiliation)) { - contributorAffiliation = subField.getValue(); + contributorAffiliation = getDisplayValues ? subField.getDisplayValue() : subField.getValue(); } } if (addContributor) { - String[] datasetContributor = new String[]{contributorName, contributorAffiliation}; + String[] datasetContributor = new String[] {contributorName, contributorAffiliation}; retList.add(datasetContributor); } } } - } - return retList; + } + return retList; } public List getDatasetProducers(){ diff --git a/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java b/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java index 8abea55b1e7..181ad7719ed 100644 --- a/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java +++ b/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java @@ -596,7 +596,7 @@ public JsonObjectBuilder json(boolean showRelevance, boolean showEntityIds, bool if (!dv.getDatasetContacts().isEmpty()) { JsonArrayBuilder contacts = Json.createArrayBuilder(); NullSafeJsonBuilder nullSafeJsonBuilderInner = jsonObjectBuilder(); - for (String contact[] : dv.getDatasetContactsNonDisplay()) { + for (String contact[] : dv.getDatasetContacts(false)) { nullSafeJsonBuilderInner.add("name", contact[0]); nullSafeJsonBuilderInner.add("affiliation", contact[1]); contacts.add(nullSafeJsonBuilderInner); From 9478caa13eda109cf353abdc6394e19d3036ffe5 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 6 Feb 2020 14:32:16 -0500 Subject: [PATCH 215/475] #6524 fix required permissions add tests --- .../command/impl/GetDatasetStorageSizeCommand.java | 2 +- .../java/edu/harvard/iq/dataverse/api/FilesIT.java | 14 +++++++++++++- .../java/edu/harvard/iq/dataverse/api/UtilIT.java | 6 ++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDatasetStorageSizeCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDatasetStorageSizeCommand.java index 271c9f214fb..f1f27fdcee2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDatasetStorageSizeCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDatasetStorageSizeCommand.java @@ -77,7 +77,7 @@ public Long execute(CommandContext ctxt) throws CommandException { public Map> getRequiredPermissions() { // for data file check permission on owning dataset return Collections.singletonMap("", - mode != null && mode.equals("storage") ? Collections.singleton(Permission.ViewUnpublishedDataset) + mode != null && mode.equals(Mode.STORAGE) ? Collections.singleton(Permission.ViewUnpublishedDataset) : version !=null && version.isDraft() ? Collections.singleton(Permission.ViewUnpublishedDataset) : Collections.emptySet()); } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java index 5a1e3b3fcdd..fbd030ab109 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java @@ -26,6 +26,7 @@ import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.NO_CONTENT; import static javax.ws.rs.core.Response.Status.OK; +import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; import static junit.framework.Assert.assertEquals; import org.hamcrest.CoreMatchers; import static org.hamcrest.CoreMatchers.equalTo; @@ -1325,7 +1326,11 @@ public void testDataSizeInDataverse() throws InterruptedException { Response publishDataversetResp = UtilIT.publishDataverseViaSword(dataverseAlias, apiToken); publishDataversetResp.then().assertThat() .statusCode(OK.getStatusCode()); + String apiTokenRando = createUserGetToken(); + Response datasetStorageSizeResponseDraft = UtilIT.findDatasetDownloadSize(datasetId.toString(), ":draft", apiTokenRando); + datasetStorageSizeResponseDraft.prettyPrint(); + assertEquals(UNAUTHORIZED.getStatusCode(), datasetStorageSizeResponseDraft.getStatusCode()); Response publishDatasetResp = UtilIT.publishDatasetViaNativeApi(datasetId, "major", apiToken); //msg(publishDatasetResp.body().asString()); publishDatasetResp.then().assertThat() @@ -1345,9 +1350,16 @@ public void testDataSizeInDataverse() throws InterruptedException { magicControlString = MessageFormat.format(BundleUtil.getStringFromBundle("datasets.api.datasize.storage"), magicSizeNumber); - Response datasetStorageSizeResponse = UtilIT.findDatasetStorageSize(datasetId.toString(), apiToken); + //no perms + + Response datasetStorageSizeResponse = UtilIT.findDatasetStorageSize(datasetId.toString(), apiTokenRando); datasetStorageSizeResponse.prettyPrint(); + assertEquals(UNAUTHORIZED.getStatusCode(), datasetStorageSizeResponse.getStatusCode()); + //has perms + datasetStorageSizeResponse = UtilIT.findDatasetStorageSize(datasetId.toString(), apiToken); + datasetStorageSizeResponse.prettyPrint(); + assertEquals(magicControlString, JsonPath.from(datasetStorageSizeResponse.body().asString()).getString("data.message")); magicControlString = MessageFormat.format(BundleUtil.getStringFromBundle("datasets.api.datasize.download"), magicSizeNumber); diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 73612ed0169..a744bcd0ba5 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -2315,4 +2315,10 @@ static Response findDatasetDownloadSize(String datasetId) { .get("/api/datasets/" + datasetId + "/versions/:latest/downloadsize"); } + static Response findDatasetDownloadSize(String datasetId, String version, String apiToken) { + return given() + .header(API_TOKEN_HTTP_HEADER, apiToken) + .get("/api/datasets/" + datasetId + "/versions/" + version + "/downloadsize"); + } + } From 9251392e4fb90369ef7da4dffc7a1770dda16d41 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 6 Feb 2020 14:46:51 -0500 Subject: [PATCH 216/475] change DDI schemaLocation to https #6553 --- .../java/edu/harvard/iq/dataverse/export/DDIExporter.java | 1 + .../edu/harvard/iq/dataverse/export/OAI_DDIExporter.java | 1 + .../edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java | 6 ++++-- .../edu/harvard/iq/dataverse/export/ddi/dataset-finch1.xml | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/export/DDIExporter.java b/src/main/java/edu/harvard/iq/dataverse/export/DDIExporter.java index a029e483c0c..39eb92ff89d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/DDIExporter.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/DDIExporter.java @@ -24,6 +24,7 @@ public class DDIExporter implements Exporter { // TODO: // move these into the ddi export utility private static String DEFAULT_XML_NAMESPACE = "ddi:codebook:2_5"; + // This redirects to https://ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd private static String DEFAULT_XML_SCHEMALOCATION = "http://www.ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd"; private static String DEFAULT_XML_VERSION = "2.5"; diff --git a/src/main/java/edu/harvard/iq/dataverse/export/OAI_DDIExporter.java b/src/main/java/edu/harvard/iq/dataverse/export/OAI_DDIExporter.java index b43fbd3e06d..0a69f3a0442 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/OAI_DDIExporter.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/OAI_DDIExporter.java @@ -18,6 +18,7 @@ public class OAI_DDIExporter implements Exporter { // TODO: move these to the export utility: private static String DEFAULT_XML_NAMESPACE = "ddi:codebook:2_5"; + // This redirects to https://ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd private static String DEFAULT_XML_SCHEMALOCATION = "http://www.ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd"; private static String DEFAULT_XML_VERSION = "2.5"; diff --git a/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java b/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java index 51975ba5efe..ea599526c7d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java @@ -110,7 +110,8 @@ private static void dtoddi(DatasetDTO datasetDto, OutputStream outputStream) thr xmlw.writeStartElement("codeBook"); xmlw.writeDefaultNamespace("ddi:codebook:2_5"); xmlw.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); - xmlw.writeAttribute("xsi:schemaLocation", "ddi:codebook:2_5 http://www.ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd"); + // This redirects to https://ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd + xmlw.writeAttribute("xsi:schemaLocation", "ddi:codebook:2_5 https://www.ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd"); writeAttribute(xmlw, "version", "2.5"); createStdyDscr(xmlw, datasetDto); createOtherMats(xmlw, datasetDto.getDatasetVersion().getFiles()); @@ -129,7 +130,8 @@ public static void datasetJson2ddi(JsonObject datasetDtoAsJson, DatasetVersion v xmlw.writeStartElement("codeBook"); xmlw.writeDefaultNamespace("ddi:codebook:2_5"); xmlw.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); - xmlw.writeAttribute("xsi:schemaLocation", "ddi:codebook:2_5 http://www.ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd"); + // This redirects to https://ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd + xmlw.writeAttribute("xsi:schemaLocation", "ddi:codebook:2_5 https://www.ddialliance.org/Specification/DDI-Codebook/2.5/XMLSchema/codebook.xsd"); writeAttribute(xmlw, "version", "2.5"); createStdyDscr(xmlw, datasetDto); createFileDscr(xmlw, version); diff --git a/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-finch1.xml b/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-finch1.xml index 3023d9eebe1..68fff96c399 100644 --- a/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-finch1.xml +++ b/src/test/java/edu/harvard/iq/dataverse/export/ddi/dataset-finch1.xml @@ -1,5 +1,5 @@ - + From ba7f66c10555cc0e03fc9052f470e5dde4a5a026 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 6 Feb 2020 15:50:02 -0500 Subject: [PATCH 217/475] #6290 Add doc to dataset role api --- doc/sphinx-guides/source/api/native-api.rst | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 541a1fbf273..45ced8545a0 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -952,6 +952,34 @@ List Role Assignments for a Dataset List all the role assignments at the given dataset:: GET http://$SERVER/api/datasets/$id/assignments?key=$apiKey + +.. _assign-role-on-a-dataverse-api: + +Assign a New Role on a Dataset +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Assigns a new role, based on the POSTed JSON: + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=xxxxxx + + curl -H X-Dataverse-key:$API_TOKEN -X POST $SERVER_URL/api/datasets/$ID/assignments --upload-file role.json + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X POST https://demo.dataverse.org/api/datasets/xxxxxx/assignments --upload-file role.json + +POSTed JSON example (the content of ``role.json`` file):: + + { + "assignee": "@uma", + "role": "curator" + } Create a Private URL for a Dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 055fa5f47eea796305b5e6410226b4e4834358b0 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 6 Feb 2020 16:39:56 -0500 Subject: [PATCH 218/475] in Search API show fileCount for datasets #6601 --- doc/sphinx-guides/source/api/search.rst | 3 +++ .../java/edu/harvard/iq/dataverse/search/SolrSearchResult.java | 1 + src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java | 1 + 3 files changed, 5 insertions(+) diff --git a/doc/sphinx-guides/source/api/search.rst b/doc/sphinx-guides/source/api/search.rst index baae7820de8..25bad2b8091 100755 --- a/doc/sphinx-guides/source/api/search.rst +++ b/doc/sphinx-guides/source/api/search.rst @@ -116,6 +116,7 @@ https://demo.dataverse.org/api/search?q=trees "Astronomy and Astrophysics", "Other" ], + "fileCount":3, "versionId":1260, "versionState":"RELEASED", "majorVersion":3, @@ -291,6 +292,7 @@ The above example ``fq=publicationStatus:Published`` retrieves only "RELEASED" v "subjects": [ "Medicine, Health and Life Sciences" ], + "fileCount":6, "versionId": 53001, "versionState": "RELEASED", "majorVersion": 1, @@ -323,6 +325,7 @@ The above example ``fq=publicationStatus:Published`` retrieves only "RELEASED" v "subjects": [ "Medicine, Health and Life Sciences" ], + "fileCount":9, "versionId": 53444, "versionState": "RELEASED", "majorVersion": 1, diff --git a/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java b/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java index 181ad7719ed..874717f77e5 100644 --- a/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java +++ b/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchResult.java @@ -584,6 +584,7 @@ public JsonObjectBuilder json(boolean showRelevance, boolean showEntityIds, bool subjects.add(subject); } nullSafeJsonBuilder.add("subjects", subjects); + nullSafeJsonBuilder.add("fileCount", dv.getFileMetadatas().size()); nullSafeJsonBuilder.add("versionId", dv.getId()); nullSafeJsonBuilder.add("versionState", dv.getVersionState().toString()); if(this.isPublishedState()){ diff --git a/src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java b/src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java index 4768a8b80c4..c83afc1470c 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java @@ -384,6 +384,7 @@ public void testDatasetThumbnail() { search2.prettyPrint(); search2.then().assertThat() .body("data.items[0].name", CoreMatchers.equalTo("Darwin's Finches")) + .body("data.items[0].fileCount", CoreMatchers.equalTo(1)) .statusCode(200); //Unpublished datafiles no longer populate the dataset thumbnail From 08475d92c5e21898d697d81d29ce68212862a829 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Thu, 6 Feb 2020 17:26:05 -0500 Subject: [PATCH 219/475] *correct* new constraint on the storageidentifier within datasets (#6522) --- src/main/java/edu/harvard/iq/dataverse/DvObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DvObject.java b/src/main/java/edu/harvard/iq/dataverse/DvObject.java index 100216a203b..8a2f710c428 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DvObject.java +++ b/src/main/java/edu/harvard/iq/dataverse/DvObject.java @@ -46,7 +46,7 @@ , @Index(columnList="owner_id") , @Index(columnList="creator_id") , @Index(columnList="releaseuser_id")}, - uniqueConstraints = {@UniqueConstraint(columnNames = {"authority,protocol,identifier"}),@UniqueConstraint(columnNames = {"dataset_id,versionnumber,minorversionnumber"})}) + uniqueConstraints = {@UniqueConstraint(columnNames = {"authority,protocol,identifier"}),@UniqueConstraint(columnNames = {"owner_id,storageidentifier"})}) public abstract class DvObject extends DataverseEntity implements java.io.Serializable { public static final String DATAVERSE_DTYPE_STRING = "Dataverse"; From 0ef44b5a2bc2a83d4031cd8959a0235ef69f4ce9 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Wed, 5 Feb 2020 17:38:22 -0500 Subject: [PATCH 220/475] wrong tooltips --- src/main/webapp/file.xhtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/file.xhtml b/src/main/webapp/file.xhtml index a9909728236..3059c3b8705 100644 --- a/src/main/webapp/file.xhtml +++ b/src/main/webapp/file.xhtml @@ -309,11 +309,11 @@ #{bundle['metrics.file.title']} + data-trigger="hover" data-original-title="#{bundle['metrics.file.tip.default']}"> + data-trigger="focus" data-html="true" data-content="#{bundle['metrics.file.tip.makedatacount']}">