Index: oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/LocalNameMapper.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/LocalNameMapper.java (revision 1463486) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/LocalNameMapper.java (working copy) @@ -28,12 +28,6 @@ */ public abstract class LocalNameMapper extends GlobalNameMapper { - private final Map local; - - protected LocalNameMapper(Map local) { - this.local = local; - } - @Override @CheckForNull public String getJcrName(String oakName) { checkNotNull(oakName); @@ -50,27 +44,26 @@ "No namespace mapping found for " + oakName); } - synchronized (local) { - for (Map.Entry entry : local.entrySet()) { - if (uri.equals(entry.getValue())) { - String jcrPrefix = entry.getKey(); - if (jcrPrefix.equals(oakPrefix)) { - return oakName; - } else { - return jcrPrefix + oakName.substring(colon); - } + Map local = getSessionLocalMappings(); + for (Map.Entry entry : local.entrySet()) { + if (uri.equals(entry.getValue())) { + String jcrPrefix = entry.getKey(); + if (jcrPrefix.equals(oakPrefix)) { + return oakName; + } else { + return jcrPrefix + oakName.substring(colon); } } + } - // local mapping not found for this URI, make sure there - // is no conflicting local mapping for the prefix - if (local.containsKey(oakPrefix)) { - for (int i = 2; true; i++) { - String jcrPrefix = oakPrefix + i; - if (!local.containsKey(jcrPrefix)) { - local.put(jcrPrefix, uri); - return jcrPrefix + oakName.substring(colon); - } + // local mapping not found for this URI, make sure there + // is no conflicting local mapping for the prefix + if (local.containsKey(oakPrefix)) { + for (int i = 2; true; i++) { + String jcrPrefix = oakPrefix + i; + if (!local.containsKey(jcrPrefix)) { + local.put(jcrPrefix, uri); + return jcrPrefix + oakName.substring(colon); } } } @@ -91,26 +84,25 @@ if (hasSessionLocalMappings()) { int colon = jcrName.indexOf(':'); if (colon > 0) { - synchronized (local) { - String jcrPrefix = jcrName.substring(0, colon); - String uri = local.get(jcrPrefix); - if (uri != null) { - String oakPrefix = getOakPrefixOrNull(uri); - if (jcrPrefix.equals(oakPrefix)) { - return jcrName; - } else if (oakPrefix != null) { - return oakPrefix + jcrName.substring(colon); - } else { - return null; - } - } - - // Check that a global mapping is present and not remapped - uri = getNamespaceMap().get(jcrPrefix); - if (uri == null || local.values().contains(uri)) { + Map local = getSessionLocalMappings(); + String jcrPrefix = jcrName.substring(0, colon); + String uri = local.get(jcrPrefix); + if (uri != null) { + String oakPrefix = getOakPrefixOrNull(uri); + if (jcrPrefix.equals(oakPrefix)) { + return jcrName; + } else if (oakPrefix != null) { + return oakPrefix + jcrName.substring(colon); + } else { return null; } } + + // Check that a global mapping is present and not remapped + uri = getNamespaceMap().get(jcrPrefix); + if (uri == null || local.values().contains(uri)) { + return null; + } } } @@ -119,9 +111,8 @@ @Override public boolean hasSessionLocalMappings() { - synchronized (local) { - return !local.isEmpty(); - } + return !getSessionLocalMappings().isEmpty(); } + protected abstract Map getSessionLocalMappings(); } Index: oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java (revision 1463486) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java (working copy) @@ -47,11 +47,16 @@ "foo", "http://www.example.com/foo", "quu", "http://www.example.com/quu"); - private NameMapper mapper = new LocalNameMapper(LOCAL) { + private NameMapper mapper = new LocalNameMapper() { @Override protected Map getNamespaceMap() { return GLOBAL; } + + @Override + protected Map getSessionLocalMappings() { + return LOCAL; + } }; private NamePathMapper npMapper = new NamePathMapperImpl(mapper); Index: oak-core/src/test/java/org/apache/jackrabbit/oak/TestNameMapper.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/TestNameMapper.java (revision 1463486) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/TestNameMapper.java (working copy) @@ -35,29 +35,35 @@ public static final Map LOCAL_MAPPING = Collections.singletonMap(TEST_LOCAL_PREFIX, TEST_URI); private final Map global; + private final Map local; public TestNameMapper() { - super(LOCAL_MAPPING); this.global = Collections.singletonMap(TEST_PREFIX, TEST_URI); + this.local = LOCAL_MAPPING; } public TestNameMapper(Map global, Map local) { - super(local); this.global = global; + this.local = local; } public TestNameMapper(Map global) { - super(global); this.global = global; + this.local = global; } public TestNameMapper(TestNameMapper base, Map local) { - super(local); this.global = base.global; + this.local = local; } @Override protected Map getNamespaceMap() { return global; } + + @Override + protected Map getSessionLocalMappings() { + return local; + } } \ No newline at end of file Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java (revision 1463486) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java (working copy) @@ -36,11 +36,9 @@ import javax.jcr.security.AccessControlManager; import javax.jcr.version.VersionManager; -import com.google.common.collect.Maps; import org.apache.jackrabbit.api.security.authorization.PrivilegeManager; import org.apache.jackrabbit.api.security.principal.PrincipalManager; import org.apache.jackrabbit.api.security.user.UserManager; -import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate; import org.apache.jackrabbit.oak.namepath.LocalNameMapper; import org.apache.jackrabbit.oak.namepath.NamePathMapper; @@ -64,6 +62,7 @@ public abstract class SessionContext implements NamePathMapper { private final RepositoryImpl repository; private final SessionDelegate delegate; + private final SessionNamespaces namespaces; private final NamePathMapper namePathMapper; private final ValueFactory valueFactory; @@ -74,31 +73,31 @@ private PrivilegeManager privilegeManager; private ObservationManagerImpl observationManager; - private SessionContext(RepositoryImpl repository, SessionDelegate delegate, - NamePathMapper namePathMapper, ValueFactory valueFactory) { + private SessionContext(RepositoryImpl repository, + final SessionDelegate delegate) { this.delegate = delegate; this.repository = repository; - this.namePathMapper = namePathMapper; - this.valueFactory = valueFactory; - } - - public static SessionContext create(final SessionDelegate delegate, RepositoryImpl repository) { - // FIXME don't rely on a naked map. See OAK-715 - final Map namespaces = Maps.newHashMap(); - final Root root = checkNotNull(delegate).getRoot(); - - LocalNameMapper nameMapper = new LocalNameMapper(namespaces) { + this.namespaces = new SessionNamespaces(this); + LocalNameMapper nameMapper = new LocalNameMapper() { @Override protected Map getNamespaceMap() { - return Namespaces.getNamespaceMap(root.getTree("/")); + return Namespaces.getNamespaceMap(delegate.getRoot().getTree("/")); } + + @Override + protected Map getSessionLocalMappings() { + return namespaces.getSessionLocalMappings(); + } }; + this.namePathMapper = new NamePathMapperImpl( + nameMapper, delegate.getIdManager()); + this.valueFactory = new ValueFactoryImpl( + delegate.getRoot().getBlobFactory(), namePathMapper); + } - NamePathMapperImpl namePathMapper = new NamePathMapperImpl(nameMapper, delegate.getIdManager()); - ValueFactoryImpl valueFactory = new ValueFactoryImpl(root.getBlobFactory(), namePathMapper); - - return new SessionContext(checkNotNull(repository), delegate, namePathMapper, valueFactory){ - private final SessionImpl session = new SessionImpl(this, namespaces); + public static SessionContext create(final SessionDelegate delegate, RepositoryImpl repository) { + return new SessionContext(checkNotNull(repository), checkNotNull(delegate)) { + private final SessionImpl session = new SessionImpl(this); private final WorkspaceImpl workspace = new WorkspaceImpl(this); @Override @@ -146,6 +145,10 @@ return delegate; } + public SessionNamespaces getNamespaces() { + return namespaces; + } + public abstract Session getSession(); public abstract Workspace getWorkspace(); @@ -250,7 +253,7 @@ @Override public boolean hasSessionLocalMappings() { - return namePathMapper.hasSessionLocalMappings(); + return !namespaces.getSessionLocalMappings().isEmpty(); } @Override @@ -318,6 +321,7 @@ if (observationManager != null) { observationManager.dispose(); } + namespaces.clear(); } void refresh() { Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java (revision 1463486) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java (working copy) @@ -19,7 +19,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Map; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -73,12 +72,9 @@ private final SessionContext sessionContext; private final SessionDelegate sd; - private final SessionNamespaces namespaces; - - SessionImpl(SessionContext sessionContext, Map namespaces) { + SessionImpl(SessionContext sessionContext) { this.sessionContext = sessionContext; this.sd = sessionContext.getSessionDelegate(); - this.namespaces = new SessionNamespaces(namespaces, sessionContext); } static void checkProtectedNodes(Session session, String... absJcrPaths) throws RepositoryException { @@ -398,7 +394,6 @@ if (sd.isAlive()) { sessionContext.dispose(); sd.logout(); - namespaces.clear(); } } @@ -586,22 +581,22 @@ @Override public void setNamespacePrefix(String prefix, String uri) throws RepositoryException { - namespaces.setNamespacePrefix(prefix, uri); + sessionContext.getNamespaces().setNamespacePrefix(prefix, uri); } @Override public String[] getNamespacePrefixes() throws RepositoryException { - return namespaces.getNamespacePrefixes(); + return sessionContext.getNamespaces().getNamespacePrefixes(); } @Override public String getNamespaceURI(String prefix) throws RepositoryException { - return namespaces.getNamespaceURI(prefix); + return sessionContext.getNamespaces().getNamespaceURI(prefix); } @Override public String getNamespacePrefix(String uri) throws RepositoryException { - return namespaces.getNamespacePrefix(uri); + return sessionContext.getNamespaces().getNamespacePrefix(uri); } //--------------------------------------------------< JackrabbitSession >--- Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionNamespaces.java =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionNamespaces.java (revision 1463486) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionNamespaces.java (working copy) @@ -16,6 +16,7 @@ */ package org.apache.jackrabbit.oak.jcr; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; @@ -30,6 +31,8 @@ import org.apache.jackrabbit.util.XMLChar; +import com.google.common.collect.Maps; + import static com.google.common.base.Preconditions.checkNotNull; /** @@ -56,9 +59,8 @@ private final SessionContext sessionContext; - SessionNamespaces(@Nonnull Map namespaces, - @Nonnull SessionContext sessionContext) { - this.namespaces = checkNotNull(namespaces); + SessionNamespaces(@Nonnull SessionContext sessionContext) { + this.namespaces = Maps.newHashMap(); this.sessionContext = checkNotNull(sessionContext); } @@ -192,10 +194,25 @@ } /** + * @return the session local namespaces that were remapped. + */ + public Map getSessionLocalMappings() { + synchronized (namespaces) { + if (namespaces.isEmpty()) { + return Collections.emptyMap(); + } else { + return new HashMap(namespaces); + } + } + } + + /** * Clears the re-mapped namespaces map. */ void clear() { - namespaces.clear(); + synchronized (namespaces) { + namespaces.clear(); + } } private NamespaceRegistry getNamespaceRegistry() Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/TargetImportHandler.java =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/TargetImportHandler.java (revision 1463486) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/TargetImportHandler.java (working copy) @@ -106,7 +106,7 @@ //-------------------------------------------------------- public NamePathMapper currentNamePathMapper() { - return new NamePathMapperImpl(new LocalNameMapper(documentPrefixMap) { + return new NamePathMapperImpl(new LocalNameMapper() { @Override protected Map getNamespaceMap() { try { @@ -115,6 +115,11 @@ return Collections.emptyMap(); } } + + @Override + protected Map getSessionLocalMappings() { + return documentPrefixMap; + } }); }