Index: test/org/apache/jackrabbit/name/QNameTest.java =================================================================== --- test/org/apache/jackrabbit/name/QNameTest.java (revision 312587) +++ test/org/apache/jackrabbit/name/QNameTest.java (working copy) @@ -37,7 +37,7 @@ public QNameTest() { // create dummy namespace resolver - resolver = new NamespaceResolver(){ + resolver = new AbstractNamespaceResolver(){ public String getURI(String prefix) { return prefix; } Index: test/org/apache/jackrabbit/name/PathTest.java =================================================================== --- test/org/apache/jackrabbit/name/PathTest.java (revision 312587) +++ test/org/apache/jackrabbit/name/PathTest.java (working copy) @@ -43,7 +43,7 @@ public PathTest() { // create dummy namespace resolver - resolver = new NamespaceResolver(){ + resolver = new AbstractNamespaceResolver(){ public String getURI(String prefix) { return prefix; } Index: java/org/apache/jackrabbit/name/SessionNamespaceResolver.java =================================================================== --- java/org/apache/jackrabbit/name/SessionNamespaceResolver.java (revision 312587) +++ java/org/apache/jackrabbit/name/SessionNamespaceResolver.java (working copy) @@ -24,7 +24,7 @@ * helper class that exposes the NamespaceResolver * interface on a Session */ -public class SessionNamespaceResolver implements NamespaceResolver { +public class SessionNamespaceResolver extends AbstractNamespaceResolver { /** * the session for the namespace lookups Index: java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java =================================================================== --- java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java (revision 0) +++ java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java (revision 0) @@ -0,0 +1,136 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.name; + +import java.util.Set; +import java.util.HashSet; +import java.util.Iterator; + +/** + * Provides default implementations for the methods: + * + * Subclasses may overwrite those methods with more efficient implementations + * e.g. using caching. This class also adds optional support for + * {@link NamespaceListener}s. To enable listener support call the constructor + * with supportListeners set to true. The default + * constructor will not enable listener support and all listener related + * methods will throw an {@link UnsupportedOperationException} in that case. + */ +public abstract class AbstractNamespaceResolver implements NamespaceResolver { + + private final Set listeners; + + /** + * @inheritDoc + */ + public QName getQName(String name) throws IllegalNameException, UnknownPrefixException { + return QName.fromJCRName(name, this); + } + + /** + * @inheritDoc + */ + public String getJCRName(QName name) throws NoPrefixDeclaredException { + return name.toJCRName(this); + } + + /** + * Creates a AbstractNamespaceResolver without listener + * support. + */ + public AbstractNamespaceResolver() { + this(false); + } + + /** + * Creates a AbstractNamespaceResolver with listener support if + * supportListeners is set to true. + * + * @param supportListeners if true listener are supported by + * this instance. + */ + public AbstractNamespaceResolver(boolean supportListeners) { + if (supportListeners) { + listeners = new HashSet(); + } else { + listeners = null; + } + } + + //----------------------< NamespaceListener support >--------------- + + /** + * Registers listener to get notifications when namespace + * mappings change. + * + * @param listener the listener to register. + * @throws UnsupportedOperationException if listener support is not enabled + * for this AbstractNamespaceResolver. + */ + public void addListener(NamespaceListener listener) { + if (listeners == null) { + throw new UnsupportedOperationException("addListener"); + } + synchronized (listeners) { + listeners.add(listener); + } + } + + /** + * Removes the listener from this NamespaceRegistery. + * + * @param listener the listener to remove. + * @throws UnsupportedOperationException if listener support is not enabled + * for this AbstractNamespaceResolver. + */ + public void removeListener(NamespaceListener listener) { + if (listeners == null) { + throw new UnsupportedOperationException("removeListener"); + } + synchronized (listeners) { + listeners.remove(listener); + } + } + + /** + * Notifies listeners that a prefix has been remapped. + * + * @param prefix the new prefix. + * @param uri the according namespace uri. + */ + protected void notifyPrefixRemapped(String prefix, String uri) { + if (listeners == null) { + throw new UnsupportedOperationException("notifyPrefixRemapped"); + } + // remapping is infrequent compared to listener registration + // -> use copy-on-read + NamespaceListener[] currentListeners; + synchronized (listeners) { + int i = 0; + currentListeners = new NamespaceListener[listeners.size()]; + for (Iterator it = listeners.iterator(); it.hasNext(); ) { + currentListeners[i++] = (NamespaceListener) it.next(); + } + } + for (int i = 0; i < currentListeners.length; i++) { + currentListeners[i].prefixRemapped(prefix, uri); + } + } +} Property changes on: java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java ___________________________________________________________________ Name: svn:eol-style + native Index: java/org/apache/jackrabbit/name/NamespaceListener.java =================================================================== --- java/org/apache/jackrabbit/name/NamespaceListener.java (revision 0) +++ java/org/apache/jackrabbit/name/NamespaceListener.java (revision 0) @@ -0,0 +1,32 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.name; + +/** + * Receives notifications when a namespace mapping changes. + */ +public interface NamespaceListener { + + /** + * Notifies the listener that the namespace uri has been + * re-mapped to the new prefix. + * + * @param prefix the new prefix for uri. + * @param uri the namespace uri. + */ + public void prefixRemapped(String prefix, String uri); +} Property changes on: java/org/apache/jackrabbit/name/NamespaceListener.java ___________________________________________________________________ Name: svn:eol-style + native Index: java/org/apache/jackrabbit/name/CachingNamespaceResolver.java =================================================================== --- java/org/apache/jackrabbit/name/CachingNamespaceResolver.java (revision 0) +++ java/org/apache/jackrabbit/name/CachingNamespaceResolver.java (revision 0) @@ -0,0 +1,122 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.name; + +import org.apache.jackrabbit.name.QName; +import org.apache.jackrabbit.name.IllegalNameException; +import org.apache.jackrabbit.name.UnknownPrefixException; +import org.apache.jackrabbit.name.NoPrefixDeclaredException; +import org.apache.jackrabbit.name.NamespaceResolver; +import org.apache.jackrabbit.name.NamespaceListener; +import org.apache.jackrabbit.name.AbstractNamespaceResolver; +import org.apache.commons.collections.map.LRUMap; + +import javax.jcr.NamespaceException; +import java.util.Map; + +/** + * Implements a {@link NamespaceResolver} that caches QName to resolved jcr names + * and vice versa. The cache is invalidated when a namespace uri to prefix + * mapping is changed. + */ +public class CachingNamespaceResolver implements NamespaceResolver, NamespaceListener { + + /** + * The base namespace resolver. + */ + private final AbstractNamespaceResolver base; + + /** + * Maps QName instances to resolved jcr name Strings. + */ + private final Map qnameToJCRName; + + /** + * Maps resolved jcr name Strings to QName instances. + */ + private final Map jcrNameToQName; + + /** + * Creates a new CachingNamespaceResolver. + * + * @param base a base namespace resolver with support for listener + * registration. + * @param cacheSize number of mappings this resolver may cache. + */ + public CachingNamespaceResolver(AbstractNamespaceResolver base, int cacheSize) { + this.base = base; + qnameToJCRName = new LRUMap(cacheSize); + jcrNameToQName = new LRUMap(cacheSize); + this.base.addListener(this); + } + + /** + * @inheritDoc + */ + public String getURI(String prefix) throws NamespaceException { + return base.getURI(prefix); + } + + /** + * @inheritDoc + */ + public String getPrefix(String uri) throws NamespaceException { + return base.getPrefix(uri); + } + + /** + * @inheritDoc + */ + public synchronized QName getQName(String name) throws IllegalNameException, UnknownPrefixException { + QName qName = (QName) jcrNameToQName.get(name); + if (qName == null) { + qName = QName.fromJCRName(name, this); + jcrNameToQName.put(name, qName); + } + return qName; + } + + /** + * @inheritDoc + */ + public synchronized String getJCRName(QName name) throws NoPrefixDeclaredException { + String jcrName = (String) qnameToJCRName.get(name); + if (jcrName == null) { + jcrName = name.toJCRName(this); + qnameToJCRName.put(name, jcrName); + } + return jcrName; + } + + /** + * Disposes this CachingNamespaceResolver. + */ + public void dispose() { + base.removeListener(this); + } + + //---------------------< NamespaceListener >------------------------ + + /** + * @inheritDoc + * Invalidates all cached mappings. + */ + public synchronized void prefixRemapped(String prefix, String uri) { + qnameToJCRName.clear(); + jcrNameToQName.clear(); + } +} Property changes on: java/org/apache/jackrabbit/name/CachingNamespaceResolver.java ___________________________________________________________________ Name: svn:eol-style + native Index: java/org/apache/jackrabbit/name/NamespaceResolver.java =================================================================== --- java/org/apache/jackrabbit/name/NamespaceResolver.java (revision 312587) +++ java/org/apache/jackrabbit/name/NamespaceResolver.java (working copy) @@ -46,4 +46,22 @@ */ String getPrefix(String uri) throws NamespaceException; + /** + * Parses the given prefixed JCR name into a qualified name. + * + * @param name the raw name, potentially prefixed. + * @return the QName instance for the raw name. + * @throws IllegalNameException if the given name is not a valid JCR name + * @throws UnknownPrefixException if the JCR name prefix does not resolve + */ + public QName getQName(String name) + throws IllegalNameException, UnknownPrefixException; + + /** + * Returns the qualified name in the prefixed JCR name format. + * + * @return name the qualified name + * @throws NoPrefixDeclaredException if the namespace can not be resolved + */ + public String getJCRName(QName name) throws NoPrefixDeclaredException; } Index: java/org/apache/jackrabbit/core/SessionImpl.java =================================================================== --- java/org/apache/jackrabbit/core/SessionImpl.java (revision 312587) +++ java/org/apache/jackrabbit/core/SessionImpl.java (working copy) @@ -1117,6 +1117,8 @@ // notify listeners that session is about to be closed notifyLoggingOut(); + // dispose name resolver + nsMappings.dispose(); // dispose session item state manager itemStateMgr.dispose(); // dispose item manager Index: java/org/apache/jackrabbit/core/LocalNamespaceMappings.java =================================================================== --- java/org/apache/jackrabbit/core/LocalNamespaceMappings.java (revision 312587) +++ java/org/apache/jackrabbit/core/LocalNamespaceMappings.java (working copy) @@ -18,6 +18,10 @@ import org.apache.jackrabbit.name.NamespaceResolver; import org.apache.jackrabbit.name.QName; +import org.apache.jackrabbit.name.IllegalNameException; +import org.apache.jackrabbit.name.UnknownPrefixException; +import org.apache.jackrabbit.name.NoPrefixDeclaredException; +import org.apache.jackrabbit.name.CachingNamespaceResolver; import org.apache.xerces.util.XMLChar; import javax.jcr.NamespaceException; @@ -40,7 +44,7 @@ * looking up the local namespace mapping and then backing to the * underlying namespace registry. */ -class LocalNamespaceMappings implements NamespaceResolver { +class LocalNamespaceMappings extends CachingNamespaceResolver { /** The underlying global and persistent namespace registry. */ private final NamespaceRegistryImpl nsReg; @@ -61,6 +65,7 @@ * @param nsReg namespace registry */ LocalNamespaceMappings(NamespaceRegistryImpl nsReg) { + super(nsReg, 100); this.nsReg = nsReg; } @@ -151,6 +156,9 @@ uriToPrefix.put(uri, prefix); hiddenPrefixes.add(globalPrefix); } + + // invalidate cache + super.prefixRemapped(prefix, uri); } /** @@ -189,8 +197,9 @@ return nsReg.getURI(prefix); } // check local mappings - if (prefixToURI.containsKey(prefix)) { - return (String) prefixToURI.get(prefix); + String uri = (String) prefixToURI.get(prefix); + if (uri != null) { + return uri; } // check global mappings @@ -211,11 +220,68 @@ } // check local mappings - if (uriToPrefix.containsKey(uri)) { - return (String) uriToPrefix.get(uri); + String prefix = (String) uriToPrefix.get(uri); + if (prefix != null) { + return prefix; } // check global mappings return nsReg.getPrefix(uri); } + + /** + * {@inheritDoc} + */ + public QName getQName(String name) + throws IllegalNameException, UnknownPrefixException { + if (prefixToURI.isEmpty()) { + // shortcut + return nsReg.getQName(name); + } + try { + // first try registry, this might result in a wrong QName because + // of locally overlayed mappings + QName candidate = nsReg.getQName(name); + // check if valid + String prefix = nsReg.getPrefix(candidate.getNamespaceURI()); + if (!hiddenPrefixes.contains(prefix)) { + return candidate; + } + } catch (UnknownPrefixException e) { + // try using local mappings + } catch (NamespaceException e) { + // may be thrown by nsReg.getPrefix() but should never happend + // because we got the namespace from the nsReg itself + throw new UnknownPrefixException(name); + } + return super.getQName(name); + } + + /** + * {@inheritDoc} + */ + public String getJCRName(QName name) + throws NoPrefixDeclaredException { + if (uriToPrefix.isEmpty()) { + // shortcut + return nsReg.getJCRName(name); + } + if (uriToPrefix.containsKey(name.getNamespaceURI())) { + // locally re-mappped + return super.getJCRName(name); + } else { + // use global mapping + return nsReg.getJCRName(name); + } + } + + /** + * @inheritDoc + * This method gets called when the NamespaceRegistry remapped a namespace + * to a new prefix or if a new namespace is registered. + */ + public void prefixRemapped(String prefix, String uri) { + // todo check overlayed mappings and adjust prefixes if necessary + super.prefixRemapped(prefix, uri); + } } Index: java/org/apache/jackrabbit/core/PropertyImpl.java =================================================================== --- java/org/apache/jackrabbit/core/PropertyImpl.java (revision 312587) +++ java/org/apache/jackrabbit/core/PropertyImpl.java (working copy) @@ -160,7 +160,7 @@ case PropertyType.NAME: QName name = (QName) value.internalValue(); try { - return name.toJCRName(session.getNamespaceResolver()).length(); + return session.getNamespaceResolver().getJCRName(name).length(); } catch (NoPrefixDeclaredException npde) { // should never happen... String msg = safeGetJCRPath() @@ -1116,7 +1116,7 @@ PropertyId propId = (PropertyId) id; QName name = propId.getName(); try { - return name.toJCRName(session.getNamespaceResolver()); + return session.getNamespaceResolver().getJCRName(name); } catch (NoPrefixDeclaredException npde) { // should never get here... String msg = "internal error: encountered unregistered namespace " + name.getNamespaceURI(); Index: java/org/apache/jackrabbit/core/NodeImpl.java =================================================================== --- java/org/apache/jackrabbit/core/NodeImpl.java (revision 312587) +++ java/org/apache/jackrabbit/core/NodeImpl.java (working copy) @@ -159,30 +159,21 @@ * first check if relPath is just a name (in which case we don't * have to build & resolve absolute path) */ - Path p = Path.create(relPath, session.getNamespaceResolver(), false); - if (p.getLength() == 1) { - Path.PathElement pe = p.getNameElement(); - if (pe.denotesName()) { - if (pe.getIndex() > 0) { - // property name can't have subscript - String msg = relPath + " is not a valid property path"; - log.debug(msg); - throw new RepositoryException(msg); - } - // check if property entry exists - NodeState thisState = (NodeState) state; - if (thisState.hasPropertyName(pe.getName())) { - return new PropertyId(thisState.getUUID(), pe.getName()); - } else { - // there's no property with that name - return null; - } + if (relPath.indexOf('/') == -1) { + QName propName = session.getNamespaceResolver().getQName(relPath); + // check if property entry exists + NodeState thisState = (NodeState) state; + if (thisState.hasPropertyName(propName)) { + return new PropertyId(thisState.getUUID(), propName); + } else { + // there's no property with that name + return null; } } /** * build and resolve absolute path */ - p = Path.create(getPrimaryPath(), relPath, session.getNamespaceResolver(), true); + Path p = Path.create(getPrimaryPath(), relPath, session.getNamespaceResolver(), true); try { ItemId id = session.getHierarchyManager().resolvePath(p); if (!id.denotesNode()) { @@ -194,7 +185,7 @@ } catch (PathNotFoundException pnfe) { return null; } - } catch (MalformedPathException e) { + } catch (BaseException e) { String msg = "failed to resolve path " + relPath + " relative to " + safeGetJCRPath(); log.debug(msg); throw new RepositoryException(msg, e); @@ -402,7 +393,7 @@ throws ConstraintViolationException, RepositoryException { QName qName; try { - qName = QName.fromJCRName(name, session.getNamespaceResolver()); + qName = session.getNamespaceResolver().getQName(name); } catch (IllegalNameException ine) { throw new RepositoryException("invalid property name: " + name, ine); } catch (UnknownPrefixException upe) { @@ -560,7 +551,7 @@ protected void removeChildProperty(String propName) throws RepositoryException { QName qName; try { - qName = QName.fromJCRName(propName, session.getNamespaceResolver()); + qName = session.getNamespaceResolver().getQName(propName); } catch (IllegalNameException ine) { throw new RepositoryException("invalid property name: " + propName, ine); @@ -1683,7 +1674,7 @@ QName name = session.getHierarchyManager().getName(id); try { - return name.toJCRName(session.getNamespaceResolver()); + return session.getNamespaceResolver().getJCRName(name); } catch (NoPrefixDeclaredException npde) { // should never get here... String msg = "internal error: encountered unregistered namespace " @@ -2372,7 +2363,7 @@ public boolean isNodeType(String nodeTypeName) throws RepositoryException { QName ntName; try { - ntName = QName.fromJCRName(nodeTypeName, session.getNamespaceResolver()); + ntName = session.getNamespaceResolver().getQName(nodeTypeName); } catch (IllegalNameException ine) { throw new RepositoryException("invalid node type name: " + nodeTypeName, ine); } catch (UnknownPrefixException upe) { @@ -2419,7 +2410,7 @@ ConstraintViolationException, LockException, RepositoryException { QName ntName; try { - ntName = QName.fromJCRName(mixinName, session.getNamespaceResolver()); + ntName = session.getNamespaceResolver().getQName(mixinName); } catch (IllegalNameException ine) { throw new RepositoryException("invalid mixin type name: " + mixinName, ine); } catch (UnknownPrefixException upe) { @@ -2437,7 +2428,7 @@ ConstraintViolationException, LockException, RepositoryException { QName ntName; try { - ntName = QName.fromJCRName(mixinName, session.getNamespaceResolver()); + ntName = session.getNamespaceResolver().getQName(mixinName); } catch (IllegalNameException ine) { throw new RepositoryException("invalid mixin type name: " + mixinName, ine); } catch (UnknownPrefixException upe) { @@ -2472,7 +2463,7 @@ QName ntName; try { - ntName = QName.fromJCRName(mixinName, session.getNamespaceResolver()); + ntName = session.getNamespaceResolver().getQName(mixinName); } catch (IllegalNameException ine) { throw new RepositoryException("invalid mixin type name: " + mixinName, ine); Index: java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java =================================================================== --- java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java (revision 312587) +++ java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java (working copy) @@ -18,8 +18,12 @@ import org.apache.jackrabbit.core.fs.FileSystem; import org.apache.jackrabbit.core.fs.FileSystemResource; -import org.apache.jackrabbit.name.NamespaceResolver; import org.apache.jackrabbit.name.QName; +import org.apache.jackrabbit.name.AbstractNamespaceResolver; +import org.apache.jackrabbit.name.IllegalNameException; +import org.apache.jackrabbit.name.UnknownPrefixException; +import org.apache.jackrabbit.name.NoPrefixDeclaredException; +import org.apache.jackrabbit.name.CachingNamespaceResolver; import org.apache.log4j.Logger; import org.apache.xerces.util.XMLChar; @@ -38,8 +42,8 @@ /** * A NamespaceRegistryImpl ... */ -public class NamespaceRegistryImpl implements NamespaceRegistry, - NamespaceResolver { +public class NamespaceRegistryImpl extends AbstractNamespaceResolver + implements NamespaceRegistry { private static Logger log = Logger.getLogger(NamespaceRegistryImpl.class); @@ -72,6 +76,8 @@ private HashMap prefixToURI = new HashMap(); private HashMap uriToPrefix = new HashMap(); + private final CachingNamespaceResolver resolver; + private final FileSystem nsRegStore; /** @@ -81,7 +87,9 @@ * @throws RepositoryException */ protected NamespaceRegistryImpl(FileSystem nsRegStore) throws RepositoryException { + super(true); // enable listener support this.nsRegStore = nsRegStore; + this.resolver = new CachingNamespaceResolver(this, 1000); load(); } @@ -257,6 +265,9 @@ // persist mappings store(); + + // notify listeners + notifyPrefixRemapped(prefix, uri); } /** @@ -298,19 +309,35 @@ * {@inheritDoc} */ public String getURI(String prefix) throws NamespaceException { - if (!prefixToURI.containsKey(prefix)) { + String uri = (String) prefixToURI.get(prefix); + if (uri == null) { throw new NamespaceException(prefix + ": is not a registered namespace prefix."); } - return (String) prefixToURI.get(prefix); + return uri; } /** * {@inheritDoc} */ public String getPrefix(String uri) throws NamespaceException { - if (!uriToPrefix.containsKey(uri)) { + String prefix = (String) uriToPrefix.get(uri); + if (prefix == null) { throw new NamespaceException(uri + ": is not a registered namespace uri."); } - return (String) uriToPrefix.get(uri); + return prefix; } + + /** + * {@inheritDoc} + */ + public QName getQName(String name) throws IllegalNameException, UnknownPrefixException { + return resolver.getQName(name); + } + + /** + * {@inheritDoc} + */ + public String getJCRName(QName name) throws NoPrefixDeclaredException { + return resolver.getJCRName(name); + } } Index: java/org/apache/jackrabbit/core/query/lucene/NamespaceMappings.java =================================================================== --- java/org/apache/jackrabbit/core/query/lucene/NamespaceMappings.java (revision 312587) +++ java/org/apache/jackrabbit/core/query/lucene/NamespaceMappings.java (working copy) @@ -21,6 +21,7 @@ import org.apache.jackrabbit.name.NoPrefixDeclaredException; import org.apache.jackrabbit.name.QName; import org.apache.jackrabbit.name.UnknownPrefixException; +import org.apache.jackrabbit.name.AbstractNamespaceResolver; import org.apache.log4j.Logger; import javax.jcr.NamespaceException; @@ -46,7 +47,7 @@ * prefix is created on the fly and associated with the namespace. Known * namespace mappings are stored in a properties file. */ -public class NamespaceMappings implements NamespaceResolver { +public class NamespaceMappings extends AbstractNamespaceResolver { /** * Default logger instance for this class Index: java/org/apache/jackrabbit/core/nodetype/xml/AdditionalNamespaceResolver.java =================================================================== --- java/org/apache/jackrabbit/core/nodetype/xml/AdditionalNamespaceResolver.java (revision 312587) +++ java/org/apache/jackrabbit/core/nodetype/xml/AdditionalNamespaceResolver.java (working copy) @@ -16,7 +16,7 @@ */ package org.apache.jackrabbit.core.nodetype.xml; -import org.apache.jackrabbit.name.NamespaceResolver; +import org.apache.jackrabbit.name.AbstractNamespaceResolver; import javax.jcr.NamespaceException; import javax.jcr.NamespaceRegistry; @@ -28,7 +28,7 @@ * A simple namespace resolver implementation, that uses the additional * namespaces declared in an XML element. */ -public class AdditionalNamespaceResolver implements NamespaceResolver { +public class AdditionalNamespaceResolver extends AbstractNamespaceResolver { /** Map from namespace prefixes to namespace URIs. */ private final Properties prefixToURI = new Properties(); Index: java/org/apache/jackrabbit/core/xml/ImportHandler.java =================================================================== --- java/org/apache/jackrabbit/core/xml/ImportHandler.java (revision 312587) +++ java/org/apache/jackrabbit/core/xml/ImportHandler.java (working copy) @@ -19,6 +19,7 @@ import org.apache.jackrabbit.core.NamespaceRegistryImpl; import org.apache.jackrabbit.name.NamespaceResolver; import org.apache.jackrabbit.name.QName; +import org.apache.jackrabbit.name.AbstractNamespaceResolver; import org.apache.log4j.Logger; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; @@ -264,7 +265,7 @@ /** * NamespaceContext supports scoped namespace declarations. */ - class NamespaceContext implements NamespaceResolver { + class NamespaceContext extends AbstractNamespaceResolver { private final NamespaceSupport nsContext;