| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.oak.jcr.session; |
| |
| import static com.google.common.base.Preconditions.checkNotNull; |
| import static com.google.common.collect.Sets.newTreeSet; |
| import static org.apache.jackrabbit.api.stats.RepositoryStatistics.Type.SESSION_COUNT; |
| import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.security.AccessControlException; |
| import java.util.Collections; |
| import java.util.Set; |
| |
| import javax.jcr.AccessDeniedException; |
| import javax.jcr.Credentials; |
| import javax.jcr.InvalidSerializedDataException; |
| import javax.jcr.Item; |
| import javax.jcr.ItemNotFoundException; |
| import javax.jcr.Node; |
| import javax.jcr.PathNotFoundException; |
| import javax.jcr.Property; |
| import javax.jcr.Repository; |
| import javax.jcr.RepositoryException; |
| import javax.jcr.Session; |
| import javax.jcr.UnsupportedRepositoryOperationException; |
| import javax.jcr.ValueFactory; |
| import javax.jcr.Workspace; |
| import javax.jcr.nodetype.ConstraintViolationException; |
| import javax.jcr.retention.RetentionManager; |
| import javax.jcr.security.AccessControlManager; |
| |
| import org.apache.jackrabbit.api.JackrabbitSession; |
| import org.apache.jackrabbit.api.security.principal.PrincipalManager; |
| import org.apache.jackrabbit.api.security.user.UserManager; |
| import org.apache.jackrabbit.api.stats.RepositoryStatistics.Type; |
| import org.apache.jackrabbit.commons.xml.DocumentViewExporter; |
| import org.apache.jackrabbit.commons.xml.Exporter; |
| import org.apache.jackrabbit.commons.xml.ParsingContentHandler; |
| import org.apache.jackrabbit.commons.xml.SystemViewExporter; |
| import org.apache.jackrabbit.commons.xml.ToXmlContentHandler; |
| import org.apache.jackrabbit.oak.api.Tree; |
| import org.apache.jackrabbit.oak.commons.PathUtils; |
| import org.apache.jackrabbit.oak.jcr.delegate.ItemDelegate; |
| import org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate; |
| import org.apache.jackrabbit.oak.jcr.delegate.PropertyDelegate; |
| import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate; |
| import org.apache.jackrabbit.oak.jcr.security.AccessManager; |
| import org.apache.jackrabbit.oak.jcr.session.operation.SessionOperation; |
| import org.apache.jackrabbit.oak.jcr.xml.ImportHandler; |
| import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider; |
| import org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials; |
| import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions; |
| import org.apache.jackrabbit.oak.stats.CounterStats; |
| import org.apache.jackrabbit.util.Text; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * TODO document |
| */ |
| public class SessionImpl implements JackrabbitSession { |
| private static final Logger log = LoggerFactory.getLogger(SessionImpl.class); |
| |
| private SessionContext sessionContext; |
| private SessionDelegate sd; |
| private final CounterStats sessionCounter; |
| |
| public SessionImpl(SessionContext sessionContext) { |
| this.sessionContext = sessionContext; |
| this.sd = sessionContext.getSessionDelegate(); |
| this.sessionCounter = sessionContext.getCount(SESSION_COUNT); |
| sessionCounter.inc(); |
| sessionContext.getMeter(Type.SESSION_LOGIN_COUNTER).mark(); |
| } |
| |
| static void checkIndexOnName(String jcrPath) throws RepositoryException { |
| int pos = jcrPath.length() - 1; |
| if (pos < 2 || jcrPath.charAt(pos) != ']') { |
| return; |
| } |
| |
| if ("0123456789".indexOf(jcrPath.charAt(--pos)) == -1) { |
| return; |
| } |
| |
| while (--pos >= 0) { |
| char ch = jcrPath.charAt(pos); |
| if (ch == '[') { |
| throw new RepositoryException("Cannot create a new node using a name including an index"); |
| } |
| if ("0123456789".indexOf(ch) == -1) { |
| return; |
| } |
| } |
| } |
| |
| private abstract class ReadOperation<T> extends SessionOperation<T> { |
| protected ReadOperation(String name) { |
| super(name); |
| } |
| |
| @Override |
| public void checkPreconditions() throws RepositoryException { |
| checkAlive(); |
| } |
| } |
| |
| private abstract class WriteOperation<T> extends SessionOperation<T> { |
| protected WriteOperation(String name) { |
| super(name, true); |
| } |
| |
| @Override |
| public void checkPreconditions() throws RepositoryException { |
| checkAlive(); |
| } |
| } |
| |
| private void checkAlive() throws RepositoryException { |
| if (sd == null) { |
| throw new RepositoryException("This session has been closed."); |
| } |
| sd.checkAlive(); |
| } |
| |
| @NotNull |
| private String getOakPathOrThrow(@NotNull String absPath) |
| throws RepositoryException { |
| String p = sessionContext.getOakPathOrThrow(absPath); |
| if (!PathUtils.isAbsolute(p)) { |
| throw new RepositoryException("Not an absolute path: " + absPath); |
| } |
| return p; |
| } |
| |
| @NotNull |
| private String getOakPathOrThrowNotFound(@NotNull String absPath) |
| throws PathNotFoundException { |
| return sessionContext.getOakPathOrThrowNotFound(absPath); |
| } |
| |
| @Nullable |
| private ItemImpl<?> getItemInternal(@NotNull String oakPath) |
| throws RepositoryException { |
| checkAlive(); |
| ItemDelegate item = sd.getItem(oakPath); |
| if (item instanceof NodeDelegate) { |
| return NodeImpl.createNode((NodeDelegate) item, sessionContext); |
| } else if (item instanceof PropertyDelegate) { |
| return new PropertyImpl((PropertyDelegate) item, sessionContext); |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| @Nullable |
| public Node getNodeOrNull(final String absPath) throws RepositoryException { |
| checkNotNull(absPath); |
| checkAlive(); |
| return sd.performNullable(new ReadOperation<Node>("getNodeOrNull") { |
| @Override |
| public Node performNullable() throws RepositoryException { |
| try { |
| return NodeImpl.createNodeOrNull(sd.getNode(getOakPathOrThrow(absPath)), sessionContext); |
| } catch (PathNotFoundException e) { |
| return null; |
| } |
| } |
| }); |
| } |
| |
| @Override |
| @Nullable |
| public Property getPropertyOrNull(final String absPath) throws RepositoryException { |
| checkAlive(); |
| if (checkNotNull(absPath).equals("/")) { |
| return null; |
| } else { |
| final String oakPath; |
| try { |
| oakPath = getOakPathOrThrow(absPath); |
| } catch (PathNotFoundException e) { |
| return null; |
| } |
| return sd.performNullable(new ReadOperation<Property>("getPropertyOrNull") { |
| @Override |
| public Property performNullable() { |
| PropertyDelegate pd = sd.getProperty(oakPath); |
| if (pd != null) { |
| return new PropertyImpl(pd, sessionContext); |
| } else { |
| return null; |
| } |
| } |
| }); |
| } |
| } |
| |
| @Override |
| @Nullable |
| public Item getItemOrNull(final String absPath) throws RepositoryException { |
| checkNotNull(absPath); |
| checkAlive(); |
| return sd.performNullable(new ReadOperation<Item>("getItemOrNull") { |
| @Override |
| public Item performNullable() throws RepositoryException { |
| return getItemInternal(getOakPathOrThrow(absPath)); |
| } |
| }); |
| } |
| |
| //------------------------------------------------------------< Session >--- |
| |
| @Override |
| @NotNull |
| public Repository getRepository() { |
| return sessionContext.getRepository(); |
| } |
| |
| @Override |
| public String getUserID() { |
| return sd.getAuthInfo().getUserID(); |
| } |
| |
| @Override |
| public String[] getAttributeNames() { |
| Set<String> names = newTreeSet(sessionContext.getAttributes().keySet()); |
| Collections.addAll(names, sd.getAuthInfo().getAttributeNames()); |
| return names.toArray(new String[names.size()]); |
| } |
| |
| @Override |
| public Object getAttribute(String name) { |
| Object attribute = sd.getAuthInfo().getAttribute(name); |
| if (attribute == null) { |
| attribute = sessionContext.getAttributes().get(name); |
| } |
| return attribute; |
| } |
| |
| @Override @NotNull |
| public Workspace getWorkspace() { |
| return sessionContext.getWorkspace(); |
| } |
| |
| @Override |
| @NotNull |
| public Session impersonate(Credentials credentials) throws RepositoryException { |
| checkAlive(); |
| |
| ImpersonationCredentials impCreds = new ImpersonationCredentials( |
| checkNotNull(credentials), sd.getAuthInfo()); |
| return getRepository().login(impCreds, sd.getWorkspaceName()); |
| } |
| |
| @Override |
| @NotNull |
| public ValueFactory getValueFactory() throws RepositoryException { |
| checkAlive(); |
| return sessionContext.getValueFactory(); |
| } |
| |
| @Override |
| @NotNull |
| public Node getRootNode() throws RepositoryException { |
| checkAlive(); |
| return sd.perform(new ReadOperation<Node>("getRootNode") { |
| @NotNull |
| @Override |
| public Node perform() throws RepositoryException { |
| NodeDelegate nd = sd.getRootNode(); |
| if (nd == null) { |
| throw new AccessDeniedException("Root node is not accessible."); |
| } |
| return NodeImpl.createNode(nd, sessionContext); |
| } |
| }); |
| } |
| |
| @Override |
| public Node getNode(String absPath) throws RepositoryException { |
| Node node = getNodeOrNull(checkNotNull(absPath)); |
| if (node == null) { |
| throw new PathNotFoundException("Node with path " + absPath + " does not exist."); |
| } |
| return node; |
| } |
| |
| @Override |
| public boolean nodeExists(String absPath) throws RepositoryException { |
| return getNodeOrNull(checkNotNull(absPath)) != null; |
| } |
| |
| @NotNull |
| private Node getNodeById(@NotNull final String id) throws RepositoryException { |
| checkAlive(); |
| return sd.perform(new ReadOperation<Node>("getNodeById") { |
| @NotNull |
| @Override |
| public Node perform() throws RepositoryException { |
| NodeDelegate nd = sd.getNodeByIdentifier(id); |
| if (nd == null) { |
| throw new ItemNotFoundException("Node with id " + id + " does not exist."); |
| } |
| return NodeImpl.createNode(nd, sessionContext); |
| } |
| }); |
| } |
| |
| @Override |
| @NotNull |
| public Node getNodeByUUID(String uuid) throws RepositoryException { |
| return getNodeById(checkNotNull(uuid)); |
| } |
| |
| @Override |
| @NotNull |
| public Node getNodeByIdentifier(String id) throws RepositoryException { |
| return getNodeById(checkNotNull(id)); |
| } |
| |
| @Override |
| public Property getProperty(String absPath) throws RepositoryException { |
| Property property = getPropertyOrNull(checkNotNull(absPath)); |
| if (property == null) { |
| throw new PathNotFoundException(absPath); |
| } |
| return property; |
| } |
| |
| @Override |
| public boolean propertyExists(String absPath) throws RepositoryException { |
| return getPropertyOrNull(checkNotNull(absPath)) != null; |
| } |
| |
| @Override |
| public Item getItem(String absPath) throws RepositoryException { |
| Item item = getItemOrNull(checkNotNull(absPath)); |
| if (item == null) { |
| throw new PathNotFoundException(absPath); |
| } |
| return item; |
| } |
| |
| @Override |
| public boolean itemExists(String absPath) throws RepositoryException { |
| return getItemOrNull(checkNotNull(absPath)) != null; |
| } |
| |
| @Override |
| public void move(String srcAbsPath, final String destAbsPath) throws RepositoryException { |
| checkAlive(); |
| checkIndexOnName(checkNotNull(destAbsPath)); |
| final String srcOakPath = getOakPathOrThrowNotFound(checkNotNull(srcAbsPath)); |
| final String destOakPath = getOakPathOrThrowNotFound(destAbsPath); |
| sd.performVoid(new WriteOperation<Void>("move") { |
| @Override |
| public void checkPreconditions() throws RepositoryException { |
| super.checkPreconditions(); |
| sd.checkProtectedNode(getParentPath(srcOakPath)); |
| sd.checkProtectedNode(getParentPath(destOakPath)); |
| } |
| |
| @Override |
| public void performVoid() throws RepositoryException { |
| sd.move(srcOakPath, destOakPath, true); |
| } |
| }); |
| } |
| |
| @Override |
| public void removeItem(final String absPath) throws RepositoryException { |
| checkAlive(); |
| final String oakPath = getOakPathOrThrowNotFound(checkNotNull(absPath)); |
| sd.performVoid(new WriteOperation<Void>("removeItem") { |
| @Override |
| public void performVoid() throws RepositoryException { |
| ItemDelegate item = sd.getItem(oakPath); |
| if (item == null) { |
| throw new PathNotFoundException(absPath); |
| } else if (item.isProtected()) { |
| throw new ConstraintViolationException( |
| item.getPath() + " is protected"); |
| } else if (!item.remove()) { |
| throw new RepositoryException( |
| item.getPath() + " could not be removed"); |
| } |
| } |
| }); |
| } |
| |
| @Override |
| public void save() throws RepositoryException { |
| checkAlive(); |
| sd.performVoid(new WriteOperation<Void>("save") { |
| @Override |
| public void performVoid() throws RepositoryException { |
| sd.save(null); |
| } |
| |
| @Override |
| public boolean isSave() { |
| return true; |
| } |
| }); |
| } |
| |
| @Override |
| public void refresh(final boolean keepChanges) throws RepositoryException { |
| checkAlive(); |
| sd.performVoid(new WriteOperation<Void>("refresh") { |
| @Override |
| public void performVoid() { |
| sd.refresh(keepChanges); |
| } |
| |
| @Override |
| public boolean isRefresh() { |
| return true; |
| } |
| }); |
| } |
| |
| @Override |
| public boolean hasPendingChanges() throws RepositoryException { |
| checkAlive(); |
| return sd.hasPendingChanges(); |
| } |
| |
| @Override |
| public boolean isLive() { |
| return sd != null && sd.isAlive(); |
| } |
| |
| @Override |
| public void logout() { |
| if (isLive()) { |
| sessionCounter.dec(); |
| try { |
| sd.performVoid(new SessionOperation<Void>("logout") { |
| @Override |
| public void performVoid() { |
| sessionContext.dispose(); |
| sd.logout(); |
| } |
| |
| @Override |
| public boolean isLogout() { |
| return true; |
| } |
| }); |
| } catch (RepositoryException e) { |
| throw new RuntimeException("Unexpected exception thrown by operation 'logout'", e); |
| } finally { |
| sd = null; |
| sessionContext = null; |
| } |
| } |
| } |
| |
| @Override |
| @NotNull |
| public ContentHandler getImportContentHandler(String parentAbsPath, |
| int uuidBehavior) throws RepositoryException { |
| return new ImportHandler(checkNotNull(parentAbsPath), sessionContext, |
| uuidBehavior, false); |
| } |
| |
| @Override |
| public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) |
| throws IOException, RepositoryException { |
| try { |
| ContentHandler handler = getImportContentHandler( |
| checkNotNull(parentAbsPath), uuidBehavior); |
| new ParsingContentHandler(handler).parse(in); |
| } catch (SAXException e) { |
| Throwable exception = e.getException(); |
| if (exception instanceof RepositoryException) { |
| throw (RepositoryException) exception; |
| } else if (exception instanceof IOException) { |
| throw (IOException) exception; |
| } else { |
| throw new InvalidSerializedDataException("XML parse error", e); |
| } |
| } finally { |
| // JCR-2903 |
| if (in != null) { |
| try { |
| in.close(); |
| } catch (IOException ignore) { |
| } |
| } |
| } |
| } |
| |
| /** |
| * Exports content at the given path using the given exporter. |
| * |
| * @param path of the node to be exported |
| * @param exporter document or system view exporter |
| * @throws SAXException if the SAX event handler failed |
| * @throws RepositoryException if another error occurs |
| */ |
| private synchronized void export(String path, Exporter exporter) |
| throws SAXException, RepositoryException { |
| Item item = getItem(path); |
| if (item.isNode()) { |
| exporter.export((Node) item); |
| } else { |
| throw new PathNotFoundException("XML export is not defined for properties: " + path); |
| } |
| } |
| |
| @Override |
| public void exportSystemView(String absPath, ContentHandler contentHandler, |
| boolean skipBinary, boolean noRecurse) throws SAXException, |
| RepositoryException { |
| export(checkNotNull(absPath), new SystemViewExporter(this, |
| checkNotNull(contentHandler), !noRecurse, !skipBinary)); |
| } |
| |
| @Override |
| public void exportSystemView(String absPath, OutputStream out, |
| boolean skipBinary, boolean noRecurse) throws IOException, |
| RepositoryException { |
| try { |
| ContentHandler handler = new ToXmlContentHandler(checkNotNull(out)); |
| export(checkNotNull(absPath), new SystemViewExporter(this, handler, |
| !noRecurse, !skipBinary)); |
| } catch (SAXException e) { |
| Exception exception = e.getException(); |
| if (exception instanceof RepositoryException) { |
| throw (RepositoryException) exception; |
| } else if (exception instanceof IOException) { |
| throw (IOException) exception; |
| } else { |
| throw new RepositoryException( |
| "Error serializing system view XML", e); |
| } |
| } |
| } |
| |
| @Override |
| public void exportDocumentView(String absPath, |
| ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) |
| throws SAXException, RepositoryException { |
| export(checkNotNull(absPath), new DocumentViewExporter(this, |
| checkNotNull(contentHandler), !noRecurse, !skipBinary)); |
| } |
| |
| @Override |
| public void exportDocumentView(String absPath, OutputStream out, |
| boolean skipBinary, boolean noRecurse) throws IOException, |
| RepositoryException { |
| try { |
| ContentHandler handler = new ToXmlContentHandler(checkNotNull(out)); |
| export(checkNotNull(absPath), new DocumentViewExporter(this, |
| handler, !noRecurse, !skipBinary)); |
| } catch (SAXException e) { |
| Exception exception = e.getException(); |
| if (exception instanceof RepositoryException) { |
| throw (RepositoryException) exception; |
| } else if (exception instanceof IOException) { |
| throw (IOException) exception; |
| } else { |
| throw new RepositoryException( |
| "Error serializing document view XML", e); |
| } |
| } |
| } |
| |
| @Override |
| public void addLockToken(String lt) { |
| try { |
| getWorkspace().getLockManager().addLockToken(checkNotNull(lt)); |
| } catch (RepositoryException e) { |
| log.warn("Unable to add lock token " + lt + " to session", e); |
| } |
| } |
| |
| @Override @NotNull |
| public String[] getLockTokens() { |
| try { |
| return getWorkspace().getLockManager().getLockTokens(); |
| } catch (RepositoryException e) { |
| log.warn("Unable to retrieve lock tokens from session", e); |
| return new String[0]; |
| } |
| } |
| |
| @Override |
| public void removeLockToken(String lt) { |
| try { |
| getWorkspace().getLockManager().removeLockToken(checkNotNull(lt)); |
| } catch (RepositoryException e) { |
| log.warn("Unable to remove lock token " + lt + " from session", e); |
| } |
| } |
| |
| @Override |
| public boolean hasPermission(String absPath, final String actions) throws RepositoryException { |
| checkAlive(); |
| final String oakPath = getOakPathOrThrow(checkNotNull(absPath)); |
| checkNotNull(actions); |
| return sd.perform(new ReadOperation<Boolean>("hasPermission") { |
| @NotNull |
| @Override |
| public Boolean perform() throws RepositoryException { |
| return sessionContext.getAccessManager().hasPermissions(oakPath, actions); |
| } |
| }); |
| } |
| |
| @Override |
| public void checkPermission(String absPath, String actions) throws RepositoryException { |
| if (!hasPermission(checkNotNull(absPath), checkNotNull(actions))) { |
| throw new AccessControlException("Access denied."); |
| } |
| } |
| |
| @Override |
| public boolean hasCapability(String methodName, Object target, Object[] arguments) throws RepositoryException { |
| checkNotNull(methodName); |
| checkNotNull(target); |
| checkAlive(); |
| |
| if (target instanceof ItemImpl) { |
| ItemDelegate dlg = ((ItemImpl<?>) target).dlg; |
| if (dlg.isProtected()) { |
| return false; |
| } |
| |
| boolean isNode = ((ItemImpl<?>) target).isNode(); |
| Node parent = (isNode) ? (Node) target : ((ItemImpl<?>) target).getParent(); |
| if (!parent.isCheckedOut()) { |
| return false; |
| } |
| boolean hasLocking = sessionContext.getRepository().getDescriptorValue(Repository.OPTION_LOCKING_SUPPORTED).getBoolean(); |
| if (hasLocking && parent.isLocked()) { |
| return false; |
| } |
| |
| AccessManager accessMgr = sessionContext.getAccessManager(); |
| long permission = Permissions.NO_PERMISSION; |
| if (isNode) { |
| Tree tree = ((NodeDelegate) dlg).getTree(); |
| if ("addNode".equals(methodName)) { |
| if (arguments != null && arguments.length > 0) { |
| // add-node needs to be checked on the (path of) the |
| // new node that has/will be added |
| String path = PathUtils.concat(tree.getPath(), sessionContext.getOakName(arguments[0].toString())); |
| return accessMgr.hasPermissions(path, Session.ACTION_ADD_NODE) && !isMountedReadOnly(path); |
| } |
| } else if ("setPrimaryType".equals(methodName) || "addMixin".equals(methodName) || "removeMixin".equals(methodName)) { |
| permission = Permissions.NODE_TYPE_MANAGEMENT; |
| } else if ("orderBefore".equals(methodName)) { |
| if (tree.isRoot()) { |
| return false; |
| } else { |
| permission = Permissions.MODIFY_CHILD_NODE_COLLECTION; |
| tree = tree.getParent(); |
| } |
| } else if ("setProperty".equals(methodName)) { |
| permission = Permissions.ADD_PROPERTY; |
| } else if ("remove".equals(methodName)) { |
| permission = Permissions.REMOVE_NODE; |
| } |
| return accessMgr.hasPermissions(tree, null, permission) && !isMountedReadOnly(tree.getPath()); |
| } else { |
| if ("setValue".equals(methodName)) { |
| permission = Permissions.MODIFY_PROPERTY; |
| } else if ("remove".equals(methodName)) { |
| permission = Permissions.REMOVE_PROPERTY; |
| } |
| NodeDelegate parentDelegate = dlg.getParent(); |
| if (parentDelegate != null) { |
| return accessMgr.hasPermissions(parentDelegate.getTree(), ((PropertyDelegate) dlg).getPropertyState(), permission) |
| && !isMountedReadOnly(parentDelegate.getPath()); |
| } else { |
| return accessMgr.hasPermissions(dlg.getPath(), (permission == Permissions.MODIFY_PROPERTY) ? Session.ACTION_SET_PROPERTY : Session.ACTION_REMOVE) |
| && !isMountedReadOnly(dlg.getPath()); |
| } |
| } |
| } |
| // TODO: add more best-effort checks |
| return true; |
| } |
| |
| private boolean isMountedReadOnly(String path) { |
| MountInfoProvider mip = sessionContext.getMountInfoProvider(); |
| return mip != null && mip.getMountByPath(path).isReadOnly(); |
| } |
| |
| @Override |
| @NotNull |
| public AccessControlManager getAccessControlManager() throws RepositoryException { |
| return sessionContext.getAccessControlManager(); |
| } |
| |
| /** |
| * @see javax.jcr.Session#getRetentionManager() |
| */ |
| @Override |
| @NotNull |
| public RetentionManager getRetentionManager() throws RepositoryException { |
| throw new UnsupportedRepositoryOperationException("Retention Management is not supported."); |
| } |
| |
| //---------------------------------------------------------< Namespaces >--- |
| |
| @Override |
| public void setNamespacePrefix(String prefix, String uri) |
| throws RepositoryException { |
| sessionContext.getNamespaces().setNamespacePrefix(checkNotNull(prefix), |
| checkNotNull(uri)); |
| } |
| |
| @Override |
| public String[] getNamespacePrefixes() throws RepositoryException { |
| return sessionContext.getNamespaces().getNamespacePrefixes(); |
| } |
| |
| @Override |
| public String getNamespaceURI(String prefix) throws RepositoryException { |
| return sessionContext.getNamespaces().getNamespaceURI( |
| checkNotNull(prefix)); |
| } |
| |
| @Override |
| public String getNamespacePrefix(String uri) throws RepositoryException { |
| return sessionContext.getNamespaces().getNamespacePrefix( |
| checkNotNull(uri)); |
| } |
| |
| //--------------------------------------------------< JackrabbitSession >--- |
| |
| @Override |
| public boolean hasPermission(String absPath, String... actions) throws RepositoryException { |
| return hasPermission(absPath, Text.implode(actions, ",")); |
| } |
| |
| @Override |
| @NotNull |
| public PrincipalManager getPrincipalManager() throws RepositoryException { |
| return sessionContext.getPrincipalManager(); |
| } |
| |
| @Override |
| @NotNull |
| public UserManager getUserManager() throws RepositoryException { |
| return sessionContext.getUserManager(); |
| } |
| |
| @Override |
| public String toString() { |
| if (isLive()) { |
| return sd.getContentSession().toString(); |
| } |
| return "null"; |
| } |
| } |