Index: oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/GlobalNameMapper.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/GlobalNameMapper.java (revision 1679973) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/GlobalNameMapper.java (working copy) @@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.jackrabbit.oak.api.Type.STRING; +import static java.util.Collections.emptyList; import static org.apache.jackrabbit.oak.api.Type.STRINGS; import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE; import static org.apache.jackrabbit.oak.plugins.name.NamespaceConstants.NAMESPACES_PATH; @@ -35,13 +35,13 @@ import javax.annotation.Nonnull; import javax.jcr.RepositoryException; -import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.plugins.tree.RootFactory; import org.apache.jackrabbit.oak.plugins.tree.TreeFactory; import org.apache.jackrabbit.oak.spi.state.NodeBuilder; import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.apache.jackrabbit.oak.util.TreeUtil; /** * Name mapper with no local prefix remappings. URI to prefix mappings @@ -71,18 +71,26 @@ } } - protected final Tree namespaces; - protected final Tree nsdata; + private final Root root; + private Tree namespaces; + private Tree nsdata; public GlobalNameMapper(Root root) { - this.namespaces = root.getTree(NAMESPACES_PATH); - this.nsdata = namespaces.getChild(REP_NSDATA); + this.root = root; + init(); } public GlobalNameMapper(NodeState root) { this(RootFactory.createReadOnlyRoot(root)); } + private void init() { + if (root != null) { + this.namespaces = root.getTree(NAMESPACES_PATH); + this.nsdata = namespaces.getChild(REP_NSDATA); + } + } + public GlobalNameMapper(Map mappings) { NodeBuilder forward = EMPTY_NODE.builder(); NodeBuilder reverse = EMPTY_NODE.builder(); @@ -98,6 +106,7 @@ reverse.setProperty(REP_PREFIXES, mappings.keySet(), STRINGS); reverse.setProperty(REP_URIS, mappings.values(), STRINGS); + this.root = null; this.namespaces = TreeFactory.createReadOnlyTree(forward.getNodeState()); this.nsdata = TreeFactory.createReadOnlyTree(reverse.getNodeState()); } @@ -165,12 +174,7 @@ return uri; } - PropertyState mapping = nsdata.getProperty(encodeUri(uri)); - if (mapping != null && mapping.getType() == STRING) { - return mapping.getValue(STRING); - } - - return null; + return getNsData(encodeUri(uri)); } @CheckForNull @@ -179,12 +183,28 @@ return prefix; } - PropertyState mapping = namespaces.getProperty(prefix); - if (mapping != null && mapping.getType() == STRING) { - return mapping.getValue(STRING); + return getNamespacesProperty(prefix); + } + + protected String getNamespacesProperty(String prefix) { + return TreeUtil.getString(namespaces, prefix); + } + + private String getNsData(String uri) { + return TreeUtil.getString(nsdata, uri); + } + + protected Iterable getPrefixes() { + Iterable prefs = TreeUtil.getStrings(nsdata, REP_PREFIXES); + if (prefs != null) { + return prefs; + } else { + return emptyList(); } + } - return null; + public void onSessionRefresh() { + init(); } } 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 1679973) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/LocalNameMapper.java (working copy) @@ -18,14 +18,12 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.jackrabbit.oak.api.Type.STRING; import java.util.Map; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; -import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Root; /** @@ -61,12 +59,11 @@ int colon = oakName.indexOf(':'); if (colon > 0) { String oakPrefix = oakName.substring(0, colon); - PropertyState mapping = namespaces.getProperty(oakPrefix); - if (mapping == null || mapping.getType() != STRING) { + String uri = getNamespacesProperty(oakPrefix); + if (uri == null) { throw new IllegalStateException( "No namespace mapping found for " + oakName); } - String uri = mapping.getValue(STRING); for (Map.Entry entry : local.entrySet()) { if (uri.equals(entry.getValue())) { @@ -123,10 +120,9 @@ } // Check that a global mapping is present and not remapped - PropertyState mapping = namespaces.getProperty(jcrPrefix); + String mapping = getNamespacesProperty(jcrPrefix); if (mapping != null - && mapping.getType() == STRING - && local.values().contains(mapping.getValue(STRING))) { + && local.values().contains(mapping)) { return null; } } Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java (revision 1679973) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java (working copy) @@ -43,6 +43,7 @@ import javax.jcr.nodetype.ConstraintViolationException; import com.google.common.collect.ImmutableMap; + import org.apache.jackrabbit.oak.api.AuthInfo; import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.api.ContentSession; @@ -52,6 +53,8 @@ import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.jcr.observation.EventFactory; import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy; +import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy.Composite; +import org.apache.jackrabbit.oak.jcr.session.SessionNamespaces; import org.apache.jackrabbit.oak.jcr.session.SessionStats; import org.apache.jackrabbit.oak.jcr.session.SessionStats.Counters; import org.apache.jackrabbit.oak.jcr.session.operation.SessionOperation; @@ -112,6 +115,8 @@ */ private final WarningLock lock = new WarningLock(new ReentrantLock()); + private final SessionNamespaces namespaces; + /** * Create a new session delegate for a {@code ContentSession}. The refresh behaviour of the * session is governed by the value of the {@code refreshInterval} argument: if the session @@ -134,10 +139,12 @@ @Nonnull Clock clock) { this.contentSession = checkNotNull(contentSession); this.securityProvider = checkNotNull(securityProvider); - this.saveCountRefresh = new SaveCountRefresh(checkNotNull(threadSaveCount)); - this.refreshStrategy = RefreshStrategy.Composite.create( - checkNotNull(refreshStrategy), refreshAtNextAccess, saveCountRefresh); this.root = contentSession.getLatestRoot(); + this.namespaces = new SessionNamespaces(this.root); + this.saveCountRefresh = new SaveCountRefresh(checkNotNull(threadSaveCount)); + this.refreshStrategy = Composite.create(checkNotNull(refreshStrategy), + refreshAtNextAccess, saveCountRefresh, new RefreshNamespaces( + namespaces)); this.idManager = new IdentifierManager(root); this.clock = checkNotNull(clock); this.sessionStats = new SessionStats(contentSession.toString(), @@ -885,4 +892,31 @@ } } + /** + * Read-only RefreshStrategy responsible for notifying the SessionNamespaces + * instance that a refresh was called + */ + private static class RefreshNamespaces implements RefreshStrategy { + + private final SessionNamespaces namespaces; + + public RefreshNamespaces(SessionNamespaces namespaces) { + this.namespaces = namespaces; + } + + @Override + public boolean needsRefresh(long secondsSinceLastAccess) { + return false; + } + + @Override + public void refreshed() { + this.namespaces.onSessionRefresh(); + } + } + + public SessionNamespaces getNamespaces() { + return namespaces; + } + } Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java (revision 1679973) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java (working copy) @@ -90,7 +90,6 @@ private final int observationQueueLength; private final CommitRateLimiter commitRateLimiter; - private final SessionNamespaces namespaces; private final NamePathMapper namePathMapper; private final ValueFactory valueFactory; @@ -126,9 +125,8 @@ SessionStats sessionStats = delegate.getSessionStats(); sessionStats.setAttributes(attributes); - this.namespaces = new SessionNamespaces(delegate.getRoot()); this.namePathMapper = new NamePathMapperImpl( - namespaces, delegate.getIdManager()); + delegate.getNamespaces(), delegate.getIdManager()); this.valueFactory = new ValueFactoryImpl( delegate.getRoot(), namePathMapper); } @@ -194,13 +192,13 @@ } SessionNamespaces getNamespaces() { - return namespaces; + return delegate.getNamespaces(); } @Override @Nonnull public Map getSessionLocalMappings() { - return namespaces.getSessionLocalMappings(); + return getNamespaces().getSessionLocalMappings(); } public ValueFactory getValueFactory() { @@ -373,7 +371,7 @@ if (observationManager != null) { observationManager.dispose(); } - namespaces.clear(); + getNamespaces().clear(); } /** Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionNamespaces.java =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionNamespaces.java (revision 1679973) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionNamespaces.java (working copy) @@ -18,9 +18,6 @@ import static com.google.common.collect.Iterables.toArray; import static com.google.common.collect.Sets.newHashSet; -import static java.util.Collections.emptyList; -import static org.apache.jackrabbit.oak.api.Type.STRINGS; -import static org.apache.jackrabbit.oak.plugins.name.NamespaceConstants.REP_PREFIXES; import java.util.HashSet; import java.util.Locale; @@ -31,7 +28,6 @@ import javax.jcr.NamespaceException; import javax.jcr.Session; -import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.namepath.LocalNameMapper; import org.apache.jackrabbit.util.XMLChar; @@ -44,9 +40,9 @@ * re-mappings and takes a snapshot of the namespace registry when initialized * (see JCR 2.0 specification, section 3.5.1). */ -class SessionNamespaces extends LocalNameMapper { +public class SessionNamespaces extends LocalNameMapper { - SessionNamespaces(@Nonnull Root root) { + public SessionNamespaces(@Nonnull Root root) { super(root, Maps.newHashMap()); } @@ -97,11 +93,7 @@ */ synchronized String[] getNamespacePrefixes() { // get registered namespace prefixes - Iterable global = emptyList(); - PropertyState property = nsdata.getProperty(REP_PREFIXES); - if (property != null && property.getType() == STRINGS) { - global = property.getValue(STRINGS); - } + Iterable global = getPrefixes(); // unless there are local remappings just use the registered ones if (local.isEmpty()) {