diff --git a/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/NamespaceHelper.java b/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/NamespaceHelper.java index a5581185c5c..16851cd57cc 100644 --- a/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/NamespaceHelper.java +++ b/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/NamespaceHelper.java @@ -72,22 +72,22 @@ public NamespaceHelper(Session session) { * @throws RepositoryException if the namespaces could not be retrieved */ public Map getNamespaces() throws RepositoryException { - Map namespaces = new HashMap(); + Map namespaces = new HashMap<>(); String[] prefixes = session.getNamespacePrefixes(); - for (String prefixe : prefixes) { - namespaces.put(prefixe, session.getNamespaceURI(prefixe)); + for (String prefix : prefixes) { + namespaces.put(prefix, session.getNamespaceURI(prefix)); } return namespaces; } /** * Returns the prefix mapped to the given namespace URI in the current - * session, or null if the namespace does not exist. + * session, or {@code null} if the namespace does not exist. * * @see Session#getNamespacePrefix(String) * @param uri namespace URI - * @return namespace prefix, or null - * @throws RepositoryException if the namespace could not be retrieved + * @return namespace prefix, or {@code null} + * @throws RepositoryException if the namespace prefix could not be retrieved */ public String getPrefix(String uri) throws RepositoryException { try { @@ -99,11 +99,11 @@ public String getPrefix(String uri) throws RepositoryException { /** * Returns the namespace URI mapped to the given prefix in the current - * session, or null if the namespace does not exist. + * session, or {@code null} if the namespace does not exist. * * @see Session#getNamespaceURI(String) * @param prefix namespace prefix - * @return namespace prefix, or null + * @return namespace prefix, or {@code null} * @throws RepositoryException if the namespace could not be retrieved */ public String getURI(String prefix) throws RepositoryException { @@ -126,7 +126,7 @@ public String getURI(String prefix) throws RepositoryException { */ public String getJcrName(String uri, String name) throws NamespaceException, RepositoryException { - if (uri != null && uri.length() > 0) { + if (uri != null && !uri.isEmpty()) { return session.getNamespacePrefix(uri) + ":" + name; } else { return name; @@ -144,6 +144,11 @@ public String getJcrName(String uri, String name) *
      *     node.getProperty(helper.getName("jcr:data"));
      * 
+ * Note that it is simpler to just use the expanded name wherever supported: + *
+     *     node.getProperty("http://www.jcp.org/jcr/1.0}data");
+     * 
+ * Also note the predefined constants in {@link org.apache.jackrabbit.JcrConstants}. * * @param name prefixed name using the standard JCR prefixes * @return prefixed name using the current session namespace mappings @@ -178,7 +183,7 @@ public String getJcrName(String name) /** * Safely registers the given namespace. If the namespace already exists, * then the prefix mapped to the namespace in the current session is - * returned. Otherwise the namespace is registered to the namespace + * returned. Otherwise, the namespace is registered to the namespace * registry. If the given prefix is already registered for some other * namespace or otherwise invalid, then another prefix is automatically * generated. After the namespace has been registered, the prefix mapped @@ -199,7 +204,7 @@ public String registerNamespace(String prefix, String uri) registry.getPrefix(uri); } catch (NamespaceException e1) { // Replace troublesome prefix hints - if (prefix == null || prefix.length() == 0 + if (prefix == null || prefix.isEmpty() || prefix.toLowerCase().startsWith("xml") || !XMLChar.isValidNCName(prefix)) { prefix = "ns"; // ns, ns2, ns3, ns4, ... @@ -231,8 +236,7 @@ public String registerNamespace(String prefix, String uri) * @throws RepositoryException if the namespaces could not be registered */ public void registerNamespaces(Map namespaces) throws RepositoryException { - for (Map.Entry stringStringEntry : namespaces.entrySet()) { - Map.Entry entry = stringStringEntry; + for (Map.Entry entry : namespaces.entrySet()) { registerNamespace(entry.getKey(), entry.getValue()); } } diff --git a/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/NamespaceHelperTest.java b/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/NamespaceHelperTest.java new file mode 100644 index 00000000000..17c849d1344 --- /dev/null +++ b/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/NamespaceHelperTest.java @@ -0,0 +1,237 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.commons; + +import junit.framework.TestCase; +import org.mockito.Mockito; + +import javax.jcr.NamespaceException; +import javax.jcr.NamespaceRegistry; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Workspace; +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +public class NamespaceHelperTest extends TestCase { + + private Session session; + + @Override + protected void setUp() throws Exception { + super.setUp(); + session = Mockito.mock(Session.class); + } + + public void testGetNamespaces() throws RepositoryException { + NamespaceHelper nsHelper = new NamespaceHelper(session); + + when(session.getNamespacePrefixes()).thenReturn(new String[0]); + Map map = nsHelper.getNamespaces(); + assertEquals(0, map.size()); + + when(session.getNamespacePrefixes()).thenReturn(new String[]{"foo"}); + map = nsHelper.getNamespaces(); + assertEquals(1, map.size()); + assertNull(map.get("foo")); + + when(session.getNamespacePrefixes()).thenReturn(new String[]{"foo", "bar"}); + when(session.getNamespaceURI("bar")).thenReturn("urn:test"); + map = nsHelper.getNamespaces(); + assertEquals(2, map.size()); + assertNull(map.get("foo")); + assertEquals("urn:test", map.get("bar")); + } + + public void testGetPrefix() throws RepositoryException { + NamespaceHelper nsHelper = new NamespaceHelper(session); + + String uri1 = "urn:test1"; + + when(session.getNamespacePrefix(uri1)).thenThrow(NamespaceException.class); + String prefix = nsHelper.getPrefix(uri1); + assertNull(prefix); + + String uri2 = "urn:test2"; + + when(session.getNamespacePrefix(uri2)).thenReturn("foo"); + prefix = nsHelper.getPrefix(uri2); + assertEquals("foo", prefix); + } + + public void testGetURI() throws RepositoryException { + NamespaceHelper nsHelper = new NamespaceHelper(session); + + String prefix1 = "prefix1"; + + when(session.getNamespaceURI(prefix1)).thenThrow(NamespaceException.class); + String uri = nsHelper.getURI(prefix1); + assertNull(uri); + + String prefix2 = "prefix2"; + + when(session.getNamespaceURI(prefix2)).thenReturn("foo:bar"); + uri = nsHelper.getURI(prefix2); + assertEquals("foo:bar", uri); + } + + public void testGetJcrName() throws RepositoryException { + NamespaceHelper nsHelper = new NamespaceHelper(session); + + when(session.getNamespacePrefix(NamespaceHelper.JCR)).thenReturn("jcr"); + assertEquals("jcr:xyz", nsHelper.getJcrName("jcr:xyz")); + + when(session.getNamespacePrefix(NamespaceHelper.MIX)).thenReturn("foo"); + assertEquals("foo:xyz", nsHelper.getJcrName("mix:xyz")); + + try { + when(session.getNamespacePrefix("urn:foo")).thenReturn("unknown"); + String shouldFail = nsHelper.getJcrName("foo:xyz"); + fail("getJcrName should fail for unknown prefix foo, but got: " + shouldFail); + } catch (IllegalArgumentException expected) { + // all good + } + + try { + when(session.getNamespacePrefix(NamespaceHelper.NT)).thenThrow(NamespaceException.class); + String shouldFail = nsHelper.getJcrName(NamespaceHelper.NT); + fail("getJcrName should fail for unknown prefix nt, but got: " + shouldFail); + } catch (IllegalArgumentException expected) { + // all good + } + } + + public void testGetJcrName2() throws RepositoryException { + NamespaceHelper nsHelper = new NamespaceHelper(session); + + assertEquals("foo", nsHelper.getJcrName(null, "foo")); + assertEquals("foo", nsHelper.getJcrName("", "foo")); + + when(session.getNamespacePrefix("urn:bar")).thenReturn("bar"); + assertEquals("bar:foo", nsHelper.getJcrName("urn:bar", "foo")); + } + + public void testRegisterNamespaceAlreadyRegistered() throws RepositoryException { + NamespaceHelper nsHelper = new NamespaceHelper(session); + + Workspace workspace = Mockito.mock(Workspace.class); + NamespaceRegistry nsReg = Mockito.mock(NamespaceRegistry.class); + + when(session.getWorkspace()).thenReturn(workspace); + when(workspace.getNamespaceRegistry()).thenReturn(nsReg); + + when(nsReg.getPrefix("foo:")).thenReturn("xyz"); + when(session.getNamespacePrefix("foo:")).thenReturn("xyz"); + String prefix = nsHelper.registerNamespace("bar", "foo:"); + assertEquals("xyz", prefix); + } + + public void testRegisterNamespace() throws RepositoryException { + Workspace workspace = Mockito.mock(Workspace.class); + NamespaceRegistry nsReg = Mockito.mock(NamespaceRegistry.class); + + when(session.getWorkspace()).thenReturn(workspace); + when(workspace.getNamespaceRegistry()).thenReturn(nsReg); + + // poor man's namespace registry + + final HashMap pref2uri = new HashMap<>(); + final HashMap uri2pref = new HashMap<>(); + + // defaults (incomplete) + pref2uri.put("xml", NamespaceRegistry.NAMESPACE_XML); + uri2pref.put(NamespaceRegistry.NAMESPACE_XML, "xml"); + pref2uri.put("jcr", NamespaceRegistry.NAMESPACE_JCR); + uri2pref.put(NamespaceRegistry.NAMESPACE_JCR, "jcr"); + + Mockito.doAnswer(invocation -> { + String rpref = invocation.getArgument(0); + String ruri = invocation.getArgument(1); + if (null != uri2pref.get(ruri) || null != pref2uri.get(rpref)) { + throw new NamespaceException(); + } else { + pref2uri.put(rpref, ruri); + uri2pref.put(ruri, rpref); + return null; + } + }).when(nsReg).registerNamespace(any(), any()); + + when(nsReg.getPrefix(any())).thenAnswer(invocation -> { + String found = uri2pref.get(invocation.getArgument(0)); + if (found != null) { + return found; + } else { + throw new NamespaceException(); + } + }); + + when(nsReg.getURI(any())).thenAnswer(invocation -> { + String found = pref2uri.get(invocation.getArgument(0)); + if (found != null) { + return found; + } else { + throw new NamespaceException(); + } + }); + + when(session.getNamespacePrefix(any())).thenAnswer(invocation -> { + String found = uri2pref.get(invocation.getArgument(0)); + if (found != null) { + return found; + } else { + throw new NamespaceException(); + } + }); + + when(session.getNamespaceURI(any())).thenAnswer(invocation -> { + String found = pref2uri.get(invocation.getArgument(0)); + if (found != null) { + return found; + } else { + throw new NamespaceException(); + } + }); + + NamespaceHelper nsHelper = new NamespaceHelper(session); + + // register namespace (test makes assumptions about implementation) + + assertEquals("ns", nsHelper.registerNamespace("", "foo:")); + assertEquals("ns2", nsHelper.registerNamespace("", "foo2:")); + assertEquals("ns3", nsHelper.registerNamespace("xmlxxx", "foo3:")); + assertEquals("ns4", nsHelper.registerNamespace("123", "foo4:")); + assertEquals("ns3", nsHelper.registerNamespace("xmlxxx", "foo3:")); + assertEquals("ns5", nsHelper.registerNamespace(null, "foo6:")); + + assertEquals("bar", nsHelper.registerNamespace("bar", "bar:")); + assertEquals("bar2", nsHelper.registerNamespace("bar", "bar2:")); + assertEquals("bar3", nsHelper.registerNamespace("bar", "bar3:")); + + assertEquals("jcr", nsHelper.registerNamespace("wtf", NamespaceRegistry.NAMESPACE_JCR)); + assertEquals("xml", nsHelper.registerNamespace("", NamespaceRegistry.NAMESPACE_XML)); + + // register namespaces + Map input = Map.of("test1", "test1:", "test2", "test2", "", "test3:"); + nsHelper.registerNamespaces(input); + assertEquals("test1", nsReg.getPrefix("test1:")); + assertEquals("test2", nsReg.getPrefix("test2")); + assertEquals("ns6", nsReg.getPrefix("test3:")); + } +}