From 8ea664adb2161b04ab8b6171bbb426d8875fe27f Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Wed, 28 Apr 2021 09:29:36 -0400 Subject: [PATCH 001/179] Add Context method to uncache all entities --- .../main/java/org/dspace/core/Context.java | 14 +++++++- .../java/org/dspace/core/DBConnection.java | 32 ++++++++++++------- .../dspace/core/HibernateDBConnection.java | 5 +++ .../java/org/dspace/core/ContextTest.java | 25 +++++++++++++++ .../core/HibernateDBConnectionTest.java | 22 +++++++++++++ 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/Context.java b/dspace-api/src/main/java/org/dspace/core/Context.java index e878367ec4c8..7c3d8b204a64 100644 --- a/dspace-api/src/main/java/org/dspace/core/Context.java +++ b/dspace-api/src/main/java/org/dspace/core/Context.java @@ -817,7 +817,19 @@ public E reloadEntity(E entity) throws SQLException } /** - * Remove an entity from the cache. This is necessary when batch processing a large number of items. + * Remove all entities from the cache and reload the current user entity. This is useful when batch processing + * a large number of entities when the calling code requires the cache to be completely cleared before continuing. + * + * @throws SQLException if a database error occurs. + */ + public void uncacheEntities() throws SQLException { + dbConnection.uncacheEntities(); + reloadContextBoundEntities(); + } + + /** + * Remove an entity from the cache. This is useful when batch processing a large number of entities + * when the calling code needs to retain some items in the cache while removing others. * * @param entity The entity to reload * @param The class of the enity. The entity must implement the {@link ReloadableEntity} interface. diff --git a/dspace-api/src/main/java/org/dspace/core/DBConnection.java b/dspace-api/src/main/java/org/dspace/core/DBConnection.java index cb5825eec1d9..3cb52983a091 100644 --- a/dspace-api/src/main/java/org/dspace/core/DBConnection.java +++ b/dspace-api/src/main/java/org/dspace/core/DBConnection.java @@ -124,28 +124,38 @@ public interface DBConnection { public long getCacheSize() throws SQLException; /** - * Reload a DSpace object from the database. This will make sure the object + * Reload an entity from the database. This will make sure the object * is valid and stored in the cache. The returned object should be used * henceforth instead of the passed object. * - * @param type of {@link entity} - * @param entity The DSpace object to reload + * @param type of entity. + * @param entity The entity to reload. * @return the reloaded entity. - * @throws java.sql.SQLException passed through. + * @throws SQLException passed through. */ public E reloadEntity(E entity) throws SQLException; /** - * Remove a DSpace object from the session cache when batch processing a - * large number of objects. + * Remove all entities from the session cache. * - *

Objects removed from cache are not saved in any way. Therefore, if you - * have modified an object, you should be sure to {@link commit()} changes + *

Entities removed from cache are not saved in any way. Therefore, if you + * have modified any entities, you should be sure to {@link #commit()} changes * before calling this method. * - * @param Type of {@link entity} - * @param entity The DSpace object to decache. - * @throws java.sql.SQLException passed through. + * @throws SQLException passed through. + */ + public void uncacheEntities() throws SQLException; + + /** + * Remove an entity from the session cache. + * + *

Entities removed from cache are not saved in any way. Therefore, if you + * have modified the entity, you should be sure to {@link #commit()} changes + * before calling this method. + * + * @param Type of entity. + * @param entity The entity to decache. + * @throws SQLException passed through. */ public void uncacheEntity(E entity) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java b/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java index 3321e4d837e5..69823a8601f4 100644 --- a/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java +++ b/dspace-api/src/main/java/org/dspace/core/HibernateDBConnection.java @@ -243,6 +243,11 @@ private void configureDatabaseMode() throws SQLException { } } + @Override + public void uncacheEntities() throws SQLException { + getSession().clear(); + } + /** * Evict an entity from the hibernate cache. *

diff --git a/dspace-api/src/test/java/org/dspace/core/ContextTest.java b/dspace-api/src/test/java/org/dspace/core/ContextTest.java index 811582c569a1..e02644b1a0fd 100644 --- a/dspace-api/src/test/java/org/dspace/core/ContextTest.java +++ b/dspace-api/src/test/java/org/dspace/core/ContextTest.java @@ -558,4 +558,29 @@ protected void init() { cleanupContext(instance); } + @Test + public void testUncacheEntities() throws Throwable { + // To set up the test, ensure the cache contains more than the current user entity + groupService.findByName(context, Group.ANONYMOUS); + assertTrue("Cache size should be greater than one", context.getDBConnection().getCacheSize() > 1); + + context.uncacheEntities(); + + assertThat("Cache size should be one (current user)", context.getDBConnection().getCacheSize(), equalTo(1L)); + context.reloadEntity(context.getCurrentUser()); + assertThat("Cache should only contain the current user", context.getDBConnection().getCacheSize(), equalTo(1L)); + } + + @Test + public void testUncacheEntity() throws Throwable { + // Remember the cache size after loading an entity + Group group = groupService.findByName(context, Group.ANONYMOUS); + long oldCacheSize = context.getDBConnection().getCacheSize(); + + // Uncache the entity + context.uncacheEntity(group); + + long newCacheSize = context.getDBConnection().getCacheSize(); + assertThat("Cache size should be reduced by one", newCacheSize, equalTo(oldCacheSize - 1)); + } } diff --git a/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java b/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java index 093f693d567f..302844ce62ac 100644 --- a/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java +++ b/dspace-api/src/test/java/org/dspace/core/HibernateDBConnectionTest.java @@ -205,6 +205,28 @@ public void testReloadEntityAfterCommit() throws SQLException { .contains(person)); } + /** + * Test of uncacheEntities method + */ + @Test + public void testUncacheEntities() throws SQLException { + // Get DBConnection associated with DSpace Context + HibernateDBConnection dbConnection = (HibernateDBConnection) context.getDBConnection(); + EPerson person = context.getCurrentUser(); + + assertTrue("Current user should be cached in session", dbConnection.getSession() + .contains(person)); + + dbConnection.uncacheEntities(); + assertFalse("Current user should be gone from cache", dbConnection.getSession() + .contains(person)); + + // Test ability to reload an uncached entity + person = dbConnection.reloadEntity(person); + assertTrue("Current user should be cached back in session", dbConnection.getSession() + .contains(person)); + } + /** * Test of uncacheEntity method */ From 15f4dc3dc18d77e255ffb130209b9c91beb3bdf6 Mon Sep 17 00:00:00 2001 From: Andreas Mahnke Date: Fri, 9 Feb 2024 14:51:46 +0100 Subject: [PATCH 002/179] Provide ability to store the id of a controlled vocabulary node / offer localized labels using cv.xml files per locale --- .../authority/DSpaceControlledVocabulary.java | 54 +++++++++---- .../controlled-vocabularies/countries.xml | 10 +++ .../controlled-vocabularies/countries_de.xml | 10 +++ .../test/data/dspaceFolder/config/local.cfg | 4 + .../DSpaceControlledVocabularyTest.java | 79 +++++++++++++++++++ 5 files changed, 141 insertions(+), 16 deletions(-) create mode 100644 dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries.xml create mode 100644 dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries_de.xml diff --git a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java index 16632ee5466b..11f7009cfaa5 100644 --- a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java +++ b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java @@ -8,6 +8,7 @@ package org.dspace.content.authority; import java.io.File; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -59,20 +60,26 @@ public class DSpaceControlledVocabulary extends SelfNamedPlugin implements HierarchicalAuthority { private static Logger log = org.apache.logging.log4j.LogManager.getLogger(DSpaceControlledVocabulary.class); - protected static String xpathTemplate = "//node[contains(translate(@label,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'," + + protected static String xpathIdTemplate = "//node[contains(translate(@id,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'," + + "'abcdefghijklmnopqrstuvwxyz'),'%s')]"; + protected static String xpathLabelTemplate = "//node[contains(translate(@label,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'," + "'abcdefghijklmnopqrstuvwxyz'),'%s')]"; protected static String idTemplate = "//node[@id = '%s']"; protected static String labelTemplate = "//node[@label = '%s']"; protected static String idParentTemplate = "//node[@id = '%s']/parent::isComposedBy/parent::node"; protected static String rootTemplate = "/node"; + protected static String idAttribute = "id"; + protected static String labelAttribute = "label"; protected static String pluginNames[] = null; - protected String vocabularyName = null; protected InputSource vocabulary = null; protected Boolean suggestHierarchy = false; protected Boolean storeHierarchy = true; protected String hierarchyDelimiter = "::"; protected Integer preloadLevel = 1; + protected String valueAttribute = labelAttribute; + protected String valueTemplate = labelTemplate; + protected String xpathValueTemplate = xpathLabelTemplate; public DSpaceControlledVocabulary() { super(); @@ -114,7 +121,7 @@ public boolean accept(File dir, String name) { } } - protected void init() { + protected void init(String locale) { if (vocabulary == null) { ConfigurationService config = DSpaceServicesFactory.getInstance().getConfigurationService(); @@ -123,13 +130,26 @@ protected void init() { String vocabulariesPath = config.getProperty("dspace.dir") + "/config/controlled-vocabularies/"; String configurationPrefix = "vocabulary.plugin." + vocabularyName; storeHierarchy = config.getBooleanProperty(configurationPrefix + ".hierarchy.store", storeHierarchy); + boolean storeIDs = config.getBooleanProperty(configurationPrefix + ".storeIDs", false); suggestHierarchy = config.getBooleanProperty(configurationPrefix + ".hierarchy.suggest", suggestHierarchy); preloadLevel = config.getIntProperty(configurationPrefix + ".hierarchy.preloadLevel", preloadLevel); String configuredDelimiter = config.getProperty(configurationPrefix + ".delimiter"); if (configuredDelimiter != null) { hierarchyDelimiter = configuredDelimiter.replaceAll("(^\"|\"$)", ""); } + if (storeIDs) { + valueAttribute = idAttribute; + valueTemplate = idTemplate; + xpathValueTemplate = xpathIdTemplate; + } + String filename = vocabulariesPath + vocabularyName + ".xml"; + if (StringUtils.isNotEmpty(locale)) { + String localizedFilename = vocabulariesPath + vocabularyName + "_" + locale + ".xml"; + if (Paths.get(localizedFilename).toFile().exists()) { + filename = localizedFilename; + } + } log.info("Loading " + filename); vocabulary = new InputSource(filename); } @@ -142,9 +162,9 @@ protected String buildString(Node node) { return (""); } else { String parentValue = buildString(node.getParentNode()); - Node currentLabel = node.getAttributes().getNamedItem("label"); - if (currentLabel != null) { - String currentValue = currentLabel.getNodeValue(); + Node currentNodeValue = node.getAttributes().getNamedItem(valueAttribute); + if (currentNodeValue != null) { + String currentValue = currentNodeValue.getNodeValue(); if (parentValue.equals("")) { return currentValue; } else { @@ -158,12 +178,13 @@ protected String buildString(Node node) { @Override public Choices getMatches(String text, int start, int limit, String locale) { - init(); + init(locale); log.debug("Getting matches for '" + text + "'"); String xpathExpression = ""; String[] textHierarchy = text.split(hierarchyDelimiter, -1); for (int i = 0; i < textHierarchy.length; i++) { - xpathExpression += String.format(xpathTemplate, textHierarchy[i].replaceAll("'", "'").toLowerCase()); + xpathExpression += + String.format(xpathValueTemplate, textHierarchy[i].replaceAll("'", "'").toLowerCase()); } XPath xpath = XPathFactory.newInstance().newXPath(); int total = 0; @@ -182,12 +203,13 @@ public Choices getMatches(String text, int start, int limit, String locale) { @Override public Choices getBestMatch(String text, String locale) { - init(); + init(locale); log.debug("Getting best matches for '" + text + "'"); String xpathExpression = ""; String[] textHierarchy = text.split(hierarchyDelimiter, -1); for (int i = 0; i < textHierarchy.length; i++) { - xpathExpression += String.format(labelTemplate, textHierarchy[i].replaceAll("'", "'")); + xpathExpression += + String.format(valueTemplate, textHierarchy[i].replaceAll("'", "'")); } XPath xpath = XPathFactory.newInstance().newXPath(); List choices = new ArrayList(); @@ -229,21 +251,21 @@ public boolean isHierarchical() { @Override public Choices getTopChoices(String authorityName, int start, int limit, String locale) { - init(); + init(locale); String xpathExpression = rootTemplate; return getChoicesByXpath(xpathExpression, start, limit); } @Override public Choices getChoicesByParent(String authorityName, String parentId, int start, int limit, String locale) { - init(); + init(locale); String xpathExpression = String.format(idTemplate, parentId); return getChoicesByXpath(xpathExpression, start, limit); } @Override public Choice getParentChoice(String authorityName, String childId, String locale) { - init(); + init(locale); try { String xpathExpression = String.format(idParentTemplate, childId); Choice choice = createChoiceFromNode(getNodeFromXPath(xpathExpression)); @@ -267,7 +289,7 @@ private boolean isRootElement(Node node) { } private Node getNode(String key) throws XPathExpressionException { - init(); + init(null); String xpathExpression = String.format(idTemplate, key); Node node = getNodeFromXPath(xpathExpression); return node; @@ -324,7 +346,7 @@ private String getNodeLabel(String key, boolean useHierarchy) { if (useHierarchy) { return this.buildString(node); } else { - return node.getAttributes().getNamedItem("label").getNodeValue(); + return node.getAttributes().getNamedItem("id").getNodeValue(); } } catch (XPathExpressionException e) { return (""); @@ -345,7 +367,7 @@ private String getValue(Node node) { if (this.storeHierarchy) { return hierarchy; } else { - return node.getAttributes().getNamedItem("label").getNodeValue(); + return node.getAttributes().getNamedItem(valueAttribute).getNodeValue(); } } diff --git a/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries.xml b/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries.xml new file mode 100644 index 000000000000..45ad97d0e158 --- /dev/null +++ b/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries_de.xml b/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries_de.xml new file mode 100644 index 000000000000..820ebac81d8a --- /dev/null +++ b/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries_de.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index 05a4cc5add01..175e125d8146 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -174,3 +174,7 @@ authority.controlled.dspace.object.owner = true # Configuration required for thorough testing of browse links webui.browse.link.1 = author:dc.contributor.* webui.browse.link.2 = subject:dc.subject.* + +# Configuration required for testing the controlled vocabulary functionality, which is configured using properties +vocabulary.plugin.countries.hierarchy.store=false +vocabulary.plugin.countries.storeIDs=true \ No newline at end of file diff --git a/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java b/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java index 255b070e5eac..e7d67600a5fa 100644 --- a/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java +++ b/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java @@ -89,6 +89,85 @@ public void testGetMatches() throws IOException, ClassNotFoundException { assertEquals("north 40", result.values[0].value); } + /** + * Test of getMatches method of class + * DSpaceControlledVocabulary using a controlled vocabulary with configured storage of node id. + * @throws java.lang.ClassNotFoundException passed through. + */ + @Test + public void testGetMatchesIdValue() throws ClassNotFoundException { + System.out.println("getMatchesIdValue"); + + final String PLUGIN_INTERFACE = "org.dspace.content.authority.ChoiceAuthority"; + + String idValue = "DZA"; + int start = 0; + int limit = 10; + String locale = null; + // This "countries" Controlled Vocab is included in TestEnvironment data + // (under /src/test/data/dspaceFolder/) and it should be auto-loaded + // by test configs in /src/test/data/dspaceFolder/config/local.cfg + DSpaceControlledVocabulary instance = (DSpaceControlledVocabulary) + CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(Class.forName(PLUGIN_INTERFACE), + "countries"); + assertNotNull(instance); + Choices result = instance.getMatches(idValue, start, limit, locale); + assertEquals(idValue, result.values[0].value); + } + + /** + * Test of getMatches method of class + * DSpaceControlledVocabulary using a localized controlled vocabulary with no locale (fallback to default) + * @throws java.lang.ClassNotFoundException passed through. + */ + + @Test + public void testGetMatchesNoLocale() throws ClassNotFoundException { + System.out.println("getMatchesNoLocale"); + + final String PLUGIN_INTERFACE = "org.dspace.content.authority.ChoiceAuthority"; + + String idValue = "DZA"; + int start = 0; + int limit = 10; + String locale = null; + // This "countries" Controlled Vocab is included in TestEnvironment data + // (under /src/test/data/dspaceFolder/) and it should be auto-loaded + // by test configs in /src/test/data/dspaceFolder/config/local.cfg + DSpaceControlledVocabulary instance = (DSpaceControlledVocabulary) + CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(Class.forName(PLUGIN_INTERFACE), + "countries"); + assertNotNull(instance); + Choices result = instance.getMatches(idValue, start, limit, locale); + assertEquals("Algeria", result.values[0].label); + } + + /** + * Test of getMatches method of class + * DSpaceControlledVocabulary using a localized controlled vocabulary with valid locale parameter (localized + * label returned) + */ + @Test + public void testGetMatchesGermanLocale() throws ClassNotFoundException { + System.out.println("getMatchesNoLocale"); + + final String PLUGIN_INTERFACE = "org.dspace.content.authority.ChoiceAuthority"; + + String idValue = "DZA"; + int start = 0; + int limit = 10; + String locale = "de"; + // This "countries" Controlled Vocab is included in TestEnvironment data + // (under /src/test/data/dspaceFolder/) and it should be auto-loaded + // by test configs in /src/test/data/dspaceFolder/config/local.cfg + DSpaceControlledVocabulary instance = (DSpaceControlledVocabulary) + CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(Class.forName(PLUGIN_INTERFACE), + "countries"); + assertNotNull(instance); + Choices result = instance.getMatches(idValue, start, limit, locale); + assertEquals("Algerien", result.values[0].label); + } + /** * Test of getBestMatch method, of class DSpaceControlledVocabulary. */ From 5c3902486e3d80a5bf2bc4059679296b9741762c Mon Sep 17 00:00:00 2001 From: Andreas Mahnke Date: Fri, 9 Feb 2024 15:12:03 +0100 Subject: [PATCH 003/179] added line endings --- .../dspaceFolder/config/controlled-vocabularies/countries.xml | 2 +- .../config/controlled-vocabularies/countries_de.xml | 2 +- dspace-api/src/test/data/dspaceFolder/config/local.cfg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries.xml b/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries.xml index 45ad97d0e158..078e8bfa3865 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries.xml @@ -7,4 +7,4 @@ - \ No newline at end of file + diff --git a/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries_de.xml b/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries_de.xml index 820ebac81d8a..b4bbf0b1e03c 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries_de.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/controlled-vocabularies/countries_de.xml @@ -7,4 +7,4 @@ - \ No newline at end of file + diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index 175e125d8146..9873f24920f1 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -177,4 +177,4 @@ webui.browse.link.2 = subject:dc.subject.* # Configuration required for testing the controlled vocabulary functionality, which is configured using properties vocabulary.plugin.countries.hierarchy.store=false -vocabulary.plugin.countries.storeIDs=true \ No newline at end of file +vocabulary.plugin.countries.storeIDs=true From 0d6836720c4f4c55415093f285f4d94348763536 Mon Sep 17 00:00:00 2001 From: Andreas Mahnke Date: Fri, 9 Feb 2024 16:02:23 +0100 Subject: [PATCH 004/179] Bugfix after IT --- .../content/authority/DSpaceControlledVocabulary.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java index 11f7009cfaa5..8169f9bf1a00 100644 --- a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java +++ b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java @@ -225,12 +225,12 @@ public Choices getBestMatch(String text, String locale) { @Override public String getLabel(String key, String locale) { - return getNodeLabel(key, this.suggestHierarchy); + return getNodeValue(key, this.suggestHierarchy); } @Override public String getValue(String key, String locale) { - return getNodeLabel(key, this.storeHierarchy); + return getNodeValue(key, this.storeHierarchy); } @Override @@ -337,7 +337,7 @@ private Map addOtherInformation(String parentCurr, String noteCu return extras; } - private String getNodeLabel(String key, boolean useHierarchy) { + private String getNodeValue(String key, boolean useHierarchy) { try { Node node = getNode(key); if (Objects.isNull(node)) { @@ -346,7 +346,7 @@ private String getNodeLabel(String key, boolean useHierarchy) { if (useHierarchy) { return this.buildString(node); } else { - return node.getAttributes().getNamedItem("id").getNodeValue(); + return node.getAttributes().getNamedItem(valueAttribute).getNodeValue(); } } catch (XPathExpressionException e) { return (""); From 5d9649a9016fa7c647b1d87eff52625054f7b713 Mon Sep 17 00:00:00 2001 From: Andreas Mahnke Date: Tue, 19 Mar 2024 11:08:58 +0100 Subject: [PATCH 005/179] Bugfix getMatches: only use label query xPathTemplate (getMatches purpose is to find choices by label) --- .../authority/DSpaceControlledVocabulary.java | 8 +-- .../DSpaceControlledVocabularyTest.java | 59 +++++++++++++------ 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java index 8169f9bf1a00..1d3760ba0c0f 100644 --- a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java +++ b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java @@ -60,9 +60,7 @@ public class DSpaceControlledVocabulary extends SelfNamedPlugin implements HierarchicalAuthority { private static Logger log = org.apache.logging.log4j.LogManager.getLogger(DSpaceControlledVocabulary.class); - protected static String xpathIdTemplate = "//node[contains(translate(@id,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'," + - "'abcdefghijklmnopqrstuvwxyz'),'%s')]"; - protected static String xpathLabelTemplate = "//node[contains(translate(@label,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'," + + protected static String xpathTemplate = "//node[contains(translate(@label,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'," + "'abcdefghijklmnopqrstuvwxyz'),'%s')]"; protected static String idTemplate = "//node[@id = '%s']"; protected static String labelTemplate = "//node[@label = '%s']"; @@ -79,7 +77,6 @@ public class DSpaceControlledVocabulary extends SelfNamedPlugin implements Hiera protected Integer preloadLevel = 1; protected String valueAttribute = labelAttribute; protected String valueTemplate = labelTemplate; - protected String xpathValueTemplate = xpathLabelTemplate; public DSpaceControlledVocabulary() { super(); @@ -140,7 +137,6 @@ protected void init(String locale) { if (storeIDs) { valueAttribute = idAttribute; valueTemplate = idTemplate; - xpathValueTemplate = xpathIdTemplate; } String filename = vocabulariesPath + vocabularyName + ".xml"; @@ -184,7 +180,7 @@ public Choices getMatches(String text, int start, int limit, String locale) { String[] textHierarchy = text.split(hierarchyDelimiter, -1); for (int i = 0; i < textHierarchy.length; i++) { xpathExpression += - String.format(xpathValueTemplate, textHierarchy[i].replaceAll("'", "'").toLowerCase()); + String.format(xpathTemplate, textHierarchy[i].replaceAll("'", "'").toLowerCase()); } XPath xpath = XPathFactory.newInstance().newXPath(); int total = 0; diff --git a/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java b/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java index e7d67600a5fa..a148863ae33e 100644 --- a/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java +++ b/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java @@ -95,15 +95,23 @@ public void testGetMatches() throws IOException, ClassNotFoundException { * @throws java.lang.ClassNotFoundException passed through. */ @Test - public void testGetMatchesIdValue() throws ClassNotFoundException { - System.out.println("getMatchesIdValue"); + public void testGetMatchesIdValueForLabel() throws ClassNotFoundException { + } + + /** + * Test of getMatches method of class + * DSpaceControlledVocabulary using a localized controlled vocabulary with no locale (fallback to default) + * @throws java.lang.ClassNotFoundException passed through. + */ + @Test + public void testGetMatchesNoLocale() throws ClassNotFoundException { final String PLUGIN_INTERFACE = "org.dspace.content.authority.ChoiceAuthority"; String idValue = "DZA"; + String labelPart = "Alge"; int start = 0; int limit = 10; - String locale = null; // This "countries" Controlled Vocab is included in TestEnvironment data // (under /src/test/data/dspaceFolder/) and it should be auto-loaded // by test configs in /src/test/data/dspaceFolder/config/local.cfg @@ -111,26 +119,21 @@ public void testGetMatchesIdValue() throws ClassNotFoundException { CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(Class.forName(PLUGIN_INTERFACE), "countries"); assertNotNull(instance); - Choices result = instance.getMatches(idValue, start, limit, locale); + Choices result = instance.getMatches(labelPart, start, limit, null); assertEquals(idValue, result.values[0].value); + assertEquals("Algeria", result.values[0].label); } /** - * Test of getMatches method of class + * Test of getBestMatch method of class * DSpaceControlledVocabulary using a localized controlled vocabulary with no locale (fallback to default) * @throws java.lang.ClassNotFoundException passed through. */ - @Test - public void testGetMatchesNoLocale() throws ClassNotFoundException { - System.out.println("getMatchesNoLocale"); - + public void testGetBestMatchIdValueNoLocale() throws ClassNotFoundException { final String PLUGIN_INTERFACE = "org.dspace.content.authority.ChoiceAuthority"; String idValue = "DZA"; - int start = 0; - int limit = 10; - String locale = null; // This "countries" Controlled Vocab is included in TestEnvironment data // (under /src/test/data/dspaceFolder/) and it should be auto-loaded // by test configs in /src/test/data/dspaceFolder/config/local.cfg @@ -138,7 +141,8 @@ public void testGetMatchesNoLocale() throws ClassNotFoundException { CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(Class.forName(PLUGIN_INTERFACE), "countries"); assertNotNull(instance); - Choices result = instance.getMatches(idValue, start, limit, locale); + Choices result = instance.getBestMatch(idValue, null); + assertEquals(idValue, result.values[0].value); assertEquals("Algeria", result.values[0].label); } @@ -149,14 +153,12 @@ public void testGetMatchesNoLocale() throws ClassNotFoundException { */ @Test public void testGetMatchesGermanLocale() throws ClassNotFoundException { - System.out.println("getMatchesNoLocale"); - final String PLUGIN_INTERFACE = "org.dspace.content.authority.ChoiceAuthority"; String idValue = "DZA"; + String labelPart = "Alge"; int start = 0; int limit = 10; - String locale = "de"; // This "countries" Controlled Vocab is included in TestEnvironment data // (under /src/test/data/dspaceFolder/) and it should be auto-loaded // by test configs in /src/test/data/dspaceFolder/config/local.cfg @@ -164,7 +166,30 @@ public void testGetMatchesGermanLocale() throws ClassNotFoundException { CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(Class.forName(PLUGIN_INTERFACE), "countries"); assertNotNull(instance); - Choices result = instance.getMatches(idValue, start, limit, locale); + Choices result = instance.getMatches(labelPart, start, limit, "de"); + assertEquals(idValue, result.values[0].value); + assertEquals("Algerien", result.values[0].label); + } + + /** + * Test of getBestMatch method of class + * DSpaceControlledVocabulary using a localized controlled vocabulary with valid locale parameter (localized + * label returned) + */ + @Test + public void testGetBestMatchIdValueGermanLocale() throws ClassNotFoundException { + final String PLUGIN_INTERFACE = "org.dspace.content.authority.ChoiceAuthority"; + + String idValue = "DZA"; + // This "countries" Controlled Vocab is included in TestEnvironment data + // (under /src/test/data/dspaceFolder/) and it should be auto-loaded + // by test configs in /src/test/data/dspaceFolder/config/local.cfg + DSpaceControlledVocabulary instance = (DSpaceControlledVocabulary) + CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(Class.forName(PLUGIN_INTERFACE), + "countries"); + assertNotNull(instance); + Choices result = instance.getBestMatch(idValue, "de"); + assertEquals(idValue, result.values[0].value); assertEquals("Algerien", result.values[0].label); } From 4426bef317058075a8c1c9754f9ec362dd408da0 Mon Sep 17 00:00:00 2001 From: Andreas Mahnke Date: Tue, 19 Mar 2024 14:48:42 +0100 Subject: [PATCH 006/179] Removed empty unused test case --- .../authority/DSpaceControlledVocabularyTest.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java b/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java index a148863ae33e..0ddcfbd18476 100644 --- a/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java +++ b/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java @@ -89,16 +89,6 @@ public void testGetMatches() throws IOException, ClassNotFoundException { assertEquals("north 40", result.values[0].value); } - /** - * Test of getMatches method of class - * DSpaceControlledVocabulary using a controlled vocabulary with configured storage of node id. - * @throws java.lang.ClassNotFoundException passed through. - */ - @Test - public void testGetMatchesIdValueForLabel() throws ClassNotFoundException { - - } - /** * Test of getMatches method of class * DSpaceControlledVocabulary using a localized controlled vocabulary with no locale (fallback to default) From bcf5adc2bf253915f703d4da5bed426e8d124291 Mon Sep 17 00:00:00 2001 From: Andreas Mahnke Date: Wed, 27 Mar 2024 11:21:44 +0100 Subject: [PATCH 007/179] always pass the locale to init, ensuring getChoice works as expected --- .../authority/DSpaceControlledVocabulary.java | 14 +++--- .../DSpaceControlledVocabularyTest.java | 45 +++++++++++++++++++ 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java index 1d3760ba0c0f..3271f440d779 100644 --- a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java +++ b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java @@ -221,19 +221,19 @@ public Choices getBestMatch(String text, String locale) { @Override public String getLabel(String key, String locale) { - return getNodeValue(key, this.suggestHierarchy); + return getNodeValue(key, locale, this.suggestHierarchy); } @Override public String getValue(String key, String locale) { - return getNodeValue(key, this.storeHierarchy); + return getNodeValue(key, locale, this.storeHierarchy); } @Override public Choice getChoice(String authKey, String locale) { Node node; try { - node = getNode(authKey); + node = getNode(authKey, locale); } catch (XPathExpressionException e) { return null; } @@ -284,8 +284,8 @@ private boolean isRootElement(Node node) { return false; } - private Node getNode(String key) throws XPathExpressionException { - init(null); + private Node getNode(String key, String locale) throws XPathExpressionException { + init(locale); String xpathExpression = String.format(idTemplate, key); Node node = getNodeFromXPath(xpathExpression); return node; @@ -333,9 +333,9 @@ private Map addOtherInformation(String parentCurr, String noteCu return extras; } - private String getNodeValue(String key, boolean useHierarchy) { + private String getNodeValue(String key, String locale, boolean useHierarchy) { try { - Node node = getNode(key); + Node node = getNode(key, locale); if (Objects.isNull(node)) { return null; } diff --git a/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java b/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java index 0ddcfbd18476..43bd20cc1553 100644 --- a/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java +++ b/dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java @@ -183,6 +183,51 @@ public void testGetBestMatchIdValueGermanLocale() throws ClassNotFoundException assertEquals("Algerien", result.values[0].label); } + /** + * Test of getChoice method of class + * DSpaceControlledVocabulary using a localized controlled vocabulary with no locale (fallback to default) + * @throws java.lang.ClassNotFoundException passed through. + */ + @Test + public void testGetChoiceNoLocale() throws ClassNotFoundException { + final String PLUGIN_INTERFACE = "org.dspace.content.authority.ChoiceAuthority"; + + String idValue = "DZA"; + // This "countries" Controlled Vocab is included in TestEnvironment data + // (under /src/test/data/dspaceFolder/) and it should be auto-loaded + // by test configs in /src/test/data/dspaceFolder/config/local.cfg + DSpaceControlledVocabulary instance = (DSpaceControlledVocabulary) + CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(Class.forName(PLUGIN_INTERFACE), + "countries"); + assertNotNull(instance); + Choice result = instance.getChoice(idValue, null); + assertEquals(idValue, result.value); + assertEquals("Algeria", result.label); + } + + /** + * Test of getChoice method of class + * DSpaceControlledVocabulary using a localized controlled vocabulary with valid locale parameter (localized + * label returned) + * @throws java.lang.ClassNotFoundException passed through. + */ + @Test + public void testGetChoiceGermanLocale() throws ClassNotFoundException { + final String PLUGIN_INTERFACE = "org.dspace.content.authority.ChoiceAuthority"; + + String idValue = "DZA"; + // This "countries" Controlled Vocab is included in TestEnvironment data + // (under /src/test/data/dspaceFolder/) and it should be auto-loaded + // by test configs in /src/test/data/dspaceFolder/config/local.cfg + DSpaceControlledVocabulary instance = (DSpaceControlledVocabulary) + CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(Class.forName(PLUGIN_INTERFACE), + "countries"); + assertNotNull(instance); + Choice result = instance.getChoice(idValue, "de"); + assertEquals(idValue, result.value); + assertEquals("Algerien", result.label); + } + /** * Test of getBestMatch method, of class DSpaceControlledVocabulary. */ From 6a8c76bbe1e7149785c17c7a7249e319199c3e0a Mon Sep 17 00:00:00 2001 From: Mikhail Schastlivtsev Date: Wed, 15 May 2024 10:08:46 +0300 Subject: [PATCH 008/179] add missing wosPublisherContrib key-ref in wos-integration.xml (#9579) --- dspace/config/spring/api/wos-integration.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dspace/config/spring/api/wos-integration.xml b/dspace/config/spring/api/wos-integration.xml index 17bd53c04a4d..ba90363a2e60 100644 --- a/dspace/config/spring/api/wos-integration.xml +++ b/dspace/config/spring/api/wos-integration.xml @@ -35,6 +35,7 @@ + From 4e541dad5d3f0616b348a82189d2e3d70f48257e Mon Sep 17 00:00:00 2001 From: Andreas Mahnke Date: Fri, 24 May 2024 11:52:32 +0200 Subject: [PATCH 009/179] fixed init call to cover new 'locale' parameter --- .../dspace/content/authority/DSpaceControlledVocabulary.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java index 80ab0b5231b5..4e30559e1c92 100644 --- a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java +++ b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java @@ -244,7 +244,7 @@ public Choice getChoice(String authKey, String locale) { @Override public boolean isHierarchical() { - init(); + init(null); return true; } @@ -277,7 +277,7 @@ public Choice getParentChoice(String authorityName, String childId, String local @Override public Integer getPreloadLevel() { - init(); + init(null); return preloadLevel; } From 3dab2a7cea812420422af160d86371a59b48374f Mon Sep 17 00:00:00 2001 From: Nathan Buckingham Date: Tue, 4 Jun 2024 16:02:53 -0400 Subject: [PATCH 010/179] 110719: Port fix to checkLinks that works on redirects --- .../ctask/general/BasicLinkChecker.java | 14 +++++-- .../impl/TestDSpaceRunnableHandler.java | 39 +++++++++++++++++ .../org/dspace/curate/CurationScriptIT.java | 42 +++++++++++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java index fbc6eebdb5b8..388036bd6744 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/BasicLinkChecker.java @@ -132,10 +132,18 @@ protected int getResponseStatus(String url) { try { URL theURL = new URL(url); HttpURLConnection connection = (HttpURLConnection) theURL.openConnection(); - int code = connection.getResponseCode(); - connection.disconnect(); + connection.setInstanceFollowRedirects(true); + int statusCode = connection.getResponseCode(); + if ((statusCode == HttpURLConnection.HTTP_MOVED_TEMP || statusCode == HttpURLConnection.HTTP_MOVED_PERM || + statusCode == HttpURLConnection.HTTP_SEE_OTHER)) { + connection.disconnect(); + String newUrl = connection.getHeaderField("Location"); + if (newUrl != null) { + return getResponseStatus(newUrl); + } - return code; + } + return statusCode; } catch (IOException ioe) { // Must be a bad URL diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/scripts/handler/impl/TestDSpaceRunnableHandler.java b/dspace-server-webapp/src/test/java/org/dspace/app/scripts/handler/impl/TestDSpaceRunnableHandler.java index 1b5b3fa7ac1a..aced81cbdfdb 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/scripts/handler/impl/TestDSpaceRunnableHandler.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/scripts/handler/impl/TestDSpaceRunnableHandler.java @@ -7,6 +7,9 @@ */ package org.dspace.app.scripts.handler.impl; +import java.util.ArrayList; +import java.util.List; + import org.dspace.scripts.handler.impl.CommandLineDSpaceRunnableHandler; /** @@ -17,6 +20,12 @@ public class TestDSpaceRunnableHandler extends CommandLineDSpaceRunnableHandler private Exception exception = null; + private final List infoMessages = new ArrayList<>(); + + private final List errorMessages = new ArrayList<>(); + + private final List warningMessages = new ArrayList<>(); + /** * We're overriding this method so that we can stop the script from doing the System.exit() if * an exception within the script is thrown @@ -33,4 +42,34 @@ public void handleException(String message, Exception e) { public Exception getException() { return exception; } + + @Override + public void logInfo(String message) { + super.logInfo(message); + infoMessages.add(message); + } + + @Override + public void logWarning(String message) { + super.logWarning(message); + warningMessages.add(message); + } + + @Override + public void logError(String message) { + super.logError(message); + errorMessages.add(message); + } + + public List getInfoMessages() { + return infoMessages; + } + + public List getErrorMessages() { + return errorMessages; + } + + public List getWarningMessages() { + return warningMessages; + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/curate/CurationScriptIT.java b/dspace-server-webapp/src/test/java/org/dspace/curate/CurationScriptIT.java index 3e40a8559482..6bb9acb92482 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/curate/CurationScriptIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/curate/CurationScriptIT.java @@ -9,6 +9,7 @@ import static com.jayway.jsonpath.JsonPath.read; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -21,6 +22,7 @@ import java.util.stream.Collectors; import com.fasterxml.jackson.databind.ObjectMapper; +import org.dspace.app.launcher.ScriptLauncher; import org.dspace.app.rest.converter.DSpaceRunnableParameterConverter; import org.dspace.app.rest.matcher.ProcessMatcher; import org.dspace.app.rest.model.ParameterValueRest; @@ -28,6 +30,7 @@ import org.dspace.app.rest.model.ScriptRest; import org.dspace.app.rest.projection.Projection; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.EPersonBuilder; @@ -41,7 +44,9 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.eperson.EPerson; import org.dspace.scripts.DSpaceCommandLineParameter; +import org.dspace.scripts.DSpaceRunnable; import org.dspace.scripts.configuration.ScriptConfiguration; +import org.dspace.scripts.factory.ScriptServiceFactory; import org.dspace.scripts.service.ScriptService; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -640,4 +645,41 @@ public void securityCurateTest() throws Exception { ProcessBuilder.deleteProcess(idItemRef.get()); } } + + @Test + public void testURLRedirectCurateTest() throws Exception { + context.turnOffAuthorisationSystem(); + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + + Item publicItem1 = ItemBuilder.createItem(context, col1) + .withTitle("Public item 1") + .withIssueDate("2017-10-17") + .withAuthor("Smith, Donald").withAuthor("Doe, John") + .withMetadata("dc", "identifier", "uri", "https://tinyurl.com/2rxpte5s") + .withSubject("ExtraEntry") + .build(); + + String[] args = new String[] {"curate", "-t", "checklinks", "-i", publicItem1.getHandle()}; + TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); + + ScriptService scriptService = ScriptServiceFactory.getInstance().getScriptService(); + ScriptConfiguration scriptConfiguration = scriptService.getScriptConfiguration(args[0]); + + DSpaceRunnable script = null; + if (scriptConfiguration != null) { + script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration); + } + if (script != null) { + script.initialize(args, testDSpaceRunnableHandler, admin); + script.run(); + } + + assertTrue(testDSpaceRunnableHandler.getInfoMessages().contains("200 - OK")); + } } From e826660cb0bd926de390e04e466d54ceedb67a1e Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Thu, 13 Jun 2024 20:48:31 +0200 Subject: [PATCH 011/179] 110719: IT checking redirect links accepted by checklinks curate task --- .../org/dspace/curate/CurationScriptIT.java | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/curate/CurationScriptIT.java b/dspace-server-webapp/src/test/java/org/dspace/curate/CurationScriptIT.java index 6bb9acb92482..8c0744a09cce 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/curate/CurationScriptIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/curate/CurationScriptIT.java @@ -9,6 +9,7 @@ import static com.jayway.jsonpath.JsonPath.read; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; @@ -22,7 +23,7 @@ import java.util.stream.Collectors; import com.fasterxml.jackson.databind.ObjectMapper; -import org.dspace.app.launcher.ScriptLauncher; +import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.converter.DSpaceRunnableParameterConverter; import org.dspace.app.rest.matcher.ProcessMatcher; import org.dspace.app.rest.model.ParameterValueRest; @@ -661,12 +662,19 @@ public void testURLRedirectCurateTest() throws Exception { .withTitle("Public item 1") .withIssueDate("2017-10-17") .withAuthor("Smith, Donald").withAuthor("Doe, John") - .withMetadata("dc", "identifier", "uri", "https://tinyurl.com/2rxpte5s") + // Value not starting with http or https + .withMetadata("dc", "identifier", "uri", "demo.dspace.org/home") + // MetadataValueLinkChecker uri field with regular link + .withMetadata("dc", "description", null, "https://google.com") + // MetadataValueLinkChecker uri field with redirect link + .withMetadata("dc", "description", "uri", "https://demo7.dspace.org/handle/123456789/1") + // MetadataValueLinkChecker uri field with non resolving link + .withMetadata("dc", "description", "uri", "https://www.atmire.com/broken-link") .withSubject("ExtraEntry") .build(); String[] args = new String[] {"curate", "-t", "checklinks", "-i", publicItem1.getHandle()}; - TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); + TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); ScriptService scriptService = ScriptServiceFactory.getInstance().getScriptService(); ScriptConfiguration scriptConfiguration = scriptService.getScriptConfiguration(args[0]); @@ -676,10 +684,27 @@ public void testURLRedirectCurateTest() throws Exception { script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration); } if (script != null) { - script.initialize(args, testDSpaceRunnableHandler, admin); + script.initialize(args, handler, admin); script.run(); } - assertTrue(testDSpaceRunnableHandler.getInfoMessages().contains("200 - OK")); + // field that should be ignored + assertFalse(checkIfInfoTextLoggedByHandler(handler, "demo.dspace.org/home")); + // redirect links in field that should not be ignored (https) => expect OK + assertTrue(checkIfInfoTextLoggedByHandler(handler, "https://demo7.dspace.org/handle/123456789/1 = 200 - OK")); + // regular link in field that should not be ignored (http) => expect OK + assertTrue(checkIfInfoTextLoggedByHandler(handler, "https://google.com = 200 - OK")); + // nonexistent link in field that should not be ignored => expect 404 + assertTrue(checkIfInfoTextLoggedByHandler(handler, "https://www.atmire.com/broken-link = 404 - FAILED")); } + + boolean checkIfInfoTextLoggedByHandler(TestDSpaceRunnableHandler handler, String text) { + for (String message: handler.getInfoMessages()) { + if (StringUtils.containsIgnoreCase(message, text)) { + return true; + } + } + return false; + } + } From cde892c8c7e1df8fff70a4cbfc693f378c2065d2 Mon Sep 17 00:00:00 2001 From: Mikhail Schastlivtsev Date: Mon, 17 Jun 2024 14:06:53 +0300 Subject: [PATCH 012/179] add missing publisher metadatum in test (#9579) --- .../org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java index f1d3f5303ec0..9f68d79c2036 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java @@ -136,6 +136,7 @@ private ArrayList getRecords() { MetadatumDTO subject15 = createMetadatumDTO("dc", "subject", null, "Coding concepts"); MetadatumDTO subject16 = createMetadatumDTO("dc", "subject", null, "Lesson design"); MetadatumDTO subject17 = createMetadatumDTO("dc", "subject", null, "Social Sciences"); + MetadatumDTO publisher = createMetadatumDTO("dc", "publisher", null, "SPRINGER"); MetadatumDTO other = createMetadatumDTO("dc", "identifier", "other", "WOS:000805105200003"); metadatums.add(edition); metadatums.add(date); @@ -166,6 +167,7 @@ private ArrayList getRecords() { metadatums.add(subject15); metadatums.add(subject16); metadatums.add(subject17); + metadatums.add(publisher); metadatums.add(other); ImportRecord firstrRecord = new ImportRecord(metadatums); @@ -205,6 +207,7 @@ private ArrayList getRecords() { MetadatumDTO subject26 = createMetadatumDTO("dc", "subject", null, "Social Sciences"); MetadatumDTO subject27 = createMetadatumDTO("dc", "subject", null, "Science & Technology"); MetadatumDTO subject28 = createMetadatumDTO("dc", "subject", null, "Life Sciences & Biomedicine"); + MetadatumDTO publisher2 = createMetadatumDTO("dc", "publisher", null, "NATURE PORTFOLIO"); MetadatumDTO other2 = createMetadatumDTO("dc", "identifier", "other", "WOS:000805100600001"); MetadatumDTO rid = createMetadatumDTO("person", "identifier", "rid", "C-6334-2011"); MetadatumDTO rid2 = createMetadatumDTO("person", "identifier", "rid", "B-1251-2008"); @@ -236,6 +239,7 @@ private ArrayList getRecords() { metadatums2.add(subject26); metadatums2.add(subject27); metadatums2.add(subject28); + metadatums2.add(publisher2); metadatums2.add(other2); metadatums2.add(rid); metadatums2.add(rid2); From 428489ca5258ea7ac6942a722621e22c3371bfcf Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 3 Jul 2024 13:23:32 +0200 Subject: [PATCH 013/179] update eperson's attributes right after successful login --- .../authenticate/LDAPAuthentication.java | 69 +++++++++++-------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index b791df15b5c0..c6df4b30faad 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -68,12 +68,8 @@ * @author Ivan Masár * @author Michael Plate */ -public class LDAPAuthentication - implements AuthenticationMethod { +public class LDAPAuthentication implements AuthenticationMethod { - /** - * log4j category - */ private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(LDAPAuthentication.class); @@ -130,7 +126,7 @@ public boolean allowSetPassword(Context context, return false; } - /* + /** * This is an explicit method. */ @Override @@ -138,7 +134,7 @@ public boolean isImplicit() { return false; } - /* + /** * Add authenticated users to the group defined in dspace.cfg by * the login.specialgroup key. */ @@ -177,7 +173,7 @@ public List getSpecialGroups(Context context, HttpServletRequest request) return Collections.EMPTY_LIST; } - /* + /** * Authenticate the given credentials. * This is the heart of the authentication method: test the * credentials for authenticity, and if accepted, attempt to match @@ -250,7 +246,7 @@ public int authenticate(Context context, } // Check a DN was found - if ((dn == null) || (dn.trim().equals(""))) { + if (StringUtils.isBlank(dn)) { log.info(LogHelper .getHeader(context, "failed_login", "no DN found for user " + netid)); return BAD_CREDENTIALS; @@ -269,6 +265,18 @@ public int authenticate(Context context, context.setCurrentUser(eperson); request.setAttribute(LDAP_AUTHENTICATED, true); + // update eperson's attributes + context.turnOffAuthorisationSystem(); + setEpersonAttributes(context, eperson, ldap, Optional.empty()); + try { + ePersonService.update(context, eperson); + context.dispatchEvents(); + } catch (AuthorizeException e) { + log.warn("update of eperson " + eperson.getID() + " failed", e); + } finally { + context.restoreAuthSystemState(); + } + // assign user to groups based on ldap dn assignGroups(dn, ldap.ldapGroup, context); @@ -313,14 +321,13 @@ public int authenticate(Context context, log.info(LogHelper.getHeader(context, "type=ldap-login", "type=ldap_but_already_email")); context.turnOffAuthorisationSystem(); - eperson.setNetid(netid.toLowerCase()); + setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); ePersonService.update(context, eperson); context.dispatchEvents(); context.restoreAuthSystemState(); context.setCurrentUser(eperson); request.setAttribute(LDAP_AUTHENTICATED, true); - // assign user to groups based on ldap dn assignGroups(dn, ldap.ldapGroup, context); @@ -331,20 +338,7 @@ public int authenticate(Context context, try { context.turnOffAuthorisationSystem(); eperson = ePersonService.create(context); - if (StringUtils.isNotEmpty(email)) { - eperson.setEmail(email); - } - if (StringUtils.isNotEmpty(ldap.ldapGivenName)) { - eperson.setFirstName(context, ldap.ldapGivenName); - } - if (StringUtils.isNotEmpty(ldap.ldapSurname)) { - eperson.setLastName(context, ldap.ldapSurname); - } - if (StringUtils.isNotEmpty(ldap.ldapPhone)) { - ePersonService.setMetadataSingleValue(context, eperson, - MD_PHONE, ldap.ldapPhone, null); - } - eperson.setNetid(netid.toLowerCase()); + setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); eperson.setCanLogIn(true); authenticationService.initEPerson(context, request, eperson); ePersonService.update(context, eperson); @@ -382,6 +376,27 @@ public int authenticate(Context context, return BAD_ARGS; } + /** + * Update eperson's attributes + */ + private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDAP ldap, Optional netid) throws SQLException { + if (StringUtils.isNotEmpty(ldap.ldapEmail)) { + eperson.setEmail(ldap.ldapEmail); + } + if (StringUtils.isNotEmpty(ldap.ldapGivenName)) { + eperson.setFirstName(context, ldap.ldapGivenName); + } + if (StringUtils.isNotEmpty(ldap.ldapSurname)) { + eperson.setLastName(context, ldap.ldapSurname); + } + if (StringUtils.isNotEmpty(ldap.ldapPhone)) { + ePersonService.setMetadataSingleValue(context, eperson, MD_PHONE, ldap.ldapPhone, null); + } + if (netid.isPresent()) { + eperson.setNetid(netid.get().toLowerCase()); + } + } + /** * Internal class to manage LDAP query and results, mainly * because there are multiple values to return. @@ -671,7 +686,7 @@ protected boolean ldapAuthenticate(String netid, String password, } } - /* + /** * Returns the URL of an external login page which is not applicable for this authn method. * * Note: Prior to DSpace 7, this method return the page of login servlet. @@ -699,7 +714,7 @@ public String getName() { return "ldap"; } - /* + /** * Add authenticated users to the group defined in dspace.cfg by * the authentication-ldap.login.groupmap.* key. * From c5ad32a9b3ece7e64043f9f39d22b594e913737f Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 3 Jul 2024 13:36:45 +0200 Subject: [PATCH 014/179] add missing import --- .../main/java/org/dspace/authenticate/LDAPAuthentication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index c6df4b30faad..9ca5245c54ba 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -17,6 +17,7 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Optional; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; From aaa74b88c99af8ece67d43fa412a39a7406fe10c Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 3 Jul 2024 13:54:53 +0200 Subject: [PATCH 015/179] fix Checkstyle violations --- .../org/dspace/authenticate/LDAPAuthentication.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index 9ca5245c54ba..4f2c5cc3d02c 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -184,7 +184,7 @@ public List getSpecialGroups(Context context, HttpServletRequest request) * @param context * DSpace context, will be modified (ePerson set) upon success. * - * @param username + * @param netid * Username (or email address) when method is explicit. Use null for * implicit method. * @@ -322,7 +322,7 @@ public int authenticate(Context context, log.info(LogHelper.getHeader(context, "type=ldap-login", "type=ldap_but_already_email")); context.turnOffAuthorisationSystem(); - setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); + setEpersonAttributes(context, eperson, ldap, Optional.of(netid)); ePersonService.update(context, eperson); context.dispatchEvents(); context.restoreAuthSystemState(); @@ -380,7 +380,9 @@ public int authenticate(Context context, /** * Update eperson's attributes */ - private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDAP ldap, Optional netid) throws SQLException { + private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDAP ldap, Optional netid) + throws SQLException { + if (StringUtils.isNotEmpty(ldap.ldapEmail)) { eperson.setEmail(ldap.ldapEmail); } @@ -389,7 +391,7 @@ private void setEpersonAttributes(Context context, EPerson eperson, SpeakerToLDA } if (StringUtils.isNotEmpty(ldap.ldapSurname)) { eperson.setLastName(context, ldap.ldapSurname); - } + } if (StringUtils.isNotEmpty(ldap.ldapPhone)) { ePersonService.setMetadataSingleValue(context, eperson, MD_PHONE, ldap.ldapPhone, null); } From 3d1bef9d0e3fe820da9705427c129b5cb49d66fb Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 16:58:00 +0200 Subject: [PATCH 016/179] put DOIs in dc.identifier.doi --- dspace/config/spring/api/scopus-integration.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/config/spring/api/scopus-integration.xml b/dspace/config/spring/api/scopus-integration.xml index 47c5a4fbb900..6f7556574d09 100644 --- a/dspace/config/spring/api/scopus-integration.xml +++ b/dspace/config/spring/api/scopus-integration.xml @@ -128,7 +128,7 @@ - + @@ -264,4 +264,4 @@ - \ No newline at end of file + From 2eff833fab361d4ed3c7b602b681823911f989af Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 17:37:07 +0200 Subject: [PATCH 017/179] fix broken test --- .../dspace/app/rest/ScopusImportMetadataSourceServiceIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java index 7f6cb53ce400..e81f662ad5a9 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java @@ -124,7 +124,7 @@ private ArrayList getRecords() { ArrayList records = new ArrayList<>(); //define first record List metadatums = new ArrayList(); - MetadatumDTO doi = createMetadatumDTO("dc", "identifier", null, "10.3934/mine.2023004"); + MetadatumDTO doi = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023004"); MetadatumDTO title = createMetadatumDTO("dc","title", null, "Hardy potential versus lower order terms in Dirichlet problems: regularizing effects"); MetadatumDTO type = createMetadatumDTO("dc", "type", null, "Journal"); @@ -171,7 +171,7 @@ private ArrayList getRecords() { //define second record List metadatums2 = new ArrayList(); - MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", null, "10.3934/mine.2023001"); + MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023001"); MetadatumDTO title2 = createMetadatumDTO("dc","title", null, "Large deviations for a binary collision model: energy evaporation"); MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2023-01-01"); From d80f49e0238981c22703abbb1423aa2896eca694 Mon Sep 17 00:00:00 2001 From: Nona Luypaert Date: Tue, 23 Jul 2024 18:28:43 +0200 Subject: [PATCH 018/179] 116609: Improve running process observability - keep temp process log files in [dspace]/log/processes/ instead of temp dir - reformat file names of process logs - ensure that running and scheduled processes are cleaned up during startup --- .../dspace/scripts/ProcessServiceImpl.java | 56 +++++++++++++++---- .../app/rest/ProcessRestRepositoryIT.java | 8 +-- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java index 2e14aeaa36c0..63751d87e92a 100644 --- a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java @@ -45,14 +45,15 @@ import org.dspace.core.LogHelper; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; -import org.dspace.eperson.service.EPersonService; import org.dspace.scripts.service.ProcessService; +import org.dspace.services.ConfigurationService; +import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; /** * The implementation for the {@link ProcessService} class */ -public class ProcessServiceImpl implements ProcessService { +public class ProcessServiceImpl implements ProcessService, InitializingBean { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(ProcessService.class); @@ -72,7 +73,26 @@ public class ProcessServiceImpl implements ProcessService { private MetadataFieldService metadataFieldService; @Autowired - private EPersonService ePersonService; + private ConfigurationService configurationService; + + @Override + public void afterPropertiesSet() throws Exception { + Context context = new Context(); + + // Processes that were running or scheduled when tomcat crashed, should be cleaned up during startup. + List processesToBeFailed = findByStatusAndCreationTimeOlderThan( + context, List.of(ProcessStatus.RUNNING, ProcessStatus.SCHEDULED), new Date()); + for (Process process : processesToBeFailed) { + context.setCurrentUser(process.getEPerson()); + // Fail the process. + log.info("Process with ID {} did not complete before tomcat shutdown, failing it now.", process.getID()); + fail(context, process); + // But still attach its log to the process. + createLogBitstream(context, process); + } + + context.complete(); + } @Override public Process create(Context context, EPerson ePerson, String scriptName, @@ -286,8 +306,8 @@ public int countSearch(Context context, ProcessQueryParameterContainer processQu @Override public void appendLog(int processId, String scriptName, String output, ProcessLogLevel processLogLevel) throws IOException { - File tmpDir = FileUtils.getTempDirectory(); - File tempFile = new File(tmpDir, scriptName + processId + ".log"); + File logsDir = getLogsDirectory(); + File tempFile = new File(logsDir, processId + "-" + scriptName + ".log"); FileWriter out = new FileWriter(tempFile, true); try { try (BufferedWriter writer = new BufferedWriter(out)) { @@ -302,12 +322,15 @@ public void appendLog(int processId, String scriptName, String output, ProcessLo @Override public void createLogBitstream(Context context, Process process) throws IOException, SQLException, AuthorizeException { - File tmpDir = FileUtils.getTempDirectory(); - File tempFile = new File(tmpDir, process.getName() + process.getID() + ".log"); - FileInputStream inputStream = FileUtils.openInputStream(tempFile); - appendFile(context, process, inputStream, Process.OUTPUT_TYPE, process.getName() + process.getID() + ".log"); - inputStream.close(); - tempFile.delete(); + File logsDir = getLogsDirectory(); + File tempFile = new File(logsDir, process.getID() + "-" + process.getName() + ".log"); + if (tempFile.exists()) { + FileInputStream inputStream = FileUtils.openInputStream(tempFile); + appendFile(context, process, inputStream, Process.OUTPUT_TYPE, + process.getID() + "-" + process.getName() + ".log"); + inputStream.close(); + tempFile.delete(); + } } @Override @@ -336,4 +359,15 @@ private String formatLogLine(int processId, String scriptName, String output, Pr return sb.toString(); } + private File getLogsDirectory() { + String pathStr = configurationService.getProperty("dspace.dir") + + File.separator + "log" + File.separator + "processes"; + File logsDir = new File(pathStr); + if (!logsDir.exists()) { + if (!logsDir.mkdirs()) { + throw new RuntimeException("Couldn't create [dspace.dir]/log/processes/ directory."); + } + } + return logsDir; + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProcessRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProcessRestRepositoryIT.java index 670d8e2f35b0..6c018df6d070 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProcessRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProcessRestRepositoryIT.java @@ -856,10 +856,10 @@ public void getProcessOutput() throws Exception { getClient(token).perform(get("/api/system/processes/" + process1.getID() + "/output")) .andExpect(status().isOk()) .andExpect(jsonPath("$.name", - is(process1.getName() + process1.getID() + ".log"))) + is(process1.getID() + "-" + process1.getName() + ".log"))) .andExpect(jsonPath("$.type", is("bitstream"))) .andExpect(jsonPath("$.metadata['dc.title'][0].value", - is(process1.getName() + process1.getID() + ".log"))) + is(process1.getID() + "-" + process1.getName() + ".log"))) .andExpect(jsonPath("$.metadata['dspace.process.filetype'][0].value", is("script_output"))); @@ -869,10 +869,10 @@ public void getProcessOutput() throws Exception { .perform(get("/api/system/processes/" + process1.getID() + "/output")) .andExpect(status().isOk()) .andExpect(jsonPath("$.name", - is(process1.getName() + process1.getID() + ".log"))) + is(process1.getID() + "-" + process1.getName() + ".log"))) .andExpect(jsonPath("$.type", is("bitstream"))) .andExpect(jsonPath("$.metadata['dc.title'][0].value", - is(process1.getName() + process1.getID() + ".log"))) + is(process1.getID() + "-" + process1.getName() + ".log"))) .andExpect(jsonPath("$.metadata['dspace.process.filetype'][0].value", is("script_output"))); From 156ad471b575dfc1c2b643ec4b2f677d6f89a314 Mon Sep 17 00:00:00 2001 From: Nona Luypaert Date: Thu, 25 Jul 2024 09:33:50 +0200 Subject: [PATCH 019/179] 116609: Add tomcat shutdown line to process log --- .../src/main/java/org/dspace/scripts/ProcessServiceImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java index 63751d87e92a..2f34fac65833 100644 --- a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java @@ -88,6 +88,9 @@ public void afterPropertiesSet() throws Exception { log.info("Process with ID {} did not complete before tomcat shutdown, failing it now.", process.getID()); fail(context, process); // But still attach its log to the process. + appendLog(process.getID(), process.getName(), + "Process did not complete before tomcat shutdown.", + ProcessLogLevel.ERROR); createLogBitstream(context, process); } From 3122f2cac80f52febc4c03107ab147b5bb474de6 Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Wed, 24 Jul 2024 19:07:44 +0200 Subject: [PATCH 020/179] [CST-14905] Orcid revoke token feature --- .../org/dspace/orcid/client/OrcidClient.java | 8 + .../dspace/orcid/client/OrcidClientImpl.java | 37 +++ .../orcid/client/OrcidConfiguration.java | 9 + .../impl/OrcidSynchronizationServiceImpl.java | 39 +++- .../ResearcherProfileRestRepositoryIT.java | 216 ++++++++++++++++-- dspace/config/modules/orcid.cfg | 1 + dspace/config/spring/api/orcid-services.xml | 1 + 7 files changed, 284 insertions(+), 27 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java index 99d1920aa53a..d21f61a922f5 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClient.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Optional; +import org.dspace.orcid.OrcidToken; import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidTokenResponseDTO; import org.orcid.jaxb.model.v3.release.record.Person; @@ -161,4 +162,11 @@ public interface OrcidClient { */ OrcidResponse deleteByPutCode(String accessToken, String orcid, String putCode, String path); + /** + * Revokes the given {@param accessToken} with a POST method. + * @param orcidToken the access token to revoke + * @throws OrcidClientException if some error occurs during the search + */ + void revokeToken(OrcidToken orcidToken); + } diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java index 8356167692e3..6c2a1512980c 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidClientImpl.java @@ -42,6 +42,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicNameValuePair; +import org.dspace.orcid.OrcidToken; import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidEntityType; import org.dspace.orcid.model.OrcidProfileSectionType; @@ -178,6 +179,16 @@ public OrcidResponse deleteByPutCode(String accessToken, String orcid, String pu return execute(buildDeleteUriRequest(accessToken, "/" + orcid + path + "/" + putCode), true); } + @Override + public void revokeToken(OrcidToken orcidToken) { + List params = new ArrayList<>(); + params.add(new BasicNameValuePair("client_id", orcidConfiguration.getClientId())); + params.add(new BasicNameValuePair("client_secret", orcidConfiguration.getClientSecret())); + params.add(new BasicNameValuePair("token", orcidToken.getAccessToken())); + + executeSuccessful(buildPostForRevokeToken(new UrlEncodedFormEntity(params, Charset.defaultCharset()))); + } + @Override public OrcidTokenResponseDTO getReadPublicAccessToken() { return getClientCredentialsAccessToken("/read-public"); @@ -220,6 +231,14 @@ private HttpUriRequest buildPostUriRequest(String accessToken, String relativePa .build(); } + private HttpUriRequest buildPostForRevokeToken(HttpEntity entity) { + return post(orcidConfiguration.getRevokeUrl()) + .addHeader("Accept", "application/json") + .addHeader("Content-Type", "application/x-www-form-urlencoded") + .setEntity(entity) + .build(); + } + private HttpUriRequest buildPutUriRequest(String accessToken, String relativePath, Object object) { return put(orcidConfiguration.getApiUrl() + relativePath.trim()) .addHeader("Content-Type", "application/vnd.orcid+xml") @@ -234,6 +253,24 @@ private HttpUriRequest buildDeleteUriRequest(String accessToken, String relative .build(); } + private void executeSuccessful(HttpUriRequest httpUriRequest) { + try { + HttpClient client = HttpClientBuilder.create().build(); + HttpResponse response = client.execute(httpUriRequest); + + if (isNotSuccessfull(response)) { + throw new OrcidClientException( + getStatusCode(response), + "Operation " + httpUriRequest.getMethod() + " for the resource " + httpUriRequest.getURI() + + " was not successful: " + new String(response.getEntity().getContent().readAllBytes(), + StandardCharsets.UTF_8) + ); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + private T executeAndParseJson(HttpUriRequest httpUriRequest, Class clazz) { HttpClient client = HttpClientBuilder.create().build(); diff --git a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java index 550b0215c435..dfa90fcae03a 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/orcid/client/OrcidConfiguration.java @@ -35,6 +35,8 @@ public final class OrcidConfiguration { private String scopes; + private String revokeUrl; + public String getApiUrl() { return apiUrl; } @@ -111,4 +113,11 @@ public boolean isApiConfigured() { return !StringUtils.isAnyBlank(clientId, clientSecret); } + public String getRevokeUrl() { + return revokeUrl; + } + + public void setRevokeUrl(String revokeUrl) { + this.revokeUrl = revokeUrl; + } } diff --git a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java index 59e4dea64145..f976864d07f9 100644 --- a/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/orcid/service/impl/OrcidSynchronizationServiceImpl.java @@ -37,6 +37,7 @@ import org.dspace.eperson.EPerson; import org.dspace.eperson.service.EPersonService; import org.dspace.orcid.OrcidToken; +import org.dspace.orcid.client.OrcidClient; import org.dspace.orcid.model.OrcidEntityType; import org.dspace.orcid.model.OrcidTokenResponseDTO; import org.dspace.orcid.service.OrcidSynchronizationService; @@ -47,6 +48,8 @@ import org.dspace.profile.OrcidSynchronizationMode; import org.dspace.profile.service.ResearcherProfileService; import org.dspace.services.ConfigurationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; /** @@ -57,6 +60,7 @@ */ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationService { + private static final Logger log = LoggerFactory.getLogger(OrcidSynchronizationServiceImpl.class); @Autowired private ItemService itemService; @@ -75,6 +79,9 @@ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationServ @Autowired private ResearcherProfileService researcherProfileService; + @Autowired + private OrcidClient orcidClient; + @Override public void linkProfile(Context context, Item profile, OrcidTokenResponseDTO token) throws SQLException { @@ -114,20 +121,33 @@ public void linkProfile(Context context, Item profile, OrcidTokenResponseDTO tok @Override public void unlinkProfile(Context context, Item profile) throws SQLException { - itemService.clearMetadata(context, profile, "person", "identifier", "orcid", Item.ANY); - itemService.clearMetadata(context, profile, "dspace", "orcid", "scope", Item.ANY); - itemService.clearMetadata(context, profile, "dspace", "orcid", "authenticated", Item.ANY); + clearOrcidProfileMetadata(context, profile); - if (!configurationService.getBooleanProperty("orcid.disconnection.remain-sync", false)) { - clearSynchronizationSettings(context, profile); - } + clearSynchronizationSettings(context, profile); - orcidTokenService.deleteByProfileItem(context, profile); + clearOrcidToken(context, profile); updateItem(context, profile); } + private void clearOrcidToken(Context context, Item profile) { + OrcidToken profileToken = orcidTokenService.findByProfileItem(context, profile); + if (profileToken == null) { + log.warn("Cannot find any token related to the user profile: {}", profile.getID()); + return; + } + + orcidTokenService.deleteByProfileItem(context, profile); + orcidClient.revokeToken(profileToken); + } + + private void clearOrcidProfileMetadata(Context context, Item profile) throws SQLException { + itemService.clearMetadata(context, profile, "person", "identifier", "orcid", Item.ANY); + itemService.clearMetadata(context, profile, "dspace", "orcid", "scope", Item.ANY); + itemService.clearMetadata(context, profile, "dspace", "orcid", "authenticated", Item.ANY); + } + @Override public boolean setEntityPreference(Context context, Item profile, OrcidEntityType type, OrcidEntitySyncPreference value) throws SQLException { @@ -273,6 +293,11 @@ private boolean updatePreferenceForSynchronizingWithOrcid(Context context, Item private void clearSynchronizationSettings(Context context, Item profile) throws SQLException { + + if (configurationService.getBooleanProperty("orcid.disconnection.remain-sync", false)) { + return; + } + itemService.clearMetadata(context, profile, "dspace", "orcid", "sync-mode", Item.ANY); itemService.clearMetadata(context, profile, "dspace", "orcid", "sync-profile", Item.ANY); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java index b3c70f8128d4..493b3bf94628 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java @@ -31,7 +31,10 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -45,6 +48,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; import java.sql.SQLException; import java.util.List; import java.util.UUID; @@ -80,11 +84,13 @@ import org.dspace.orcid.exception.OrcidClientException; import org.dspace.orcid.model.OrcidTokenResponseDTO; import org.dspace.orcid.service.OrcidQueueService; +import org.dspace.orcid.service.OrcidSynchronizationService; import org.dspace.orcid.service.OrcidTokenService; import org.dspace.services.ConfigurationService; import org.dspace.util.UUIDUtils; import org.junit.After; import org.junit.Test; +import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MvcResult; @@ -115,7 +121,11 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra @Autowired private OrcidClient orcidClient; - private OrcidClient orcidClientMock = mock(OrcidClient.class); + @Mock + private OrcidClient orcidClientMock; + + @Autowired + private OrcidSynchronizationService orcidSynchronizationService; private EPerson user; @@ -159,16 +169,36 @@ public void setUp() throws Exception { context.restoreAuthSystemState(); - researcherProfileAddOrcidOperation.setOrcidClient(orcidClientMock); - + useInstanceForBean(orcidSynchronizationService, orcidClientMock); + useInstanceForBean(researcherProfileAddOrcidOperation, orcidClientMock); } @After public void after() { orcidTokenService.deleteAll(context); - researcherProfileAddOrcidOperation.setOrcidClient(orcidClient); + useInstanceForBean(orcidSynchronizationService, orcidClient); + useInstanceForBean(researcherProfileAddOrcidOperation, orcidClient); } + private void useInstanceForBean(B bean, I instance) { + Field[] fields = bean.getClass().getDeclaredFields(); + + for (Field field : fields) { + if (field.getType().isAssignableFrom(instance.getClass())) { + boolean accessible = field.isAccessible(); + try { + field.setAccessible(true); + field.set(bean, instance); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } finally { + field.setAccessible(accessible); + } + } + } + } + + /** * Verify that the findById endpoint returns the own profile. * @@ -609,30 +639,38 @@ public void testDeleteWithProfileLinkedWithOrcid() throws Exception { .withOrcidAuthenticated("authenticated") .build(); + context.restoreAuthSystemState(); + String id = user.getID().toString(); String authToken = getAuthToken(user.getEmail(), password); + OrcidToken orcidToken = orcidTokenService.findByProfileItem(context, profileItem); - context.restoreAuthSystemState(); - - getClient(authToken).perform(get("/api/eperson/profiles/{id}", id)) + getClient(authToken) + .perform(get("/api/eperson/profiles/{id}", id)) .andExpect(status().isOk()); assertThat(profileItem.getMetadata(), hasItem(with("person.identifier.orcid", "0000-1111-2222-3333"))); assertThat(profileItem.getMetadata(), hasItem(with("dspace.orcid.authenticated", "authenticated"))); - assertThat(getOrcidAccessToken(profileItem), notNullValue()); + assertThat(orcidToken.getAccessToken(), notNullValue()); getClient(authToken).perform(get("/api/eperson/profiles/{id}/item", id)) .andExpect(status().isOk()) .andExpect(jsonPath("$", hasJsonPath("$.metadata", matchMetadataNotEmpty("dspace.object.owner")))); + getClient(authToken).perform(delete("/api/eperson/profiles/{id}", id)) .andExpect(status().isNoContent()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profileItem = context.reloadEntity(profileItem); + orcidToken = orcidTokenService.findByProfileItem(context, profileItem); + assertThat(profileItem.getMetadata(), not(hasItem(with("person.identifier.orcid", "0000-1111-2222-3333")))); assertThat(profileItem.getMetadata(), not(hasItem(with("dspace.orcid.authenticated", "authenticated")))); - assertThat(getOrcidAccessToken(profileItem), nullValue()); + assertThat(orcidToken, nullValue()); } @@ -1851,7 +1889,60 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + + Item profile = createProfile(ePerson); + + context.restoreAuthSystemState(); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); + assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); + + getClient(getAuthToken(ePerson.getEmail(), password)) + .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) + .content(getPatchContent(asList(new RemoveOperation("/orcid")))) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(ePerson.getID().toString()))) + .andExpect(jsonPath("$.visible", is(false))) + .andExpect(jsonPath("$.type", is("profile"))) + .andExpect(jsonPath("$.orcid").doesNotExist()) + .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + + verify(orcidClientMock, times(1)) + .revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + + profile = context.reloadEntity(profile); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), empty()); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), empty()); + assertThat(getOrcidAccessToken(profile), nullValue()); + } + + @Test + public void testPatchToDisconnectProfileFromOrcidRevokesOrcidToken() throws Exception { + + configurationService.setProperty("orcid.disconnection.allowed-users", "admin_and_owner"); + + context.turnOffAuthorisationSystem(); + + EPerson ePerson = EPersonBuilder.createEPerson(context) + .withCanLogin(true) + .withOrcid("0000-1111-2222-3333") + .withOrcidScope("/read") + .withOrcidScope("/write") + .withEmail("test@email.it") + .withPassword(password) + .withNameInMetadata("Test", "User") + .build(); + + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -1873,6 +1964,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -1881,6 +1975,54 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration assertThat(getOrcidAccessToken(profile), nullValue()); } + @Test + public void testPatchToDisconnectProfileFromOrcidDoesntRevokeOrcidToken() throws Exception { + + configurationService.setProperty("orcid.disconnection.allowed-users", "admin_and_owner"); + + context.turnOffAuthorisationSystem(); + + EPerson ePerson = EPersonBuilder.createEPerson(context) + .withCanLogin(true) + .withOrcid("0000-1111-2222-3333") + .withOrcidScope("/read") + .withOrcidScope("/write") + .withEmail("test@email.it") + .withPassword(password) + .withNameInMetadata("Test", "User") + .build(); + + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + + Item profile = createProfile(ePerson); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); + assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); + + context.restoreAuthSystemState(); + + doThrow(new OrcidClientException(403, "")).when(orcidClientMock).revokeToken(any(OrcidToken.class)); + + getClient(getAuthToken(ePerson.getEmail(), password)) + .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) + .content(getPatchContent(asList(new RemoveOperation("/orcid")))) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isInternalServerError()); + + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + + profile = context.reloadEntity(profile); + + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); + assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); + assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); + } + @Test public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration() throws Exception { @@ -2024,7 +2166,8 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyAdminConfiguration .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -2035,6 +2178,7 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyAdminConfiguration context.restoreAuthSystemState(); + getClient(getAuthToken(admin.getEmail(), password)) .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) @@ -2046,6 +2190,9 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyAdminConfiguration .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2112,17 +2259,18 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .withPassword(password) .withNameInMetadata("Test", "User") .build(); - - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); + context.restoreAuthSystemState(); + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); - context.restoreAuthSystemState(); getClient(getAuthToken(ePerson.getEmail(), password)) .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) @@ -2135,6 +2283,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2160,7 +2311,8 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -2171,6 +2323,7 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura context.restoreAuthSystemState(); + getClient(getAuthToken(admin.getEmail(), password)) .perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString()) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) @@ -2182,6 +2335,10 @@ public void testAdminPatchToDisconnectProfileFromOrcidWithAdminAndOwnerConfigura .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2250,7 +2407,8 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemoved() .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); @@ -2285,6 +2443,7 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemoved() assertThat(metadata, hasItem(with("dspace.orcid.sync-fundings",ALL.name()))); assertThat(getMetadataValues(profile, "dspace.orcid.sync-profile"), hasSize(2)); + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) .contentType(MediaType.APPLICATION_JSON_VALUE)) @@ -2295,6 +2454,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemoved() .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2324,17 +2486,18 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemain() t .withNameInMetadata("Test", "User") .build(); - OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); + OrcidToken orcidToken = + OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build(); Item profile = createProfile(ePerson); + context.restoreAuthSystemState(); + assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty())); assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty())); assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4")); - context.restoreAuthSystemState(); - String authToken = getAuthToken(ePerson.getEmail(), password); String ePersonId = ePerson.getID().toString(); List operations = asList(new ReplaceOperation("/orcid/mode", "BATCH"), @@ -2359,6 +2522,7 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemain() t assertThat(metadata, hasItem(with("dspace.orcid.sync-fundings",ALL.name()))); assertThat(getMetadataValues(profile, "dspace.orcid.sync-profile"), hasSize(2)); + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId) .content(getPatchContent(asList(new RemoveOperation("/orcid")))) .contentType(MediaType.APPLICATION_JSON_VALUE)) @@ -2369,6 +2533,9 @@ public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemain() t .andExpect(jsonPath("$.orcid").doesNotExist()) .andExpect(jsonPath("$.orcidSynchronization").doesNotExist()); + verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken)); + verifyNoMoreInteractions(orcidClientMock); + profile = context.reloadEntity(profile); assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty()); @@ -2778,4 +2945,13 @@ private OrcidTokenResponseDTO buildOrcidTokenResponse(String orcid, String acces return token; } + private static OrcidToken matchesToken(OrcidToken orcidToken) { + return argThat( + token -> + token != null && + orcidToken.getAccessToken().equals(token.getAccessToken()) && + orcidToken.getID().equals(token.getID()) + ); + } + } diff --git a/dspace/config/modules/orcid.cfg b/dspace/config/modules/orcid.cfg index 28e8df60f83d..ad31371cb890 100644 --- a/dspace/config/modules/orcid.cfg +++ b/dspace/config/modules/orcid.cfg @@ -17,6 +17,7 @@ orcid.disconnection.remain-sync = true # ORCID API (https://github.com/ORCID/ORCID-Source/tree/master/orcid-api-web#endpoints) orcid.domain-url= https://sandbox.orcid.org orcid.authorize-url = ${orcid.domain-url}/oauth/authorize +orcid.revoke-url = ${orcid.domain-url}/oauth/revoke orcid.token-url = ${orcid.domain-url}/oauth/token orcid.api-url = https://api.sandbox.orcid.org/v3.0 orcid.public-url = https://pub.sandbox.orcid.org/v3.0 diff --git a/dspace/config/spring/api/orcid-services.xml b/dspace/config/spring/api/orcid-services.xml index 8286a16a88fb..6ec9be9fdf5d 100644 --- a/dspace/config/spring/api/orcid-services.xml +++ b/dspace/config/spring/api/orcid-services.xml @@ -30,6 +30,7 @@ + From bdf7069cb752782a4f8df62885c9ae6116be9dde Mon Sep 17 00:00:00 2001 From: Nona Luypaert Date: Thu, 25 Jul 2024 14:13:16 +0200 Subject: [PATCH 021/179] 116687: Never handle exception with null message --- .../rest/scripts/handler/impl/RestDSpaceRunnableHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/scripts/handler/impl/RestDSpaceRunnableHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/scripts/handler/impl/RestDSpaceRunnableHandler.java index 596ab4429093..ee67baa8ab38 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/scripts/handler/impl/RestDSpaceRunnableHandler.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/scripts/handler/impl/RestDSpaceRunnableHandler.java @@ -130,7 +130,7 @@ public void handleCompletion() { @Override public void handleException(Exception e) { - handleException(null, e); + handleException(e.getMessage(), e); } @Override From 070fe689d70d8dbfcde63899d377f2524f38d6db Mon Sep 17 00:00:00 2001 From: Nona Luypaert Date: Mon, 29 Jul 2024 13:48:32 +0200 Subject: [PATCH 022/179] 116609: Add try catch to init method in ProcessServiceImpl --- .../dspace/scripts/ProcessServiceImpl.java | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java index c34705a64d5d..ab5147221cfc 100644 --- a/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/scripts/ProcessServiceImpl.java @@ -77,24 +77,29 @@ public class ProcessServiceImpl implements ProcessService, InitializingBean { @Override public void afterPropertiesSet() throws Exception { - Context context = new Context(); - - // Processes that were running or scheduled when tomcat crashed, should be cleaned up during startup. - List processesToBeFailed = findByStatusAndCreationTimeOlderThan( - context, List.of(ProcessStatus.RUNNING, ProcessStatus.SCHEDULED), new Date()); - for (Process process : processesToBeFailed) { - context.setCurrentUser(process.getEPerson()); - // Fail the process. - log.info("Process with ID {} did not complete before tomcat shutdown, failing it now.", process.getID()); - fail(context, process); - // But still attach its log to the process. - appendLog(process.getID(), process.getName(), - "Process did not complete before tomcat shutdown.", - ProcessLogLevel.ERROR); - createLogBitstream(context, process); - } + try { + Context context = new Context(); + + // Processes that were running or scheduled when tomcat crashed, should be cleaned up during startup. + List processesToBeFailed = findByStatusAndCreationTimeOlderThan( + context, List.of(ProcessStatus.RUNNING, ProcessStatus.SCHEDULED), new Date()); + for (Process process : processesToBeFailed) { + context.setCurrentUser(process.getEPerson()); + // Fail the process. + log.info("Process with ID {} did not complete before tomcat shutdown, failing it now.", + process.getID()); + fail(context, process); + // But still attach its log to the process. + appendLog(process.getID(), process.getName(), + "Process did not complete before tomcat shutdown.", + ProcessLogLevel.ERROR); + createLogBitstream(context, process); + } - context.complete(); + context.complete(); + } catch (Exception e) { + log.error("Unable to clean up Processes: ", e); + } } @Override From e8ec0c1b1d20dd5e812f38593a24718fff1d8c6e Mon Sep 17 00:00:00 2001 From: Agustina Martinez Date: Mon, 5 Aug 2024 11:06:06 +0200 Subject: [PATCH 023/179] Fix 9734: Check configured workflow.reviewer.file-edit to show item edit functionality in workflow UI --- .../processingaction/ScoreReviewAction.java | 15 ++++++++++++++- .../processingaction/SingleUserReviewAction.java | 8 ++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java index a8ed4fd3dae9..50f338499282 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/ScoreReviewAction.java @@ -8,6 +8,7 @@ package org.dspace.xmlworkflow.state.actions.processingaction; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -20,6 +21,8 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.MetadataFieldName; import org.dspace.core.Context; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.xmlworkflow.service.WorkflowRequirementsService; import org.dspace.xmlworkflow.state.Step; import org.dspace.xmlworkflow.state.actions.ActionAdvancedInfo; @@ -34,6 +37,9 @@ public class ScoreReviewAction extends ProcessingAction { private static final Logger log = LogManager.getLogger(ScoreReviewAction.class); + private final ConfigurationService configurationService + = DSpaceServicesFactory.getInstance().getConfigurationService(); + // Option(s) public static final String SUBMIT_SCORE = "submit_score"; @@ -114,7 +120,14 @@ private boolean checkRequestValid(int score, String review) { @Override public List getOptions() { - return List.of(SUBMIT_SCORE, RETURN_TO_POOL); + List options = new ArrayList<>(); + options.add(SUBMIT_SCORE); + if (configurationService.getBooleanProperty("workflow.reviewer.file-edit", false)) { + options.add(SUBMIT_EDIT_METADATA); + } + options.add(RETURN_TO_POOL); + + return options; } @Override diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java index 64e0957b65b7..c46fa851e4f1 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/state/actions/processingaction/SingleUserReviewAction.java @@ -21,6 +21,8 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.core.Context; import org.dspace.eperson.EPerson; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.workflow.WorkflowException; import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory; import org.dspace.xmlworkflow.state.Step; @@ -40,6 +42,9 @@ public class SingleUserReviewAction extends ProcessingAction { private static final Logger log = LogManager.getLogger(SingleUserReviewAction.class); + private final ConfigurationService configurationService + = DSpaceServicesFactory.getInstance().getConfigurationService(); + public static final int OUTCOME_REJECT = 1; protected static final String SUBMIT_DECLINE_TASK = "submit_decline_task"; @@ -95,6 +100,9 @@ public ActionResult processAccept(Context c, XmlWorkflowItem wfi) throws SQLExce public List getOptions() { List options = new ArrayList<>(); options.add(SUBMIT_APPROVE); + if (configurationService.getBooleanProperty("workflow.reviewer.file-edit", false)) { + options.add(SUBMIT_EDIT_METADATA); + } options.add(SUBMIT_REJECT); options.add(SUBMIT_DECLINE_TASK); return options; From 7477c4311c93a214dcb7225874d872ccdda7f14a Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 5 Aug 2024 11:40:35 +0200 Subject: [PATCH 024/179] refactoring OpenSearchController: remove SyndicationFeed dependency --- .../dspace/app/rest/OpenSearchController.java | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java index baf45c14b6eb..6bc7034b5b09 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java @@ -9,9 +9,7 @@ import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; @@ -24,7 +22,6 @@ import org.apache.logging.log4j.Logger; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ScopeResolver; -import org.dspace.app.util.SyndicationFeed; import org.dspace.app.util.factory.UtilServiceFactory; import org.dspace.app.util.service.OpenSearchService; import org.dspace.authorize.factory.AuthorizeServiceFactory; @@ -200,12 +197,10 @@ public void search(HttpServletRequest request, log.info("opensearch done, query=\"" + query + "\",results=" + qResults.getTotalSearchResults()); - // format and return results - Map labelMap = getLabels(request); List dsoResults = qResults.getIndexableObjects(); Document resultsDoc = openSearchService.getResultsDoc(context, format, query, (int) qResults.getTotalSearchResults(), qResults.getStart(), - qResults.getMaxResults(), container, dsoResults, labelMap); + qResults.getMaxResults(), container, dsoResults); try { Transformer xf = TransformerFactory.newInstance().newTransformer(); response.setContentType(openSearchService.getContentType(format)); @@ -274,20 +269,4 @@ private void init() { public void setOpenSearchService(OpenSearchService oSS) { openSearchService = oSS; } - - - /** - * Internal method to get labels for the returned document - */ - private Map getLabels(HttpServletRequest request) { - // TODO: get strings from translation file or configuration - Map labelMap = new HashMap(); - labelMap.put(SyndicationFeed.MSG_UNTITLED, "notitle"); - labelMap.put(SyndicationFeed.MSG_LOGO_TITLE, "logo.title"); - labelMap.put(SyndicationFeed.MSG_FEED_DESCRIPTION, "general-feed.description"); - for (String selector : SyndicationFeed.getDescriptionSelectors()) { - labelMap.put("metadata." + selector, selector); - } - return labelMap; - } } From 4374505cc9c3e2e520f3405cb33845b40b8db5ed Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 5 Aug 2024 11:44:10 +0200 Subject: [PATCH 025/179] refactoring of OpenSearchService interface: remove label method parameter --- .../app/util/service/OpenSearchService.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java b/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java index 03f41e535c53..74bdd5bc7a6c 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java +++ b/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java @@ -10,7 +10,6 @@ import java.io.IOException; import java.sql.SQLException; import java.util.List; -import java.util.Map; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; @@ -85,15 +84,13 @@ public interface OpenSearchService { * @param start - start result index * @param pageSize - page size * @param scope - search scope, null or the community/collection - * @param results the retreived DSpace objects satisfying search - * @param labels labels to apply - format specific + * @param results the retrieved DSpace objects satisfying search * @return formatted search results * @throws IOException if IO error */ public String getResultsString(Context context, String format, String query, int totalResults, int start, - int pageSize, - IndexableObject scope, List results, - Map labels) throws IOException; + int pageSize, IndexableObject scope, List results,) + throws IOException; /** * Returns a formatted set of search results as a document @@ -105,14 +102,12 @@ public String getResultsString(Context context, String format, String query, int * @param start - start result index * @param pageSize - page size * @param scope - search scope, null or the community/collection - * @param results the retreived DSpace objects satisfying search - * @param labels labels to apply - format specific + * @param results the retrieved DSpace objects satisfying search * @return formatted search results * @throws IOException if IO error */ public Document getResultsDoc(Context context, String format, String query, int totalResults, int start, - int pageSize, - IndexableObject scope, List results, Map labels) + int pageSize, IndexableObject scope, List results) throws IOException; public DSpaceObject resolveScope(Context context, String scope) throws SQLException; From 7b525e183a184e16ff0e389dd1c3603b7dc8fab4 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 5 Aug 2024 11:47:46 +0200 Subject: [PATCH 026/179] refactoring of OpenSearchServiceImpl: adapt to changes made in interface --- .../app/util/OpenSearchServiceImpl.java | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java index bff741b5ca42..2800ae6d10a2 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java @@ -14,7 +14,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; import com.rometools.modules.opensearch.OpenSearchModule; import com.rometools.modules.opensearch.entity.OSQuery; @@ -58,12 +57,12 @@ public class OpenSearchServiceImpl implements OpenSearchService { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(OpenSearchServiceImpl.class); // Namespaces used - protected final String osNs = "http://a9.com/-/spec/opensearch/1.1/"; + protected final static String osNs = "http://a9.com/-/spec/opensearch/1.1/"; - @Autowired(required = true) + @Autowired protected ConfigurationService configurationService; - @Autowired(required = true) + @Autowired protected HandleService handleService; protected OpenSearchServiceImpl() { @@ -119,11 +118,10 @@ public String getDescription(String scope) { @Override public String getResultsString(Context context, String format, String query, int totalResults, int start, - int pageSize, - IndexableObject scope, List results, - Map labels) throws IOException { + int pageSize, IndexableObject scope, List results) + throws IOException { try { - return getResults(context, format, query, totalResults, start, pageSize, scope, results, labels) + return getResults(context, format, query, totalResults, start, pageSize, scope, results) .outputString(); } catch (FeedException e) { log.error(e.toString(), e); @@ -133,11 +131,10 @@ public String getResultsString(Context context, String format, String query, int @Override public Document getResultsDoc(Context context, String format, String query, int totalResults, int start, - int pageSize, - IndexableObject scope, List results, Map labels) + int pageSize, IndexableObject scope, List results) throws IOException { try { - return getResults(context, format, query, totalResults, start, pageSize, scope, results, labels) + return getResults(context, format, query, totalResults, start, pageSize, scope, results) .outputW3CDom(); } catch (FeedException e) { log.error(e.toString(), e); @@ -146,8 +143,7 @@ public Document getResultsDoc(Context context, String format, String query, int } protected SyndicationFeed getResults(Context context, String format, String query, int totalResults, int start, - int pageSize, IndexableObject scope, - List results, Map labels) { + int pageSize, IndexableObject scope, List results) { // Encode results in requested format if ("rss".equals(format)) { format = "rss_2.0"; @@ -156,7 +152,7 @@ protected SyndicationFeed getResults(Context context, String format, String quer } SyndicationFeed feed = new SyndicationFeed(); - feed.populate(null, context, scope, results, labels); + feed.populate(null, context, scope, results); feed.setType(format); feed.addModule(openSearchMarkup(query, totalResults, start, pageSize)); return feed; From 70dde2db0b1161a1891da2726171d01122042cf2 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 5 Aug 2024 11:54:58 +0200 Subject: [PATCH 027/179] refactoring of SyndicationFeed: move method getLabels from OpenSearchController --- .../org/dspace/app/util/SyndicationFeed.java | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java index 654036963572..d736ab5a06a7 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java @@ -11,6 +11,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -135,8 +136,6 @@ public class SyndicationFeed { protected String[] podcastableMIMETypes = configurationService.getArrayProperty("webui.feed.podcast.mimetypes", new String[] {"audio/x-mpeg"}); - // -------- Instance variables: - // the feed object we are building protected SyndFeed feed = null; @@ -146,9 +145,6 @@ public class SyndicationFeed { protected CommunityService communityService; protected ItemService itemService; - /** - * Constructor. - */ public SyndicationFeed() { feed = new SyndFeedImpl(); ContentServiceFactory contentServiceFactory = ContentServiceFactory.getInstance(); @@ -157,16 +153,6 @@ public SyndicationFeed() { communityService = contentServiceFactory.getCommunityService(); } - /** - * Returns list of metadata selectors used to compose the description element - * - * @return selector list - format 'schema.element[.qualifier]' - */ - public static String[] getDescriptionSelectors() { - return (String[]) ArrayUtils.clone(descriptionFields); - } - - /** * Fills in the feed and entry-level metadata from DSpace objects. * @@ -174,10 +160,9 @@ public static String[] getDescriptionSelectors() { * @param context context * @param dso the scope * @param items array of objects - * @param labels label map */ public void populate(HttpServletRequest request, Context context, IndexableObject dso, - List items, Map labels) { + List items) { String logoURL = null; String objectURL = null; String defaultTitle = null; @@ -553,5 +538,19 @@ protected String getOneDC(Item item, String field) { List dcv = itemService.getMetadataByMetadataString(item, field); return (dcv.size() > 0) ? dcv.get(0).getValue() : null; } -} + /** + * Internal method to get labels for the returned document + */ + private Map getLabels() { + // TODO: get strings from translation file or configuration + Map labelMap = new HashMap<>(); + labelMap.put(SyndicationFeed.MSG_UNTITLED, "notitle"); + labelMap.put(SyndicationFeed.MSG_LOGO_TITLE, "logo.title"); + labelMap.put(SyndicationFeed.MSG_FEED_DESCRIPTION, "general-feed.description"); + for (String selector : descriptionFields) { + labelMap.put("metadata." + selector, selector); + } + return labelMap; + } +} From c533a5754ac1fca02ff8a7f1800f456f66a86c87 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 5 Aug 2024 12:06:02 +0200 Subject: [PATCH 028/179] call private method getLabels() directly --- .../src/main/java/org/dspace/app/util/SyndicationFeed.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java index d736ab5a06a7..bcd4067c8daa 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java @@ -168,6 +168,9 @@ public void populate(HttpServletRequest request, Context context, IndexableObjec String defaultTitle = null; boolean podcastFeed = false; this.request = request; + + Map labels = getLabels(); + // dso is null for the whole site, or a search without scope if (dso == null) { defaultTitle = configurationService.getProperty("dspace.name"); From 7bb76d8523949b4da35badda979eb9f51f3ca760 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 5 Aug 2024 12:10:17 +0200 Subject: [PATCH 029/179] fixed compilation error (obsolete comma) --- .../java/org/dspace/app/util/service/OpenSearchService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java b/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java index 74bdd5bc7a6c..78b208faa2bc 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java +++ b/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java @@ -89,7 +89,7 @@ public interface OpenSearchService { * @throws IOException if IO error */ public String getResultsString(Context context, String format, String query, int totalResults, int start, - int pageSize, IndexableObject scope, List results,) + int pageSize, IndexableObject scope, List results) throws IOException; /** From fa9f9457f77a9b882322054ce180bf8e12ba07a5 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Mon, 5 Aug 2024 12:22:27 +0200 Subject: [PATCH 030/179] resolve lint warnings: remove trailing whitespaces --- .../src/main/java/org/dspace/app/util/SyndicationFeed.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java index bcd4067c8daa..e6220cd220de 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java @@ -168,9 +168,9 @@ public void populate(HttpServletRequest request, Context context, IndexableObjec String defaultTitle = null; boolean podcastFeed = false; this.request = request; - + Map labels = getLabels(); - + // dso is null for the whole site, or a search without scope if (dso == null) { defaultTitle = configurationService.getProperty("dspace.name"); @@ -555,5 +555,5 @@ private Map getLabels() { labelMap.put("metadata." + selector, selector); } return labelMap; - } + } } From 4b32fa216caede8b0ac4922bbfc3d7fd0d006750 Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Tue, 6 Aug 2024 15:38:55 +0200 Subject: [PATCH 031/179] Make submissiondefinition pagination test more flexible --- .../SubmissionDefinitionsControllerIT.java | 45 +++++++++++-------- .../matcher/SubmissionDefinitionsMatcher.java | 15 +++++-- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java index babb1fac2326..6ad6aff7e9b0 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java @@ -8,6 +8,7 @@ package org.dspace.app.rest; import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; +import static org.dspace.app.rest.matcher.SubmissionDefinitionsMatcher.matchSubmissionConfig; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasSize; @@ -17,8 +18,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.List; + import org.dspace.app.rest.matcher.SubmissionDefinitionsMatcher; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.app.util.SubmissionConfig; +import org.dspace.app.util.SubmissionConfigReader; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.content.Collection; @@ -239,13 +244,17 @@ public void findSections() throws Exception { @Test public void findAllPaginationTest() throws Exception { + List definitions = new SubmissionConfigReader().getAllSubmissionConfigs(100, 0); + int totalCount = definitions.size(); + String tokenAdmin = getAuthToken(admin.getEmail(), password); + getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") .param("size", "1") .param("page", "0")) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) - .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("traditional"))) + .andExpect(jsonPath("$._embedded.submissiondefinitions[0]", matchSubmissionConfig(definitions.get(0)))) .andExpect(jsonPath("$._links.first.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=0"), Matchers.containsString("size=1")))) @@ -259,8 +268,8 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=6"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(7))) - .andExpect(jsonPath("$.page.totalPages", is(7))) + .andExpect(jsonPath("$.page.totalElements", is(totalCount))) + .andExpect(jsonPath("$.page.totalPages", is(totalCount))) .andExpect(jsonPath("$.page.number", is(0))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -268,7 +277,7 @@ public void findAllPaginationTest() throws Exception { .param("page", "1")) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) - .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("test-hidden"))) + .andExpect(jsonPath("$._embedded.submissiondefinitions[0]", matchSubmissionConfig(definitions.get(1)))) .andExpect(jsonPath("$._links.first.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=0"), Matchers.containsString("size=1")))) @@ -285,8 +294,8 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page="), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(7))) - .andExpect(jsonPath("$.page.totalPages", is(7))) + .andExpect(jsonPath("$.page.totalElements", is(totalCount))) + .andExpect(jsonPath("$.page.totalPages", is(totalCount))) .andExpect(jsonPath("$.page.number", is(1))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -294,7 +303,7 @@ public void findAllPaginationTest() throws Exception { .param("page", "2")) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) - .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("accessConditionNotDiscoverable"))) + .andExpect(jsonPath("$._embedded.submissiondefinitions[0]", matchSubmissionConfig(definitions.get(2)))) .andExpect(jsonPath("$._links.first.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=0"), Matchers.containsString("size=1")))) @@ -311,8 +320,8 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=6"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(7))) - .andExpect(jsonPath("$.page.totalPages", is(7))) + .andExpect(jsonPath("$.page.totalElements", is(totalCount))) + .andExpect(jsonPath("$.page.totalPages", is(totalCount))) .andExpect(jsonPath("$.page.number", is(2))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -320,7 +329,7 @@ public void findAllPaginationTest() throws Exception { .param("page", "3")) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) - .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("languagetestprocess"))) + .andExpect(jsonPath("$._embedded.submissiondefinitions[0]", matchSubmissionConfig(definitions.get(3)))) .andExpect(jsonPath("$._links.first.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=0"), Matchers.containsString("size=1")))) @@ -337,8 +346,8 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=6"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(7))) - .andExpect(jsonPath("$.page.totalPages", is(7))) + .andExpect(jsonPath("$.page.totalElements", is(totalCount))) + .andExpect(jsonPath("$.page.totalPages", is(totalCount))) .andExpect(jsonPath("$.page.number", is(3))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -346,7 +355,7 @@ public void findAllPaginationTest() throws Exception { .param("page", "4")) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) - .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("qualdroptest"))) + .andExpect(jsonPath("$._embedded.submissiondefinitions[0]", matchSubmissionConfig(definitions.get(4)))) .andExpect(jsonPath("$._links.first.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=0"), Matchers.containsString("size=1")))) @@ -363,8 +372,8 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=6"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(7))) - .andExpect(jsonPath("$.page.totalPages", is(7))) + .andExpect(jsonPath("$.page.totalElements", is(totalCount))) + .andExpect(jsonPath("$.page.totalPages", is(totalCount))) .andExpect(jsonPath("$.page.number", is(4))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -372,7 +381,7 @@ public void findAllPaginationTest() throws Exception { .param("page", "5")) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) - .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("extractiontestprocess"))) + .andExpect(jsonPath("$._embedded.submissiondefinitions[0]", matchSubmissionConfig(definitions.get(5)))) .andExpect(jsonPath("$._links.first.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=0"), Matchers.containsString("size=1")))) @@ -389,8 +398,8 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=6"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(7))) - .andExpect(jsonPath("$.page.totalPages", is(7))) + .andExpect(jsonPath("$.page.totalElements", is(totalCount))) + .andExpect(jsonPath("$.page.totalPages", is(totalCount))) .andExpect(jsonPath("$.page.number", is(5))); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/SubmissionDefinitionsMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/SubmissionDefinitionsMatcher.java index 398097db6fba..86f1c7830a0a 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/SubmissionDefinitionsMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/SubmissionDefinitionsMatcher.java @@ -13,6 +13,7 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.is; +import org.dspace.app.util.SubmissionConfig; import org.hamcrest.Matcher; /** @@ -25,7 +26,7 @@ private SubmissionDefinitionsMatcher() { } public static Matcher matchSubmissionDefinition(boolean isDefault, String name, String id) { return allOf( matchProperties(isDefault, name, id), - matchLinks() + matchLinks(id) ); } @@ -42,8 +43,8 @@ public static Matcher matchFullEmbeds() { /** * Gets a matcher for all expected links. */ - public static Matcher matchLinks() { - return HalMatcher.matchLinks(REST_SERVER_URL + "config/submissiondefinitions/traditional", + public static Matcher matchLinks(String id) { + return HalMatcher.matchLinks(REST_SERVER_URL + "config/submissiondefinitions/" + id, "collections", "sections", "self" @@ -61,4 +62,12 @@ public static Matcher matchProperties(boolean isDefault, String is(REST_SERVER_URL + "config/submissiondefinitions/" + id + "/sections")) ); } + + public static Matcher matchSubmissionConfig(SubmissionConfig config) { + return matchSubmissionDefinition( + config.isDefaultConf(), + config.getSubmissionName(), + config.getSubmissionName() + ); + } } From 6baf93dc07add4ceafd34ba0e5ad08e4d89ce17d Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Wed, 31 Jul 2024 14:26:02 -0400 Subject: [PATCH 032/179] Make POI record buffer size adjustable. 'bin/dspace filter-media' was giving us RecordFormatException on OOXML files with enormous records. --- .../dspace/app/mediafilter/TikaTextExtractionFilter.java | 9 ++++++--- dspace/config/dspace.cfg | 7 +++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java index e83bf706ed02..a51e45c68f7b 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java @@ -18,6 +18,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.poi.util.IOUtils; import org.apache.tika.Tika; import org.apache.tika.exception.TikaException; import org.apache.tika.metadata.Metadata; @@ -72,21 +73,23 @@ public InputStream getDestinationStream(Item currentItem, InputStream source, bo // Not using temporary file. We'll use Tika's default in-memory parsing. // Get maximum characters to extract. Default is 100,000 chars, which is also Tika's default setting. String extractedText; - int maxChars = configurationService.getIntProperty("textextractor.max-chars", 100000); + int maxChars = configurationService.getIntProperty("textextractor.max-chars", 100_000); try { // Use Tika to extract text from input. Tika will automatically detect the file type. Tika tika = new Tika(); tika.setMaxStringLength(maxChars); // Tell Tika the maximum number of characters to extract + IOUtils.setByteArrayMaxOverride( + configurationService.getIntProperty("textextractor.max-array", 1_000_000)); extractedText = tika.parseToString(source); } catch (IOException e) { System.err.format("Unable to extract text from bitstream in Item %s%n", currentItem.getID().toString()); - e.printStackTrace(); + e.printStackTrace(System.err); log.error("Unable to extract text from bitstream in Item {}", currentItem.getID().toString(), e); throw e; } catch (OutOfMemoryError oe) { System.err.format("OutOfMemoryError occurred when extracting text from bitstream in Item %s. " + "You may wish to enable 'textextractor.use-temp-file'.%n", currentItem.getID().toString()); - oe.printStackTrace(); + oe.printStackTrace(System.err); log.error("OutOfMemoryError occurred when extracting text from bitstream in Item {}. " + "You may wish to enable 'textextractor.use-temp-file'.", currentItem.getID().toString(), oe); throw oe; diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index 55c472c68702..3a5d9890761b 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -519,6 +519,13 @@ filter.org.dspace.app.mediafilter.PDFBoxThumbnail.inputFormats = Adobe PDF # text ("filter-media -f" ) and then reindex your site ("index-discovery -b"). #textextractor.use-temp-file = false +# Maximum size of a record buffer for text extraction. Set this if you are +# seeing RecordFormatException calling out excessive array length from +# 'dspace filter-media'. It is likely that you will need to increase the +# size of the Java heap if you greatly increase this value -- see JAVA_OPTS +# in 'bin/dspace' or 'bin/dspace/bat'. +#textextractor.max-array = 1000000 + # Custom settings for ImageMagick Thumbnail Filters # ImageMagick and GhostScript must be installed on the server, set the path to ImageMagick and GhostScript executable # http://www.imagemagick.org/ From 9d1d4c819d80f1fa1cf5f79c9b5bac8b7d1cf3e9 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Wed, 31 Jul 2024 15:02:15 -0400 Subject: [PATCH 033/179] Get the stock default value right. --- .../org/dspace/app/mediafilter/TikaTextExtractionFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java index a51e45c68f7b..17e7b85e9bfc 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/TikaTextExtractionFilter.java @@ -79,7 +79,7 @@ public InputStream getDestinationStream(Item currentItem, InputStream source, bo Tika tika = new Tika(); tika.setMaxStringLength(maxChars); // Tell Tika the maximum number of characters to extract IOUtils.setByteArrayMaxOverride( - configurationService.getIntProperty("textextractor.max-array", 1_000_000)); + configurationService.getIntProperty("textextractor.max-array", 100_000_000)); extractedText = tika.parseToString(source); } catch (IOException e) { System.err.format("Unable to extract text from bitstream in Item %s%n", currentItem.getID().toString()); From 2bcea0f860db9a3dc915119a5e111d057d2b2936 Mon Sep 17 00:00:00 2001 From: autavares-dev Date: Wed, 7 Aug 2024 16:34:38 -0300 Subject: [PATCH 034/179] Changes Group2GroupCache computation --- .../org/dspace/eperson/Group2GroupCache.java | 3 +- .../org/dspace/eperson/GroupServiceImpl.java | 72 +++++++++--------- .../eperson/dao/Group2GroupCacheDAO.java | 74 +++++++++++++++++-- .../dao/impl/Group2GroupCacheDAOImpl.java | 34 +++++++++ 4 files changed, 143 insertions(+), 40 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java b/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java index a1c12371f5ff..0c6ea58b1977 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java +++ b/dspace-api/src/main/java/org/dspace/eperson/Group2GroupCache.java @@ -15,6 +15,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import org.dspace.core.HibernateProxyHelper; /** @@ -23,7 +24,7 @@ * @author kevinvandevelde at atmire.com */ @Entity -@Table(name = "group2groupcache") +@Table(name = "group2groupcache", uniqueConstraints = { @UniqueConstraint(columnNames = {"parent_id", "child_id"}) }) public class Group2GroupCache implements Serializable { @Id diff --git a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java index 3fb20e2f1e6f..b52f17a5c692 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java @@ -20,6 +20,7 @@ import java.util.UUID; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.SetUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; @@ -673,15 +674,14 @@ protected boolean isEPersonInGroup(Context context, Group group, EPerson ePerson /** - * Regenerate the group cache AKA the group2groupcache table in the database - - * meant to be called when a group is added or removed from another group + * Returns a set with pairs of parent and child group UUIDs, representing the new cache table rows. * - * @param context The relevant DSpace Context. - * @param flushQueries flushQueries Flush all pending queries + * @param context The relevant DSpace Context. + * @param flushQueries flushQueries Flush all pending queries + * @return Pairs of parent and child group UUID of the new cache. * @throws SQLException An exception that provides information on a database access error or other errors. */ - protected void rethinkGroupCache(Context context, boolean flushQueries) throws SQLException { - + private Set> computeNewCache(Context context, boolean flushQueries) throws SQLException { Map> parents = new HashMap<>(); List> group2groupResults = groupDAO.getGroup2GroupResults(context, flushQueries); @@ -689,19 +689,8 @@ protected void rethinkGroupCache(Context context, boolean flushQueries) throws S UUID parent = group2groupResult.getLeft(); UUID child = group2groupResult.getRight(); - // if parent doesn't have an entry, create one - if (!parents.containsKey(parent)) { - Set children = new HashSet<>(); - - // add child id to the list - children.add(child); - parents.put(parent, children); - } else { - // parent has an entry, now add the child to the parent's record - // of children - Set children = parents.get(parent); - children.add(child); - } + parents.putIfAbsent(parent, new HashSet<>()); + parents.get(parent).add(child); } // now parents is a hash of all of the IDs of groups that are parents @@ -714,27 +703,42 @@ protected void rethinkGroupCache(Context context, boolean flushQueries) throws S parent.getValue().addAll(myChildren); } - // empty out group2groupcache table - group2GroupCacheDAO.deleteAll(context); - - // write out new one + // write out new cache IN MEMORY ONLY and returns it + Set> newCache = new HashSet<>(); for (Map.Entry> parent : parents.entrySet()) { UUID key = parent.getKey(); - for (UUID child : parent.getValue()) { + newCache.add(Pair.of(key, child)); + } + } + return newCache; + } - Group parentGroup = find(context, key); - Group childGroup = find(context, child); + /** + * Regenerate the group cache AKA the group2groupcache table in the database - + * meant to be called when a group is added or removed from another group + * + * @param context The relevant DSpace Context. + * @param flushQueries flushQueries Flush all pending queries + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + protected void rethinkGroupCache(Context context, boolean flushQueries) throws SQLException { + // current cache in the database + var oldCache = group2GroupCacheDAO.getCache(context); - if (parentGroup != null && childGroup != null && group2GroupCacheDAO - .find(context, parentGroup, childGroup) == null) { - Group2GroupCache group2GroupCache = group2GroupCacheDAO.create(context, new Group2GroupCache()); - group2GroupCache.setParent(parentGroup); - group2GroupCache.setChild(childGroup); - group2GroupCacheDAO.save(context, group2GroupCache); - } - } + // correct cache, computed from the Group table + var newCache = computeNewCache(context, flushQueries); + + var toDelete = SetUtils.difference(oldCache, newCache); + var toCreate = SetUtils.difference(newCache, oldCache); + + for (var pair : toDelete ) { + group2GroupCacheDAO.deleteFromCache(context, pair.getLeft(), pair.getRight()); + } + + for (var pair : toCreate ) { + group2GroupCacheDAO.addToCache(context, pair.getLeft(), pair.getRight()); } } diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java b/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java index 7db569a59e2b..d41d52c7e618 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/Group2GroupCacheDAO.java @@ -9,7 +9,10 @@ import java.sql.SQLException; import java.util.List; +import java.util.Set; +import java.util.UUID; +import org.apache.commons.lang3.tuple.Pair; import org.dspace.core.Context; import org.dspace.core.GenericDAO; import org.dspace.eperson.Group; @@ -25,13 +28,74 @@ */ public interface Group2GroupCacheDAO extends GenericDAO { - public List findByParent(Context context, Group group) throws SQLException; + /** + * Returns the current cache table as a set of UUID pairs. + * @param context The relevant DSpace Context. + * @return Set of UUID pairs, where the first element is the parent UUID and the second one is the child UUID. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + Set> getCache(Context context) throws SQLException; - public List findByChildren(Context context, Iterable groups) throws SQLException; + /** + * Returns all cache entities that are children of a given parent Group entity. + * @param context The relevant DSpace Context. + * @param group Parent group to perform the search. + * @return List of cached groups that are children of the parent group. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + List findByParent(Context context, Group group) throws SQLException; - public Group2GroupCache findByParentAndChild(Context context, Group parent, Group child) throws SQLException; + /** + * Returns all cache entities that are parents of at least one group from a children groups list. + * @param context The relevant DSpace Context. + * @param groups Children groups to perform the search. + * @return List of cached groups that are parents of at least one group from the children groups list. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + List findByChildren(Context context, Iterable groups) throws SQLException; - public Group2GroupCache find(Context context, Group parent, Group child) throws SQLException; + /** + * Returns the cache entity given specific parent and child groups. + * @param context The relevant DSpace Context. + * @param parent Parent group. + * @param child Child gruoup. + * @return Cached group. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + Group2GroupCache findByParentAndChild(Context context, Group parent, Group child) throws SQLException; - public void deleteAll(Context context) throws SQLException; + /** + * Returns the cache entity given specific parent and child groups. + * @param context The relevant DSpace Context. + * @param parent Parent group. + * @param child Child gruoup. + * @return Cached group. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + Group2GroupCache find(Context context, Group parent, Group child) throws SQLException; + + /** + * Completely deletes the current cache table. + * @param context The relevant DSpace Context. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + void deleteAll(Context context) throws SQLException; + + /** + * Deletes a specific cache row given parent and child groups UUIDs. + * @param context The relevant DSpace Context. + * @param parent Parent group UUID. + * @param child Child group UUID. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + void deleteFromCache(Context context, UUID parent, UUID child) throws SQLException; + + /** + * Adds a single row to the cache table given parent and child groups UUIDs. + * @param context The relevant DSpace Context. + * @param parent Parent group UUID. + * @param child Child group UUID. + * @throws SQLException An exception that provides information on a database access error or other errors. + */ + void addToCache(Context context, UUID parent, UUID child) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java index 1cd359188ca3..adbd776ffab6 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/Group2GroupCacheDAOImpl.java @@ -8,14 +8,18 @@ package org.dspace.eperson.dao.impl; import java.sql.SQLException; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Set; +import java.util.UUID; import jakarta.persistence.Query; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; +import org.apache.commons.lang3.tuple.Pair; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.Group; @@ -35,6 +39,16 @@ protected Group2GroupCacheDAOImpl() { super(); } + @Override + public Set> getCache(Context context) throws SQLException { + Query query = createQuery( + context, + "SELECT new org.apache.commons.lang3.tuple.ImmutablePair(g.parent.id, g.child.id) FROM Group2GroupCache g" + ); + List> results = query.getResultList(); + return new HashSet>(results); + } + @Override public List findByParent(Context context, Group group) throws SQLException { CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); @@ -90,4 +104,24 @@ public Group2GroupCache find(Context context, Group parent, Group child) throws public void deleteAll(Context context) throws SQLException { createQuery(context, "delete from Group2GroupCache").executeUpdate(); } + + @Override + public void deleteFromCache(Context context, UUID parent, UUID child) throws SQLException { + Query query = getHibernateSession(context).createNativeQuery( + "delete from group2groupcache g WHERE g.parent_id = :parent AND g.child_id = :child" + ); + query.setParameter("parent", parent); + query.setParameter("child", child); + query.executeUpdate(); + } + + @Override + public void addToCache(Context context, UUID parent, UUID child) throws SQLException { + Query query = getHibernateSession(context).createNativeQuery( + "insert into group2groupcache (parent_id, child_id) VALUES (:parent, :child)" + ); + query.setParameter("parent", parent); + query.setParameter("child", child); + query.executeUpdate(); + } } From 743b7049cfeeabfd414c38526bcdbf2e52426739 Mon Sep 17 00:00:00 2001 From: autavares-dev Date: Thu, 8 Aug 2024 15:52:03 -0300 Subject: [PATCH 035/179] Refactor 'var' variables to explicit types --- .../java/org/dspace/eperson/GroupServiceImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java index b52f17a5c692..4cec4c9c0d93 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java @@ -725,19 +725,19 @@ private Set> computeNewCache(Context context, boolean flushQuer */ protected void rethinkGroupCache(Context context, boolean flushQueries) throws SQLException { // current cache in the database - var oldCache = group2GroupCacheDAO.getCache(context); + Set> oldCache = group2GroupCacheDAO.getCache(context); // correct cache, computed from the Group table - var newCache = computeNewCache(context, flushQueries); + Set> newCache = computeNewCache(context, flushQueries); - var toDelete = SetUtils.difference(oldCache, newCache); - var toCreate = SetUtils.difference(newCache, oldCache); + SetUtils.SetView> toDelete = SetUtils.difference(oldCache, newCache); + SetUtils.SetView> toCreate = SetUtils.difference(newCache, oldCache); - for (var pair : toDelete ) { + for (Pair pair : toDelete ) { group2GroupCacheDAO.deleteFromCache(context, pair.getLeft(), pair.getRight()); } - for (var pair : toCreate ) { + for (Pair pair : toCreate ) { group2GroupCacheDAO.addToCache(context, pair.getLeft(), pair.getRight()); } } From 002e637d4fc69b31c2a2321230d96534e49ee33e Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 27 Aug 2024 10:33:01 +0200 Subject: [PATCH 036/179] fix failed first login attempt in HAL browser --- .../src/main/resources/static/login.html | 128 ++++++++++-------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/dspace-server-webapp/src/main/resources/static/login.html b/dspace-server-webapp/src/main/resources/static/login.html index 50d95b80472f..0597a66bfe96 100644 --- a/dspace-server-webapp/src/main/resources/static/login.html +++ b/dspace-server-webapp/src/main/resources/static/login.html @@ -32,7 +32,7 @@ border-radius: 5px; box-shadow: 0 1px 2px rgba(0, 0, 0, .05); } - .form-signin .form-signin-heading, .form-signin .checkbox { + .form-signin .form-signin-heading, .form-signin { margin-bottom: 10px; } .form-signin input[type="text"], .form-signin input[type="password"] { @@ -94,63 +94,71 @@

Other login methods:

"onclick" : function() { toastr.remove(); } } + // retrieves a valid CSRF token (please note that this method works both in DS 7 and DS 8) + // HTTP response code 403 is expected at this point (the response contains the DSPACE-XSRF-TOKEN header) + $.ajax({ + url : window.location.href.replace("login.html", "") + 'api/authn/login', + type : 'POST', + error : function(xhr) { + // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) + checkForUpdatedCSRFTokenInResponse(xhr); + } + }); + // When the login page loads, we do *two* AJAX requests. - // (1) Call GET /api/authn/status. This call has two purposes. First, it checks to see if you are logged in, - // (if not, WWW-Authenticate will return login options). Second, it retrieves the CSRF token, if a - // new one has been assigned (as a valid CSRF token is required for the POST call). + // (1) Call GET /api/authn/status. This call checks to see if you are logged in + // (if not, WWW-Authenticate will return login options). // (2) If that /api/authn/status call finds authentication data, call POST /api/authn/login. - // This scenario occurs when you login via an external authentication system (e.g. Shibboleth)... + // This scenario occurs when you log in via an external authentication system (e.g. Shibboleth) // in which case the main role of /api/authn/login is to simply ensure the "Authorization" header // is sent back to the client (based on your authentication data). $.ajax({ - url : window.location.href.replace("login.html", "") + 'api/authn/status', - type : 'GET', - success : function(result, status, xhr) { - // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) - checkForUpdatedCSRFTokenInResponse(xhr); + url : window.location.href.replace("login.html", "") + 'api/authn/status', + type : 'GET', + success : function(result, status, xhr) { - // Check for WWW-Authenticate header. If found, this means we are not yet authenticated, and - // therefore we need to display available authentication options. - var authenticate = xhr.getResponseHeader("WWW-Authenticate"); - if (authenticate !== null) { - var element = $('div.other-login-methods'); - var realms = authenticate.match(/(\w+ (\w+=((".*?")|[^,]*)(, )?)*)/g); - if (realms.length == 1){ - var loc = /location="([^,]*)"/.exec(authenticate); - if (loc !== null && loc.length === 2) { - document.location = loc[1]; - } - } else if (realms.length > 1){ - for (var i = 0; i < realms.length; i++){ - addLocationButton(realms[i], element); + // Check for WWW-Authenticate header. If found, this means we are not yet authenticated, and + // therefore we need to display available authentication options. + var authenticate = xhr.getResponseHeader("WWW-Authenticate"); + if (authenticate !== null && authenticate.contains('location=')) { + var element = $('div.other-login-methods'); + var realms = authenticate.match(/(\w+ (\w+=((".*?")|[^,]*)(, )?)*)/g); + if (realms.length === 1){ + var loc = /location="([^,]*)"/.exec(authenticate); + if (loc !== null && loc.length === 2) { + document.location = loc[1]; + } + } else if (realms.length > 1){ + for (var i = 0; i < realms.length; i++){ + addLocationButton(realms[i], element); + } } + } else { + // If Authentication data was found, do a POST /api/authn/login to ensure that data's JWT + // is sent back in the "Authorization" header. This simply completes an external authentication + // process (e.g. Shibboleth) + $.ajax({ + url : window.location.href.replace("login.html", "") + 'api/authn/login', + type : 'POST', + beforeSend: function (xhr) { + // If CSRF token found in cookie, send it back as X-XSRF-Token header + var csrfToken = getCSRFToken(); + if (csrfToken != null) { + xhr.setRequestHeader('X-XSRF-Token', csrfToken); + } + }, + success : successHandler, + error : function(xhr) { + // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) + checkForUpdatedCSRFTokenInResponse(xhr); + toastr.error('Failed to logged in. Please check for errors in Javascript console.', 'Login Failed'); + } + }); } - } else { - // If Authentication data was found, do a POST /api/authn/login to ensure that data's JWT - // is sent back in the "Authorization" header. This simply completes an external authentication - // process (e.g. Shibboleth) - $.ajax({ - url : window.location.href.replace("login.html", "") + 'api/authn/login', - type : 'POST', - beforeSend: function (xhr, settings) { - // If CSRF token found in cookie, send it back as X-XSRF-Token header - var csrfToken = getCSRFToken(); - if (csrfToken != null) { - xhr.setRequestHeader('X-XSRF-Token', csrfToken); - } - }, - success : successHandler, - error : function(xhr, textStatus, errorThrown) { - // Check for an update to the CSRF Token & save to a MyHalBrowserCsrfToken cookie (if found) - checkForUpdatedCSRFTokenInResponse(xhr); - toastr.error('Failed to logged in. Please check for errors in Javascript console.', 'Login Failed'); - } - }); + }, + error : function() { + toastr.error('Failed to connect with backend. Please check for errors in Javascript console.', 'Could Not Load'); } - }, - error : function(xhr, textStatus, errorThrown) { - toastr.error('Failed to connect with backend. Please check for errors in Javascript console.', 'Could Not Load'); - } }); function addLocationButton(realm, element){ @@ -166,22 +174,22 @@

