diff --git a/dspace-api/src/main/java/org/dspace/identifier/HandleIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/HandleIdentifierProvider.java index 92eb7ca6b3..8f02b9c5ff 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/HandleIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/HandleIdentifierProvider.java @@ -15,6 +15,7 @@ import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.handle.service.HandleService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -51,20 +52,30 @@ public class HandleIdentifierProvider extends IdentifierProvider { public boolean supports(String identifier) { String prefix = handleService.getPrefix(); - String handleResolver = ConfigurationManager.getProperty("handle.canonical.prefix"); + String canonicalPrefix = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty("handle.canonical.prefix"); if (identifier == null) { return false; } - if (identifier.startsWith(prefix) - || identifier.startsWith(handleResolver) - || identifier.startsWith("http://hdl.handle.net/") + // return true if handle has valid starting pattern + if (identifier.startsWith(prefix + "/") + || identifier.startsWith(canonicalPrefix) || identifier.startsWith("hdl:") - || identifier.startsWith("info:hdl")) + || identifier.startsWith("info:hdl") + || identifier.matches("^https?://hdl\\.handle\\.net/.*") + || identifier.matches("^https?://.+/handle/.*")) { return true; } + //Check additional prefixes supported in the config file + String[] additionalPrefixes = DSpaceServicesFactory.getInstance().getConfigurationService().getArrayProperty("handle.additional.prefixes"); + for(String additionalPrefix: additionalPrefixes) { + if (identifier.startsWith(additionalPrefix + "/")) { + return true; + } + } + return false; } diff --git a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java index 49cd18886d..c23c6e19e9 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java @@ -16,6 +16,7 @@ import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.handle.service.HandleService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.*; import org.dspace.versioning.service.VersionHistoryService; import org.dspace.versioning.service.VersioningService; @@ -70,21 +71,32 @@ public class VersionedHandleIdentifierProvider extends IdentifierProvider { @Override public boolean supports(String identifier) { - String prefix = handleService.getPrefix(); - String handleResolver = ConfigurationManager.getProperty("handle.canonical.prefix"); + String prefix = handleService.getPrefix(); + String canonicalPrefix = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty("handle.canonical.prefix"); if (identifier == null) { return false; } - if (identifier.startsWith(prefix) - || identifier.startsWith(handleResolver) - || identifier.startsWith("http://hdl.handle.net/") + // return true if handle has valid starting pattern + if (identifier.startsWith(prefix + "/") + || identifier.startsWith(canonicalPrefix) || identifier.startsWith("hdl:") - || identifier.startsWith("info:hdl")) + || identifier.startsWith("info:hdl") + || identifier.matches("^https?://hdl\\.handle\\.net/.*") + || identifier.matches("^https?://.+/handle/.*")) { return true; } - + + //Check additional prefixes supported in the config file + String[] additionalPrefixes = DSpaceServicesFactory.getInstance().getConfigurationService().getArrayProperty("handle.additional.prefixes"); + for(String additionalPrefix: additionalPrefixes) { + if (identifier.startsWith(additionalPrefix + "/")) { + return true; + } + } + + // otherwise, assume invalid handle return false; } diff --git a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java index e455825bf5..68782cc2a2 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java +++ b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProviderWithCanonicalHandles.java @@ -16,6 +16,7 @@ import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.handle.service.HandleService; +import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.versioning.*; import org.dspace.versioning.service.VersionHistoryService; import org.dspace.versioning.service.VersioningService; @@ -66,21 +67,32 @@ public class VersionedHandleIdentifierProviderWithCanonicalHandles extends Ident @Override public boolean supports(String identifier) { - String prefix = handleService.getPrefix(); - String handleResolver = ConfigurationManager.getProperty("handle.canonical.prefix"); + String prefix = handleService.getPrefix(); + String canonicalPrefix = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty("handle.canonical.prefix"); if (identifier == null) { return false; } - if (identifier.startsWith(prefix) - || identifier.startsWith(handleResolver) - || identifier.startsWith("http://hdl.handle.net/") + // return true if handle has valid starting pattern + if (identifier.startsWith(prefix + "/") + || identifier.startsWith(canonicalPrefix) || identifier.startsWith("hdl:") - || identifier.startsWith("info:hdl")) + || identifier.startsWith("info:hdl") + || identifier.matches("^https?://hdl\\.handle\\.net/.*") + || identifier.matches("^https?://.+/handle/.*")) { return true; } - + + //Check additional prefixes supported in the config file + String[] additionalPrefixes = DSpaceServicesFactory.getInstance().getConfigurationService().getArrayProperty("handle.additional.prefixes"); + for(String additionalPrefix: additionalPrefixes) { + if (identifier.startsWith(additionalPrefix + "/")) { + return true; + } + } + + // otherwise, assume invalid handle return false; } diff --git a/dspace-api/src/test/java/org/dspace/identifier/HandleIdentifierProviderTest.java b/dspace-api/src/test/java/org/dspace/identifier/HandleIdentifierProviderTest.java new file mode 100644 index 0000000000..550c0f5c34 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/identifier/HandleIdentifierProviderTest.java @@ -0,0 +1,369 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.identifier; + +import java.io.IOException; +import java.util.Map; +import java.util.Properties; +import org.dspace.AbstractDSpaceTest; +import org.dspace.kernel.ServiceManager; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +import static org.junit.Assert.*; + +/** + * Test the HandleIdentifierProvider. + *

+ * We need to define a Bean for the System Under Test so that we can get Spring + * to do autowiring on it. There are several conflicting definitions of Handle + * provider beans in the XML Spring configuration, so to test them all we'd have + * to reconfigure between tests. Instead, create a new definition just for + * testing so that we know that we have the one that we want. + * + * @author mwood + */ +public class HandleIdentifierProviderTest + extends AbstractDSpaceTest +{ + /** A name for our testing bean definition. */ + private static final String BEAN_NAME = "test-HandleIdentifierProvider"; + + /** Spring application context. */ + private static AnnotationConfigApplicationContext applicationContext; + + public HandleIdentifierProviderTest() + { + } + + /** + * The special test bean for the target class is defined here. + */ + @BeforeClass + public static void setUpClass() + { + ServiceManager serviceManager = kernelImpl.getServiceManager(); + + // Get the normal ApplicationContext + ApplicationContext parentApplicationContext + = (ApplicationContext) serviceManager.getServiceByName( + ApplicationContext.class.getName(), + ApplicationContext.class); + + // Wrap it in a new empty context that we can configure. + applicationContext = new AnnotationConfigApplicationContext(); + applicationContext.setParent(parentApplicationContext); + applicationContext.setId("TestingContext"); + + // Define our special bean for testing the target class. + GenericBeanDefinition bd = new GenericBeanDefinition(); + bd.setBeanClass(HandleIdentifierProvider.class); + bd.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); + bd.setScope(GenericBeanDefinition.SCOPE_PROTOTYPE); + applicationContext.registerBeanDefinition(BEAN_NAME, bd); // Now our SUT is a Bean. + applicationContext.refresh(); + } + + /** + * Clean up special test Spring stuff. + */ + @AfterClass + public static void tearDownClass() + { + // Clean up testing ApplicationContext and any beans within. + applicationContext.close(); + } + + @Before + public void setUp() + { + } + + @After + public void tearDown() + { + } + + /** + * Test of supports(Class) method, of class HandleIdentifierProvider. + */ +/* + @Test + public void testSupports_Class() + { + System.out.println("supports(Class)"); + Class identifier = null; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + boolean expResult = false; + boolean result = instance.supports(identifier); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of supports(String) method, of class HandleIdentifierProvider. + * Read a property list of identifiers and ask an instance of the provider + * whether it supports each. Properties are "identifier = true/false", + * where the value indicates whether the identifier should be supported. + * The list is a .properties on the class path. + */ + @Test + public void testSupports_String() + { + System.out.println("supports(String)"); + + DSpaceServicesFactory.getInstance().getConfigurationService().setProperty("handle.prefix", "123456789"); + DSpaceServicesFactory.getInstance().getConfigurationService().setProperty("handle.additional.prefixes", "123456789.1,123456789.2"); + + // We have to get Spring to instantiate the provider as a Bean, because + // the bean class has autowired fields. + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + applicationContext.getAutowireCapableBeanFactory().autowireBeanProperties( + instance, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true); + + // Load the test cases + Properties forms = new Properties(); + try { + forms.load(this.getClass().getResourceAsStream("handle-forms.properties")); + } catch (IOException e) { + System.err.format("Could not load handle-forms.properties: %s%n", e.getMessage()); + return; + } + + // Test each case + for (Map.Entry entry : forms.entrySet()) + { + String identifier = (String)entry.getKey(); + boolean expResult = Boolean.parseBoolean((String)entry.getValue()); + boolean result = instance.supports(identifier); + String message = expResult ? + "This provider should support " + identifier : + "This provider should not support " + identifier; + assertEquals(message, expResult, result); + } + } + + /** + * Test of register method, of class HandleIdentifierProvider. + */ +/* + @Test + public void testRegister_Context_DSpaceObject() + { + System.out.println("register"); + Context context = null; + DSpaceObject dso = null; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + String expResult = ""; + String result = instance.register(context, dso); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of register method, of class HandleIdentifierProvider. + */ +/* + @Test + public void testRegister_3args() + { + System.out.println("register"); + Context context = null; + DSpaceObject dso = null; + String identifier = ""; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + instance.register(context, dso, identifier); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of reserve method, of class HandleIdentifierProvider. + */ +/* + @Test + public void testReserve() + { + System.out.println("reserve"); + Context context = null; + DSpaceObject dso = null; + String identifier = ""; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + instance.reserve(context, dso, identifier); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of mint method, of class HandleIdentifierProvider. + */ +/* + @Test + public void testMint() + { + System.out.println("mint"); + Context context = null; + DSpaceObject dso = null; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + String expResult = ""; + String result = instance.mint(context, dso); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of resolve method, of class HandleIdentifierProvider. + */ +/* + @Test + public void testResolve() + { + System.out.println("resolve"); + Context context = null; + String identifier = ""; + String[] attributes = null; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + DSpaceObject expResult = null; + DSpaceObject result = instance.resolve(context, identifier, attributes); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of lookup method, of class HandleIdentifierProvider. + * @throws java.lang.Exception passed through. + */ +/* + @Test + public void testLookup() + throws Exception + { + System.out.println("lookup"); + Context context = null; + DSpaceObject dso = null; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + String expResult = ""; + String result = instance.lookup(context, dso); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of delete method, of class HandleIdentifierProvider. + * @throws java.lang.Exception passed through. + */ +/* + @Test + public void testDelete_3args() + throws Exception + { + System.out.println("delete"); + Context context = null; + DSpaceObject dso = null; + String identifier = ""; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + instance.delete(context, dso, identifier); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of delete method, of class HandleIdentifierProvider. + * @throws java.lang.Exception passed through. + */ +/* + @Test + public void testDelete_Context_DSpaceObject() + throws Exception + { + System.out.println("delete"); + Context context = null; + DSpaceObject dso = null; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + instance.delete(context, dso); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of retrieveHandleOutOfUrl method, of class HandleIdentifierProvider. + * @throws java.lang.Exception passed through. + */ +/* + @Test + public void testRetrieveHandleOutOfUrl() + throws Exception + { + System.out.println("retrieveHandleOutOfUrl"); + String url = ""; + String expResult = ""; + String result = HandleIdentifierProvider.retrieveHandleOutOfUrl(url); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of getPrefix method, of class HandleIdentifierProvider. + */ +/* + @Test + public void testGetPrefix() + { + System.out.println("getPrefix"); + String expResult = ""; + String result = HandleIdentifierProvider.getPrefix(); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ + + /** + * Test of populateHandleMetadata method, of class HandleIdentifierProvider. + * @throws java.lang.Exception passed through. + */ +/* + @Test + public void testPopulateHandleMetadata() + throws Exception + { + System.out.println("populateHandleMetadata"); + Context context = null; + Item item = null; + String handle = ""; + HandleIdentifierProvider instance = new HandleIdentifierProvider(); + instance.populateHandleMetadata(context, item, handle); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } +*/ +} diff --git a/dspace-api/src/test/resources/org/dspace/identifier/handle-forms.properties b/dspace-api/src/test/resources/org/dspace/identifier/handle-forms.properties new file mode 100644 index 0000000000..e29a3962ef --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/identifier/handle-forms.properties @@ -0,0 +1,26 @@ +# Key is the identifier to be tested; value is "true" or "false": should this +# identifier be supported by the provider under test? + +http://dx.doi.org/10.14279/depositonce-5383 = false + +# Note: This next one only succeeds because handle.prefix=123456789 in Test Framework +123456789/1 = true + +# Note: This next one only succeeds because handle.additional.prefixes=123456789.1,123456789.2 in Test +123456789.1/1 = true +123456789.2/1 = true +123456789.3/1 = false + +# Other matches that should succeed +hdl:123456789/1 = true +hdl:123.456/1.2 = true +info:hdl/12345/4000 = true +http://hdl.handle.net/20.500.1/1.2 = true +https://hdl.handle.net/987/1 = true +http://my.dspace.edu/handle/123/456 = true +https://my.dspace.edu/handle/1.23/45.6 = true + +# Other matches that should fail +http://example.com/ = false +987654321/1 = false +12.3456789/1 = false \ No newline at end of file