sorry, forgot the commit msg: JCR-235 Cache jcr name to QName mappings
On 10/12/05, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote: > Author: stefan > Date: Wed Oct 12 02:04:31 2005 > New Revision: 314827 > > URL: http://svn.apache.org/viewcvs?rev=314827&view=rev > Log: (empty) > > Added: > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java > (with props) > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/CachingNamespaceResolver.java > (with props) > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java > (with props) > Modified: > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/xml/AdditionalNamespaceResolver.java > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/query/lucene/NamespaceMappings.java > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceResolver.java > > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/SessionNamespaceResolver.java > > incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/PathTest.java > > incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/QNameTest.java > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java > Wed Oct 12 02:04:31 2005 > @@ -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); > + } > + > + /** > + * [EMAIL PROTECTED] > + */ > + 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); > + } > + > + /** > + * [EMAIL PROTECTED] > + */ > + 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); > } > } > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java > Wed Oct 12 02:04:31 2005 > @@ -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 <code>NamespaceRegistryImpl</code> ... > */ > -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; > > /** > @@ -80,13 +86,17 @@ > * @param nsRegStore > * @throws RepositoryException > */ > - protected NamespaceRegistryImpl(FileSystem nsRegStore) throws > RepositoryException { > + protected NamespaceRegistryImpl(FileSystem nsRegStore) > + throws RepositoryException { > + super(true); // enable listener support > this.nsRegStore = nsRegStore; > + resolver = new CachingNamespaceResolver(this, 1000); > load(); > } > > private void load() throws RepositoryException { > - FileSystemResource propFile = new FileSystemResource(nsRegStore, > NS_REG_RESOURCE); > + FileSystemResource propFile = > + new FileSystemResource(nsRegStore, NS_REG_RESOURCE); > try { > if (!propFile.exists()) { > // clear existing mappings > @@ -150,7 +160,8 @@ > } > > private void store() throws RepositoryException { > - FileSystemResource propFile = new FileSystemResource(nsRegStore, > NS_REG_RESOURCE); > + FileSystemResource propFile = > + new FileSystemResource(nsRegStore, NS_REG_RESOURCE); > try { > propFile.makeParentDirs(); > OutputStream os = propFile.getOutputStream(); > @@ -249,7 +260,8 @@ > * (in names of nodes/properties/node types etc.) we simply > don't allow it. > */ > throw new NamespaceException("failed to register namespace " > - + prefix + " -> " + uri + ": remapping existing prefixes > is not supported."); > + + prefix + " -> " + uri > + + ": remapping existing prefixes is not supported."); > } > > prefixToURI.put(prefix, uri); > @@ -257,6 +269,9 @@ > > // persist mappings > store(); > + > + // notify listeners > + notifyPrefixRemapped(prefix, uri); > } > > /** > @@ -298,19 +313,38 @@ > * [EMAIL PROTECTED] > */ > public String getURI(String prefix) throws NamespaceException { > - if (!prefixToURI.containsKey(prefix)) { > - throw new NamespaceException(prefix + ": is not a registered > namespace 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; > } > > /** > * [EMAIL PROTECTED] > */ > public String getPrefix(String uri) throws NamespaceException { > - if (!uriToPrefix.containsKey(uri)) { > - throw new NamespaceException(uri + ": is not a registered > namespace 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; > + } > + > + /** > + * [EMAIL PROTECTED] > + */ > + public QName getQName(String name) > + throws IllegalNameException, UnknownPrefixException { > + return resolver.getQName(name); > + } > + > + /** > + * [EMAIL PROTECTED] > + */ > + public String getJCRName(QName name) throws NoPrefixDeclaredException { > + return resolver.getJCRName(name); > } > } > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java > Wed Oct 12 02:04:31 2005 > @@ -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); > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java > Wed Oct 12 02:04:31 2005 > @@ -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(); > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java > Wed Oct 12 02:04:31 2005 > @@ -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 > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/xml/AdditionalNamespaceResolver.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/xml/AdditionalNamespaceResolver.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/xml/AdditionalNamespaceResolver.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/xml/AdditionalNamespaceResolver.java > Wed Oct 12 02:04:31 2005 > @@ -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(); > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/query/lucene/NamespaceMappings.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/query/lucene/NamespaceMappings.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/query/lucene/NamespaceMappings.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/query/lucene/NamespaceMappings.java > Wed Oct 12 02:04:31 2005 > @@ -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 > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java > Wed Oct 12 02:04:31 2005 > @@ -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 @@ > /** > * <code>NamespaceContext</code> supports scoped namespace declarations. > */ > - class NamespaceContext implements NamespaceResolver { > + class NamespaceContext extends AbstractNamespaceResolver { > > private final NamespaceSupport nsContext; > > > Added: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java?rev=314827&view=auto > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java > (added) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java > Wed Oct 12 02:04:31 2005 > @@ -0,0 +1,137 @@ > +/* > + * 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: > + * <ul> > + * <li>[EMAIL PROTECTED] #getQName(String)}</li> > + * <li>[EMAIL PROTECTED] #getJCRName(QName)}</li> > + * </ul> > + * Subclasses may overwrite those methods with more efficient implementations > + * e.g. using caching. This class also adds optional support for > + * [EMAIL PROTECTED] NamespaceListener}s. To enable listener support call > the constructor > + * with <code>supportListeners</code> set to <code>true</code>. The default > + * constructor will not enable listener support and all listener related > + * methods will throw an [EMAIL PROTECTED] 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 <code>AbstractNamespaceResolver</code> without listener > + * support. > + */ > + public AbstractNamespaceResolver() { > + this(false); > + } > + > + /** > + * Creates a <code>AbstractNamespaceResolver</code> with listener > support if > + * <code>supportListeners</code> is set to <code>true</code>. > + * > + * @param supportListeners if <code>true</code> listener are supported by > + * this instance. > + */ > + public AbstractNamespaceResolver(boolean supportListeners) { > + if (supportListeners) { > + listeners = new HashSet(); > + } else { > + listeners = null; > + } > + } > + > + //--------------------------------------------< NamespaceListener > support > > + > + /** > + * Registers <code>listener</code> to get notifications when namespace > + * mappings change. > + * > + * @param listener the listener to register. > + * @throws UnsupportedOperationException if listener support is not > enabled > + * for this > <code>AbstractNamespaceResolver</code>. > + */ > + public void addListener(NamespaceListener listener) { > + if (listeners == null) { > + throw new UnsupportedOperationException("addListener"); > + } > + synchronized (listeners) { > + listeners.add(listener); > + } > + } > + > + /** > + * Removes the <code>listener</code> from this > <code>NamespaceRegistery</code>. > + * > + * @param listener the listener to remove. > + * @throws UnsupportedOperationException if listener support is not > enabled > + * for this > <code>AbstractNamespaceResolver</code>. > + */ > + 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); > + } > + } > +} > > Propchange: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Added: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/CachingNamespaceResolver.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/CachingNamespaceResolver.java?rev=314827&view=auto > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/CachingNamespaceResolver.java > (added) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/CachingNamespaceResolver.java > Wed Oct 12 02:04:31 2005 > @@ -0,0 +1,125 @@ > +/* > + * 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 [EMAIL PROTECTED] 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 <code>CachingNamespaceResolver</code>. > + * > + * @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 <code>CachingNamespaceResolver</code>. > + */ > + public void dispose() { > + base.removeListener(this); > + } > + > + //----------------------------------------------------< > NamespaceListener > > + > + /** > + * @inheritDoc > + * Invalidates all cached mappings. > + */ > + public synchronized void prefixRemapped(String prefix, String uri) { > + qnameToJCRName.clear(); > + jcrNameToQName.clear(); > + } > +} > > Propchange: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/CachingNamespaceResolver.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Added: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java?rev=314827&view=auto > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java > (added) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java > Wed Oct 12 02:04:31 2005 > @@ -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 <code>uri</code> has been > + * re-mapped to the new <code>prefix</code>. > + * > + * @param prefix the new prefix for <code>uri</code>. > + * @param uri the namespace uri. > + */ > + public void prefixRemapped(String prefix, String uri); > +} > > Propchange: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceResolver.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceResolver.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceResolver.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceResolver.java > Wed Oct 12 02:04:31 2005 > @@ -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; > } > > Modified: > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/SessionNamespaceResolver.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/SessionNamespaceResolver.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/SessionNamespaceResolver.java > (original) > +++ > incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/SessionNamespaceResolver.java > Wed Oct 12 02:04:31 2005 > @@ -24,7 +24,7 @@ > * helper class that exposes the <code>NamespaceResolver</code> > * interface on a <code>Session</code> > */ > -public class SessionNamespaceResolver implements NamespaceResolver { > +public class SessionNamespaceResolver extends AbstractNamespaceResolver { > > /** > * the session for the namespace lookups > > Modified: > incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/PathTest.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/PathTest.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/PathTest.java > (original) > +++ > incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/PathTest.java > Wed Oct 12 02:04:31 2005 > @@ -43,7 +43,7 @@ > public PathTest() { > > // create dummy namespace resolver > - resolver = new NamespaceResolver(){ > + resolver = new AbstractNamespaceResolver(){ > public String getURI(String prefix) { > return prefix; > } > > Modified: > incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/QNameTest.java > URL: > http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/QNameTest.java?rev=314827&r1=314826&r2=314827&view=diff > ============================================================================== > --- > incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/QNameTest.java > (original) > +++ > incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/name/QNameTest.java > Wed Oct 12 02:04:31 2005 > @@ -37,7 +37,7 @@ > public QNameTest() { > > // create dummy namespace resolver > - resolver = new NamespaceResolver(){ > + resolver = new AbstractNamespaceResolver(){ > public String getURI(String prefix) { > return prefix; > } > > >