Other login methods:

return string.charAt(0).toUpperCase() + string.slice(1); } - /** - * Check current response headers to see if the CSRF Token has changed. If a new value is found in headers, - * save the new value into our "MyHalBrowserCsrfToken" cookie. - **/ + /** + * Check current response headers to see if the CSRF Token has changed. If a new value is found in headers, + * save the new value into our "MyHalBrowserCsrfToken" cookie. + **/ function checkForUpdatedCSRFTokenInResponse(jqxhr) { // look for DSpace-XSRF-TOKEN header & save to our MyHalBrowserCsrfToken cookie (if found) var updatedCsrfToken = jqxhr.getResponseHeader('DSPACE-XSRF-TOKEN'); if (updatedCsrfToken != null) { - document.cookie = "MyHalBrowserCsrfToken=" + updatedCsrfToken; + document.cookie = "MyHalBrowserCsrfToken=" + updatedCsrfToken; } } - /** - * Get CSRF Token by parsing it out of the "MyHalBrowserCsrfToken" cookie. - * This cookie is set in login.html after a successful login occurs. - **/ + /** + * Get CSRF Token by parsing it out of the "MyHalBrowserCsrfToken" cookie. + * This cookie is set in login.html after a successful login occurs. + **/ function getCSRFToken() { var cookie = document.cookie.match('(^|;)\\s*' + 'MyHalBrowserCsrfToken' + '\\s*=\\s*([^;]+)'); if (cookie != null) { @@ -204,11 +212,11 @@

Other login methods:

user: $("#username").val(), password: $("#password").val() }, - beforeSend: function (xhr, settings) { + beforeSend: function (xhr) { // If CSRF token found in cookie, send it back as X-XSRF-Token header var csrfToken = getCSRFToken(); if (csrfToken != null) { - xhr.setRequestHeader('X-XSRF-Token', csrfToken); + xhr.setRequestHeader('X-XSRF-Token', csrfToken); } }, success : successHandler, From 546afb189e1df8bdfbc9948e790004baa81ec894 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 29 Aug 2024 16:24:38 +0200 Subject: [PATCH 037/179] applied change suggested by reviewer: use String.prototype.includes --- dspace-server-webapp/src/main/resources/static/login.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/resources/static/login.html b/dspace-server-webapp/src/main/resources/static/login.html index 0597a66bfe96..959190020a13 100644 --- a/dspace-server-webapp/src/main/resources/static/login.html +++ b/dspace-server-webapp/src/main/resources/static/login.html @@ -120,7 +120,7 @@

Other login methods:

// Check for WWW-Authenticate header. If found, this means we are not yet authenticated, and // therefore we need to display available authentication options. var authenticate = xhr.getResponseHeader("WWW-Authenticate"); - if (authenticate !== null && authenticate.contains('location=')) { + if (authenticate !== null && authenticate.includes('location=')) { var element = $('div.other-login-methods'); var realms = authenticate.match(/(\w+ (\w+=((".*?")|[^,]*)(, )?)*)/g); if (realms.length === 1){ From a5e8d7aa15bc56c268ba67f19657f19edaa45253 Mon Sep 17 00:00:00 2001 From: igorbaptist4 Date: Tue, 10 Sep 2024 13:10:14 -0300 Subject: [PATCH 038/179] fix: set default configFile --- .../java/org/dspace/app/statistics/LogAnalyser.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java b/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java index 982c339963d2..2408a693b6fd 100644 --- a/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java +++ b/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java @@ -281,10 +281,14 @@ public class LogAnalyser { */ private static String fileTemplate = "dspace\\.log.*"; + private static final ConfigurationService configurationService = + DSpaceServicesFactory.getInstance().getConfigurationService(); + /** * the configuration file from which to configure the analyser */ - private static String configFile; + private static String configFile = configurationService.getProperty("dspace.dir") + + File.separator + "config" + File.separator + "dstat.cfg"; /** * the output file to which to write aggregation data @@ -616,8 +620,6 @@ public static String processLogs(Context context, String myLogDir, } // now do the host name and url lookup - ConfigurationService configurationService - = DSpaceServicesFactory.getInstance().getConfigurationService(); hostName = Utils.getHostName(configurationService.getProperty("dspace.ui.url")); name = configurationService.getProperty("dspace.name").trim(); url = configurationService.getProperty("dspace.ui.url").trim(); @@ -658,8 +660,6 @@ public static void setParameters(String myLogDir, String myFileTemplate, String myConfigFile, String myOutFile, Date myStartDate, Date myEndDate, boolean myLookUp) { - ConfigurationService configurationService - = DSpaceServicesFactory.getInstance().getConfigurationService(); if (myLogDir != null) { logDir = myLogDir; @@ -673,9 +673,6 @@ public static void setParameters(String myLogDir, String myFileTemplate, if (myConfigFile != null) { configFile = myConfigFile; - } else { - configFile = configurationService.getProperty("dspace.dir") - + File.separator + "config" + File.separator + "dstat.cfg"; } if (myStartDate != null) { From 412d5751f29f31bbdd872820a62b74970333f066 Mon Sep 17 00:00:00 2001 From: igorbaptist4 Date: Tue, 10 Sep 2024 18:44:15 -0300 Subject: [PATCH 039/179] fix: properly type in field id, adjust use of getProperty and add error handling when dbPath is null (when property usage-statistics.dbfile is commented --- .../org/dspace/statistics/util/StatisticsImporter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java index 95736a8bd6d9..1bd97a6f5ec9 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java @@ -357,7 +357,7 @@ protected void load(String filename, Context context, boolean verbose) { SolrInputDocument sid = new SolrInputDocument(); sid.addField("ip", ip); sid.addField("type", dso.getType()); - sid.addField("id", dso.getID()); + sid.addField("id", dso.getID().toString()); sid.addField("time", DateFormatUtils.format(date, SolrLoggerServiceImpl.DATE_FORMAT_8601)); sid.addField("continent", continent); sid.addField("country", country); @@ -471,13 +471,13 @@ public static void main(String[] args) throws Exception { boolean verbose = line.hasOption('v'); // Find our solr server - String sserver = configurationService.getProperty("solr-statistics", "server"); + String sserver = configurationService.getProperty("solr-statistics.server"); if (verbose) { System.out.println("Writing to solr server at: " + sserver); } solr = new HttpSolrClient.Builder(sserver).build(); - String dbPath = configurationService.getProperty("usage-statistics", "dbfile"); + String dbPath = configurationService.getProperty("usage-statistics.dbfile"); try { File dbFile = new File(dbPath); geoipLookup = new DatabaseReader.Builder(dbFile).build(); @@ -492,6 +492,10 @@ public static void main(String[] args) throws Exception { "Unable to load GeoLite Database file (" + dbPath + ")! You may need to reinstall it. See the DSpace " + "installation instructions for more details.", e); + } catch (NullPointerException e) { + log.error( + "The value of the property usage-statistics.dbfile is null. You may need to install the GeoLite Database file and/or uncomment the property in the config file!", + e); } From 338f3b1d3efaa0f7f3852654121cf1f93adeae7e Mon Sep 17 00:00:00 2001 From: igorbaptist4 Date: Tue, 10 Sep 2024 20:16:47 -0300 Subject: [PATCH 040/179] fix line length checkstyle --- .../java/org/dspace/statistics/util/StatisticsImporter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java index 1bd97a6f5ec9..354c803fe2ae 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java @@ -494,7 +494,8 @@ public static void main(String[] args) throws Exception { e); } catch (NullPointerException e) { log.error( - "The value of the property usage-statistics.dbfile is null. You may need to install the GeoLite Database file and/or uncomment the property in the config file!", + "The value of the property usage-statistics.dbfile is null. You may need to install the GeoLite " + + "Database file and/or uncomment the property in the config file!", e); } From b8f4ab0eb3e90b080eaae057fb5ee673d3477dc2 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Tue, 17 Sep 2024 08:47:54 -0400 Subject: [PATCH 041/179] More information about failed DOI registrations. --- .../dspace/identifier/doi/DOIOrganiser.java | 3 ++- .../identifier/doi/DataCiteConnector.java | 22 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java index b03af68b42ab..0ee64f94b799 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -577,7 +577,8 @@ public void update(DOI doiRow) { } } catch (IdentifierException ex) { if (!(ex instanceof DOIIdentifierException)) { - LOG.error("It wasn't possible to register the identifier online. ", ex); + LOG.error("Registering DOI {} for object {}: the registrar returned an error.", + doiRow.getDoi(), dso.getID(), ex); } DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java index 23af904f2c71..e56a82942369 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -461,6 +461,10 @@ public void reserveDOI(Context context, DSpaceObject dso, String doi) log.warn("While reserving the DOI {}, we got a http status code " + "{} and the message \"{}\".", doi, Integer.toString(resp.statusCode), resp.getContent()); + Format format = Format.getCompactFormat(); + format.setEncoding("UTF-8"); + XMLOutputter xout = new XMLOutputter(format); + log.info("We send the following XML:\n{}", xout.outputString(root)); throw new DOIIdentifierException("Unable to parse an answer from " + "DataCite API. Please have a look into DSpace logs.", DOIIdentifierException.BAD_ANSWER); @@ -632,6 +636,14 @@ protected DataCiteResponse sendGetRequest(String doi, String path) return sendHttpRequest(httpget, doi); } + /** + * Send a DataCite metadata document to the registrar. + * + * @param doi identify the object. + * @param metadataRoot describe the object. The root element of the document. + * @return the registrar's response. + * @throws DOIIdentifierException passed through. + */ protected DataCiteResponse sendMetadataPostRequest(String doi, Element metadataRoot) throws DOIIdentifierException { Format format = Format.getCompactFormat(); @@ -640,6 +652,14 @@ protected DataCiteResponse sendMetadataPostRequest(String doi, Element metadataR return sendMetadataPostRequest(doi, xout.outputString(new Document(metadataRoot))); } + /** + * Send a DataCite metadata document to the registrar. + * + * @param doi identify the object. + * @param metadata describe the object. + * @return the registrar's response. + * @throws DOIIdentifierException passed through. + */ protected DataCiteResponse sendMetadataPostRequest(String doi, String metadata) throws DOIIdentifierException { // post mds/metadata/ @@ -687,7 +707,7 @@ protected DataCiteResponse sendMetadataPostRequest(String doi, String metadata) * properties such as request URI and method type. * @param doi DOI string to operate on * @return response from DataCite - * @throws DOIIdentifierException if DOI error + * @throws DOIIdentifierException if registrar returns an error. */ protected DataCiteResponse sendHttpRequest(HttpUriRequest req, String doi) throws DOIIdentifierException { From 353cf71f3af08a121e62374cf3af0451f8006027 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Wed, 18 Sep 2024 11:36:45 -0400 Subject: [PATCH 042/179] Fix new ErrorProne errors from new EP version, and a few ancient warnings. --- .../dspace/authenticate/LDAPAuthentication.java | 6 ++++-- .../main/java/org/dspace/curate/Curation.java | 16 ++++++++++++---- .../rest/repository/DSpaceRestRepository.java | 5 ----- .../app/rest/utils/DSpaceKernelInitializer.java | 1 + .../dspace/services/email/EmailServiceImpl.java | 1 + .../java/org/dspace/app/ServerApplication.java | 6 +++--- pom.xml | 2 +- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index b791df15b5c0..81280051ff21 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -503,6 +503,7 @@ protected String getDNOfUser(String adminUser, String adminPassword, Context con } else { searchName = ldap_provider_url + ldap_search_context; } + @SuppressWarnings("BanJNDI") NamingEnumeration answer = ctx.search( searchName, "(&({0}={1}))", new Object[] {ldap_id_field, @@ -553,7 +554,7 @@ protected String getDNOfUser(String adminUser, String adminPassword, Context con att = atts.get(attlist[4]); if (att != null) { // loop through all groups returned by LDAP - ldapGroup = new ArrayList(); + ldapGroup = new ArrayList<>(); for (NamingEnumeration val = att.getAll(); val.hasMoreElements(); ) { ldapGroup.add((String) val.next()); } @@ -633,7 +634,8 @@ protected boolean ldapAuthenticate(String netid, String password, ctx.addToEnvironment(javax.naming.Context.AUTHORITATIVE, "true"); ctx.addToEnvironment(javax.naming.Context.REFERRAL, "follow"); // dummy operation to check if authentication has succeeded - ctx.getAttributes(""); + @SuppressWarnings("BanJNDI") + Attributes trash = ctx.getAttributes(""); } else if (!useTLS) { // Authenticate env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "Simple"); diff --git a/dspace-api/src/main/java/org/dspace/curate/Curation.java b/dspace-api/src/main/java/org/dspace/curate/Curation.java index 4d70286e79e0..ece1b7738af3 100644 --- a/dspace-api/src/main/java/org/dspace/curate/Curation.java +++ b/dspace-api/src/main/java/org/dspace/curate/Curation.java @@ -165,7 +165,7 @@ private long runQueue(TaskQueue queue, Curator curator) throws SQLException, Aut * End of curation script; logs script time if -v verbose is set * * @param timeRun Time script was started - * @throws SQLException If DSpace contextx can't complete + * @throws SQLException If DSpace context can't complete */ private void endScript(long timeRun) throws SQLException { context.complete(); @@ -300,9 +300,17 @@ private void initGeneralLineOptionsAndCheckIfValid() { // scope if (this.commandLine.getOptionValue('s') != null) { this.scope = this.commandLine.getOptionValue('s'); - if (this.scope != null && Curator.TxScope.valueOf(this.scope.toUpperCase()) == null) { - this.handler.logError("Bad transaction scope '" + this.scope + "': only 'object', 'curation' or " + - "'open' recognized"); + boolean knownScope; + try { + Curator.TxScope.valueOf(this.scope.toUpperCase()); + knownScope = true; + } catch (IllegalArgumentException | NullPointerException e) { + knownScope = false; + } + if (!knownScope) { + this.handler.logError("Bad transaction scope '" + + this.scope + + "': only 'object', 'curation' or 'open' recognized"); throw new IllegalArgumentException( "Bad transaction scope '" + this.scope + "': only 'object', 'curation' or " + "'open' recognized"); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java index 296c4322a3fc..cde28b836c6d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java @@ -50,17 +50,12 @@ public abstract class DSpaceRestRepository, PagingAndSortingRepository, BeanNameAware { - private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(DSpaceRestRepository.class); - private String thisRepositoryBeanName; private DSpaceRestRepository thisRepository; @Autowired private ApplicationContext applicationContext; - @Autowired - private MetadataFieldService metadataFieldService; - /** * From BeanNameAware. Allows us to capture the name of the bean, so we can load it into thisRepository. * See getThisRepository() method. diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DSpaceKernelInitializer.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DSpaceKernelInitializer.java index 7dfcd1d76d1d..88a093c0575d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DSpaceKernelInitializer.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DSpaceKernelInitializer.java @@ -81,6 +81,7 @@ public void initialize(final ConfigurableApplicationContext applicationContext) * Initially look for JNDI Resource called "java:/comp/env/dspace.dir". * If not found, use value provided in "dspace.dir" in Spring Environment */ + @SuppressWarnings("BanJNDI") private String getDSpaceHome(ConfigurableEnvironment environment) { // Load the "dspace.dir" property from Spring Boot's Configuration (application.properties) // This gives us the location of our DSpace configurations, necessary to start the kernel diff --git a/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java b/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java index e26954ff0259..b8de1c79994a 100644 --- a/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java +++ b/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java @@ -62,6 +62,7 @@ public Session getSession() { } @PostConstruct + @SuppressWarnings("BanJNDI") public void init() { // See if there is already a Session in our environment String sessionName = cfg.getProperty("mail.session.name"); diff --git a/dspace/modules/server/src/main/java/org/dspace/app/ServerApplication.java b/dspace/modules/server/src/main/java/org/dspace/app/ServerApplication.java index 34acc778b7f3..bc8e4f8a78a5 100644 --- a/dspace/modules/server/src/main/java/org/dspace/app/ServerApplication.java +++ b/dspace/modules/server/src/main/java/org/dspace/app/ServerApplication.java @@ -23,7 +23,7 @@ * NOTE: This extends SpringBootServletInitializer in order to allow us to build * a deployable WAR file with Spring Boot. See: * http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file - * + * * @author Luca Giamminonni (luca.giamminonni at 4science.it) * */ @@ -39,8 +39,8 @@ public class ServerApplication extends SpringBootServletInitializer { *

* See: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file * - * @param application - * @return + * @param application some builder. + * @return the builder, configured with DSpace sources and initializers. */ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { diff --git a/pom.xml b/pom.xml index 6129e74daa55..d59342adcb17 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 8.11.3 3.10.8 - 2.10.0 + 2.32.0 2.16.0 2.16.0 From 082756fa70ff22e5b77ba310c420367fd571a176 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Wed, 18 Sep 2024 15:18:55 -0400 Subject: [PATCH 043/179] Fix ErrorProne errors in tests. Also fix some of the hundreds of warnings. This uncovered still more warnings that hadn't been previously reported, probably because there are simply too many. --- .../dspace/util/DSpaceKernelInitializer.java | 1 + .../rest/repository/DSpaceRestRepository.java | 2 - .../AuthorizationFeatureRestRepositoryIT.java | 17 +- .../rest/AuthorizationFeatureServiceIT.java | 18 ++- .../rest/AuthorizationRestRepositoryIT.java | 152 +++++++++--------- .../app/rest/CollectionRestRepositoryIT.java | 6 +- .../app/rest/CommunityRestRepositoryIT.java | 4 +- .../DSpaceConfigurationServiceTest.java | 18 ++- .../servicemanager/ProviderHolderTest.java | 15 +- .../servicemanager/ProviderStackTest.java | 43 ++--- 10 files changed, 137 insertions(+), 139 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/util/DSpaceKernelInitializer.java b/dspace-api/src/test/java/org/dspace/util/DSpaceKernelInitializer.java index a6f381bafbae..8f9169875ab3 100644 --- a/dspace-api/src/test/java/org/dspace/util/DSpaceKernelInitializer.java +++ b/dspace-api/src/test/java/org/dspace/util/DSpaceKernelInitializer.java @@ -83,6 +83,7 @@ public void initialize(final ConfigurableApplicationContext applicationContext) * Initially look for JNDI Resource called "java:/comp/env/dspace.dir". * If not found, use value provided in "dspace.dir" in Spring Environment */ + @SuppressWarnings("BanJNDI") private String getDSpaceHome(ConfigurableEnvironment environment) { // Load the "dspace.dir" property from Spring's configuration. // This gives us the location of our DSpace configuration, which is diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java index cde28b836c6d..cf7c556e3ac3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java @@ -17,7 +17,6 @@ import com.fasterxml.jackson.databind.JsonNode; import jakarta.servlet.http.HttpServletRequest; -import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.RESTAuthorizationException; import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException; @@ -26,7 +25,6 @@ import org.dspace.app.rest.model.RestAddressableModel; import org.dspace.app.rest.model.patch.Patch; import org.dspace.authorize.AuthorizeException; -import org.dspace.content.service.MetadataFieldService; import org.dspace.core.Context; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java index 0aadff7a9927..c318a1038754 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java @@ -37,12 +37,12 @@ public class AuthorizationFeatureRestRepositoryIT extends AbstractControllerInte @Autowired private AuthorizationFeatureService authzFeatureService; - @Test /** - * All the features should be returned + * All the features should be returned. * * @throws Exception */ + @Test public void findAllTest() throws Exception { int featuresNum = authzFeatureService.findAll().size(); int expReturn = featuresNum > 20 ? 20 : featuresNum; @@ -62,20 +62,20 @@ public void findAllTest() throws Exception { } - @Test /** * The feature endpoint must provide proper pagination. Unauthorized and * forbidden scenarios are managed in the findAllTest * * @throws Exception */ + @Test public void findAllWithPaginationTest() throws Exception { int featuresNum = authzFeatureService.findAll().size(); String adminToken = getAuthToken(admin.getEmail(), password); - List featureIDs = new ArrayList(); + List featureIDs = new ArrayList<>(); for (int page = 0; page < featuresNum; page++) { - AtomicReference idRef = new AtomicReference(); + AtomicReference idRef = new AtomicReference<>(); getClient(adminToken) .perform(get("/api/authz/features").param("page", String.valueOf(page)).param("size", "1")) @@ -101,12 +101,13 @@ public void findAllWithPaginationTest() throws Exception { } } - @Test /** - * The feature resource endpoint must expose the proper structure and be reserved to administrators + * The feature resource endpoint must expose the proper structure and be + * reserved to administrators. * * @throws Exception */ + @Test public void findOneTest() throws Exception { getClient().perform(get("/api/authz/features/withdrawItem")).andExpect(status().isOk()) .andExpect(jsonPath("$.id", is("withdrawItem"))) @@ -121,12 +122,12 @@ public void findOneNotFoundTest() throws Exception { } - @Test /** * It should be possible to find features by resourcetype. The endpoint is only available to administrators * * @throws Exception */ + @Test public void findByResourceTypeTest() throws Exception { AuthorizationFeature alwaysTrueFeature = authzFeatureService.find(AlwaysTrueFeature.NAME); String adminToken = getAuthToken(admin.getEmail(), password); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureServiceIT.java index 66be81035272..31db90f54fe6 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureServiceIT.java @@ -49,12 +49,12 @@ public class AuthorizationFeatureServiceIT extends AbstractControllerIntegration @Autowired private AuthorizationFeatureService authzFeatureService; - @Test /** - * All the features available in the Sprint Context should be returned + * All the features available in the Sprint Context should be returned. * * @throws Exception */ + @Test public void findAllTest() throws Exception { List authzFeatureServiceFindAll = authzFeatureService.findAll(); @@ -70,12 +70,13 @@ public void findAllTest() throws Exception { equalTo(featureNames.size())); } - @Test /** - * The find method should return existing feature and null in the case the feature doesn't exist + * The find method should return existing feature or {@code null} in the + * case the feature doesn't exist. * * @throws Exception */ + @Test public void findTest() throws Exception { AuthorizationFeature aFeature = authzFeatureService.find(AlwaysTrueFeature.NAME); assertThat("check that one of our mock feature is retrieved", aFeature.getName(), @@ -85,12 +86,12 @@ public void findTest() throws Exception { assertThat("check that not existing feature name return null", aNotExistingFeature, equalTo(null)); } - @Test /** - * The findByResourceType must return only features that support the specified type + * The findByResourceType must return only features that support the specified type. * * @throws Exception */ + @Test public void findByResourceTypeTest() throws Exception { // we have at least one feature that support the Site object final String siteUniqueType = SiteRest.CATEGORY + "." + SiteRest.NAME; @@ -119,12 +120,13 @@ public void findByResourceTypeTest() throws Exception { assertThat(notExistingTypeFeatures.size(), equalTo(0)); } - @Test /** - * The isAuthorized must return true for authorized feature and false for not authorized feature + * The isAuthorized must return {@code true} for authorized feature and + * {@code false} for not authorized feature. * * @throws Exception */ + @Test public void isAuthorizedTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java index 3f139caae777..9fcf1bab4797 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java @@ -70,7 +70,7 @@ /** * Test suite for the Authorization endpoint - * + * * @author Andrea Bollini (andrea.bollini at 4science.it) * */ @@ -99,37 +99,37 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration private Utils utils; private SiteService siteService; - /** + /** * this hold a reference to the test feature {@link AlwaysTrueFeature} */ private AuthorizationFeature alwaysTrue; - /** + /** * this hold a reference to the test feature {@link AlwaysFalseFeature} */ private AuthorizationFeature alwaysFalse; - /** + /** * this hold a reference to the test feature {@link AlwaysThrowExceptionFeature} */ private AuthorizationFeature alwaysException; - /** + /** * this hold a reference to the test feature {@link TrueForAdminsFeature} */ private AuthorizationFeature trueForAdmins; - /** + /** * this hold a reference to the test feature {@link TrueForLoggedUsersFeature} */ private AuthorizationFeature trueForLoggedUsers; - /** + /** * this hold a reference to the test feature {@link TrueForTestFeature} */ private AuthorizationFeature trueForTestUsers; - /** + /** * this hold a reference to the test feature {@link TrueForUsersInGroupTestFeature} */ private AuthorizationFeature trueForUsersInGroupTest; @@ -150,12 +150,12 @@ public void setUp() throws Exception { configurationService.setProperty("webui.user.assumelogin", true); } - @Test /** * This method is not implemented * * @throws Exception */ + @Test public void findAllTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); getClient(adminToken).perform(get("/api/authz/authorizations")) @@ -164,12 +164,12 @@ public void findAllTest() throws Exception { .andExpect(status().isMethodNotAllowed()); } - @Test /** * Verify that an user can access a specific authorization * * @throws Exception */ + @Test public void findOneTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -206,12 +206,12 @@ public void findOneTest() throws Exception { Matchers.is(AuthorizationMatcher.matchAuthorization(authAnonymousUserSite)))); } - @Test /** * Verify that the unauthorized return code is used in the appropriate scenarios * * @throws Exception */ + @Test public void findOneUnauthorizedTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -229,12 +229,12 @@ public void findOneUnauthorizedTest() throws Exception { .andExpect(status().isUnauthorized()); } - @Test /** * Verify that the forbidden return code is used in the appropriate scenarios * * @throws Exception */ + @Test public void findOneForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); Site site = siteService.findSite(context); @@ -265,12 +265,12 @@ public void findOneForbiddenTest() throws Exception { .andExpect(status().isForbidden()); } - @Test /** * Verify that the not found return code is used in the appropriate scenarios * * @throws Exception */ + @Test public void findOneNotFoundTest() throws Exception { context.turnOffAuthorisationSystem(); Site site = siteService.findSite(context); @@ -352,12 +352,12 @@ public void findOneNotFoundTest() throws Exception { } - @Test /** * Verify that an exception in the feature check will be reported back * * @throws Exception */ + @Test public void findOneInternalServerErrorTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -375,16 +375,16 @@ public void findOneInternalServerErrorTest() throws Exception { .andExpect(status().isInternalServerError()); } - @Test /** * Verify that the search by object works properly in allowed scenarios: * - for an administrator * - for an administrator that want to inspect permission of the anonymous users or another user * - for a logged-in "normal" user * - for anonymous - * + * * @throws Exception */ + @Test public void findByObjectTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -667,13 +667,13 @@ public void findByObjectTest() throws Exception { .andExpect(jsonPath("$.page.totalElements", greaterThanOrEqualTo(1))); } - @Test /** * Verify that the findByObject return an empty page when the requested object doesn't exist but the uri is * potentially valid (i.e. deleted object) - * + * * @throws Exception */ + @Test public void findByNotExistingObjectTest() throws Exception { String wrongSiteUri = "http://localhost/api/core/sites/" + UUID.randomUUID(); @@ -759,12 +759,12 @@ public void findByNotExistingObjectTest() throws Exception { .andExpect(jsonPath("$.page.totalElements", is(0))); } - @Test /** * Verify that the findByObject return the 400 Bad Request response for invalid or missing URI (required parameter) - * + * * @throws Exception */ + @Test public void findByObjectBadRequestTest() throws Exception { String[] invalidUris = new String[] { "invalid-uri", @@ -837,12 +837,12 @@ public void findByObjectBadRequestTest() throws Exception { .andExpect(status().isBadRequest()); } - @Test /** * Verify that the findByObject return the 401 Unauthorized response when an eperson is involved - * + * * @throws Exception */ + @Test public void findByObjectUnauthorizedTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -876,13 +876,13 @@ public void findByObjectUnauthorizedTest() throws Exception { .andExpect(status().isUnauthorized()); } - @Test /** * Verify that the findByObject return the 403 Forbidden response when a non-admin eperson try to search the - * authorization of another eperson - * + * authorization of another eperson. + * * @throws Exception */ + @Test public void findByObjectForbiddenTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -920,11 +920,11 @@ public void findByObjectForbiddenTest() throws Exception { .andExpect(status().isForbidden()); } - @Test /** * Verify that an exception in the feature check will be reported back * @throws Exception */ + @Test public void findByObjectInternalServerErrorTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -977,16 +977,18 @@ public void findByObjectInternalServerErrorTest() throws Exception { .andExpect(status().isInternalServerError()); } - @Test /** - * Verify that the search by object and feature works properly in allowed scenarios: - * - for an administrator - * - for an administrator that want to inspect permission of the anonymous users or another user - * - for a logged-in "normal" user - * - for anonymous - * + * Verify that the search by object and feature works properly in allowed scenarios. + *

    + *
  • for an administrator
  • + *
  • for an administrator that wants to inspect permission of the anonymous users or another user
  • + *
  • for a logged-in "normal" user
  • + *
  • for a not-logged-in "normal" user
  • + *
+ * * @throws Exception */ + @Test public void findByObjectAndFeatureTest() throws Exception { context.turnOffAuthorisationSystem(); Community com = CommunityBuilder.createCommunity(context).withName("A test community").build(); @@ -1146,12 +1148,12 @@ public void findByObjectAndFeatureTest() throws Exception { ))); } - @Test /** * Verify that the search by object and feature works return 204 No Content when a feature is not granted - * + * * @throws Exception */ + @Test public void findByObjectAndFeatureNotGrantedTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -1208,13 +1210,13 @@ public void findByObjectAndFeatureNotGrantedTest() throws Exception { .andExpect(jsonPath("$.page.totalElements", is(0))); } - @Test /** * Verify that the findByObject return the 204 No Content code when the requested object doesn't exist but the uri * is potentially valid (i.e. deleted object) or the feature doesn't exist - * + * * @throws Exception */ + @Test public void findByNotExistingObjectAndFeatureTest() throws Exception { String wrongSiteUri = "http://localhost/api/core/sites/" + UUID.randomUUID(); Site site = siteService.findSite(context); @@ -1315,13 +1317,13 @@ public void findByNotExistingObjectAndFeatureTest() throws Exception { .andExpect(jsonPath("$.page.totalElements", is(0))); } - @Test /** - * Verify that the findByObject return the 400 Bad Request response for invalid or missing URI or feature (required - * parameters) + * Verify that the findByObject return the 400 Bad Request response for + * invalid or missing URI or feature (required parameters). * * @throws Exception */ + @Test public void findByObjectAndFeatureBadRequestTest() throws Exception { String[] invalidUris = new String[] { "invalid-uri", @@ -1390,12 +1392,12 @@ public void findByObjectAndFeatureBadRequestTest() throws Exception { } } - @Test /** * Verify that the findByObjectAndFeature return the 401 Unauthorized response when an eperson is involved - * + * * @throws Exception */ + @Test public void findByObjectAndFeatureUnauthorizedTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -1433,13 +1435,14 @@ public void findByObjectAndFeatureUnauthorizedTest() throws Exception { .andExpect(status().isUnauthorized()); } - @Test /** - * Verify that the findByObjectAndFeature return the 403 Forbidden response when a non-admin eperson try to search - * the authorization of another eperson - * + * Verify that the findByObjectAndFeature returns the 403 Forbidden response + * when a non-admin eperson tries to search the authorization of another + * eperson. + * * @throws Exception */ + @Test public void findByObjectAndFeatureForbiddenTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -1481,11 +1484,11 @@ public void findByObjectAndFeatureForbiddenTest() throws Exception { .andExpect(status().isForbidden()); } - @Test /** - * Verify that an exception in the feature check will be reported back + * Verify that an exception in the feature check will be reported back. * @throws Exception */ + @Test public void findByObjectAndFeatureInternalServerErrorTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -1528,16 +1531,18 @@ public void findByObjectAndFeatureInternalServerErrorTest() throws Exception { .andExpect(status().isInternalServerError()); } - @Test /** - * Verify that the search by multiple objects and features works properly in allowed scenarios: - * - for an administrator - * - for an administrator that want to inspect permission of the anonymous users or another user - * - for a logged-in "normal" user - * - for anonymous + * Verify that the search by multiple objects and features works properly in allowed scenarios. + *
    + *
  • for an administrator
  • + *
  • for an administrator that wants to inspect permission of the anonymous users or another user
  • + *
  • for a logged-in "normal" user
  • + *
  • for a not-logged-in user
  • + *
* * @throws Exception */ + @Test public void findByMultipleObjectsAndFeaturesTest() throws Exception { context.turnOffAuthorisationSystem(); Community com = CommunityBuilder.createCommunity(context).withName("A test community").build(); @@ -1899,16 +1904,19 @@ public void findByMultipleObjectsAndFeaturesTest() throws Exception { ))); } - @Test /** - * Verify that the paginated search by multiple objects and features works properly in allowed scenarios: - * - for an administrator - * - for an administrator that want to inspect permission of the anonymous users or another user - * - for a logged-in "normal" user - * - for anonymous + * Verify that the paginated search by multiple objects and features works + * properly in allowed scenarios. + *
    + *
  • for an administrator
  • + *
  • for an administrator that wants to inspect permission of the anonymous users or another user
  • + *
  • for a logged-in "normal" user
  • + *
  • for a not-logged-in user
  • + *
* * @throws Exception */ + @Test public void findByMultipleObjectsAndFeaturesPaginationTest() throws Exception { context.turnOffAuthorisationSystem(); @@ -2098,12 +2106,12 @@ public void findByMultipleObjectsAndFeaturesPaginationTest() throws Exception { ))); } - @Test /** * Verify that the search by many objects and features works return 204 No Content when no feature is granted. * * @throws Exception */ + @Test public void findByMultipleObjectsAndFeatureNotGrantedTest() throws Exception { context.turnOffAuthorisationSystem(); @@ -2190,14 +2198,15 @@ public void findByMultipleObjectsAndFeatureNotGrantedTest() throws Exception { .andExpect(jsonPath("$.page.totalElements", is(0))); } - @Test /** * Verify that the find by multiple objects and features - * return the 204 No Content code when the requested object doesn't exist but the uri - * is potentially valid (i.e. deleted object) or the feature doesn't exist + * return the 204 No Content code when the requested object doesn't exist + * but the uri is potentially valid (a deleted object) or the feature + * doesn't exist. * * @throws Exception */ + @Test public void findByNotExistingMultipleObjectsAndFeatureTest() throws Exception { String wrongSiteId = UUID.randomUUID().toString(); Site site = siteService.findSite(context); @@ -2322,13 +2331,13 @@ public void findByNotExistingMultipleObjectsAndFeatureTest() throws Exception { .andExpect(jsonPath("$.page.totalElements", is(0))); } - @Test /** * Verify that the find by multiple objects and features * return the 400 Bad Request response for invalid or missing UUID or type * * @throws Exception */ + @Test public void findByMultipleObjectsAndFeatureBadRequestTest() throws Exception { String[] invalidUris = new String[] { "foo", @@ -2441,13 +2450,13 @@ public void findByMultipleObjectsAndFeatureBadRequestTest() throws Exception { .andExpect(status().isBadRequest()); } - @Test /** * Verify that the find by multiple objects and features return * the 401 Unauthorized response when an eperson is involved * * @throws Exception */ + @Test public void findByMultipleObjectsAndFeatureUnauthorizedTest() throws Exception { Site site = siteService.findSite(context); String siteId = site.getID().toString(); @@ -2488,7 +2497,6 @@ public void findByMultipleObjectsAndFeatureUnauthorizedTest() throws Exception { .andExpect(status().isUnauthorized()); } - @Test /** * Verify that the find by multiple objects and features * returns the 403 Forbidden response when a non-admin eperson try to search @@ -2496,6 +2504,7 @@ public void findByMultipleObjectsAndFeatureUnauthorizedTest() throws Exception { * * @throws Exception */ + @Test public void findByMultipleObjectsAndFeatureForbiddenTest() throws Exception { Site site = siteService.findSite(context); String siteId = site.getID().toString(); @@ -2545,11 +2554,11 @@ public void findByMultipleObjectsAndFeatureForbiddenTest() throws Exception { .andExpect(status().isForbidden()); } - @Test /** * Verify that an exception in the multiple authorization features check will be reported back * @throws Exception */ + @Test public void findByMultipleObjectsAndFeatureInternalServerErrorTest() throws Exception { Site site = siteService.findSite(context); String siteId = site.getID().toString(); @@ -2596,14 +2605,14 @@ public void findByMultipleObjectsAndFeatureInternalServerErrorTest() throws Exce .andExpect(status().isInternalServerError()); } - @Test /** * This test will check that special group are correctly used to verify - * authorization for the current loggedin user but not inherited from the + * authorization for the current logged-in user but not inherited from the * Administrators login when they look to authorization of third users - * + * * @throws Exception */ + @Test public void verifySpecialGroupMembershipTest() throws Exception { Site site = siteService.findSite(context); SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); @@ -2802,5 +2811,4 @@ private String getAuthorizationID(String epersonUuid, String featureName, String + id.toString(); } - } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java index afd2c7f1f3cd..fcc1c68d26bc 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java @@ -1259,7 +1259,7 @@ public void createTestByAuthorizedUser() throws Exception { authorizeService.addPolicy(context, parentCommunity, Constants.ADD, eperson); context.restoreAuthSystemState(); - AtomicReference idRef = new AtomicReference(); + AtomicReference idRef = new AtomicReference<>(); try { String authToken = getAuthToken(eperson.getEmail(), password); @@ -3197,8 +3197,8 @@ public void patchMetadataCheckReindexingTest() throws Exception { ))) .andExpect(jsonPath("$.page.totalElements", is(1))); - List updateTitle = new ArrayList(); - Map value = new HashMap(); + List updateTitle = new ArrayList<>(); + Map value = new HashMap<>(); value.put("value", "New Name"); updateTitle.add(new ReplaceOperation("/metadata/dc.title/0", value)); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java index 60b6d39a0705..6837b8900398 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java @@ -1410,11 +1410,11 @@ public void findAllSubCommunitiesGrantAccessAdminsTest() throws Exception { .withAdminGroup(child2Admin) .build(); - Community ommunityChild1Child1 = CommunityBuilder.createSubCommunity(context, communityChild1) + Community communityChild1Child1 = CommunityBuilder.createSubCommunity(context, communityChild1) .withName("Sub1 Community 1") .build(); - Community сommunityChild2Child1 = CommunityBuilder.createSubCommunity(context, communityChild2) + Community communityChild2Child1 = CommunityBuilder.createSubCommunity(context, communityChild2) .withName("Sub2 Community 1") .build(); diff --git a/dspace-services/src/test/java/org/dspace/servicemanager/config/DSpaceConfigurationServiceTest.java b/dspace-services/src/test/java/org/dspace/servicemanager/config/DSpaceConfigurationServiceTest.java index f15cae0ab48c..4002e5e43308 100644 --- a/dspace-services/src/test/java/org/dspace/servicemanager/config/DSpaceConfigurationServiceTest.java +++ b/dspace-services/src/test/java/org/dspace/servicemanager/config/DSpaceConfigurationServiceTest.java @@ -56,7 +56,7 @@ public void init() { configurationService.clear(); // Start fresh with out own set of configs - Map l = new HashMap(); + Map l = new HashMap<>(); l.put("service.name", "DSpace"); l.put("sample.array", "itemA,itemB,itemC"); l.put("sample.number", "123"); @@ -86,7 +86,7 @@ public void tearDown() { @Test public void testVariableReplacement() { - Map l = new HashMap(); + Map l = new HashMap<>(); l.put("service.name", "DSpace"); l.put("aaronz", "Aaron Zeckoski"); l.put("current.user", "${aaronz}"); @@ -295,7 +295,7 @@ public void testGetPropertyAsTypeStringClassOfT() { assertEquals("itemC", array[2]); Integer number = configurationService.getPropertyAsType("sample.number", Integer.class); assertNotNull(number); - assertEquals(new Integer(123), number); + assertEquals(Integer.valueOf(123), number); Boolean bool = configurationService.getPropertyAsType("sample.boolean", Boolean.class); assertNotNull(bool); @@ -306,7 +306,6 @@ public void testGetPropertyAsTypeStringClassOfT() { assertEquals(Boolean.FALSE, bool2); boolean bool3 = configurationService.getPropertyAsType("INVALID.PROPERTY", boolean.class); - assertNotNull(bool3); assertEquals(false, bool3); assertEquals(123, (int) configurationService.getPropertyAsType("sample.number", int.class)); @@ -333,9 +332,9 @@ public void testGetPropertyAsTypeStringT() { assertEquals("itemB", array[1]); assertEquals("itemC", array[2]); - Integer number = configurationService.getPropertyAsType("sample.number", new Integer(12345)); + Integer number = configurationService.getPropertyAsType("sample.number", 12345); assertNotNull(number); - assertEquals(new Integer(123), number); + assertEquals(Integer.valueOf(123), number); Boolean bool = configurationService.getPropertyAsType("sample.boolean", Boolean.FALSE); assertNotNull(bool); @@ -522,8 +521,11 @@ public void testReloadConfig() { } /** - * Tests the ability of our ConfigurationService to automatically reload properties after a set period - * of time. + * Tests the ability of our ConfigurationService to automatically reload + * properties after a set period of time. + * @throws ConfigurationException passed through. + * @throws IOException if test properties file cannot be created or copied. + * @throws InterruptedException if sleep is interrupted. */ @Test public void testAutomaticReload() throws ConfigurationException, IOException, InterruptedException { diff --git a/dspace-services/src/test/java/org/dspace/utils/servicemanager/ProviderHolderTest.java b/dspace-services/src/test/java/org/dspace/utils/servicemanager/ProviderHolderTest.java index 995d3ba62445..5ff526983ee5 100644 --- a/dspace-services/src/test/java/org/dspace/utils/servicemanager/ProviderHolderTest.java +++ b/dspace-services/src/test/java/org/dspace/utils/servicemanager/ProviderHolderTest.java @@ -8,7 +8,6 @@ package org.dspace.utils.servicemanager; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; @@ -16,7 +15,7 @@ import org.junit.Test; /** - * Tests the ability of a provider holder to release a reference correctly + * Tests the ability of a provider holder to release a reference correctly. * * @author Aaron Zeckoski (azeckoski @ gmail.com) */ @@ -28,7 +27,7 @@ public class Thing { @Test public void testHolder() { - ProviderHolder holder = new ProviderHolder(); + ProviderHolder holder = new ProviderHolder<>(); assertNull(holder.getProvider()); Thing t = new Thing(); @@ -44,7 +43,7 @@ public void testHolder() { @Test public void testHolderRelease() { - ProviderHolder holder = new ProviderHolder(); + ProviderHolder holder = new ProviderHolder<>(); Thing t = new Thing(); holder.setProvider(t); @@ -66,7 +65,7 @@ public void testHolderRelease() { @Test public void testHolderException() { - ProviderHolder holder = new ProviderHolder(); + ProviderHolder holder = new ProviderHolder<>(); try { holder.getProviderOrFail(); fail("Should have died"); @@ -87,14 +86,10 @@ public void testHolderException() { @Test public void testHolderHashEqualsString() { - ProviderHolder holder = new ProviderHolder(); - assertNotNull(holder.hashCode()); - assertFalse(holder.equals(null)); + ProviderHolder holder = new ProviderHolder<>(); assertNotNull(holder.toString()); holder.setProvider(new Thing()); - assertNotNull(holder.hashCode()); - assertFalse(holder.equals(null)); assertNotNull(holder.toString()); holder = null; diff --git a/dspace-services/src/test/java/org/dspace/utils/servicemanager/ProviderStackTest.java b/dspace-services/src/test/java/org/dspace/utils/servicemanager/ProviderStackTest.java index 47c2b302a7d1..6641adb3b3ab 100644 --- a/dspace-services/src/test/java/org/dspace/utils/servicemanager/ProviderStackTest.java +++ b/dspace-services/src/test/java/org/dspace/utils/servicemanager/ProviderStackTest.java @@ -43,6 +43,7 @@ public UnorderedProvider(String prefix) { this.prefix = prefix; } + @Override public String getPrefix() { return prefix; } @@ -56,6 +57,7 @@ public OrderedProvider(String prefix, int order) { this.order = order; } + @Override public int getOrder() { return order; } @@ -78,11 +80,11 @@ public ConfigurableApplicationContext getApplicationContext() { } public List getServicesByType(Class type) { - return new ArrayList(); + return new ArrayList<>(); } public List getServicesNames() { - return new ArrayList(); + return new ArrayList<>(); } public Map getServicesWithNamesByType(Class type) { @@ -111,11 +113,10 @@ public T registerServiceClass(String name, Class type) { public void unregisterService(String name) { } }; - ProviderStack providers = new ProviderStack(sm, Provider.class); - assertNotNull(providers.hashCode()); + ProviderStack providers = new ProviderStack<>(sm, Provider.class); assertNotNull(providers.toString()); assertEquals(0, providers.size()); - assertTrue(providers.getProviders().size() == 0); + assertTrue(providers.getProviders().isEmpty()); providers.clear(); providers = null; @@ -126,13 +127,12 @@ public void unregisterService(String name) { */ @Test public void testProviderStackTArray() { - ProviderStack providers = new ProviderStack(new Provider[] { + ProviderStack providers = new ProviderStack<>(new Provider[] { new UnorderedProvider("ccc"), new UnorderedProvider("ddd"), new OrderedProvider("bbb", 5), new OrderedProvider("aaa", 2) }); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(4, providers.size()); // check the order @@ -153,13 +153,12 @@ public void testProviderStackTArray() { @Test public void testAddProvider() { // preload - ProviderStack providers = new ProviderStack(new Provider[] { + ProviderStack providers = new ProviderStack<>(new Provider[] { new UnorderedProvider("ccc"), new UnorderedProvider("ddd"), new OrderedProvider("bbb", 5), new OrderedProvider("aaa", 2) }); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(4, providers.size()); // check the order @@ -218,13 +217,12 @@ public void testAddProvider() { @Test public void testRemoveProvider() { // preload - ProviderStack providers = new ProviderStack(new Provider[] { + ProviderStack providers = new ProviderStack<>(new Provider[] { new UnorderedProvider("ccc"), new UnorderedProvider("ddd"), new OrderedProvider("bbb", 5), new OrderedProvider("aaa", 2) }); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(4, providers.size()); @@ -249,13 +247,12 @@ public void testRemoveProvider() { @Test public void testGetProviders() { // preload - ProviderStack providers = new ProviderStack(new Provider[] { + ProviderStack providers = new ProviderStack<>(new Provider[] { new UnorderedProvider("ccc"), new UnorderedProvider("ddd"), new OrderedProvider("bbb", 5), new OrderedProvider("aaa", 2) }); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(4, providers.size()); @@ -264,7 +261,7 @@ public void testGetProviders() { assertEquals(4, l.size()); l = null; - providers = new ProviderStack(); + providers = new ProviderStack<>(); l = providers.getProviders(); assertNotNull(l); assertEquals(0, l.size()); @@ -280,13 +277,12 @@ public void testGetProviders() { @Test public void testGetIterator() { // preload - ProviderStack providers = new ProviderStack(new Provider[] { + ProviderStack providers = new ProviderStack<>(new Provider[] { new UnorderedProvider("ccc"), new UnorderedProvider("ddd"), new OrderedProvider("bbb", 5), new OrderedProvider("aaa", 2) }); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(4, providers.size()); @@ -302,7 +298,7 @@ public void testGetIterator() { assertNotNull(it.next()); assertFalse(it.hasNext()); - providers = new ProviderStack(); + providers = new ProviderStack<>(); it = providers.getIterator(); assertNotNull(it); assertFalse(it.hasNext()); @@ -318,13 +314,12 @@ public void testGetIterator() { @Test public void testGetProvider() { // preload - ProviderStack providers = new ProviderStack(new Provider[] { + ProviderStack providers = new ProviderStack<>(new Provider[] { new UnorderedProvider("ccc"), new UnorderedProvider("ddd"), new OrderedProvider("bbb", 5), new OrderedProvider("aaa", 2) }); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(4, providers.size()); @@ -347,13 +342,12 @@ public void testGetProvider() { @Test public void testSize() { // preload - ProviderStack providers = new ProviderStack(new Provider[] { + ProviderStack providers = new ProviderStack<>(new Provider[] { new UnorderedProvider("ccc"), new UnorderedProvider("ddd"), new OrderedProvider("bbb", 5), new OrderedProvider("aaa", 2) }); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(4, providers.size()); @@ -367,18 +361,16 @@ public void testSize() { @Test public void testClear() { // preload - ProviderStack providers = new ProviderStack(new Provider[] { + ProviderStack providers = new ProviderStack<>(new Provider[] { new UnorderedProvider("ccc"), new UnorderedProvider("ddd"), new OrderedProvider("bbb", 5), new OrderedProvider("aaa", 2) }); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(4, providers.size()); providers.clear(); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(0, providers.size()); @@ -393,14 +385,13 @@ public void testClear() { public void testRefresh() { Provider p1 = new OrderedProvider("aaa", 2); Provider p2 = new UnorderedProvider("ccc"); - ProviderStack providers = new ProviderStack(new Provider[] { + ProviderStack providers = new ProviderStack<>(new Provider[] { p2, new UnorderedProvider("ddd"), new OrderedProvider("bbb", 5), p1 }); - assertNotNull(providers.hashCode()); assertNotNull(providers.toString()); assertEquals(4, providers.size()); From 2e4bfe9bee34c20723f5ec0ef824b2056734e786 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Thu, 19 Sep 2024 14:13:25 +0200 Subject: [PATCH 044/179] Small spelling fixes to import tests and resource files. (also metadatums->metadata) --- .../contributor/SimpleConcatContributor.java | 2 +- .../CiniiImportMetadataSourceServiceIT.java | 24 +++++++++---------- .../rest/RelationshipRestRepositoryIT.java | 2 +- .../WOSImportMetadataSourceServiceIT.java | 4 ++-- ...esponce-ids.xml => cinii-response-ids.xml} | 0 .../{wos-responce.xml => wos-response.xml} | 0 6 files changed, 16 insertions(+), 16 deletions(-) rename dspace-server-webapp/src/test/resources/org/dspace/app/rest/{cinii-responce-ids.xml => cinii-response-ids.xml} (100%) rename dspace-server-webapp/src/test/resources/org/dspace/app/rest/{wos-responce.xml => wos-response.xml} (100%) diff --git a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleConcatContributor.java b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleConcatContributor.java index d84bc65701c6..9a2aa242c6b8 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleConcatContributor.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/metadatamapping/contributor/SimpleConcatContributor.java @@ -26,7 +26,7 @@ * This contributor is able to concat multi value. * Given a certain path, if it contains several nodes, * the values of nodes will be concatenated into a single one. - * The concrete example we can see in the file wos-responce.xml in the node, + * The concrete example we can see in the file wos-response.xml in the node, * which may contain several

paragraphs, * this Contributor allows concatenating all

paragraphs. to obtain a single one. * diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CiniiImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CiniiImportMetadataSourceServiceIT.java index 87f1bf7d8d95..b8d21fb7a78c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CiniiImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CiniiImportMetadataSourceServiceIT.java @@ -51,7 +51,7 @@ public void ciniiImportMetadataGetRecordsTest() throws Exception { InputStream ciniiRefResp2 = null; InputStream ciniiRefResp3 = null; try { - ciniiRefResp = getClass().getResourceAsStream("cinii-responce-ids.xml"); + ciniiRefResp = getClass().getResourceAsStream("cinii-response-ids.xml"); ciniiRefResp2 = getClass().getResourceAsStream("cinii-first.xml"); ciniiRefResp3 = getClass().getResourceAsStream("cinii-second.xml"); @@ -89,7 +89,7 @@ public void ciniiImportMetadataGetRecordsCountTest() throws Exception { context.turnOffAuthorisationSystem(); CloseableHttpClient originalHttpClient = liveImportClientImpl.getHttpClient(); CloseableHttpClient httpClient = Mockito.mock(CloseableHttpClient.class); - try (InputStream file = getClass().getResourceAsStream("cinii-responce-ids.xml")) { + try (InputStream file = getClass().getResourceAsStream("cinii-response-ids.xml")) { String ciniiXmlResp = IOUtils.toString(file, Charset.defaultCharset()); liveImportClientImpl.setHttpClient(httpClient); @@ -107,31 +107,31 @@ public void ciniiImportMetadataGetRecordsCountTest() throws Exception { private ArrayList getRecords() { ArrayList records = new ArrayList<>(); //define first record - List metadatums = new ArrayList(); + List metadata = new ArrayList(); MetadatumDTO title = createMetadatumDTO("dc", "title", null, "Understanding the impact of mandatory accrual accounting on management practices:" + " Interpretation of Japanese local governments’ behavior"); MetadatumDTO identifier = createMetadatumDTO("dc", "identifier", "other", "1010572092222310146"); - metadatums.add(title); - metadatums.add(identifier); + metadata.add(title); + metadata.add(identifier); - ImportRecord firstrRecord = new ImportRecord(metadatums); + ImportRecord firstRecord = new ImportRecord(metadata); //define second record - List metadatums2 = new ArrayList(); + List metadata2 = new ArrayList(); MetadatumDTO title2 = createMetadatumDTO("dc", "title", null, "Band structures of passive films on titanium in simulated bioliquids determined" + " by photoelectrochemical response: principle governing the biocompatibility"); MetadatumDTO language = createMetadatumDTO("dc", "language", "iso", "en"); MetadatumDTO identifier2 = createMetadatumDTO("dc", "identifier", "other", "1050010687833449984"); - metadatums2.add(title2); - metadatums2.add(language); - metadatums2.add(identifier2); + metadata2.add(title2); + metadata2.add(language); + metadata2.add(identifier2); - ImportRecord secondRecord = new ImportRecord(metadatums2); - records.add(firstrRecord); + ImportRecord secondRecord = new ImportRecord(metadata2); + records.add(firstRecord); records.add(secondRecord); return records; } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java index ee4ab9bf6d80..25be24a786ab 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java @@ -3306,7 +3306,7 @@ public void findByItemsAndTypeUnprocessableEntityTest() throws Exception { } @Test - public void findByItemsAndTypeEmptyResponceTest() throws Exception { + public void findByItemsAndTypeEmptyResponseTest() throws Exception { context.turnOffAuthorisationSystem(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java index 9f68d79c2036..7ec6734d1b4a 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WOSImportMetadataSourceServiceIT.java @@ -51,7 +51,7 @@ public void wosImportMetadataGetRecordsTest() throws Exception { } CloseableHttpClient originalHttpClient = liveImportClientImpl.getHttpClient(); CloseableHttpClient httpClient = Mockito.mock(CloseableHttpClient.class); - try (InputStream file = getClass().getResourceAsStream("wos-responce.xml")) { + try (InputStream file = getClass().getResourceAsStream("wos-response.xml")) { String wosXmlResp = IOUtils.toString(file, Charset.defaultCharset()); liveImportClientImpl.setHttpClient(httpClient); @@ -80,7 +80,7 @@ public void wosImportMetadataGetRecordsCountTest() throws Exception { } CloseableHttpClient originalHttpClient = liveImportClientImpl.getHttpClient(); CloseableHttpClient httpClient = Mockito.mock(CloseableHttpClient.class); - try (InputStream file = getClass().getResourceAsStream("wos-responce.xml")) { + try (InputStream file = getClass().getResourceAsStream("wos-response.xml")) { String wosXmlResp = IOUtils.toString(file, Charset.defaultCharset()); liveImportClientImpl.setHttpClient(httpClient); diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/cinii-responce-ids.xml b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/cinii-response-ids.xml similarity index 100% rename from dspace-server-webapp/src/test/resources/org/dspace/app/rest/cinii-responce-ids.xml rename to dspace-server-webapp/src/test/resources/org/dspace/app/rest/cinii-response-ids.xml diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/wos-responce.xml b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/wos-response.xml similarity index 100% rename from dspace-server-webapp/src/test/resources/org/dspace/app/rest/wos-responce.xml rename to dspace-server-webapp/src/test/resources/org/dspace/app/rest/wos-response.xml From e6ea19829ec52d70c2c4261a9d4dd05dbdf728bf Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Thu, 19 Sep 2024 14:26:57 +0200 Subject: [PATCH 045/179] Normalise / fix references to the word "reinstate". I think the noun form might be "reinstatement" rather than "reinstantiation" (reinstantiate being a slightly different word) but to avoid confusion I found it easier to just rewrite a few error messages so that the verb "reinstate" could be used and we can avoid nominalisation. --- .../main/java/org/dspace/app/util/AuthorizeUtil.java | 4 ++-- .../org/dspace/authorize/AuthorizeConfiguration.java | 8 ++++---- .../src/main/java/org/dspace/rdf/RDFConsumer.java | 2 +- .../operation/ItemWithdrawReplaceOperation.java | 4 ++-- .../rest/authorization/ReinstateFeatureRestIT.java | 12 ++++++------ dspace/config/dspace.cfg | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/AuthorizeUtil.java b/dspace-api/src/main/java/org/dspace/app/util/AuthorizeUtil.java index ed59f4b24f05..9b63750e4368 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/AuthorizeUtil.java +++ b/dspace-api/src/main/java/org/dspace/app/util/AuthorizeUtil.java @@ -523,9 +523,9 @@ public static void authorizeReinstateItem(Context context, Item item) for (Collection coll : colls) { if (!AuthorizeConfiguration - .canCollectionAdminPerformItemReinstatiate()) { + .canCollectionAdminPerformItemReinstate()) { if (AuthorizeConfiguration - .canCommunityAdminPerformItemReinstatiate() + .canCommunityAdminPerformItemReinstate() && authorizeService.authorizeActionBoolean(context, coll.getCommunities().get(0), Constants.ADMIN)) { // authorized diff --git a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeConfiguration.java b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeConfiguration.java index 1e051c78b960..65fe46fdd19b 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeConfiguration.java @@ -174,9 +174,9 @@ public static boolean canCommunityAdminPerformItemWithdrawn() { * * @return true/false */ - public static boolean canCommunityAdminPerformItemReinstatiate() { + public static boolean canCommunityAdminPerformItemReinstate() { init(); - return configurationService.getBooleanProperty("core.authorization.community-admin.item.reinstatiate", true); + return configurationService.getBooleanProperty("core.authorization.community-admin.item.reinstate", true); } /** @@ -306,9 +306,9 @@ public static boolean canCollectionAdminPerformItemWithdrawn() { * * @return true/false */ - public static boolean canCollectionAdminPerformItemReinstatiate() { + public static boolean canCollectionAdminPerformItemReinstate() { init(); - return configurationService.getBooleanProperty("core.authorization.collection-admin.item.reinstatiate", true); + return configurationService.getBooleanProperty("core.authorization.collection-admin.item.reinstate", true); } /** diff --git a/dspace-api/src/main/java/org/dspace/rdf/RDFConsumer.java b/dspace-api/src/main/java/org/dspace/rdf/RDFConsumer.java index 8b43ad69d78c..0101472c212a 100644 --- a/dspace-api/src/main/java/org/dspace/rdf/RDFConsumer.java +++ b/dspace-api/src/main/java/org/dspace/rdf/RDFConsumer.java @@ -243,7 +243,7 @@ public void consumeCommunityCollectionItem(Context ctx, Event event) throws SQLE DSOIdentifier id = new DSOIdentifier(dso, ctx); // If an item gets withdrawn, a MODIFY event is fired. We have to // delete the item from the triple store instead of converting it. - // we don't have to take care for reinstantions of items as they can + // we don't have to take care for reinstate events on items as they can // be processed as normal modify events. if (dso instanceof Item && event.getDetail() != null diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemWithdrawReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemWithdrawReplaceOperation.java index 42a47ee7e9e5..c3e91ed65e65 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemWithdrawReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemWithdrawReplaceOperation.java @@ -76,9 +76,9 @@ public R perform(Context context, R object, Operation operation) { return object; } } catch (AuthorizeException e) { - throw new RESTAuthorizationException("Unauthorized user for item withdrawal/reinstation"); + throw new RESTAuthorizationException("Unauthorized user for item withdraw / reinstate operation"); } catch (SQLException e) { - throw new DSpaceBadRequestException("SQL exception during item withdrawal/reinstation"); + throw new DSpaceBadRequestException("SQL exception during item withdraw / reinstate operation"); } } else { throw new DSpaceBadRequestException("ItemWithdrawReplaceOperation does not support this operation"); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ReinstateFeatureRestIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ReinstateFeatureRestIT.java index 8c630a6795c7..1ae94391fccc 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ReinstateFeatureRestIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/ReinstateFeatureRestIT.java @@ -123,9 +123,9 @@ public void checkAuthorizationAsCommunityAdminTest() throws Exception { Matchers.is(AuthorizationMatcher.matchAuthorization(authAdminWithdraw)))) ); - // verify that the property core.authorization.collection-admin.item.reinstatiate = false is respected + // verify that the property core.authorization.collection-admin.item.reinstate = false is respected // the community admins should be still authorized - configurationService.setProperty("core.authorization.collection-admin.item.reinstatiate", false); + configurationService.setProperty("core.authorization.collection-admin.item.reinstate", false); getClient(comAdminToken).perform(get("/api/authz/authorizations/" + authAdminWithdraw.getID())) .andExpect(status().isOk()) .andExpect(jsonPath("$", @@ -140,11 +140,11 @@ public void checkAuthorizationAsCommunityAdminTest() throws Exception { Matchers.is(AuthorizationMatcher.matchAuthorization(authAdminWithdraw)))) ); - // now verify that the property core.authorization.community-admin.item.reinstatiate = false is respected + // now verify that the property core.authorization.community-admin.item.reinstate = false is respected // and also community admins are blocked // Please note that set to false the configuration for community keeping true for collection don't // make any sense as a community admin is always also a collection admin - configurationService.setProperty("core.authorization.community-admin.item.reinstatiate", false); + configurationService.setProperty("core.authorization.community-admin.item.reinstate", false); getClient(comAdminToken).perform(get("/api/authz/authorizations/" + authAdminWithdraw.getID())) .andExpect(status().isNotFound()); @@ -183,8 +183,8 @@ public void checkAuthorizationAsCollectionAdminTest() throws Exception { .andExpect(jsonPath("$._embedded.authorizations", contains( Matchers.is(AuthorizationMatcher.matchAuthorization(authAdminWithdraw)))) ); - // verify that the property core.authorization.collection-admin.item.reinstatiate = false is respected - configurationService.setProperty("core.authorization.collection-admin.item.reinstatiate", false); + // verify that the property core.authorization.collection-admin.item.reinstate = false is respected + configurationService.setProperty("core.authorization.collection-admin.item.reinstate", false); getClient(colAdminToken).perform(get("/api/authz/authorizations/" + authAdminWithdraw.getID())) .andExpect(status().isNotFound()); diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index 0d8086751d0d..4d66fdcde489 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -350,7 +350,7 @@ handle.dir = ${dspace.dir}/handle-server # Authorize community administrators to manage item settings (for items owned by collections under the community) #core.authorization.community-admin.item.delete = true #core.authorization.community-admin.item.withdraw = true -#core.authorization.community-admin.item.reinstatiate = true +#core.authorization.community-admin.item.reinstate = true #core.authorization.community-admin.item.policies = true # Authorize community administrators to manage bundles/bitstreams of those items #core.authorization.community-admin.item.create-bitstream = true @@ -367,7 +367,7 @@ handle.dir = ${dspace.dir}/handle-server # Authorize collection administrators to manage item settings (for items owned by the collection) #core.authorization.collection-admin.item.delete = true #core.authorization.collection-admin.item.withdraw = true -#core.authorization.collection-admin.item.reinstatiate = true +#core.authorization.collection-admin.item.reinstate = true #core.authorization.collection-admin.item.policies = true # Authorize collection administrators to manage bundles/bitstreams of those items (owned by the collection) #core.authorization.collection-admin.item.create-bitstream = true From 5758d9e90302d4da33ec869b6ec656e5c25b865a Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Fri, 27 Sep 2024 12:07:52 +0200 Subject: [PATCH 046/179] minor fix in parameter description --- dspace/config/emails/subscriptions_content | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/config/emails/subscriptions_content b/dspace/config/emails/subscriptions_content index 9b8c91e559df..a1b107e8fc50 100644 --- a/dspace/config/emails/subscriptions_content +++ b/dspace/config/emails/subscriptions_content @@ -1,7 +1,7 @@ ## E-mail sent to designated address about updates on subscribed items ## -## Parameters: {0} Collections updates -## {1} Communities updates +## Parameters: {0} Communities updates +## {1} Collections updates #set($subject = "${config.get('dspace.name')} Subscriptions") This email is sent from ${config.get('dspace.name')} based on the chosen subscription preferences. From 27dd5a2ec58970256964f15f0879834c436aa542 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 27 Sep 2024 12:52:03 +0200 Subject: [PATCH 047/179] fix: performance of claiming workflow task --- .../storedcomponents/PoolTaskServiceImpl.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java index fb673725e181..d3c8f6334d8f 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTaskServiceImpl.java @@ -13,6 +13,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.Set; import org.apache.commons.collections4.CollectionUtils; @@ -100,12 +101,17 @@ public PoolTask findByWorkflowIdAndEPerson(Context context, XmlWorkflowItem work //If the user does not have a claimedtask yet, see whether one of the groups of the user has pooltasks //for this workflow item Set groups = groupService.allMemberGroupsSet(context, ePerson); - for (Group group : groups) { - poolTask = poolTaskDAO.findByWorkflowItemAndGroup(context, group, workflowItem); - if (poolTask != null) { - return poolTask; - } + List generalTasks = poolTaskDAO.findByWorkflowItem(context, workflowItem); + Optional firstClaimedTask = groups.stream() + .flatMap(group -> generalTasks.stream() + .filter(f -> f.getGroup().getID().equals(group.getID())) + .findFirst() + .stream()) + .findFirst(); + + if (firstClaimedTask.isPresent()) { + return firstClaimedTask.get(); } } } From 46dfd902f113b9ea13ce53b496aff6979024d67e Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 10 Oct 2024 16:02:53 -0500 Subject: [PATCH 048/179] Bump to Spring 6.1.13, Spring Boot 3.3.4 and Spring Security 6.3.3 --- dspace-server-webapp/pom.xml | 14 +++++++++++++- pom.xml | 6 +++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 2e8f2cafc0a9..5cb25649e933 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -343,6 +343,18 @@ org.springframework.boot spring-boot-starter-actuator ${spring-boot.version} + + + + io.micrometer + micrometer-observation + + + + io.micrometer + micrometer-commons + + @@ -437,7 +449,7 @@ spring-boot-starter-security ${spring-boot.version} - + io.micrometer micrometer-observation diff --git a/pom.xml b/pom.xml index d59342adcb17..404225fff5b1 100644 --- a/pom.xml +++ b/pom.xml @@ -19,9 +19,9 @@ 17 - 6.1.8 - 3.2.6 - 6.2.4 + 6.1.13 + 3.3.4 + 6.3.3 6.4.8.Final 8.0.1.Final 42.7.3 From 352f4c21523237cefa5bf67c99f7d7b26a51d72b Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 14 Oct 2024 17:03:15 +0200 Subject: [PATCH 049/179] 118774: status of doi should be set to TO_BE_DELETED when related item is removed permanently --- .../src/main/java/org/dspace/content/ItemServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index dc7820b669be..9a97851937e5 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -67,6 +67,7 @@ import org.dspace.harvest.HarvestedItem; import org.dspace.harvest.service.HarvestedItemService; import org.dspace.identifier.DOI; +import org.dspace.identifier.DOIIdentifierProvider; import org.dspace.identifier.IdentifierException; import org.dspace.identifier.service.DOIService; import org.dspace.identifier.service.IdentifierService; @@ -851,6 +852,7 @@ protected void rawDelete(Context context, Item item) throws AuthorizeException, DOI doi = doiService.findDOIByDSpaceObject(context, item); if (doi != null) { doi.setDSpaceObject(null); + doi.setStatus(DOIIdentifierProvider.TO_BE_DELETED); } // remove version attached to the item From 9ce645e08b50cd752e48a640e340b55466f019be Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 15 Oct 2024 23:23:24 +0200 Subject: [PATCH 050/179] Add Eclipse JDT .factorypath to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2fcb46b9932c..529351edc5c2 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ tags .project .classpath .checkstyle +.factorypath ## Ignore project files created by IntelliJ IDEA *.iml From 29067b6572b538650e4686e983edafcc355d87c5 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 17 Oct 2024 20:17:06 +0200 Subject: [PATCH 051/179] use dc.relation.hasversion for externally generated DOIs --- dspace/config/spring/api/scopus-integration.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace/config/spring/api/scopus-integration.xml b/dspace/config/spring/api/scopus-integration.xml index 6f7556574d09..d3e8150c74b1 100644 --- a/dspace/config/spring/api/scopus-integration.xml +++ b/dspace/config/spring/api/scopus-integration.xml @@ -128,7 +128,7 @@ - + From d61dc8d911a4d226362d9a554226da5c304ad722 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 17 Oct 2024 20:19:04 +0200 Subject: [PATCH 052/179] use dc.relation.hasversion instead of dc.identifier.doi --- .../dspace/app/rest/ScopusImportMetadataSourceServiceIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java index e81f662ad5a9..f9164ddc5994 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ScopusImportMetadataSourceServiceIT.java @@ -124,7 +124,7 @@ private ArrayList getRecords() { ArrayList records = new ArrayList<>(); //define first record List metadatums = new ArrayList(); - MetadatumDTO doi = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023004"); + MetadatumDTO doi = createMetadatumDTO("dc", "relation", "hasversion", "10.3934/mine.2023004"); MetadatumDTO title = createMetadatumDTO("dc","title", null, "Hardy potential versus lower order terms in Dirichlet problems: regularizing effects"); MetadatumDTO type = createMetadatumDTO("dc", "type", null, "Journal"); @@ -171,7 +171,7 @@ private ArrayList getRecords() { //define second record List metadatums2 = new ArrayList(); - MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", "doi", "10.3934/mine.2023001"); + MetadatumDTO doi2 = createMetadatumDTO("dc", "relation", "hasversion", "10.3934/mine.2023001"); MetadatumDTO title2 = createMetadatumDTO("dc","title", null, "Large deviations for a binary collision model: energy evaporation"); MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2023-01-01"); From e96dbfefeb6924c4b17c66535215878576190fb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 20:21:19 +0000 Subject: [PATCH 053/179] Bump the maven group with 3 updates Bumps the maven group with 3 updates: [org.springframework:spring-context](https://github.com/spring-projects/spring-framework), org.eclipse.jetty:jetty-server and org.eclipse.jetty:jetty-http. Updates `org.springframework:spring-context` from 6.1.13 to 6.1.14 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.13...v6.1.14) Updates `org.eclipse.jetty:jetty-server` from 9.4.54.v20240208 to 9.4.55.v20240627 Updates `org.eclipse.jetty:jetty-http` from 9.4.54.v20240208 to 9.4.55.v20240627 --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production dependency-group: maven - dependency-name: org.eclipse.jetty:jetty-server dependency-type: direct:production dependency-group: maven - dependency-name: org.eclipse.jetty:jetty-http dependency-type: direct:production dependency-group: maven ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 404225fff5b1..a94dac3dd693 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 17 - 6.1.13 + 6.1.14 3.3.4 6.3.3 6.4.8.Final @@ -38,7 +38,7 @@ 4.0.5 1.1.1 - 9.4.54.v20240208 + 9.4.55.v20240627 2.23.1 2.0.31 1.19.0 From 02f52c7d5c245eaae09dbd636fc8c7935d7cc242 Mon Sep 17 00:00:00 2001 From: Jukka Lipka <3710455+jlipka@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:11:08 +0200 Subject: [PATCH 054/179] fix(submission): Submission scope naming fixed According to the documentation, the value for the property is 'submission' in the 'submission-forms.xml'. Without this change, an empty input field will never be marked as an error, even if the field is marked as 'required'. --- dspace-api/src/main/java/org/dspace/app/util/DCInput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java index dd88390cb856..846a74cad5d5 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java @@ -163,7 +163,7 @@ public class DCInput { * The scope of the input sets, this restricts hidden metadata fields from * view by the end user during submission. */ - public static final String SUBMISSION_SCOPE = "submit"; + public static final String SUBMISSION_SCOPE = "submission"; /** * Class constructor for creating a DCInput object based on the contents of From 29e487e1d30a377be3a1f746c05ede0ef339ca0e Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 28 Oct 2024 14:55:30 -0500 Subject: [PATCH 055/179] Create dependabot.yml --- .github/dependabot.yml | 115 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000000..6f4f3ae601a0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,115 @@ +#------------------- +# DSpace's dependabot rules. Enables maven updates for all dependencies on a weekly basis +# for main and any maintenance branches. Security updates only apply to main. +#------------------- +version: 2 +updates: + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "weekly" + # Allow up to 10 open PRs for dependencies + open-pull-requests-limit: 10 + # Group together some upgrades in a single PR + groups: + # Group together all Build Tools in a single PR + build-tools: + applies-to: version-updates + patterns: + - "org.apache.maven.plugins:*" + - "*:*-maven-plugin" + - "*:maven-*-plugin" + - "com.github.spotbugs:spotbugs" + - "com.google.code.findbugs:*" + - "com.google.errorprone:*" + - "com.puppycrawl.tools:checkstyle" + - "org.sonatype.plugins:*" + update-types: + - "minor" + - "patch" + test-tools: + applies-to: version-updates + patterns: + - "junit:*" + - "com.github.stefanbirker:system-rules" + - "com.h2database:*" + - "io.findify:s3mock*" + - "io.netty:*" + - "org.hamcrest:*" + - "org.mock-server:*" + - "org.mockito:*" + update-types: + - "minor" + - "patch" + # Group together all Apache Commons deps in a single PR + apache-commons: + applies-to: version-updates + patterns: + - "org.apache.commons:*" + - "commons-*:commons-*" + update-types: + - "minor" + - "patch" + # Group together all fasterxml deps in a single PR + fasterxml: + applies-to: version-updates + patterns: + - "com.fasterxml:*" + - "com.fasterxml.*:*" + update-types: + - "minor" + - "patch" + # Group together all Hibernate deps in a single PR + hibernate: + applies-to: version-updates + patterns: + - "org.hibernate.*:*" + update-types: + - "minor" + - "patch" + # Group together all Jakarta deps in a single PR + jakarta: + applies-to: version-updates + patterns: + - "jakarta.*:*" + - "org.eclipse.angus:jakarta.mail" + - "org.glassfish.jaxb:jaxb-runtime" + update-types: + - "minor" + - "patch" + # Group together all Google deps in a single PR + google-apis: + applies-to: version-updates + patterns: + - "com.google.apis:*" + - "com.google.api-client:*" + - "com.google.http-client:*" + - "com.google.oauth-client:*" + update-types: + - "minor" + - "patch" + # Group together all Spring deps in a single PR + spring: + applies-to: version-updates + patterns: + - "org.springframework:*" + - "org.springframework.*:*" + update-types: + - "minor" + - "patch" + # Group together all WebJARs deps in a single PR + webjars: + applies-to: version-updates + patterns: + - "org.webjars:*" + - "org.webjars.*:*" + update-types: + - "minor" + - "patch" + ignore: + # Don't try to auto-update any DSpace dependencies + - dependency-name: "org.dspace:*" + - dependency-name: "org.dspace.*:*" + # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. + - dependency-name: "*" + update-types: ["version-update:semver-major"] From ed1e7bb972d6af5bd1e85701781890a0f33e8daa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 19:50:42 +0000 Subject: [PATCH 056/179] Bump org.postgresql:postgresql from 42.7.3 to 42.7.4 Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.3 to 42.7.4. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.7.3...REL42.7.4) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a94dac3dd693..eea78764d4ce 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 6.3.3 6.4.8.Final 8.0.1.Final - 42.7.3 + 42.7.4 10.10.0 8.11.3 From efdd3515b8e5f99e07c07fbbc76639101a96855c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Oct 2024 15:01:41 -0500 Subject: [PATCH 057/179] Exclude spring from build-tools group in dependabot.yml --- .github/dependabot.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6f4f3ae601a0..b6412b25b660 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -24,6 +24,9 @@ updates: - "com.google.errorprone:*" - "com.puppycrawl.tools:checkstyle" - "org.sonatype.plugins:*" + exclude-patterns: + # Exclude anything from Spring, as that is in a separate group + - "org.springframework.*:*" update-types: - "minor" - "patch" From 3d12676fc21bb0dc798683979b09eabc1623aeb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:02:16 +0000 Subject: [PATCH 058/179] Bump org.webjars.npm:json-editor__json-editor in the webjars group Bumps the webjars group with 1 update: [org.webjars.npm:json-editor__json-editor](https://github.com/json-editor/json-editor). Updates `org.webjars.npm:json-editor__json-editor` from 2.6.1 to 2.15.1 - [Changelog](https://github.com/json-editor/json-editor/blob/master/CHANGELOG.md) - [Commits](https://github.com/json-editor/json-editor/compare/2.6.1...2.15.1) --- updated-dependencies: - dependency-name: org.webjars.npm:json-editor__json-editor dependency-type: direct:production update-type: version-update:semver-minor dependency-group: webjars ... Signed-off-by: dependabot[bot] --- dspace-server-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 5cb25649e933..dcbb1171b56f 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -431,7 +431,7 @@ org.webjars.npm json-editor__json-editor - 2.6.1 + 2.15.1 - 2.16.0 - 2.16.0 + 2.18.1 + 2.18.1 2.1.1 4.0.2 4.0.5 @@ -1788,7 +1788,7 @@ com.fasterxml classmate - 1.6.0 + 1.7.0 com.fasterxml.jackson.core From 89e6863754ae41f8776fd94b3aec5295ccfec9ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:02:24 +0000 Subject: [PATCH 061/179] Bump the test-tools group with 8 updates Bumps the test-tools group with 8 updates: | Package | From | To | | --- | --- | --- | | [com.h2database:h2](https://github.com/h2database/h2database) | `2.2.224` | `2.3.232` | | [org.mock-server:mockserver-junit-rule](https://github.com/jamesdbloom/mockservice) | `5.11.2` | `5.15.0` | | [io.netty:netty-buffer](https://github.com/netty/netty) | `4.1.106.Final` | `4.1.114.Final` | | [io.netty:netty-transport](https://github.com/netty/netty) | `4.1.106.Final` | `4.1.114.Final` | | [io.netty:netty-transport-native-unix-common](https://github.com/netty/netty) | `4.1.106.Final` | `4.1.114.Final` | | [io.netty:netty-common](https://github.com/netty/netty) | `4.1.106.Final` | `4.1.114.Final` | | [io.netty:netty-handler](https://github.com/netty/netty) | `4.1.106.Final` | `4.1.114.Final` | | [io.netty:netty-codec](https://github.com/netty/netty) | `4.1.106.Final` | `4.1.114.Final` | Updates `com.h2database:h2` from 2.2.224 to 2.3.232 - [Release notes](https://github.com/h2database/h2database/releases) - [Commits](https://github.com/h2database/h2database/compare/version-2.2.224...version-2.3.232) Updates `org.mock-server:mockserver-junit-rule` from 5.11.2 to 5.15.0 - [Changelog](https://github.com/mock-server/mockserver/blob/master/changelog.md) - [Commits](https://github.com/jamesdbloom/mockservice/compare/mockserver-5.11.2...mockserver-5.15.0) Updates `io.netty:netty-buffer` from 4.1.106.Final to 4.1.114.Final - [Commits](https://github.com/netty/netty/compare/netty-4.1.106.Final...netty-4.1.114.Final) Updates `io.netty:netty-transport` from 4.1.106.Final to 4.1.114.Final - [Commits](https://github.com/netty/netty/compare/netty-4.1.106.Final...netty-4.1.114.Final) Updates `io.netty:netty-transport-native-unix-common` from 4.1.106.Final to 4.1.114.Final - [Commits](https://github.com/netty/netty/compare/netty-4.1.106.Final...netty-4.1.114.Final) Updates `io.netty:netty-common` from 4.1.106.Final to 4.1.114.Final - [Commits](https://github.com/netty/netty/compare/netty-4.1.106.Final...netty-4.1.114.Final) Updates `io.netty:netty-handler` from 4.1.106.Final to 4.1.114.Final - [Commits](https://github.com/netty/netty/compare/netty-4.1.106.Final...netty-4.1.114.Final) Updates `io.netty:netty-codec` from 4.1.106.Final to 4.1.114.Final - [Commits](https://github.com/netty/netty/compare/netty-4.1.106.Final...netty-4.1.114.Final) --- updated-dependencies: - dependency-name: com.h2database:h2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: test-tools - dependency-name: org.mock-server:mockserver-junit-rule dependency-type: direct:development update-type: version-update:semver-minor dependency-group: test-tools - dependency-name: io.netty:netty-buffer dependency-type: direct:production update-type: version-update:semver-patch dependency-group: test-tools - dependency-name: io.netty:netty-transport dependency-type: direct:production update-type: version-update:semver-patch dependency-group: test-tools - dependency-name: io.netty:netty-transport-native-unix-common dependency-type: direct:production update-type: version-update:semver-patch dependency-group: test-tools - dependency-name: io.netty:netty-common dependency-type: direct:production update-type: version-update:semver-patch dependency-group: test-tools - dependency-name: io.netty:netty-handler dependency-type: direct:production update-type: version-update:semver-patch dependency-group: test-tools - dependency-name: io.netty:netty-codec dependency-type: direct:production update-type: version-update:semver-patch dependency-group: test-tools ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 14 +++++++------- pom.xml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index ea182a748360..80dec5929543 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -814,7 +814,7 @@ org.mock-server mockserver-junit-rule - 5.11.2 + 5.15.0 test @@ -865,32 +865,32 @@ io.netty netty-buffer - 4.1.106.Final + 4.1.114.Final io.netty netty-transport - 4.1.106.Final + 4.1.114.Final io.netty netty-transport-native-unix-common - 4.1.106.Final + 4.1.114.Final io.netty netty-common - 4.1.106.Final + 4.1.114.Final io.netty netty-handler - 4.1.106.Final + 4.1.114.Final io.netty netty-codec - 4.1.106.Final + 4.1.114.Final org.apache.velocity diff --git a/pom.xml b/pom.xml index a94dac3dd693..fb6e28f238a5 100644 --- a/pom.xml +++ b/pom.xml @@ -1730,7 +1730,7 @@ com.h2database h2 - 2.2.224 + 2.3.232 test From 84f76babff801049bf3af6066c71241410c17ece Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:02:27 +0000 Subject: [PATCH 062/179] Bump the apache-commons group with 11 updates Bumps the apache-commons group with 11 updates: | Package | From | To | | --- | --- | --- | | commons-cli:commons-cli | `1.6.0` | `1.9.0` | | [commons-codec:commons-codec](https://github.com/apache/commons-codec) | `1.16.0` | `1.17.1` | | org.apache.commons:commons-configuration2 | `2.10.1` | `2.11.0` | | org.apache.commons:commons-dbcp2 | `2.11.0` | `2.12.0` | | commons-io:commons-io | `2.15.1` | `2.17.0` | | org.apache.commons:commons-lang3 | `3.14.0` | `3.17.0` | | commons-logging:commons-logging | `1.3.0` | `1.3.4` | | org.apache.commons:commons-compress | `1.26.0` | `1.27.1` | | [org.apache.commons:commons-csv](https://github.com/apache/commons-csv) | `1.10.0` | `1.12.0` | | org.apache.commons:commons-text | `1.10.0` | `1.12.0` | | commons-validator:commons-validator | `1.7` | `1.9.0` | Updates `commons-cli:commons-cli` from 1.6.0 to 1.9.0 Updates `commons-codec:commons-codec` from 1.16.0 to 1.17.1 - [Changelog](https://github.com/apache/commons-codec/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-codec/compare/rel/commons-codec-1.16.0...rel/commons-codec-1.17.1) Updates `org.apache.commons:commons-configuration2` from 2.10.1 to 2.11.0 Updates `org.apache.commons:commons-dbcp2` from 2.11.0 to 2.12.0 Updates `commons-io:commons-io` from 2.15.1 to 2.17.0 Updates `org.apache.commons:commons-lang3` from 3.14.0 to 3.17.0 Updates `commons-logging:commons-logging` from 1.3.0 to 1.3.4 Updates `org.apache.commons:commons-compress` from 1.26.0 to 1.27.1 Updates `org.apache.commons:commons-csv` from 1.10.0 to 1.12.0 - [Changelog](https://github.com/apache/commons-csv/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-csv/compare/rel/commons-csv-1.10.0...rel/commons-csv-1.12.0) Updates `org.apache.commons:commons-text` from 1.10.0 to 1.12.0 Updates `commons-validator:commons-validator` from 1.7 to 1.9.0 --- updated-dependencies: - dependency-name: commons-cli:commons-cli dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-codec:commons-codec dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-configuration2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-dbcp2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-lang3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-logging:commons-logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: apache-commons - dependency-name: org.apache.commons:commons-compress dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-csv dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: org.apache.commons:commons-text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons - dependency-name: commons-validator:commons-validator dependency-type: direct:production update-type: version-update:semver-minor dependency-group: apache-commons ... Signed-off-by: dependabot[bot] --- pom.xml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index a94dac3dd693..3e8be8a75d32 100644 --- a/pom.xml +++ b/pom.xml @@ -1457,12 +1457,12 @@ commons-cli commons-cli - 1.6.0 + 1.9.0 commons-codec commons-codec - 1.16.0 + 1.17.1 org.apache.commons @@ -1480,12 +1480,12 @@ org.apache.commons commons-configuration2 - 2.10.1 + 2.11.0 org.apache.commons commons-dbcp2 - 2.11.0 + 2.12.0 @@ -1497,29 +1497,29 @@ commons-io commons-io - 2.15.1 + 2.17.0 org.apache.commons commons-lang3 - 3.14.0 + 3.17.0 commons-logging commons-logging - 1.3.0 + 1.3.4 org.apache.commons commons-compress - 1.26.0 + 1.27.1 org.apache.commons commons-csv - 1.10.0 + 1.12.0 org.apache.commons @@ -1529,12 +1529,12 @@ org.apache.commons commons-text - 1.10.0 + 1.12.0 commons-validator commons-validator - 1.7 + 1.9.0 joda-time From b98069916307a2ad26e45b563ed6a4f952db1894 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:02:33 +0000 Subject: [PATCH 063/179] Bump org.springframework.security:spring-security-test Bumps the spring group with 1 update in the / directory: [org.springframework.security:spring-security-test](https://github.com/spring-projects/spring-security). Updates `org.springframework.security:spring-security-test` from 6.3.3 to 6.3.4 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/6.3.3...6.3.4) --- updated-dependencies: - dependency-name: org.springframework.security:spring-security-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: spring ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a94dac3dd693..9a8629317abc 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 17 6.1.14 3.3.4 - 6.3.3 + 6.3.4 6.4.8.Final 8.0.1.Final 42.7.3 From d02f1d31c2723ae46799654911ad788f6ca8f740 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:03:05 +0000 Subject: [PATCH 064/179] Bump solr.client.version from 8.11.3 to 8.11.4 Bumps `solr.client.version` from 8.11.3 to 8.11.4. Updates `org.apache.solr:solr-solrj` from 8.11.3 to 8.11.4 Updates `org.apache.lucene:lucene-core` from 8.11.3 to 8.11.4 Updates `org.apache.lucene:lucene-analyzers-icu` from 8.11.3 to 8.11.4 Updates `org.apache.lucene:lucene-analyzers-smartcn` from 8.11.3 to 8.11.4 Updates `org.apache.lucene:lucene-analyzers-stempel` from 8.11.3 to 8.11.4 Updates `org.apache.solr:solr-core` from 8.11.3 to 8.11.4 --- updated-dependencies: - dependency-name: org.apache.solr:solr-solrj dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.lucene:lucene-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.lucene:lucene-analyzers-icu dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.lucene:lucene-analyzers-smartcn dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.lucene:lucene-analyzers-stempel dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.solr:solr-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a94dac3dd693..151da4c235ef 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ 8.0.1.Final 42.7.3 10.10.0 - 8.11.3 + 8.11.4 3.10.8 2.32.0 From 1a8ccb4219e675764c39f1549603a795cbf6b0fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:03:52 +0000 Subject: [PATCH 065/179] Bump the build-tools group across 1 directory with 24 updates Bumps the build-tools group with 24 updates in the / directory: | Package | From | To | | --- | --- | --- | | [com.google.errorprone:error_prone_core](https://github.com/google/error-prone) | `2.32.0` | `2.35.1` | | [com.google.errorprone:error_prone_annotations](https://github.com/google/error-prone) | `2.32.0` | `2.35.1` | | [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `8.38` | `8.45.1` | | [com.github.spotbugs:spotbugs](https://github.com/spotbugs/spotbugs) | `4.8.2` | `4.8.6` | | [org.apache.maven.plugins:maven-enforcer-plugin](https://github.com/apache/maven-enforcer) | `3.4.1` | `3.5.0` | | [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) | `3.3.0` | `3.4.2` | | [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `3.2.5` | `3.5.1` | | [org.apache.maven.plugins:maven-failsafe-plugin](https://github.com/apache/maven-surefire) | `3.2.5` | `3.5.1` | | [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) | `3.3.1` | `3.6.0` | | [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) | `4.8.2.0` | `4.8.6.5` | | [org.apache.maven.plugins:maven-clean-plugin](https://github.com/apache/maven-clean-plugin) | `3.3.2` | `3.4.0` | | [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin) | `3.6.1` | `3.8.1` | | org.sonatype.plugins:nexus-staging-maven-plugin | `1.6.13` | `1.7.0` | | [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) | `3.6.3` | `3.10.1` | | [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) | `3.3.0` | `3.3.1` | | [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) | `3.2.1` | `3.2.7` | | [org.jacoco:jacoco-maven-plugin](https://github.com/jacoco/jacoco) | `0.8.11` | `0.8.12` | | [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) | `3.0.0` | `3.1.1` | | [org.codehaus.mojo:xml-maven-plugin](https://github.com/mojohaus/xml-maven-plugin) | `1.0.2` | `1.1.0` | | [org.codehaus.mojo:license-maven-plugin](https://github.com/mojohaus/license-maven-plugin) | `2.0.0` | `2.4.0` | | [org.codehaus.mojo:build-helper-maven-plugin](https://github.com/mojohaus/build-helper-maven-plugin) | `3.4.0` | `3.6.0` | | [org.codehaus.mojo:buildnumber-maven-plugin](https://github.com/mojohaus/buildnumber-maven-plugin) | `3.2.0` | `3.2.1` | | [org.codehaus.mojo:jaxb2-maven-plugin](https://github.com/mojohaus/jaxb2-maven-plugin) | `3.1.0` | `3.2.0` | | [org.codehaus.mojo:properties-maven-plugin](https://github.com/mojohaus/properties-maven-plugin) | `1.1.0` | `1.2.1` | Updates `com.google.errorprone:error_prone_core` from 2.32.0 to 2.35.1 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.32.0...v2.35.1) Updates `com.google.errorprone:error_prone_annotations` from 2.32.0 to 2.35.1 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.32.0...v2.35.1) Updates `com.puppycrawl.tools:checkstyle` from 8.38 to 8.45.1 - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-8.38...checkstyle-8.45.1) Updates `com.github.spotbugs:spotbugs` from 4.8.2 to 4.8.6 - [Release notes](https://github.com/spotbugs/spotbugs/releases) - [Changelog](https://github.com/spotbugs/spotbugs/blob/master/CHANGELOG.md) - [Commits](https://github.com/spotbugs/spotbugs/compare/4.8.2...4.8.6) Updates `com.google.errorprone:error_prone_annotations` from 2.32.0 to 2.35.1 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.32.0...v2.35.1) Updates `org.apache.maven.plugins:maven-enforcer-plugin` from 3.4.1 to 3.5.0 - [Release notes](https://github.com/apache/maven-enforcer/releases) - [Commits](https://github.com/apache/maven-enforcer/compare/enforcer-3.4.1...enforcer-3.5.0) Updates `org.apache.maven.plugins:maven-jar-plugin` from 3.3.0 to 3.4.2 - [Release notes](https://github.com/apache/maven-jar-plugin/releases) - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.2) Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.2.5 to 3.5.1 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.5...surefire-3.5.1) Updates `org.apache.maven.plugins:maven-failsafe-plugin` from 3.2.5 to 3.5.1 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.5...surefire-3.5.1) Updates `org.apache.maven.plugins:maven-checkstyle-plugin` from 3.3.1 to 3.6.0 - [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.1...maven-checkstyle-plugin-3.6.0) Updates `com.github.spotbugs:spotbugs-maven-plugin` from 4.8.2.0 to 4.8.6.5 - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.8.2.0...spotbugs-maven-plugin-4.8.6.5) Updates `org.apache.maven.plugins:maven-clean-plugin` from 3.3.2 to 3.4.0 - [Release notes](https://github.com/apache/maven-clean-plugin/releases) - [Commits](https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.3.2...maven-clean-plugin-3.4.0) Updates `org.apache.maven.plugins:maven-dependency-plugin` from 3.6.1 to 3.8.1 - [Release notes](https://github.com/apache/maven-dependency-plugin/releases) - [Commits](https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.6.1...maven-dependency-plugin-3.8.1) Updates `org.sonatype.plugins:nexus-staging-maven-plugin` from 1.6.13 to 1.7.0 Updates `org.apache.maven.plugins:maven-javadoc-plugin` from 3.6.3 to 3.10.1 - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.3...maven-javadoc-plugin-3.10.1) Updates `org.apache.maven.plugins:maven-source-plugin` from 3.3.0 to 3.3.1 - [Release notes](https://github.com/apache/maven-source-plugin/releases) - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1) Updates `org.apache.maven.plugins:maven-gpg-plugin` from 3.2.1 to 3.2.7 - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.1...maven-gpg-plugin-3.2.7) Updates `org.jacoco:jacoco-maven-plugin` from 0.8.11 to 0.8.12 - [Release notes](https://github.com/jacoco/jacoco/releases) - [Commits](https://github.com/jacoco/jacoco/compare/v0.8.11...v0.8.12) Updates `org.apache.maven.plugins:maven-release-plugin` from 3.0.0 to 3.1.1 - [Release notes](https://github.com/apache/maven-release/releases) - [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.0...maven-release-3.1.1) Updates `org.codehaus.mojo:xml-maven-plugin` from 1.0.2 to 1.1.0 - [Release notes](https://github.com/mojohaus/xml-maven-plugin/releases) - [Commits](https://github.com/mojohaus/xml-maven-plugin/compare/xml-maven-plugin-1.0.2...1.1.0) Updates `org.codehaus.mojo:license-maven-plugin` from 2.0.0 to 2.4.0 - [Release notes](https://github.com/mojohaus/license-maven-plugin/releases) - [Commits](https://github.com/mojohaus/license-maven-plugin/compare/license-maven-plugin-2.0.0...2.4.0) Updates `org.codehaus.mojo:build-helper-maven-plugin` from 3.4.0 to 3.6.0 - [Release notes](https://github.com/mojohaus/build-helper-maven-plugin/releases) - [Commits](https://github.com/mojohaus/build-helper-maven-plugin/compare/3.4.0...3.6.0) Updates `org.codehaus.mojo:buildnumber-maven-plugin` from 3.2.0 to 3.2.1 - [Release notes](https://github.com/mojohaus/buildnumber-maven-plugin/releases) - [Commits](https://github.com/mojohaus/buildnumber-maven-plugin/compare/3.2.0...3.2.1) Updates `org.codehaus.mojo:jaxb2-maven-plugin` from 3.1.0 to 3.2.0 - [Release notes](https://github.com/mojohaus/jaxb2-maven-plugin/releases) - [Commits](https://github.com/mojohaus/jaxb2-maven-plugin/compare/jaxb2-maven-plugin-3.1.0...jaxb2-maven-plugin-3.2.0) Updates `org.codehaus.mojo:properties-maven-plugin` from 1.1.0 to 1.2.1 - [Release notes](https://github.com/mojohaus/properties-maven-plugin/releases) - [Commits](https://github.com/mojohaus/properties-maven-plugin/compare/properties-maven-plugin-1.1.0...1.2.1) --- updated-dependencies: - dependency-name: com.google.errorprone:error_prone_core dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.google.errorprone:error_prone_annotations dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.github.spotbugs:spotbugs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: com.google.errorprone:error_prone_annotations dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-enforcer-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-jar-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-failsafe-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-clean-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-dependency-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.jacoco:jacoco-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.apache.maven.plugins:maven-release-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:xml-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:license-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:build-helper-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:buildnumber-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch dependency-group: build-tools - dependency-name: org.codehaus.mojo:jaxb2-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools - dependency-name: org.codehaus.mojo:properties-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor dependency-group: build-tools ... Signed-off-by: dependabot[bot] --- dspace-api/pom.xml | 6 +++--- dspace-server-webapp/pom.xml | 2 +- pom.xml | 38 ++++++++++++++++++------------------ 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index ea182a748360..e9aeb7f2f426 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -102,7 +102,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.4.0 + 3.6.0 validate @@ -116,7 +116,7 @@ org.codehaus.mojo buildnumber-maven-plugin - 3.2.0 + 3.2.1 UNKNOWN_REVISION @@ -177,7 +177,7 @@ org.codehaus.mojo jaxb2-maven-plugin - 3.1.0 + 3.2.0 workflow-curation diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 5cb25649e933..b4b7326b34c2 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -31,7 +31,7 @@ org.codehaus.mojo properties-maven-plugin - 1.1.0 + 1.2.1 initialize diff --git a/pom.xml b/pom.xml index a94dac3dd693..44a42f2b1089 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 8.11.3 3.10.8 - 2.32.0 + 2.35.1 2.16.0 2.16.0 @@ -89,7 +89,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.4.1 + 3.5.0 enforce-java @@ -176,7 +176,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.2 @@ -207,7 +207,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.5.1 @@ -234,7 +234,7 @@ maven-failsafe-plugin - 3.2.5 + 3.5.1 @@ -266,7 +266,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.3.1 + 3.6.0 verify-style @@ -295,14 +295,14 @@ com.puppycrawl.tools checkstyle - 8.38 + 8.45.1 com.github.spotbugs spotbugs-maven-plugin - 4.8.2.0 + 4.8.6.5 Max Low @@ -312,7 +312,7 @@ com.github.spotbugs spotbugs - 4.8.2 + 4.8.6 @@ -328,7 +328,7 @@ maven-clean-plugin - 3.3.2 + 3.4.0 @@ -347,7 +347,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.6.1 + 3.8.1 org.apache.maven.plugins @@ -364,13 +364,13 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.13 + 1.7.0 org.apache.maven.plugins maven-javadoc-plugin - 3.6.3 + 3.10.1 false @@ -385,7 +385,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.0 + 3.3.1 @@ -398,13 +398,13 @@ org.apache.maven.plugins maven-gpg-plugin - 3.2.1 + 3.2.7 org.jacoco jacoco-maven-plugin - 0.8.11 + 0.8.12 @@ -416,7 +416,7 @@ org.apache.maven.plugins maven-release-plugin - 3.0.0 + 3.1.1 @@ -484,7 +484,7 @@ org.codehaus.mojo xml-maven-plugin - 1.0.2 + 1.1.0 validate-ALL-xml-and-xsl @@ -692,7 +692,7 @@ org.codehaus.mojo license-maven-plugin - 2.0.0 + 2.4.0 false From b11f4e08386a3709837c46791e877fe24bcfda39 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Oct 2024 17:02:14 -0500 Subject: [PATCH 066/179] Fix checkstyle.xml syntax for bump to 8.45.1 --- checkstyle.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkstyle.xml b/checkstyle.xml index e0fa808d83cb..a33fc4831950 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -92,7 +92,7 @@ For more information on CheckStyle configurations below, see: http://checkstyle. - + From a824e4d6ff24ae4c225fbcfe568cc8d421de68b7 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 29 Oct 2024 17:02:46 -0500 Subject: [PATCH 067/179] Minor checkstyle fixes after bump to 8.45.1. All are indentation / spacing fixes which are more strict now. --- .../rest/AuthenticationRestController.java | 2 +- .../app/rest/model/AuthorizationRest.java | 6 +-- .../dspace/app/rest/model/BitstreamRest.java | 15 ++---- .../app/rest/model/BrowseIndexRest.java | 10 +--- .../org/dspace/app/rest/model/BundleRest.java | 15 ++---- .../app/rest/model/ClaimedTaskRest.java | 5 +- .../dspace/app/rest/model/CollectionRest.java | 40 +++------------ .../dspace/app/rest/model/CommunityRest.java | 25 ++-------- .../dspace/app/rest/model/EPersonRest.java | 5 +- .../dspace/app/rest/model/EntityTypeRest.java | 5 +- .../app/rest/model/ExternalSourceRest.java | 5 +- .../org/dspace/app/rest/model/GroupRest.java | 15 ++---- .../org/dspace/app/rest/model/ItemRest.java | 50 ++++--------------- .../app/rest/model/OrcidHistoryRest.java | 2 +- .../dspace/app/rest/model/PoolTaskRest.java | 5 +- .../dspace/app/rest/model/ProcessRest.java | 15 ++---- .../app/rest/model/RelationshipRest.java | 5 +- .../app/rest/model/ResearcherProfileRest.java | 4 +- .../dspace/app/rest/model/SuggestionRest.java | 4 +- .../app/rest/model/SuggestionTargetRest.java | 2 +- .../app/rest/model/VersionHistoryRest.java | 10 +--- .../dspace/app/rest/model/VersionRest.java | 10 +--- .../model/VocabularyEntryDetailsRest.java | 6 +-- .../dspace/app/rest/model/VocabularyRest.java | 4 +- .../rest/model/WorkflowDefinitionRest.java | 10 +--- .../app/rest/model/WorkflowItemRest.java | 20 ++------ .../app/rest/model/WorkflowStepRest.java | 5 +- .../app/rest/model/WorkspaceItemRest.java | 20 ++------ .../org/dspace/app/rest/utils/RegexUtils.java | 2 +- .../app/rest/matcher/RegistrationMatcher.java | 2 +- 30 files changed, 75 insertions(+), 249 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java index 070f3d8a1868..63ac50b6ea06 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/AuthenticationRestController.java @@ -220,7 +220,7 @@ private AuthenticationTokenResource shortLivedTokenResponse(HttpServletRequest r * @return ResponseEntity */ @RequestMapping(value = "/login", method = { RequestMethod.GET, RequestMethod.PUT, RequestMethod.PATCH, - RequestMethod.DELETE }) + RequestMethod.DELETE }) public ResponseEntity login() { return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body("Only POST is allowed for login requests."); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java index fa463a7c3968..cd3e33b9e2fa 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AuthorizationRest.java @@ -18,9 +18,9 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(method = "getEperson", name = AuthorizationRest.EPERSON), - @LinkRest(method = "getFeature", name = AuthorizationRest.FEATURE), - @LinkRest(method = "getObject", name = AuthorizationRest.OBJECT) + @LinkRest(method = "getEperson", name = AuthorizationRest.EPERSON), + @LinkRest(method = "getFeature", name = AuthorizationRest.FEATURE), + @LinkRest(method = "getObject", name = AuthorizationRest.OBJECT) }) public class AuthorizationRest extends BaseObjectRest { public static final String NAME = "authorization"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java index d2c2268b3f35..d456f7222308 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BitstreamRest.java @@ -16,18 +16,9 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = BitstreamRest.BUNDLE, - method = "getBundle" - ), - @LinkRest( - name = BitstreamRest.FORMAT, - method = "getFormat" - ), - @LinkRest( - name = BitstreamRest.THUMBNAIL, - method = "getThumbnail" - ) + @LinkRest(name = BitstreamRest.BUNDLE, method = "getBundle"), + @LinkRest(name = BitstreamRest.FORMAT, method = "getFormat"), + @LinkRest(name = BitstreamRest.THUMBNAIL, method = "getThumbnail") }) public class BitstreamRest extends DSpaceObjectRest { public static final String PLURAL_NAME = "bitstreams"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java index a3c0b37ba576..e5b089479971 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BrowseIndexRest.java @@ -20,14 +20,8 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = BrowseIndexRest.LINK_ITEMS, - method = "listBrowseItems" - ), - @LinkRest( - name = BrowseIndexRest.LINK_ENTRIES, - method = "listBrowseEntries" - ) + @LinkRest(name = BrowseIndexRest.LINK_ITEMS, method = "listBrowseItems"), + @LinkRest(name = BrowseIndexRest.LINK_ENTRIES, method = "listBrowseEntries") }) public class BrowseIndexRest extends BaseObjectRest { private static final long serialVersionUID = -4870333170249999559L; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java index 1ec9f448dde4..4a417e6c54c3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/BundleRest.java @@ -16,18 +16,9 @@ * @author Jelle Pelgrims (jelle.pelgrims at atmire.com) */ @LinksRest(links = { - @LinkRest( - name = BundleRest.ITEM, - method = "getItem" - ), - @LinkRest( - name = BundleRest.BITSTREAMS, - method = "getBitstreams" - ), - @LinkRest( - name = BundleRest.PRIMARY_BITSTREAM, - method = "getPrimaryBitstream" - ) + @LinkRest(name = BundleRest.ITEM, method = "getItem"), + @LinkRest(name = BundleRest.BITSTREAMS, method = "getBitstreams"), + @LinkRest(name = BundleRest.PRIMARY_BITSTREAM, method = "getPrimaryBitstream") }) public class BundleRest extends DSpaceObjectRest { public static final String NAME = "bundle"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java index 0973fac987d2..d29bf7a7ce6b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClaimedTaskRest.java @@ -16,10 +16,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = ClaimedTaskRest.STEP, - method = "getStep" - ) + @LinkRest(name = ClaimedTaskRest.STEP, method = "getStep") }) public class ClaimedTaskRest extends BaseObjectRest { public static final String NAME = "claimedtask"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java index f00bb883959c..34faba4cb4d9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CollectionRest.java @@ -15,38 +15,14 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = CollectionRest.LICENSE, - method = "getLicense" - ), - @LinkRest( - name = CollectionRest.LOGO, - method = "getLogo" - ), - @LinkRest( - name = CollectionRest.MAPPED_ITEMS, - method = "getMappedItems" - ), - @LinkRest( - name = CollectionRest.PARENT_COMMUNITY, - method = "getParentCommunity" - ), - @LinkRest( - name = CollectionRest.ADMIN_GROUP, - method = "getAdminGroup" - ), - @LinkRest( - name = CollectionRest.SUBMITTERS_GROUP, - method = "getSubmittersGroup" - ), - @LinkRest( - name = CollectionRest.ITEM_READ_GROUP, - method = "getItemReadGroup" - ), - @LinkRest( - name = CollectionRest.BITSTREAM_READ_GROUP, - method = "getBitstreamReadGroup" - ), + @LinkRest(name = CollectionRest.LICENSE, method = "getLicense"), + @LinkRest(name = CollectionRest.LOGO, method = "getLogo"), + @LinkRest(name = CollectionRest.MAPPED_ITEMS, method = "getMappedItems"), + @LinkRest(name = CollectionRest.PARENT_COMMUNITY, method = "getParentCommunity"), + @LinkRest(name = CollectionRest.ADMIN_GROUP, method = "getAdminGroup"), + @LinkRest(name = CollectionRest.SUBMITTERS_GROUP, method = "getSubmittersGroup"), + @LinkRest(name = CollectionRest.ITEM_READ_GROUP, method = "getItemReadGroup"), + @LinkRest(name = CollectionRest.BITSTREAM_READ_GROUP, method = "getBitstreamReadGroup"), }) public class CollectionRest extends DSpaceObjectRest { public static final String NAME = "collection"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java index 0004e0b91ca4..e70b30803da3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/CommunityRest.java @@ -15,26 +15,11 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = CommunityRest.COLLECTIONS, - method = "getCollections" - ), - @LinkRest( - name = CommunityRest.LOGO, - method = "getLogo" - ), - @LinkRest( - name = CommunityRest.SUBCOMMUNITIES, - method = "getSubcommunities" - ), - @LinkRest( - name = CommunityRest.PARENT_COMMUNITY, - method = "getParentCommunity" - ), - @LinkRest( - name = CommunityRest.ADMIN_GROUP, - method = "getAdminGroup" - ) + @LinkRest(name = CommunityRest.COLLECTIONS, method = "getCollections"), + @LinkRest(name = CommunityRest.LOGO, method = "getLogo"), + @LinkRest(name = CommunityRest.SUBCOMMUNITIES, method = "getSubcommunities"), + @LinkRest(name = CommunityRest.PARENT_COMMUNITY, method = "getParentCommunity"), + @LinkRest(name = CommunityRest.ADMIN_GROUP, method = "getAdminGroup") }) public class CommunityRest extends DSpaceObjectRest { public static final String NAME = "community"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java index c06ed0e3fe1f..db243400259d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EPersonRest.java @@ -20,10 +20,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = EPersonRest.GROUPS, - method = "getGroups" - ) + @LinkRest(name = EPersonRest.GROUPS, method = "getGroups") }) public class EPersonRest extends DSpaceObjectRest { public static final String NAME = "eperson"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java index 9d4a729ded93..e73aa709180d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java @@ -15,10 +15,7 @@ * Refer to {@link org.dspace.content.EntityType} for explanation of the properties */ @LinksRest(links = { - @LinkRest( - name = EntityTypeRest.RELATION_SHIP_TYPES, - method = "getEntityTypeRelationship" - ) + @LinkRest(name = EntityTypeRest.RELATION_SHIP_TYPES, method = "getEntityTypeRelationship") }) public class EntityTypeRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java index 58402954e8db..21f41241b293 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceRest.java @@ -13,10 +13,7 @@ * This class serves as a REST representation for an External Source */ @LinksRest(links = { - @LinkRest( - name = ExternalSourceRest.ENTITY_TYPES, - method = "getSupportedEntityTypes" - ) + @LinkRest(name = ExternalSourceRest.ENTITY_TYPES, method = "getSupportedEntityTypes") }) public class ExternalSourceRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java index 7d56af2e7204..0a4963b66fa0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/GroupRest.java @@ -18,18 +18,9 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) @LinksRest(links = { - @LinkRest( - name = GroupRest.SUBGROUPS, - method = "getGroups" - ), - @LinkRest( - name = GroupRest.EPERSONS, - method = "getMembers" - ), - @LinkRest( - name = GroupRest.OBJECT, - method = "getParentObject" - ) + @LinkRest(name = GroupRest.SUBGROUPS, method = "getGroups"), + @LinkRest(name = GroupRest.EPERSONS, method = "getMembers"), + @LinkRest(name = GroupRest.OBJECT, method = "getParentObject") }) public class GroupRest extends DSpaceObjectRest { public static final String NAME = "group"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java index b3ae373ceed8..a47667441cc8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ItemRest.java @@ -17,46 +17,16 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = ItemRest.ACCESS_STATUS, - method = "getAccessStatus" - ), - @LinkRest( - name = ItemRest.BUNDLES, - method = "getBundles" - ), - @LinkRest( - name = ItemRest.IDENTIFIERS, - method = "getIdentifiers" - ), - @LinkRest( - name = ItemRest.MAPPED_COLLECTIONS, - method = "getMappedCollections" - ), - @LinkRest( - name = ItemRest.OWNING_COLLECTION, - method = "getOwningCollection" - ), - @LinkRest( - name = ItemRest.RELATIONSHIPS, - method = "getRelationships" - ), - @LinkRest( - name = ItemRest.VERSION, - method = "getItemVersion" - ), - @LinkRest( - name = ItemRest.TEMPLATE_ITEM_OF, - method = "getTemplateItemOf" - ), - @LinkRest( - name = ItemRest.THUMBNAIL, - method = "getThumbnail" - ), - @LinkRest( - name = ItemRest.SUBMITTER, - method = "getItemSubmitter" - ) + @LinkRest(name = ItemRest.ACCESS_STATUS, method = "getAccessStatus"), + @LinkRest(name = ItemRest.BUNDLES, method = "getBundles"), + @LinkRest(name = ItemRest.IDENTIFIERS, method = "getIdentifiers"), + @LinkRest(name = ItemRest.MAPPED_COLLECTIONS, method = "getMappedCollections"), + @LinkRest(name = ItemRest.OWNING_COLLECTION, method = "getOwningCollection"), + @LinkRest(name = ItemRest.RELATIONSHIPS, method = "getRelationships"), + @LinkRest(name = ItemRest.VERSION, method = "getItemVersion"), + @LinkRest(name = ItemRest.TEMPLATE_ITEM_OF, method = "getTemplateItemOf"), + @LinkRest(name = ItemRest.THUMBNAIL, method = "getThumbnail"), + @LinkRest(name = ItemRest.SUBMITTER, method = "getItemSubmitter") }) public class ItemRest extends DSpaceObjectRest { public static final String NAME = "item"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java index 2c4c7cbe6043..433d5626ca42 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/OrcidHistoryRest.java @@ -39,7 +39,7 @@ public class OrcidHistoryRest extends BaseObjectRest { private String responseMessage; - public OrcidHistoryRest(){} + public OrcidHistoryRest() {} @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java index 0b66f0604b2e..94c70037330e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/PoolTaskRest.java @@ -17,10 +17,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = PoolTaskRest.STEP, - method = "getStep" - ) + @LinkRest(name = PoolTaskRest.STEP, method = "getStep") }) public class PoolTaskRest extends BaseObjectRest { public static final String NAME = "pooltask"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java index d3d88c2776ce..fee104b4e389 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ProcessRest.java @@ -21,18 +21,9 @@ * This class serves as a REST representation for the {@link Process} class */ @LinksRest(links = { - @LinkRest( - name = ProcessRest.FILES, - method = "getFilesFromProcess" - ), - @LinkRest( - name = ProcessRest.FILE_TYPES, - method = "getFileTypesFromProcess" - ), - @LinkRest( - name = ProcessRest.OUTPUT, - method = "getOutputFromProcess" - ) + @LinkRest(name = ProcessRest.FILES, method = "getFilesFromProcess"), + @LinkRest(name = ProcessRest.FILE_TYPES, method = "getFileTypesFromProcess"), + @LinkRest(name = ProcessRest.OUTPUT, method = "getOutputFromProcess") }) public class ProcessRest extends BaseObjectRest { public static final String NAME = "process"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java index 76a7a4348682..723f7e148b27 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipRest.java @@ -19,10 +19,7 @@ * Refer to {@link org.dspace.content.Relationship} for explanation about the properties */ @LinksRest(links = { - @LinkRest( - name = RelationshipRest.RELATIONSHIP_TYPE, - method = "getRelationshipType" - ) + @LinkRest(name = RelationshipRest.RELATIONSHIP_TYPE, method = "getRelationshipType") }) public class RelationshipRest extends BaseObjectRest { public static final String NAME = "relationship"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java index 13faa2e2bbdf..629dbdf85821 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ResearcherProfileRest.java @@ -20,8 +20,8 @@ * */ @LinksRest(links = { - @LinkRest(name = ResearcherProfileRest.ITEM, method = "getItem"), - @LinkRest(name = ResearcherProfileRest.EPERSON, method = "getEPerson") + @LinkRest(name = ResearcherProfileRest.ITEM, method = "getItem"), + @LinkRest(name = ResearcherProfileRest.EPERSON, method = "getEPerson") }) public class ResearcherProfileRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionRest.java index c7210e892558..7b1a05127fc7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionRest.java @@ -21,7 +21,9 @@ * * @author Andrea Bollini (andrea.bollini at 4science.it) */ -@LinksRest(links = { @LinkRest(name = SuggestionRest.TARGET, method = "getTarget") }) +@LinksRest(links = { + @LinkRest(name = SuggestionRest.TARGET, method = "getTarget") +}) public class SuggestionRest extends BaseObjectRest { private static final long serialVersionUID = 1L; public static final String NAME = "suggestion"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionTargetRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionTargetRest.java index 65764507e247..b6518eff7488 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionTargetRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SuggestionTargetRest.java @@ -19,7 +19,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(name = SuggestionTargetRest.TARGET, method = "getTarget") + @LinkRest(name = SuggestionTargetRest.TARGET, method = "getTarget") }) public class SuggestionTargetRest extends BaseObjectRest { private static final long serialVersionUID = 1L; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java index 5aab7028a8c6..80f704c77936 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionHistoryRest.java @@ -13,14 +13,8 @@ * The REST object for the {@link org.dspace.versioning.VersionHistory} object */ @LinksRest(links = { - @LinkRest( - name = VersionHistoryRest.VERSIONS, - method = "getVersions" - ), - @LinkRest( - name = VersionHistoryRest.DRAFT_VERSION, - method = "getDraftVersion" - ) + @LinkRest(name = VersionHistoryRest.VERSIONS, method = "getVersions"), + @LinkRest(name = VersionHistoryRest.DRAFT_VERSION, method = "getDraftVersion") }) public class VersionHistoryRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java index 21bf82804dd2..d9ebdd67e408 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VersionRest.java @@ -16,14 +16,8 @@ * The REST object for the {@link org.dspace.versioning.Version} objects */ @LinksRest(links = { - @LinkRest( - name = VersionRest.VERSION_HISTORY, - method = "getVersionHistory" - ), - @LinkRest( - name = VersionRest.ITEM, - method = "getVersionItem" - ) + @LinkRest(name = VersionRest.VERSION_HISTORY, method = "getVersionHistory"), + @LinkRest(name = VersionRest.ITEM, method = "getVersionItem") }) public class VersionRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java index e5869a852521..884e14642cf9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyEntryDetailsRest.java @@ -18,9 +18,9 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(name = VocabularyEntryDetailsRest.PARENT, method = "getParent"), - @LinkRest(name = VocabularyEntryDetailsRest.CHILDREN, method = "getChildren") - }) + @LinkRest(name = VocabularyEntryDetailsRest.PARENT, method = "getParent"), + @LinkRest(name = VocabularyEntryDetailsRest.CHILDREN, method = "getChildren") +}) public class VocabularyEntryDetailsRest extends BaseObjectRest { public static final String PLURAL_NAME = "vocabularyEntryDetails"; public static final String NAME = "vocabularyEntryDetail"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java index f119059c2bb7..a54d93c643b4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/VocabularyRest.java @@ -15,9 +15,7 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest(name = VocabularyRest.ENTRIES, - method = "filter" - ), + @LinkRest(name = VocabularyRest.ENTRIES, method = "filter"), }) public class VocabularyRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java index 0ec967d09876..9cef79aaf3be 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowDefinitionRest.java @@ -18,14 +18,8 @@ * @author Maria Verdonck (Atmire) on 11/12/2019 */ @LinksRest(links = { - @LinkRest( - name = WorkflowDefinitionRest.COLLECTIONS_MAPPED_TO, - method = "getCollections" - ), - @LinkRest( - name = WorkflowDefinitionRest.STEPS, - method = "getSteps" - ) + @LinkRest(name = WorkflowDefinitionRest.COLLECTIONS_MAPPED_TO, method = "getCollections"), + @LinkRest(name = WorkflowDefinitionRest.STEPS, method = "getSteps") }) public class WorkflowDefinitionRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java index 65fa531c5e42..d08abb3546a3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java @@ -15,22 +15,10 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = WorkflowItemRest.STEP, - method = "getStep" - ), - @LinkRest( - name = WorkflowItemRest.SUBMITTER, - method = "getWorkflowItemSubmitter" - ), - @LinkRest( - name = WorkflowItemRest.ITEM, - method = "getWorkflowItemItem" - ), - @LinkRest( - name = WorkflowItemRest.COLLECTION, - method = "getWorkflowItemCollection" - ) + @LinkRest(name = WorkflowItemRest.STEP, method = "getStep"), + @LinkRest(name = WorkflowItemRest.SUBMITTER, method = "getWorkflowItemSubmitter"), + @LinkRest(name = WorkflowItemRest.ITEM, method = "getWorkflowItemItem"), + @LinkRest(name = WorkflowItemRest.COLLECTION, method = "getWorkflowItemCollection") }) public class WorkflowItemRest extends AInprogressSubmissionRest { public static final String NAME = "workflowitem"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java index b3397721c117..53ddf38709e4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowStepRest.java @@ -18,10 +18,7 @@ * @author Maria Verdonck (Atmire) on 10/01/2020 */ @LinksRest(links = { - @LinkRest( - name = WorkflowStepRest.ACTIONS, - method = "getActions" - ), + @LinkRest(name = WorkflowStepRest.ACTIONS, method = "getActions"), }) public class WorkflowStepRest extends BaseObjectRest { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java index e311cd259231..8e0d52123f99 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java @@ -15,22 +15,10 @@ * @author Andrea Bollini (andrea.bollini at 4science.it) */ @LinksRest(links = { - @LinkRest( - name = WorkspaceItemRest.SUPERVISION_ORDERS, - method = "getSupervisionOrders" - ), - @LinkRest( - name = WorkspaceItemRest.SUBMITTER, - method = "getWorkspaceItemSubmitter" - ), - @LinkRest( - name = WorkspaceItemRest.ITEM, - method = "getWorkspaceItemItem" - ), - @LinkRest( - name = WorkspaceItemRest.COLLECTION, - method = "getWorkspaceItemCollection" - ) + @LinkRest(name = WorkspaceItemRest.SUPERVISION_ORDERS, method = "getSupervisionOrders"), + @LinkRest(name = WorkspaceItemRest.SUBMITTER, method = "getWorkspaceItemSubmitter"), + @LinkRest(name = WorkspaceItemRest.ITEM, method = "getWorkspaceItemItem"), + @LinkRest(name = WorkspaceItemRest.COLLECTION, method = "getWorkspaceItemCollection") }) public class WorkspaceItemRest extends AInprogressSubmissionRest { public static final String NAME = "workspaceitem"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java index b358e785c3b3..df525f679323 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/RegexUtils.java @@ -13,7 +13,7 @@ */ public class RegexUtils { - private RegexUtils(){} + private RegexUtils() {} /** * Regular expression in the request mapping to accept UUID as identifier diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java index a154091a2eff..2a4cee8375be 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/RegistrationMatcher.java @@ -17,7 +17,7 @@ public class RegistrationMatcher { - private RegistrationMatcher(){} + private RegistrationMatcher() {} public static Matcher matchRegistration(String email, UUID epersonUuid) { return allOf( From dd8b1d91cb74c5afadc1e545b2192b5ebb8848b1 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Wed, 30 Oct 2024 13:37:53 +0100 Subject: [PATCH 068/179] 119960: Fixed NPE when retrieving a DSpace object with the api/dso/find endpoint without the required permissions --- .../app/rest/UUIDLookupRestController.java | 10 ++++- .../app/rest/UUIDLookupRestControllerIT.java | 37 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/UUIDLookupRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/UUIDLookupRestController.java index 40c0a79b97be..21631a6737a9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/UUIDLookupRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/UUIDLookupRestController.java @@ -24,9 +24,11 @@ import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.DSpaceObjectUtils; import org.dspace.app.rest.utils.Utils; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.DSpaceObject; +import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.discovery.SearchServiceException; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.Link; @@ -65,6 +67,9 @@ public class UUIDLookupRestController implements InitializingBean { @Autowired private DiscoverableEndpointsService discoverableEndpointsService; + @Autowired + private AuthorizeService authorizeService; + @Autowired private ConverterService converter; @@ -85,13 +90,14 @@ public void afterPropertiesSet() throws Exception { public void getDSObyIdentifier(HttpServletRequest request, HttpServletResponse response, @RequestParam(PARAM) UUID uuid) - throws IOException, SQLException, SearchServiceException { + throws IOException, SQLException, AuthorizeException { Context context = null; try { context = ContextUtil.obtainContext(request); DSpaceObject dso = dspaceObjectUtil.findDSpaceObject(context, uuid); if (dso != null) { + authorizeService.authorizeAction(context, dso, Constants.READ); DSpaceObjectRest dsor = converter.toRest(dso, utils.obtainProjection()); URI link = linkTo(dsor.getController(), dsor.getCategory(), dsor.getTypePlural()).slash(dsor.getId()) .toUri(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/UUIDLookupRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/UUIDLookupRestControllerIT.java index 8a6debce3ec7..3b0821645861 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/UUIDLookupRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/UUIDLookupRestControllerIT.java @@ -17,6 +17,8 @@ import org.apache.commons.codec.CharEncoding; import org.apache.commons.io.IOUtils; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.builder.BitstreamBuilder; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; @@ -31,6 +33,7 @@ import org.dspace.eperson.Group; import org.junit.Ignore; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; /** * Integration test for the UUIDLookup endpoint @@ -39,6 +42,9 @@ */ public class UUIDLookupRestControllerIT extends AbstractControllerIntegrationTest { + @Autowired + ResourcePolicyService resourcePolicyService; + @Test /** * Test the proper redirection of a site's uuid @@ -307,4 +313,35 @@ public void testMissingIdentifierParameter() throws Exception { .andExpect(status().isUnprocessableEntity()); } + @Test + public void testUnauthorized() throws Exception { + context.turnOffAuthorisationSystem(); + Community community = CommunityBuilder.createCommunity(context) + .build(); + for (ResourcePolicy rp : resourcePolicyService.find(context, community)) { + resourcePolicyService.delete(context, rp); + } + context.restoreAuthSystemState(); + + getClient().perform(get("/api/dso/find") + .param("uuid", community.getID().toString())) + .andExpect(status().isUnauthorized()); + } + + @Test + public void testForbidden() throws Exception { + context.turnOffAuthorisationSystem(); + Community community = CommunityBuilder.createCommunity(context) + .build(); + for (ResourcePolicy rp : resourcePolicyService.find(context, community)) { + resourcePolicyService.delete(context, rp); + } + context.restoreAuthSystemState(); + + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform(get("/api/dso/find") + .param("uuid", community.getID().toString())) + .andExpect(status().isForbidden()); + } + } From ebd36a93881015b18e13f020b86439fcac80090f Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 30 Oct 2024 14:49:04 -0500 Subject: [PATCH 069/179] Update jsoneditor.js reference in Hal Browser --- dspace-server-webapp/src/main/resources/static/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/resources/static/index.html b/dspace-server-webapp/src/main/resources/static/index.html index c780286107d8..0b80f806767e 100644 --- a/dspace-server-webapp/src/main/resources/static/index.html +++ b/dspace-server-webapp/src/main/resources/static/index.html @@ -321,7 +321,7 @@

Embedded Resources

- +