| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. 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.session; |
| |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| import javax.jcr.NamespaceException; |
| import javax.jcr.NamespaceRegistry; |
| import javax.jcr.RepositoryException; |
| import javax.jcr.UnsupportedRepositoryOperationException; |
| |
| import org.apache.xerces.util.XMLChar; |
| |
| public final class SessionNamespaceRegistry implements NamespaceRegistry { |
| |
| /** The underlying global namespace registry. */ |
| private final NamespaceRegistry registry; |
| |
| /** Local prefix to namespace URI mappings. */ |
| private final Properties prefixToURI; |
| |
| /** Local namespace URI to prefix mappings. */ |
| private final Properties uriToPrefix; |
| |
| /** The global prefixes hidden by local mappings. */ |
| private final Set hiddenPrefixes; |
| |
| /** |
| * Creates a local namespace registry based on the given global |
| * namespace registry. The local namespace mappings are initially empty. |
| * |
| * @param registry global namespace registry |
| */ |
| public SessionNamespaceRegistry(NamespaceRegistry registry) { |
| this.registry = registry; |
| this.prefixToURI = new Properties(); |
| this.uriToPrefix = new Properties(); |
| this.hiddenPrefixes = new HashSet(); |
| } |
| |
| /** |
| * Creates a local namespace mapping. See the JCR specification |
| * for the details of this rather complex operation. |
| * <p> |
| * This method implements the specified semantics of the |
| * Session.setNamespacePrefix method. Session implementations can use |
| * this method as follows: |
| * <pre> |
| * NamespaceRegistry registry = new SessionNamespaceRegistry( |
| * getWorkspace().getNamespaceRegistry()); |
| * |
| * public void setNamespacePrefix(String prefix, String uri) |
| * throws NamespaceException, RepositoryException { |
| * return registry.registerNamespace(prefix, uri); |
| * } |
| * </pre> |
| * |
| * @param prefix namespace prefix |
| * @param uri namespace URI |
| * @throws NamespaceException if the given namespace mapping is invalid |
| * @throws RepositoryException on repository errors |
| * @see NamespaceRegistry#registerNamespace(String, String) |
| * @see javax.jcr.Session#setNamespacePrefix(String, String) |
| */ |
| public void registerNamespace(String prefix, String uri) |
| throws NamespaceException, RepositoryException { |
| if (prefix.length() == 0) { |
| throw new NamespaceException("The empty prefix is reserved"); |
| } else if (uri.length() == 0) { |
| throw new NamespaceException("The empty namespace URI is reserved"); |
| } else if (prefix.toLowerCase().startsWith("xml")) { |
| throw new NamespaceException("The xml* prefixes are reserved"); |
| } else if (!XMLChar.isValidNCName(prefix)) { |
| throw new NamespaceException("Invalid prefix format"); |
| } |
| |
| // Note: throws a NamespaceException if the URI is not registered |
| String oldPrefix = getPrefix(uri); |
| |
| String oldURI; |
| try { |
| oldURI = getURI(prefix); |
| } catch (NamespaceException e) { |
| oldURI = null; |
| } |
| if (oldURI == null) { |
| hiddenPrefixes.add(oldPrefix); |
| prefixToURI.remove(oldPrefix); |
| prefixToURI.setProperty(prefix, uri); |
| uriToPrefix.setProperty(uri, prefix); |
| } else if (!uri.equals(oldURI)) { |
| throw new NamespaceException( |
| "Cannot hide an existing namespace mapping"); |
| } |
| } |
| |
| /** |
| * Not implemented. It is not possible to unregister namespaces from |
| * a session, you need to access the global namespace registry directly. |
| * |
| * @param prefix namespace prefix |
| * @throws UnsupportedRepositoryOperationException always thrown |
| */ |
| public void unregisterNamespace(String prefix) |
| throws UnsupportedRepositoryOperationException { |
| throw new UnsupportedRepositoryOperationException(); |
| } |
| |
| /** |
| * Returns the currently mapped namespace prefixes. The returned set |
| * contains all locally mapped prefixes and those global prefixes that |
| * have not been hidden by local mappings. |
| * <p> |
| * This method implements the specified semantics of the |
| * Session.getNamespacePrefixes method. Session implementations can use |
| * this method as follows: |
| * <pre> |
| * NamespaceRegistry registry = new SessionNamespaceRegistry( |
| * getWorkspace().getNamespaceRegistry()); |
| * |
| * public String getNamespacePrefixes() throws RepositoryException { |
| * return registry.getPrefixes(); |
| * } |
| * </pre> |
| * |
| * @return namespace prefixes |
| * @throws RepositoryException on repository errors |
| * @see NamespaceRegistry#getPrefixes() |
| * @see javax.jcr.Session#getNamespacePrefixes() |
| */ |
| public String[] getPrefixes() throws RepositoryException { |
| HashSet prefixes = new HashSet(); |
| prefixes.addAll(Arrays.asList(registry.getPrefixes())); |
| prefixes.removeAll(hiddenPrefixes); |
| prefixes.addAll(prefixToURI.keySet()); |
| return (String[]) prefixes.toArray(new String[prefixes.size()]); |
| } |
| |
| /** |
| * Returns the registered namespace URIs. This method call is simply |
| * forwarded to the underlying global namespace registry as it is not |
| * possible to locally add new namespace URIs. |
| * |
| * @return namespace URIs |
| * @throws RepositoryException on repository errors |
| * @see NamespaceRegistry#getURIs() |
| */ |
| public String[] getURIs() throws RepositoryException { |
| return registry.getURIs(); |
| } |
| |
| /** |
| * Returns the namespace URI that is mapped to the given prefix. |
| * Returns the local namespace mapping if the prefix is locally |
| * mapped, otherwise falls back to the underlying global namespace |
| * registry unless the prefix has been hidden by local namespace |
| * mappings. |
| * <p> |
| * This method implements the specified semantics of the |
| * Session.getNamespaceURI method. Session implementations can use |
| * this method as follows: |
| * <pre> |
| * NamespaceRegistry registry = new SessionNamespaceRegistry( |
| * getWorkspace().getNamespaceRegistry()); |
| * |
| * public String getNamespaceURI(String prefix) |
| * throws NamespaceException, RepositoryException { |
| * return registry.getURI(prefix); |
| * } |
| * </pre> |
| * |
| * @param prefix namespace prefix |
| * @return namespace URI |
| * @throws NamespaceException if the prefix is not registered or |
| * currently visible |
| * @throws RepositoryException on repository errors |
| * @see NamespaceRegistry#getURI(String) |
| * @see javax.jcr.Session#getNamespaceURI(String) |
| */ |
| public String getURI(String prefix) |
| throws NamespaceException, RepositoryException { |
| String uri = prefixToURI.getProperty(prefix); |
| if (uri != null) { |
| return uri; |
| } else if (!hiddenPrefixes.contains(prefix)) { |
| return registry.getURI(prefix); |
| } else { |
| throw new NamespaceException( |
| "Namespace mapping not found for prefix " + prefix); |
| } |
| } |
| |
| /** |
| * Returns the prefix that is mapped to the given namespace URI. |
| * Returns the local prefix if the namespace URI is locally mapped, |
| * otherwise falls back to the underlying global namespace registry. |
| * <p> |
| * This method implements the specified semantics of the |
| * Session.getNamespacePrefix method. Session implementations can use |
| * this method as follows: |
| * <pre> |
| * NamespaceRegistry registry = new SessionNamespaceRegistry( |
| * getWorkspace().getNamespaceRegistry()); |
| * |
| * public String getNamespacePrefix(String uri) |
| * throws NamespaceException, RepositoryException { |
| * return registry.getPrefix(uri); |
| * } |
| * </pre> |
| * |
| * @param uri namespace URI |
| * @return namespace prefix |
| * @throws NamespaceException if the namespace URI is not registered |
| * @throws RepositoryException on repository errors |
| * @see NamespaceRegistry#getPrefix(String) |
| * @see javax.jcr.Session#getNamespacePrefix(String) |
| */ |
| public String getPrefix(String uri) |
| throws NamespaceException, RepositoryException { |
| String prefix = uriToPrefix.getProperty(uri); |
| if (prefix != null) { |
| return prefix; |
| } else { |
| return registry.getPrefix(uri); |
| } |
| } |
| |
| } |