Package org.jboss.dna.jcr

Source Code of org.jboss.dna.jcr.JcrSession

/*
* JBoss DNA (http://www.jboss.org/dna)
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of
* individual contributors.
*
* JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
* is licensed to you under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JBoss DNA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.dna.jcr;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.AccessControlException;
import java.util.Calendar;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.jcr.Credentials;
import javax.jcr.InvalidSerializedDataException;
import javax.jcr.Item;
import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.NamespaceException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyType;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.ValueFormatException;
import javax.jcr.Workspace;
import javax.jcr.nodetype.ConstraintViolationException;
import net.jcip.annotations.Immutable;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.SecurityContext;
import org.jboss.dna.graph.property.Binary;
import org.jboss.dna.graph.property.DateTime;
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.PathFactory;
import org.jboss.dna.graph.property.ValueFactories;
import org.jboss.dna.graph.property.basic.LocalNamespaceRegistry;
import org.jboss.dna.graph.session.GraphSession;
import org.jboss.dna.jcr.JcrContentHandler.EnclosingSAXException;
import org.jboss.dna.jcr.JcrContentHandler.SaveMode;
import org.jboss.dna.jcr.JcrNamespaceRegistry.Behavior;
import org.jboss.dna.jcr.SessionCache.JcrPropertyPayload;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

/**
* The DNA implementation of a {@link Session JCR Session}.
*/
@NotThreadSafe
class JcrSession implements Session {

    private static final String[] NO_ATTRIBUTES_NAMES = new String[] {};

    public static final String DNA_READ_PERMISSION = "readonly";
    public static final String DNA_WRITE_PERMISSION = "readwrite";
    public static final String DNA_ADMIN_PERMISSION = "admin";

    public static final String DNA_REGISTER_NAMESPACE_PERMISSION = "register_namespace";
    public static final String DNA_REGISTER_TYPE_PERMISSION = "register_type";

    public static final String JCR_ADD_NODE_PERMISSION = "add_node";
    public static final String JCR_SET_PROPERTY_PERMISSION = "set_property";
    public static final String JCR_REMOVE_PERMISSION = "remove";
    public static final String JCR_READ_PERMISSION = "read";

    /**
     * The repository that created this session.
     */
    private final JcrRepository repository;

    /**
     * The workspace that corresponds to this session.
     */
    private final JcrWorkspace workspace;

    /**
     * A JCR namespace registry that is specific to this session, with any locally-defined namespaces defined in this session.
     * This is backed by the workspace's namespace registry.
     */
    private final JcrNamespaceRegistry sessionRegistry;

    /**
     * The execution context for this session, which uses the {@link #sessionRegistry session's namespace registry}
     */
    protected final ExecutionContext executionContext;

    /**
     * The session-specific attributes that came from the {@link SimpleCredentials}' {@link SimpleCredentials#getAttributeNames()}
     */
    private final Map<String, Object> sessionAttributes;

    /**
     * The graph representing this session, which uses the {@link #graph session's graph}.
     */
    private final Graph graph;

    private final SessionCache cache;

    /**
     * A cached instance of the root path.
     */
    private final Path rootPath;

    private boolean isLive;

    JcrSession( JcrRepository repository,
                JcrWorkspace workspace,
                ExecutionContext workspaceContext,
                Map<String, Object> sessionAttributes ) {
        assert repository != null;
        assert workspace != null;
        assert sessionAttributes != null;
        assert workspaceContext != null;
        this.repository = repository;
        this.sessionAttributes = sessionAttributes;
        this.workspace = workspace;

        // Create an execution context for this session, which should use the local namespace registry ...
        NamespaceRegistry workspaceRegistry = workspaceContext.getNamespaceRegistry();
        NamespaceRegistry local = new LocalNamespaceRegistry(workspaceRegistry);
        this.executionContext = workspaceContext.with(local);
        this.sessionRegistry = new JcrNamespaceRegistry(Behavior.JSR170_SESSION, local, workspaceRegistry, this);
        this.rootPath = this.executionContext.getValueFactories().getPathFactory().createRootPath();

        // Set up the graph to use for this session (which uses the session's namespace registry and context) ...
        this.graph = workspace.graph();

        this.cache = new SessionCache(this);
        this.isLive = true;

        assert this.sessionAttributes != null;
        assert this.workspace != null;
        assert this.repository != null;
        assert this.executionContext != null;
        assert this.sessionRegistry != null;
        assert this.graph != null;
        assert this.executionContext.getSecurityContext() != null;
    }

