You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by Stefan Guggisberg <st...@gmail.com> on 2005/10/12 11:08:57 UTC

Re: svn commit: r314827 - in /incubator/jackrabbit/trunk/src: java/org/apache/jackrabbit/core/ java/org/apache/jackrabbit/core/nodetype/xml/ java/org/apache/jackrabbit/core/query/lucene/ java/org/apache/jackrabbit/core/xml/ java/org/apache/jackrabbit

sorry, forgot the commit msg:

JCR-235  Cache jcr name to QName mappings

On 10/12/05, stefan@apache.org <st...@apache.org> 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);
> +    }
> +
> +    /**
> +     * {@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);
>      }
>  }
>
> 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 @@
>       * {@inheritDoc}
>       */
>      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;
>      }
>
>      /**
>       * {@inheritDoc}
>       */
>      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;
> +    }
> +
> +    /**
> +     * {@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);
>      }
>  }
>
> 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>{@link #getQName(String)}</li>
> + * <li>{@link #getJCRName(QName)}</li>
> + * </ul>
> + * 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 <code>supportListeners</code> set to <code>true</code>. 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 <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 {@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 <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;
>              }
>
>
>

Re: svn commit: r314827 - in /incubator/jackrabbit/trunk/src: java/org/apache/jackrabbit/core/ java/org/apache/jackrabbit/core/nodetype/xml/ java/org/apache/jackrabbit/core/query/lucene/ java/org/apache/jackrabbit/core/xml/ java/org/apache/jackrabbit

Posted by Stefan Guggisberg <st...@gmail.com>.
On 10/12/05, Marcel Reutegger <ma...@gmail.com> wrote:
> LOL

:-)

>
> thanks for applying the patch...
>
> btw. what's the feeling about caching remapped namespace uris in the
> session? I think we should remove it again, because it adds complexity
> for a feature which is not used in most cases.

i agree, +1 for removing it.

cheers
stefan

>
> regards
>   marcel
>
> Stefan Guggisberg wrote:
> > sorry, forgot the commit msg:
> >
> > JCR-235  Cache jcr name to QName mappings
>

Re: svn commit: r314827 - in /incubator/jackrabbit/trunk/src: java/org/apache/jackrabbit/core/ java/org/apache/jackrabbit/core/nodetype/xml/ java/org/apache/jackrabbit/core/query/lucene/ java/org/apache/jackrabbit/core/xml/ java/org/apache/jackrabbit

Posted by Marcel Reutegger <ma...@gmail.com>.
LOL

thanks for applying the patch...

btw. what's the feeling about caching remapped namespace uris in the 
session? I think we should remove it again, because it adds complexity 
for a feature which is not used in most cases.

regards
  marcel

Stefan Guggisberg wrote:
> sorry, forgot the commit msg:
> 
> JCR-235  Cache jcr name to QName mappings