Index: java/org/apache/jackrabbit/core/SessionImpl.java =================================================================== --- java/org/apache/jackrabbit/core/SessionImpl.java (revision 293275) +++ java/org/apache/jackrabbit/core/SessionImpl.java (working copy) @@ -171,6 +171,11 @@ protected final LocalNamespaceMappings nsMappings; /** + * The QName resolver for this session. + */ + protected final CachingQNameResolver nameResolver; + + /** * The version manager for this session */ protected final VersionManager versionMgr; @@ -235,6 +240,7 @@ } this.subject = subject; nsMappings = new LocalNamespaceMappings(rep.getNamespaceRegistry()); + nameResolver = new CachingQNameResolver(rep.getNamespaceRegistry(), nsMappings, 1000); ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), getNamespaceResolver()); String wspName = wspConfig.getName(); wsp = createWorkspaceInstance(wspConfig, @@ -376,6 +382,15 @@ } /** + * Returns the QNameResolver of this session. + * + * @return the QNameResolver of this session. + */ + public QNameResolver getQNameResolver() { + return nameResolver; + } + + /** * Returns the SessionItemStateManager associated with this session. * * @return the SessionItemStateManager associated with this session @@ -1117,6 +1132,8 @@ // notify listeners that session is about to be closed notifyLoggingOut(); + // dispose caching name resolver + nameResolver.dispose(); // dispose session item state manager itemStateMgr.dispose(); // dispose item manager @@ -1192,6 +1209,7 @@ public void setNamespacePrefix(String prefix, String uri) throws NamespaceException, RepositoryException { nsMappings.setNamespacePrefix(prefix, uri); + nameResolver.prefixRemapped(prefix, uri); } /** Index: java/org/apache/jackrabbit/core/PropertyImpl.java =================================================================== --- java/org/apache/jackrabbit/core/PropertyImpl.java (revision 293275) +++ 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.getQNameResolver().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.getQNameResolver().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 293275) +++ java/org/apache/jackrabbit/core/NodeImpl.java (working copy) @@ -402,7 +402,7 @@ throws ConstraintViolationException, RepositoryException { QName qName; try { - qName = QName.fromJCRName(name, session.getNamespaceResolver()); + qName = session.getQNameResolver().getQName(name); } catch (IllegalNameException ine) { throw new RepositoryException("invalid property name: " + name, ine); } catch (UnknownPrefixException upe) { @@ -560,7 +560,7 @@ protected void removeChildProperty(String propName) throws RepositoryException { QName qName; try { - qName = QName.fromJCRName(propName, session.getNamespaceResolver()); + qName = session.getQNameResolver().getQName(propName); } catch (IllegalNameException ine) { throw new RepositoryException("invalid property name: " + propName, ine); @@ -1674,7 +1674,7 @@ QName name = session.getHierarchyManager().getName(id); try { - return name.toJCRName(session.getNamespaceResolver()); + return session.getQNameResolver().getJCRName(name); } catch (NoPrefixDeclaredException npde) { // should never get here... String msg = "internal error: encountered unregistered namespace " @@ -2363,7 +2363,7 @@ public boolean isNodeType(String nodeTypeName) throws RepositoryException { QName ntName; try { - ntName = QName.fromJCRName(nodeTypeName, session.getNamespaceResolver()); + ntName = session.getQNameResolver().getQName(nodeTypeName); } catch (IllegalNameException ine) { throw new RepositoryException("invalid node type name: " + nodeTypeName, ine); } catch (UnknownPrefixException upe) { @@ -2410,7 +2410,7 @@ ConstraintViolationException, LockException, RepositoryException { QName ntName; try { - ntName = QName.fromJCRName(mixinName, session.getNamespaceResolver()); + ntName = session.getQNameResolver().getQName(mixinName); } catch (IllegalNameException ine) { throw new RepositoryException("invalid mixin type name: " + mixinName, ine); } catch (UnknownPrefixException upe) { @@ -2428,7 +2428,7 @@ ConstraintViolationException, LockException, RepositoryException { QName ntName; try { - ntName = QName.fromJCRName(mixinName, session.getNamespaceResolver()); + ntName = session.getQNameResolver().getQName(mixinName); } catch (IllegalNameException ine) { throw new RepositoryException("invalid mixin type name: " + mixinName, ine); } catch (UnknownPrefixException upe) { @@ -2463,7 +2463,7 @@ QName ntName; try { - ntName = QName.fromJCRName(mixinName, session.getNamespaceResolver()); + ntName = session.getQNameResolver().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 293275) +++ java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java (working copy) @@ -34,6 +34,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Properties; +import java.util.Set; /** * A NamespaceRegistryImpl ... @@ -72,6 +73,8 @@ private HashMap prefixToURI = new HashMap(); private HashMap uriToPrefix = new HashMap(); + private Set listeners = new HashSet(); + private final FileSystem nsRegStore; /** @@ -197,6 +200,51 @@ return "_pre" + (prefixToURI.size() + 1); } + //----------------------< NamespaceRegistryListener support >--------------- + + /** + * Registers listener to get notifications when namespace + * mappings change. + * + * @param listener the listener to register. + */ + public void addListener(NamespaceRegistryListener listener) { + synchronized (listeners) { + listeners.add(listener); + } + } + + /** + * Removes the listener from this NamespaceRegistery. + * + * @param listener the listener to remove. + */ + public void removeListener(NamespaceRegistryListener listener) { + 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) { + NamespaceRegistryListener[] currentListeners; + synchronized (listeners) { + int i = 0; + currentListeners = new NamespaceRegistryListener[listeners.size()]; + for (Iterator it = listeners.iterator(); it.hasNext(); ) { + currentListeners[i++] = (NamespaceRegistryListener) it.next(); + } + } + for (int i = 0; i < currentListeners.length; i++) { + currentListeners[i].prefixRemapped(prefix, uri); + } + } + //----------------------------------------------------< NamespaceRegistry > /** * {@inheritDoc} @@ -257,6 +305,9 @@ // persist mappings store(); + + // notify listeners + notifyPrefixRemapped(prefix, uri); } /** Index: java/org/apache/jackrabbit/core/QNameResolver.java =================================================================== --- java/org/apache/jackrabbit/core/QNameResolver.java (revision 0) +++ java/org/apache/jackrabbit/core/QNameResolver.java (revision 0) @@ -0,0 +1,47 @@ +/* + * 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.core; + +import org.apache.jackrabbit.name.QName; +import org.apache.jackrabbit.name.IllegalNameException; +import org.apache.jackrabbit.name.UnknownPrefixException; +import org.apache.jackrabbit.name.NoPrefixDeclaredException; + +/** + * Maps QNames to resolved jcr names and vice versa. + */ +public interface QNameResolver { + + /** + * 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; +} Property changes on: java/org/apache/jackrabbit/core/QNameResolver.java ___________________________________________________________________ Name: svn:eol-style + native Index: java/org/apache/jackrabbit/core/CachingQNameResolver.java =================================================================== --- java/org/apache/jackrabbit/core/CachingQNameResolver.java (revision 0) +++ java/org/apache/jackrabbit/core/CachingQNameResolver.java (revision 0) @@ -0,0 +1,117 @@ +/* + * 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.core; + +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.commons.collections.map.LRUMap; + +import java.util.Map; + +/** + * Implements a {@link QNameResolver} that caches QName to resolved jcr names + * and vice versa. The cache is invalidated when a namespace uri to prefix + * mapping is changed. + */ +class CachingQNameResolver implements QNameResolver, NamespaceRegistryListener { + + /** + * The namespace registry. + */ + private final NamespaceRegistryImpl nsRegistry; + + /** + * The namespace resolver of current session. + */ + private final NamespaceResolver resolver; + + /** + * 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 CachingQNameResolver. + * + * @param nsReg the global namespace registry. + * @param resolver the namespace resolver of the current session. + * @param cacheSize number of mappings this resolver may cache. + */ + CachingQNameResolver(NamespaceRegistryImpl nsReg, NamespaceResolver resolver, int cacheSize) { + this.nsRegistry = nsReg; + this.resolver = resolver; + qnameToJCRName = new LRUMap(cacheSize); + jcrNameToQName = new LRUMap(cacheSize); + nsRegistry.addListener(this); + } + + /** + * @inheritDoc + */ + public synchronized QName getQName(String name) throws IllegalNameException, UnknownPrefixException { + if (false) { + return QName.fromJCRName(name, resolver); + } + QName qName = (QName) jcrNameToQName.get(name); + if (qName == null) { + qName = QName.fromJCRName(name, resolver); + jcrNameToQName.put(name, qName); + } + return qName; + } + + /** + * @inheritDoc + */ + public synchronized String getJCRName(QName name) throws NoPrefixDeclaredException { + if (false) { + return name.toJCRName(resolver); + } + String jcrName = (String) qnameToJCRName.get(name); + if (jcrName == null) { + jcrName = name.toJCRName(resolver); + qnameToJCRName.put(name, jcrName); + } + return jcrName; + } + + /** + * Disposes this CachingQNameResolver. + */ + public void dispose() { + nsRegistry.removeListener(this); + } + + //---------------------< NamespaceRegistryListener >------------------------ + + /** + * @inheritDoc + * Invalidates all cached mappings. + */ + public synchronized void prefixRemapped(String prefix, String uri) { + qnameToJCRName.clear(); + jcrNameToQName.clear(); + } +} Property changes on: java/org/apache/jackrabbit/core/CachingQNameResolver.java ___________________________________________________________________ Name: svn:eol-style + native Index: java/org/apache/jackrabbit/core/NamespaceRegistryListener.java =================================================================== --- java/org/apache/jackrabbit/core/NamespaceRegistryListener.java (revision 0) +++ java/org/apache/jackrabbit/core/NamespaceRegistryListener.java (revision 0) @@ -0,0 +1,33 @@ +/* + * 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.core; + +/** + * Receives notifications when a namespace mapping changes in a namespace + * registry. + */ +public interface NamespaceRegistryListener { + + /** + * Informs that the namespace registry has remapped the uri 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/core/NamespaceRegistryListener.java ___________________________________________________________________ Name: svn:eol-style + native