    // Added to facilitate mock testing of items without necessarily requiring an entire repository structure to be built
    final SessionCache cache() {
        return this.cache;
    }

    ExecutionContext getExecutionContext() {
        return this.executionContext;
    }

    JcrNodeTypeManager nodeTypeManager() {
        return this.workspace.nodeTypeManager();
    }

    NamespaceRegistry namespaces() {
        return this.executionContext.getNamespaceRegistry();
    }

    JcrWorkspace workspace() {
        return this.workspace;
    }

    JcrRepository repository() {
        return this.repository;
    }

    Graph.Batch createBatch() {
        return graph.batch();
    }

    Graph graph() {
        return graph;
    }

    String sourceName() {
        return this.repository.getRepositorySourceName();
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getWorkspace()
     */
    public Workspace getWorkspace() {
        return this.workspace;
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getRepository()
     */
    public Repository getRepository() {
        return this.repository;
    }

    /**
     * {@inheritDoc}
     *
     * @return <code>null</code>
     * @see javax.jcr.Session#getAttribute(java.lang.String)
     */
    public Object getAttribute( String name ) {
        return sessionAttributes.get(name);
    }

    /**
     * {@inheritDoc}
     *
     * @return An empty array
     * @see javax.jcr.Session#getAttributeNames()
     */
    public String[] getAttributeNames() {
        Set<String> names = sessionAttributes.keySet();
        if (names.isEmpty()) return NO_ATTRIBUTES_NAMES;
        return names.toArray(new String[names.size()]);
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getNamespacePrefix(java.lang.String)
     */
    public String getNamespacePrefix( String uri ) throws RepositoryException {
        return sessionRegistry.getPrefix(uri);
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getNamespacePrefixes()
     */
    public String[] getNamespacePrefixes() {
        return sessionRegistry.getPrefixes();
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getNamespaceURI(java.lang.String)
     */
    public String getNamespaceURI( String prefix ) throws RepositoryException {
        return sessionRegistry.getURI(prefix);
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#setNamespacePrefix(java.lang.String, java.lang.String)
     */
    public void setNamespacePrefix( String newPrefix,
                                    String existingUri ) throws NamespaceException, RepositoryException {
        sessionRegistry.registerNamespace(newPrefix, existingUri);
    }

    /**
     * {@inheritDoc}
     *
     * @throws UnsupportedOperationException always
     * @see javax.jcr.Session#addLockToken(java.lang.String)
     */
    public void addLockToken( String lt ) {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns whether the authenticated user has the given role.
     *
     * @param roleName the name of the role to check
     * @param workspaceName the workspace under which the user must have the role. This may be different from the current
     *        workspace.
     * @return true if the user has the role and is logged in; false otherwise
     */
    final boolean hasRole( String roleName,
                           String workspaceName ) {
        SecurityContext context = getExecutionContext().getSecurityContext();

        return context.hasRole(roleName) || context.hasRole(roleName + "." + this.repository.getName())
               || context.hasRole(roleName + "." + this.repository.getName() + "." + workspaceName);
    }

    /**
     * {@inheritDoc}
     *
     * @throws IllegalArgumentException if either <code>path</code> or <code>actions</code> is empty or <code>null</code>.
     * @see javax.jcr.Session#checkPermission(java.lang.String, java.lang.String)
     */
    public void checkPermission( String path,
                                 String actions ) {
        CheckArg.isNotEmpty(path, "path");

        this.checkPermission(executionContext.getValueFactories().getPathFactory().create(path), actions);
    }

    /**
     * Throws an {@link AccessControlException} if the current user does not have permission for all of the named actions in the
     * current workspace, otherwise returns silently.
     * <p>
     * The {@code path} parameter is included for future use and is currently ignored
     * </p>
     *
     * @param path the path on which the actions are occurring
     * @param actions a comma-delimited list of actions to check
     */
    void checkPermission( Path path,
                          String actions ) {
        checkPermission(this.workspace().getName(), path, actions);
    }

    /**
     * Throws an {@link AccessControlException} if the current user does not have permission for all of the named actions in the
     * named workspace, otherwise returns silently.
     * <p>
     * The {@code path} parameter is included for future use and is currently ignored
     * </p>
     *
     * @param workspaceName the name of the workspace in which the path exists
     * @param path the path on which the actions are occurring
     * @param actions a comma-delimited list of actions to check
     */
    void checkPermission( String workspaceName,
                          Path path,
                          String actions ) {

        CheckArg.isNotEmpty(actions, "actions");

        boolean hasPermission = true;
        for (String action : actions.split(",")) {
            if (JCR_READ_PERMISSION.equals(action)) {
                hasPermission &= hasRole(DNA_READ_PERMISSION, workspaceName) || hasRole(DNA_WRITE_PERMISSION, workspaceName)
                                 || hasRole(DNA_ADMIN_PERMISSION, workspaceName);
            } else if (DNA_REGISTER_NAMESPACE_PERMISSION.equals(action) || DNA_REGISTER_TYPE_PERMISSION.equals(action)) {
                hasPermission &= hasRole(DNA_ADMIN_PERMISSION, workspaceName);
            } else {
                hasPermission &= hasRole(DNA_ADMIN_PERMISSION, workspaceName) || hasRole(DNA_WRITE_PERMISSION, workspaceName);
            }
        }

        if (hasPermission) return;

        String pathAsString = path != null ? path.getString(this.namespaces()) : "<unknown>";
        throw new AccessControlException(JcrI18n.permissionDenied.text(pathAsString, actions));

    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#exportDocumentView(java.lang.String, org.xml.sax.ContentHandler, boolean, boolean)
     */
    public void exportDocumentView( String absPath,
                                    ContentHandler contentHandler,
                                    boolean skipBinary,
                                    boolean noRecurse ) throws RepositoryException, SAXException {
        CheckArg.isNotNull(absPath, "absPath");
        CheckArg.isNotNull(contentHandler, "contentHandler");

        Path exportRootPath = executionContext.getValueFactories().getPathFactory().create(absPath);
        Node exportRootNode = getNode(exportRootPath);

        AbstractJcrExporter exporter = new JcrDocumentViewExporter(this);

        exporter.exportView(exportRootNode, contentHandler, skipBinary, noRecurse);
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#exportDocumentView(java.lang.String, java.io.OutputStream, boolean, boolean)
     */
    public void exportDocumentView( String absPath,
                                    OutputStream out,
                                    boolean skipBinary,
                                    boolean noRecurse ) throws RepositoryException {
        CheckArg.isNotNull(absPath, "absPath");
        CheckArg.isNotNull(out, "out");

        Path exportRootPath = executionContext.getValueFactories().getPathFactory().create(absPath);
        Node exportRootNode = getNode(exportRootPath);

        AbstractJcrExporter exporter = new JcrDocumentViewExporter(this);

        exporter.exportView(exportRootNode, out, skipBinary, noRecurse);
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#exportSystemView(java.lang.String, org.xml.sax.ContentHandler, boolean, boolean)
     */
    public void exportSystemView( String absPath,
                                  ContentHandler contentHandler,
                                  boolean skipBinary,
                                  boolean noRecurse ) throws RepositoryException, SAXException {
        CheckArg.isNotNull(absPath, "absPath");
        CheckArg.isNotNull(contentHandler, "contentHandler");

        Path exportRootPath = executionContext.getValueFactories().getPathFactory().create(absPath);
        Node exportRootNode = getNode(exportRootPath);

        AbstractJcrExporter exporter = new JcrSystemViewExporter(this);

        exporter.exportView(exportRootNode, contentHandler, skipBinary, noRecurse);
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#exportSystemView(java.lang.String, java.io.OutputStream, boolean, boolean)
     */
    public void exportSystemView( String absPath,
                                  OutputStream out,
                                  boolean skipBinary,
                                  boolean noRecurse ) throws RepositoryException {
        CheckArg.isNotNull(absPath, "absPath");
        CheckArg.isNotNull(out, "out");

        Path exportRootPath = executionContext.getValueFactories().getPathFactory().create(absPath);
        Node exportRootNode = getNode(exportRootPath);

        AbstractJcrExporter exporter = new JcrSystemViewExporter(this);

        exporter.exportView(exportRootNode, out, skipBinary, noRecurse);
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getImportContentHandler(java.lang.String, int)
     */
    public ContentHandler getImportContentHandler( String parentAbsPath,
                                                   int uuidBehavior ) throws PathNotFoundException, RepositoryException {
        Path parentPath = this.executionContext.getValueFactories().getPathFactory().create(parentAbsPath);

        return new JcrContentHandler(this, parentPath, uuidBehavior, SaveMode.SESSION);
    }

    /**
     * {@inheritDoc}
     *
     * @throws IllegalArgumentException if <code>absolutePath</code> is empty or <code>null</code>.
     * @see javax.jcr.Session#getItem(java.lang.String)
     */
    public Item getItem( String absolutePath ) throws RepositoryException {
        CheckArg.isNotEmpty(absolutePath, "absolutePath");
        // Return root node if path is "/"
        Path path = executionContext.getValueFactories().getPathFactory().create(absolutePath);
        if (path.isRoot()) {
            return getRootNode();
        }
        // Since we don't know whether path refers to a node or a property, look to see if we can tell it's a node ...
        if (path.getLastSegment().hasIndex()) {
            return getNode(path);
        }
        // We can't tell from the name, so ask for an item ...
        try {
            return cache.findJcrItem(null, rootPath, path.relativeTo(rootPath));
        } catch (ItemNotFoundException e) {
            throw new PathNotFoundException(e.getMessage(), e);
        }
    }

    /**
     * {@inheritDoc}
     *
     * @throws UnsupportedOperationException always
     * @see javax.jcr.Session#getLockTokens()
     */
    public String[] getLockTokens() {
        throw new UnsupportedOperationException();
    }

    /**
     * Find or create a JCR Node for the given path. This method works for the root node, too.
     *
     * @param path the path; may not be null
     * @return the JCR node instance for the given path; never null
     * @throws PathNotFoundException if the path could not be found
     * @throws RepositoryException if there is a problem
     */
    AbstractJcrNode getNode( Path path ) throws RepositoryException, PathNotFoundException {
        if (path.isRoot()) return cache.findJcrRootNode();
        try {
            return cache.findJcrNode(null, path);
        } catch (ItemNotFoundException e) {
            throw new PathNotFoundException(e.getMessage());
        }
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getNodeByUUID(java.lang.String)
     */
    public Node getNodeByUUID( String uuid ) throws ItemNotFoundException, RepositoryException {
        return cache.findJcrNode(Location.create(UUID.fromString(uuid)));
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getRootNode()
     */
    public Node getRootNode() throws RepositoryException {
        return cache.findJcrRootNode();
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getUserID()
     * @see SecurityContext#getUserName()
     */
    public String getUserID() {
        return executionContext.getSecurityContext().getUserName();
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#getValueFactory()
     */
    public ValueFactory getValueFactory() {
        final ValueFactories valueFactories = executionContext.getValueFactories();
        final SessionCache sessionCache = this.cache;

        return new ValueFactory() {

            public Value createValue( String value,
                                      int propertyType ) throws ValueFormatException {
                return new JcrValue(valueFactories, sessionCache, propertyType, convertValueToType(value, propertyType));
            }

            public Value createValue( Node value ) throws RepositoryException {
                if (!value.isNodeType(JcrMixLexicon.REFERENCEABLE.getString(JcrSession.this.namespaces()))) {
                    throw new RepositoryException(JcrI18n.nodeNotReferenceable.text());
                }
                String uuid = valueFactories.getStringFactory().create(value.getUUID());
                return new JcrValue(valueFactories, sessionCache, PropertyType.REFERENCE, uuid);
            }

            public Value createValue( InputStream value ) {
                Binary binary = valueFactories.getBinaryFactory().create(value);
                return new JcrValue(valueFactories, sessionCache, PropertyType.BINARY, binary);
            }

            public Value createValue( Calendar value ) {
                DateTime dateTime = valueFactories.getDateFactory().create(value);
                return new JcrValue(valueFactories, sessionCache, PropertyType.DATE, dateTime);
            }

            public Value createValue( boolean value ) {
                return new JcrValue(valueFactories, sessionCache, PropertyType.BOOLEAN, value);
            }

            public Value createValue( double value ) {
                return new JcrValue(valueFactories, sessionCache, PropertyType.DOUBLE, value);
            }

            public Value createValue( long value ) {
                return new JcrValue(valueFactories, sessionCache, PropertyType.LONG, value);
            }

            public Value createValue( String value ) {
                return new JcrValue(valueFactories, sessionCache, PropertyType.STRING, value);
            }

            Object convertValueToType( Object value,
                                       int toType ) throws ValueFormatException {
                switch (toType) {
                    case PropertyType.BOOLEAN:
                        try {
                            return valueFactories.getBooleanFactory().create(value);
                        } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
                            throw new ValueFormatException(vfe);
                        }

                    case PropertyType.DATE:
                        try {
                            return valueFactories.getDateFactory().create(value);
                        } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
                            throw new ValueFormatException(vfe);
                        }

                    case PropertyType.NAME:
                        try {
                            return valueFactories.getNameFactory().create(value);
                        } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
                            throw new ValueFormatException(vfe);
                        }

                    case PropertyType.PATH:
                        try {
                            return valueFactories.getPathFactory().create(value);
                        } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
                            throw new ValueFormatException(vfe);
                        }

                    case PropertyType.REFERENCE:
                        try {
                            return valueFactories.getReferenceFactory().create(value);
                        } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
                            throw new ValueFormatException(vfe);
                        }
                    case PropertyType.DOUBLE:
                        try {
                            return valueFactories.getDoubleFactory().create(value);
                        } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
                            throw new ValueFormatException(vfe);
                        }
                    case PropertyType.LONG:
                        try {
                            return valueFactories.getLongFactory().create(value);
                        } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
                            throw new ValueFormatException(vfe);
                        }

                        // Anything can be converted to these types
                    case PropertyType.BINARY:
                        try {
                            return valueFactories.getBinaryFactory().create(value);
                        } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
                            throw new ValueFormatException(vfe);
                        }
                    case PropertyType.STRING:
                        try {
                            return valueFactories.getStringFactory().create(value);
                        } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
                            throw new ValueFormatException(vfe);
                        }
                    case PropertyType.UNDEFINED:
                        return value;

                    default:
                        assert false : "Unexpected JCR property type " + toType;
                        // This should still throw an exception even if assertions are turned off
                        throw new IllegalStateException("Invalid property type " + toType);
                }
            }

        };
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#hasPendingChanges()
     */
    public boolean hasPendingChanges() {
        return cache.hasPendingChanges();
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#impersonate(javax.jcr.Credentials)
     */
    public Session impersonate( Credentials credentials ) throws RepositoryException {
        return repository.login(credentials, this.workspace.getName());
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#importXML(java.lang.String, java.io.InputStream, int)
     */
    public void importXML( String parentAbsPath,
                           InputStream in,
                           int uuidBehavior ) throws IOException, InvalidSerializedDataException, RepositoryException {

        try {
            XMLReader parser = XMLReaderFactory.createXMLReader();

            parser.setContentHandler(getImportContentHandler(parentAbsPath, uuidBehavior));
            parser.parse(new InputSource(in));
        } catch (EnclosingSAXException ese) {
            Exception cause = ese.getException();
            if (cause instanceof ItemExistsException) {
                throw (ItemExistsException)cause;
            } else if (cause instanceof ConstraintViolationException) {
                throw (ConstraintViolationException)cause;
            }
            throw new RepositoryException(cause);
        } catch (SAXParseException se) {
            throw new InvalidSerializedDataException(se);
        } catch (SAXException se) {
            throw new RepositoryException(se);
        }
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#isLive()
     */
    public boolean isLive() {
        return isLive;
    }

    /**
     * {@inheritDoc}
     *
     * @throws IllegalArgumentException if <code>absolutePath</code> is empty or <code>null</code>.
     * @see javax.jcr.Session#itemExists(java.lang.String)
     */
    public boolean itemExists( String absolutePath ) throws RepositoryException {
        try {
            return (getItem(absolutePath) != null);
        } catch (PathNotFoundException error) {
            return false;
        }
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#logout()
     */
    public void logout() {
        if (!isLive()) {
            return;
        }

        this.executionContext.getSecurityContext().logout();
        isLive = false;
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#move(java.lang.String, java.lang.String)
     */
    public void move( String srcAbsPath,
                      String destAbsPath ) throws ItemExistsException, RepositoryException {
        CheckArg.isNotNull(srcAbsPath, "srcAbsPath");
        CheckArg.isNotNull(destAbsPath, "destAbsPath");

        PathFactory pathFactory = executionContext.getValueFactories().getPathFactory();
        Path destPath = pathFactory.create(destAbsPath);

        Path.Segment newNodeName = destPath.getSegment(destPath.size() - 1);
        // Doing a literal test here because the path factory will canonicalize "/node[1]" to "/node"
        if (destAbsPath.endsWith("]")) {
            throw new RepositoryException(JcrI18n.pathCannotHaveSameNameSiblingIndex.text(destAbsPath));
        }

        AbstractJcrNode sourceNode = getNode(pathFactory.create(srcAbsPath));
        AbstractJcrNode newParentNode = getNode(destPath.getParent());

        String newNodeNameAsString = newNodeName.getString(executionContext.getNamespaceRegistry());
        if (newParentNode.hasNode(newNodeName.getString(executionContext.getNamespaceRegistry()))) {
            throw new ItemExistsException(JcrI18n.childNodeAlreadyExists.text(newNodeNameAsString, newParentNode.getPath()));
        }

        newParentNode.editor().moveToBeChild(sourceNode, newNodeName.getName());
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#refresh(boolean)
     */
    public void refresh( boolean keepChanges ) {
        this.cache.refresh(keepChanges);
    }

    /**
     * {@inheritDoc}
     *
     * @throws UnsupportedOperationException always
     * @see javax.jcr.Session#removeLockToken(java.lang.String)
     */
    public void removeLockToken( String lt ) {
        throw new UnsupportedOperationException();
    }

    /**
     * {@inheritDoc}
     *
     * @see javax.jcr.Session#save()
     */
    public void save() throws RepositoryException {
        cache.save();
    }

    /**
     * Get a snapshot of the current session state. This snapshot is immutable and will not reflect any future state changes in
     * the session.
     *
     * @return the snapshot; never null
     */
    public Snapshot getSnapshot() {
        return new Snapshot(cache.graphSession().getRoot().getSnapshot(false));
    }

    /**
     * {@inheritDoc}
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return getSnapshot().toString();
    }

    @Immutable
    public class Snapshot {
        private final GraphSession.StructureSnapshot<JcrPropertyPayload> rootSnapshot;

        protected Snapshot( GraphSession.StructureSnapshot<JcrPropertyPayload> snapshot ) {
            this.rootSnapshot = snapshot;
        }

        /**
         * {@inheritDoc}
         *
         * @see java.lang.Object#toString()
         */
        @Override
        public String toString() {
            return rootSnapshot.toString();
        }
    }
}
TOP

Related Classes of org.jboss.dna.jcr.JcrSession

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.