You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2006/07/12 15:33:27 UTC

svn commit: r421270 [6/23] - in /jackrabbit/trunk/contrib/spi: ./ commons/ commons/src/ commons/src/main/ commons/src/main/java/ commons/src/main/java/org/ commons/src/main/java/org/apache/ commons/src/main/java/org/apache/jackrabbit/ commons/src/main/...

Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/RepositoryImpl.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/RepositoryImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/RepositoryImpl.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,117 @@
+/*
+ * 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.jcr2spi;
+
+import org.apache.jackrabbit.jcr2spi.config.RepositoryConfig;
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.XASessionInfo;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import java.util.Properties;
+
+/**
+ * <code>RepositoryImpl</code>...
+ */
+public class RepositoryImpl implements Repository {
+
+    private static Logger log = LoggerFactory.getLogger(RepositoryImpl.class);
+
+    // configuration of the repository
+    private final RepositoryConfig config;
+    private final Properties descriptors;
+
+    private RepositoryImpl(RepositoryConfig config) throws RepositoryException {
+        this.config = config;
+        descriptors = config.getRepositoryService().getRepositoryDescriptors();
+    }
+
+    public static Repository create(RepositoryConfig config) throws RepositoryException {
+        return new RepositoryImpl(config);
+    }
+
+    //---------------------------------------------------------< Repository >---
+    /**
+     * @see Repository#getDescriptorKeys()
+     */
+    public String[] getDescriptorKeys() {
+        String[] keys = (String[]) descriptors.keySet().toArray(new String[descriptors.keySet().size()]);
+        return keys;
+    }
+
+    /**
+     * @see Repository#getDescriptor(String)
+     */
+    public String getDescriptor(String descriptorKey) {
+	return descriptors.getProperty(descriptorKey);
+    }
+
+    /**
+     * @see Repository#login(javax.jcr.Credentials, String)
+     */
+    public Session login(Credentials credentials, String workspaceName) throws LoginException, NoSuchWorkspaceException, RepositoryException {
+        SessionInfo info = config.getRepositoryService().login(credentials, workspaceName);
+        if (info instanceof XASessionInfo) {
+            return new XASessionImpl((XASessionInfo) info, this, config);
+        } else {
+            return new SessionImpl(info, this, config);
+        }
+    }
+
+    /**
+     * @see Repository#login(javax.jcr.Credentials)
+     */
+    public Session login(Credentials credentials) throws LoginException, NoSuchWorkspaceException, RepositoryException {
+	return login(credentials, null);
+    }
+
+    /**
+     * @see Repository#login(String)
+     */
+    public Session login(String workspaceName) throws LoginException, NoSuchWorkspaceException, RepositoryException {
+	return login(null, workspaceName);
+    }
+
+    /**
+     * @see Repository#login()
+     */
+    public Session login() throws LoginException, NoSuchWorkspaceException, RepositoryException {
+	return login(null, null);
+    }
+
+
+    //--------------------------------------------< implementation specific >---
+    /*
+     * DIFF JACKRABBIT:
+     *
+     * - workspaces are not read from config any more.
+     * - therefore no workspace Infos
+     * - NamespaceRegistry/NodeTypeRegistry can only be loaded after login
+     *   since they also have to obey the access-control and transaction
+     *   mechanisms.
+     * - SharedItemStateManager retrieved by 'getWorkspaceStateManager(String)'
+     *   has not relevance any more (correct?)
+     * - only the UpdatableItemStateManager 'local' statemanager retrieved from
+     *   the workspace exists. it depends on the SessionInfo.
+     */
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/RepositoryImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/RepositoryImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,866 @@
+/*
+ * 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.jcr2spi;
+
+import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeManagerImpl;
+import org.apache.jackrabbit.jcr2spi.nodetype.ItemDefinitionManager;
+import org.apache.jackrabbit.jcr2spi.security.SecurityConstants;
+import org.apache.jackrabbit.jcr2spi.security.AccessManager;
+import org.apache.jackrabbit.jcr2spi.state.SessionItemStateManager;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateManager;
+import org.apache.jackrabbit.jcr2spi.state.UpdatableItemStateManager;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
+import org.apache.jackrabbit.jcr2spi.xml.DocViewSAXEventGenerator;
+import org.apache.jackrabbit.jcr2spi.xml.SysViewSAXEventGenerator;
+import org.apache.jackrabbit.jcr2spi.xml.ImportHandler;
+import org.apache.jackrabbit.jcr2spi.xml.ImporterImpl;
+import org.apache.jackrabbit.jcr2spi.xml.Importer;
+import org.apache.jackrabbit.jcr2spi.lock.LockManager;
+import org.apache.jackrabbit.jcr2spi.version.VersionManager;
+import org.apache.jackrabbit.jcr2spi.operation.Move;
+import org.apache.jackrabbit.jcr2spi.operation.Operation;
+import org.apache.jackrabbit.jcr2spi.name.LocalNamespaceMappings;
+import org.apache.jackrabbit.jcr2spi.config.RepositoryConfig;
+import org.apache.jackrabbit.name.MalformedPathException;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.name.Path;
+import org.apache.jackrabbit.spi.RepositoryService;
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.ItemId;
+import org.apache.jackrabbit.spi.IdFactory;
+import org.apache.commons.collections.map.ReferenceMap;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.InvalidSerializedDataException;
+import javax.jcr.Item;
+import javax.jcr.ItemExistsException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.LoginException;
+import javax.jcr.NamespaceException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFactory;
+import javax.jcr.Workspace;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.version.VersionException;
+import javax.security.auth.Subject;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.TransformerException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.AccessControlException;
+import java.security.Principal;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * <code>SessionImpl</code>...
+ */
+public class SessionImpl implements Session, ManagerProvider {
+
+    private static Logger log = LoggerFactory.getLogger(SessionImpl.class);
+
+    // DIFF JR: moved access-right constants to AcessManager
+
+    private boolean alive;
+
+    /**
+     * the attributes of this session
+     */
+    private final HashMap attributes = new HashMap();
+    /**
+     * Listeners (weak references)
+     */
+    private final Map listeners = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
+
+    private final Repository repository;
+    private final WorkspaceImpl workspace;
+
+    private final String userId;
+    private final Subject subject;
+
+    private final LocalNamespaceMappings nsMappings;
+    private final NodeTypeManagerImpl ntManager;
+    private final ValueFactory valueFactory;
+    
+    private final SessionItemStateManager itemStateManager;
+    private final ItemManager itemManager;
+    private final ItemStateValidator validator;
+
+    SessionImpl(SessionInfo sessionInfo, Repository repository, RepositoryConfig config)
+        throws RepositoryException {
+
+        alive = true;
+        this.repository = repository;
+        this.subject = sessionInfo.getSubject();
+
+        // DIFF JACKRABBIT don't expect principals
+        // TODO: not totally correct to use the first principles name as UserId
+        Set principals = sessionInfo.getSubject().getPrincipals();
+        if (!principals.isEmpty()) {
+            // use 1st principal in case there are more that one
+            Principal principal = (Principal) principals.iterator().next();
+            userId = principal.getName();
+        } else {
+            userId = null;
+        }
+
+        workspace = createWorkspaceInstance(config.getRepositoryService(), sessionInfo);
+        valueFactory = config.getValueFactory();
+
+        // build local name-mapping
+        nsMappings = new LocalNamespaceMappings(workspace.getNamespaceRegistryImpl());
+
+        // build nodetype manager
+        ntManager = new NodeTypeManagerImpl(workspace.getNodeTypeRegistry(), getNamespaceResolver(), getValueFactory());
+
+        validator = new ItemStateValidator(workspace.getNodeTypeRegistry(), this);
+
+        // build the state mananger
+        // DIFF JACKRABBIT: itemStateMgr = createSessionItemStateManager(wsp.getSessionItemStateManager());
+        itemStateManager = createSessionItemStateManager(workspace.getRootNodeId(), workspace.getUpdatableItemStateManager(), nsMappings);
+
+        // DIFF JACKRABBIT: itemManager = createItemManager(itemStateMgr, hierMgr);
+        itemManager = createItemManager(itemStateManager, getHierarchyManager());
+    }
+
+    //--------------------------------------------------< Session interface >---
+    /**
+     * @see javax.jcr.Session#getRepository()
+     */
+    public Repository getRepository() {
+        return repository;
+    }
+
+    /**
+     * @see javax.jcr.Session#getUserID()
+     */
+    public String getUserID() {
+        return userId;
+    }
+
+    /**
+     * @see javax.jcr.Session#getAttribute(String)
+     */
+    public Object getAttribute(String name) {
+        return attributes.get(name);
+    }
+
+    /**
+     * @see javax.jcr.Session#getAttributeNames()
+     */
+    public String[] getAttributeNames() {
+        return (String[]) attributes.keySet().toArray(new String[attributes.size()]);
+
+    }
+
+    /**
+     * @see javax.jcr.Session#getWorkspace()
+     */
+    public Workspace getWorkspace() {
+        return workspace;
+    }
+
+    /**
+     * @see javax.jcr.Session#impersonate(Credentials)
+     */
+    public Session impersonate(Credentials credentials) throws LoginException, RepositoryException {
+        checkIsAlive();
+        // TODO: check whether restriction to SimpleCredentials is correct
+        if (!(credentials instanceof SimpleCredentials)) {
+            String msg = "impersonate failed: incompatible credentials, SimpleCredentials expected";
+            log.debug(msg);
+            throw new RepositoryException(msg);
+        }
+
+        // set IMPERSONATOR_ATTRIBUTE attribute of given credentials
+        // with subject of current session
+        SimpleCredentials creds = (SimpleCredentials) credentials;
+        creds.setAttribute(SecurityConstants.IMPERSONATOR_ATTRIBUTE, subject);
+
+        try {
+            return repository.login(credentials, getWorkspace().getName());
+        } catch (NoSuchWorkspaceException nswe) {
+            // should never get here...
+            String msg = "impersonate failed";
+            log.error(msg, nswe);
+            throw new RepositoryException(msg, nswe);
+        } finally {
+            // make sure IMPERSONATOR_ATTRIBUTE is removed
+            creds.removeAttribute(SecurityConstants.IMPERSONATOR_ATTRIBUTE);
+        }
+    }
+
+    /**
+     * @see javax.jcr.Session#getRootNode()
+     */
+    public Node getRootNode() throws RepositoryException {
+        checkIsAlive();
+        return (Node) itemManager.getItem(workspace.getRootNodeId());
+    }
+
+    /**
+     * @see javax.jcr.Session#getNodeByUUID(String)
+     */
+    public Node getNodeByUUID(String uuid) throws ItemNotFoundException, RepositoryException {
+        // sanity check performed by getNodeById
+        NodeImpl node = getNodeById(getIdFactory().createNodeId(uuid));
+        if (node.isNodeType(QName.MIX_REFERENCEABLE)) {
+            return node;
+        } else {
+            // there is a node with that uuid but the node does not expose it
+            throw new ItemNotFoundException(uuid);
+        }
+    }
+
+    /**
+     * Retrieve the <code>Node</code> with the given id.
+     *
+     * @param id
+     * @return node with the given <code>NodeId</code>.
+     * @throws ItemNotFoundException if no such node exists or if this
+     * <code>Session</code> does not have permission to access the node.
+     * @throws RepositoryException
+     */
+    private NodeImpl getNodeById(NodeId id) throws ItemNotFoundException, RepositoryException {
+        // check sanity of this session
+        checkIsAlive();
+        try {
+            return (NodeImpl) getItemManager().getItem(id);
+        } catch (AccessDeniedException ade) {
+            throw new ItemNotFoundException(id.toString());
+        }
+    }
+
+    /**
+     * @see javax.jcr.Session#getItem(String)
+     */
+    public Item getItem(String absPath) throws PathNotFoundException, RepositoryException {
+        checkIsAlive();
+        try {
+            Path qPath = getQPath(absPath);
+            return getItemManager().getItem(qPath.getNormalizedPath());
+        } catch (AccessDeniedException ade) {
+            throw new PathNotFoundException(absPath);
+        } catch (MalformedPathException e) {
+            throw new RepositoryException(e);
+        }
+    }
+
+    /**
+     * @see javax.jcr.Session#itemExists(String)
+     */
+    public boolean itemExists(String absPath) throws RepositoryException {
+        checkIsAlive();
+        try {
+            Path qPath = getQPath(absPath);
+            return getItemManager().itemExists(qPath.getNormalizedPath());
+        } catch (MalformedPathException e) {
+            throw new RepositoryException(e);
+        }
+    }
+
+    /**
+     * @see javax.jcr.Session#move(String, String)
+     */
+    public void move(String srcAbsPath, String destAbsPath) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, RepositoryException {
+        checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+        checkIsAlive();
+
+        // retrieve qualified paths
+        Path srcPath = getQPath(srcAbsPath);
+        Path destPath = getQPath(destAbsPath);
+
+        // all validation is performed by Move Operation and state-manager
+        Operation op = Move.create(srcPath, destPath, validator);
+        itemStateManager.execute(op);
+    }
+
+    /**
+     * @see javax.jcr.Session#save()
+     */
+    public void save() throws AccessDeniedException, ConstraintViolationException, InvalidItemStateException, VersionException, LockException, RepositoryException {
+        checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+        // delegate to the root node (including check for isAlive)
+        getRootNode().save();
+    }
+
+    /**
+     * @see javax.jcr.Session#refresh(boolean)
+     */
+    public void refresh(boolean keepChanges) throws RepositoryException {
+        // delegate to the root node (including check for isAlive)
+        getRootNode().refresh(keepChanges);
+    }
+
+    /**
+     * @see javax.jcr.Session#hasPendingChanges()
+     */
+    public boolean hasPendingChanges() throws RepositoryException {
+        checkIsAlive();
+        return itemStateManager.hasPendingChanges();
+    }
+
+    /**
+     * @see javax.jcr.Session#getValueFactory()
+     */
+    public ValueFactory getValueFactory() throws UnsupportedRepositoryOperationException, RepositoryException {
+        // must throw UnsupportedRepositoryOperationException if writing is
+        // not supported
+        checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+        return valueFactory;
+    }
+
+    /**
+     * @see javax.jcr.Session#checkPermission(String, String)
+     */
+    public void checkPermission(String absPath, String actions) throws AccessControlException, RepositoryException {
+        checkIsAlive();
+        // build the array of actions to be checked
+        String[] actionsArr = actions.split(",");
+
+        // DIFF JR: different AccessManager (delegating to RS). No translation of actions to READ, WRITE, REMOVE.
+        Path targetPath = getQPath(absPath);
+        boolean isGranted;
+        if (itemExists(absPath)) {
+            ItemId id = getHierarchyManager().getItemId(targetPath);
+            isGranted = getAccessManager().isGranted(id, actionsArr);
+        } else {
+            // TODO: if spi-ids are used, its possible to build an id for a non-existing item (see also Node.restore)
+            // The given abs-path may point to a non-existing item
+            Path parentPath = targetPath;
+            NodeId parentId = null;
+            while (parentId == null) {
+                parentPath = parentPath.getAncestor(1);
+                if (itemManager.itemExists(parentPath)) {
+                    ItemId id = getHierarchyManager().getItemId(parentPath);
+                    if (id.denotesNode()) {
+                        parentId = (NodeId) id;
+                    }
+                }
+            }
+            // TODO build Id instead
+            try {
+                Path relPath = parentPath.computeRelativePath(targetPath);
+                isGranted = getAccessManager().isGranted(parentId, relPath, actionsArr);
+                if (!isGranted) {
+                    throw new AccessControlException(actions);
+                }
+            } catch (MalformedPathException e) {
+                // should not occurs
+                throw new RepositoryException(e);
+            }
+        }
+    }
+
+    /**
+     * @see Session#getImportContentHandler(String, int)
+     */
+    public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior) throws PathNotFoundException, ConstraintViolationException, VersionException, LockException, RepositoryException {
+        checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+        checkIsAlive();
+
+        Path parentPath = getQPath(parentAbsPath);
+        // DIFF JR: check for writable parent is performed within importer
+        Importer importer = new ImporterImpl(parentPath, this, getHierarchyManager(), itemStateManager, validator, getIdFactory(), uuidBehavior, false);
+        return new ImportHandler(importer, getNamespaceResolver(), workspace.getNamespaceRegistry(), getIdFactory());
+    }
+
+    // DIFF JR: dont cast getImportContentHandler to 'ImportHandler' check for instanceof ErrorHandler
+    /**
+     * @see javax.jcr.Session#importXML(String, java.io.InputStream, int)
+     */
+    public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) throws IOException, PathNotFoundException, ItemExistsException, ConstraintViolationException, VersionException, InvalidSerializedDataException, LockException, RepositoryException {
+        // NOTE: checks are performed by 'getImportContentHandler'
+        ContentHandler handler = getImportContentHandler(parentAbsPath, uuidBehavior);
+        try {
+            XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
+            parser.setContentHandler(handler);
+            if (handler instanceof ErrorHandler) {
+                parser.setErrorHandler((ErrorHandler)handler);
+            }
+            // being paranoid...
+            parser.setFeature("http://xml.org/sax/features/namespaces", true);
+            parser.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+            parser.parse(new InputSource(in));
+        } catch (SAXException se) {
+            // check for wrapped repository exception
+            Exception e = se.getException();
+            if (e != null && e instanceof RepositoryException) {
+                throw (RepositoryException) e;
+            } else {
+                String msg = "failed to parse XML stream";
+                log.debug(msg);
+                throw new InvalidSerializedDataException(msg, se);
+            }
+        }
+    }
+
+    /**
+     * @see javax.jcr.Session#exportSystemView(String, org.xml.sax.ContentHandler, boolean, boolean)
+     */
+    public void exportSystemView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) throws PathNotFoundException, SAXException, RepositoryException {
+        checkIsAlive();
+        Item item = getItem(absPath);
+        if (!item.isNode()) {
+            // a property instead of a node exists at the specified path
+            throw new PathNotFoundException(absPath);
+        }
+        new SysViewSAXEventGenerator((Node)item, noRecurse, skipBinary, contentHandler).serialize();
+    }
+
+    /**
+     * @see javax.jcr.Session#exportSystemView(String, OutputStream, boolean, boolean)
+     */
+    public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) throws IOException, PathNotFoundException, RepositoryException {
+        SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+        try {
+            TransformerHandler th = stf.newTransformerHandler();
+            th.setResult(new StreamResult(out));
+            th.getTransformer().setParameter(OutputKeys.METHOD, "xml");
+            th.getTransformer().setParameter(OutputKeys.ENCODING, "UTF-8");
+            th.getTransformer().setParameter(OutputKeys.INDENT, "no");
+
+            exportSystemView(absPath, th, skipBinary, noRecurse);
+        } catch (TransformerException te) {
+            throw new RepositoryException(te);
+        } catch (SAXException se) {
+            throw new RepositoryException(se);
+        }
+    }
+
+    /**
+     * @see javax.jcr.Session#exportDocumentView(String, org.xml.sax.ContentHandler, boolean, boolean)
+     */
+    public void exportDocumentView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) throws InvalidSerializedDataException, PathNotFoundException, SAXException, RepositoryException {
+        checkIsAlive();
+        Item item = getItem(absPath);
+        if (!item.isNode()) {
+            // a property instead of a node exists at the specified path
+            throw new PathNotFoundException(absPath);
+        }
+        new DocViewSAXEventGenerator((Node) item, noRecurse, skipBinary, contentHandler).serialize();
+    }
+
+    /**
+     * @see javax.jcr.Session#exportDocumentView(String, OutputStream, boolean, boolean)
+     */
+    public void exportDocumentView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) throws InvalidSerializedDataException, IOException, PathNotFoundException, RepositoryException {
+        SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+        try {
+            TransformerHandler th = stf.newTransformerHandler();
+            th.setResult(new StreamResult(out));
+            th.getTransformer().setParameter(OutputKeys.METHOD, "xml");
+            th.getTransformer().setParameter(OutputKeys.ENCODING, "UTF-8");
+            th.getTransformer().setParameter(OutputKeys.INDENT, "no");
+
+            exportDocumentView(absPath, th, skipBinary, noRecurse);
+        } catch (TransformerException te) {
+            throw new RepositoryException(te);
+        } catch (SAXException se) {
+            throw new RepositoryException(se);
+        }
+    }
+
+    /**
+     * @see javax.jcr.Session#setNamespacePrefix(String, String)
+     * @see LocalNamespaceMappings#setNamespacePrefix(String, String)
+     */
+    public void setNamespacePrefix(String prefix, String uri) throws NamespaceException, RepositoryException {
+        nsMappings.setNamespacePrefix(prefix, uri);
+    }
+
+    /**
+     * @see javax.jcr.Session#getNamespacePrefixes()
+     * @see LocalNamespaceMappings#getPrefixes()
+     */
+    public String[] getNamespacePrefixes() throws RepositoryException {
+        return nsMappings.getPrefixes();
+    }
+
+    /**
+     * @see javax.jcr.Session#getNamespaceURI(String)
+     * @see NamespaceResolver#getURI(String)
+     */
+    public String getNamespaceURI(String prefix) throws NamespaceException, RepositoryException {
+        return nsMappings.getURI(prefix);
+    }
+
+    /**
+     * @see javax.jcr.Session#getNamespacePrefix(String)
+     * @see NamespaceResolver#getPrefix(String)
+     */
+    public String getNamespacePrefix(String uri) throws NamespaceException, RepositoryException {
+        return nsMappings.getPrefix(uri);
+    }
+
+    /**
+     * @see javax.jcr.Session#logout()
+     */
+    public void logout() {
+        if (!alive) {
+            // ignore
+            return;
+        }
+
+        // notify listeners that session is about to be closed
+        notifyLoggingOut();
+
+        // dispose name resolver
+        nsMappings.dispose();
+        // dispose session item state manager
+        itemStateManager.dispose();
+        // dispose item manager
+        itemManager.dispose();
+        // dispose workspace
+
+        // TODO
+        // wsp.dispose();
+
+        // invalidate session
+        alive = false;
+        /*
+        // TODO
+        // logout JAAS subject
+        if (loginContext != null) {
+        try {
+        loginContext.logout();
+        } catch (javax.security.auth.login.LoginException le) {
+        log.warn("failed to logout current subject: " + le.getMessage());
+        }
+        loginContext = null;
+        }
+
+        try {
+        accessMgr.close();
+        } catch (Exception e) {
+        log.warn("error while closing AccessManager", e);
+        }
+        */
+        // finally notify listeners that session has been closed
+        notifyLoggedOut();
+    }
+
+    /**
+     * @see javax.jcr.Session#isLive()
+     */
+    public boolean isLive() {
+        return alive;
+    }
+
+    /**
+     * @see javax.jcr.Session#addLockToken(String)
+     */
+    public void addLockToken(String lt) {
+        try {
+            getLockManager().addLockToken(lt);
+        } catch (RepositoryException e) {
+            log.warn("Unable to add lock token '" +lt+ "' to this session.", e);
+        }
+    }
+
+    /**
+     * @see javax.jcr.Session#getLockTokens()
+     */
+    public String[] getLockTokens() {
+        return getLockManager().getLockTokens();
+    }
+
+    /**
+     * @see javax.jcr.Session#removeLockToken(String)
+     */
+    public void removeLockToken(String lt) {
+        try {
+            getLockManager().removeLockToken(lt);
+        } catch (RepositoryException e) {
+            log.warn("Unable to remove lock token '" +lt+ "' from this session.", e);
+        }
+    }
+
+    //--------------------------------------< register and inform listeners >---
+    /**
+     * Add a <code>SessionListener</code>
+     *
+     * @param listener the new listener to be informed on modifications
+     */
+    public void addListener(SessionListener listener) {
+        if (!listeners.containsKey(listener)) {
+            listeners.put(listener, listener);
+        }
+    }
+
+    /**
+     * Remove a <code>SessionListener</code>
+     *
+     * @param listener an existing listener
+     */
+    public void removeListener(SessionListener listener) {
+        listeners.remove(listener);
+    }
+
+    /**
+     * Notify the listeners that this session is about to be closed.
+     */
+    private void notifyLoggingOut() {
+        // copy listeners to array to avoid ConcurrentModificationException
+        SessionListener[] la = (SessionListener[])listeners.values().toArray(new SessionListener[listeners.size()]);
+        for (int i = 0; i < la.length; i++) {
+            if (la[i] != null) {
+                la[i].loggingOut(this);
+            }
+        }
+    }
+
+    /**
+     * Notify the listeners that this session has been closed.
+     */
+    private void notifyLoggedOut() {
+        // copy listeners to array to avoid ConcurrentModificationException
+        SessionListener[] la = (SessionListener[])listeners.values().toArray(new SessionListener[listeners.size()]);
+        for (int i = 0; i < la.length; i++) {
+            if (la[i] != null) {
+                la[i].loggedOut(this);
+            }
+        }
+    }
+
+    //-------------------------------------------------------< init methods >---
+    protected WorkspaceImpl createWorkspaceInstance(RepositoryService service, SessionInfo sessionInfo) throws RepositoryException {
+        return new WorkspaceImpl(sessionInfo.getWorkspaceName(), this, service, sessionInfo);
+    }
+
+    protected SessionItemStateManager createSessionItemStateManager(NodeId rootId, UpdatableItemStateManager workspaceStateManager, NamespaceResolver nsResolver) {
+        return new SessionItemStateManager(rootId, workspaceStateManager, getIdFactory(), valueFactory, getValidator(), nsResolver);
+    }
+
+    protected ItemManager createItemManager(ItemStateManager itemStateMgr, HierarchyManager hierarchyMgr) {
+        return new ItemManagerImpl(itemStateMgr, hierarchyMgr, this);
+    }
+
+    //---------------------------------------------------< ManagerProvider > ---
+    public NamespaceResolver getNamespaceResolver() {
+        return nsMappings;
+    }
+
+    public HierarchyManager getHierarchyManager() {
+        return itemStateManager.getHierarchyManager();
+    }
+
+    public ItemStateManager getItemStateManager() {
+        return itemStateManager;
+    }
+
+    public LockManager getLockManager() {
+        return workspace.getLockManager();
+    }
+
+    /**
+     * Returns the <code>AccessManager</code> associated with this session.
+     *
+     * @return the <code>AccessManager</code> associated with this session
+     */
+    public AccessManager getAccessManager() {
+        return workspace.getAccessManager();
+    }
+
+    /**
+     * Returns the <code>VersionManager</code> associated with this session.
+     *
+     * @return the <code>VersionManager</code> associated with this session
+     */
+    public VersionManager getVersionManager() {
+        return workspace.getVersionManager();
+    }
+
+    //--------------------------------------------------------------------------
+    ItemManager getItemManager() {
+        return itemManager;
+    }
+
+    ItemStateValidator getValidator() {
+        return validator;
+    }
+
+    IdFactory getIdFactory() {
+        return workspace.getIdFactory();
+    }
+
+    /**
+     * Returns the <code>ItemStateManager</code> associated with this session.
+     *
+     * @return the <code>ItemStateManager</code> associated with this session
+     */
+    SessionItemStateManager getSessionItemStateManager() {
+        return itemStateManager;
+    }
+
+    NodeTypeManagerImpl getNodeTypeManager() {
+        return ntManager;
+    }
+
+    public ItemDefinitionManager getItemDefinitionManager() {
+        return ntManager;
+    }
+
+    //--------------------------------------------------------------------------
+    SessionImpl switchWorkspace(String workspaceName) throws AccessDeniedException,
+        NoSuchWorkspaceException, RepositoryException {
+        Credentials creds = null; // TODO: missing impl.
+        return (SessionImpl) repository.login(creds, workspaceName);
+    }
+
+    /**
+     * Builds an qualified path from the given absolute path.
+     *
+     * @param absPath
+     * @return
+     * @throws RepositoryException if the resulting qualified path is not absolute
+     * or if the given path cannot be resolved to a qualified path.
+     */
+    Path getQPath(String absPath) throws RepositoryException {
+        try {
+            Path p = getNamespaceResolver().getQPath(absPath);
+            if (!p.isAbsolute()) {
+                throw new RepositoryException("Not an absolute path: " + absPath);
+            }
+            return p;
+        } catch (MalformedPathException mpe) {
+            String msg = "Invalid path: " + absPath;
+            log.debug(msg);
+            throw new RepositoryException(msg, mpe);
+        }
+    }
+
+    //------------------------------------------------------< check methods >---
+    /**
+     * Performs a sanity check on this session.
+     *
+     * @throws RepositoryException if this session has been rendered invalid
+     * for some reason (e.g. if this session has been closed explicitly by logout)
+     */
+    void checkIsAlive() throws RepositoryException {
+        // check session status
+        if (!alive) {
+            throw new RepositoryException("This session has been closed.");
+        }
+    }
+
+    /**
+     * Returns true if the repository supports the given option. False otherwise.
+     *
+     * @param option Any of the option constants defined by {@link Repository}
+     * that either returns 'true' or 'false'. I.e.
+     * <ul>
+     * <li>{@link Repository#LEVEL_1_SUPPORTED}</li>
+     * <li>{@link Repository#LEVEL_2_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_TRANSACTIONS_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_VERSIONING_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_OBSERVATION_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_LOCKING_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_QUERY_SQL_SUPPORTED}</li>
+     * </ul>
+     * @return true if the repository supports the given option. False otherwise.
+     */
+    boolean isSupportedOption(String option) {
+        String desc = repository.getDescriptor(option);
+        return Boolean.valueOf(desc).booleanValue();
+    }
+
+    /**
+     * Make sure the repository supports the option indicated by the given string.
+     *
+     * @param option Any of the option constants defined by {@link Repository}
+     * that either returns 'true' or 'false'. I.e.
+     * <ul>
+     * <li>{@link Repository#LEVEL_1_SUPPORTED}</li>
+     * <li>{@link Repository#LEVEL_2_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_TRANSACTIONS_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_VERSIONING_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_OBSERVATION_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_LOCKING_SUPPORTED}</li>
+     * <li>{@link Repository#OPTION_QUERY_SQL_SUPPORTED}</li>
+     * </ul>
+     * @throws UnsupportedRepositoryOperationException
+     * @throws RepositoryException
+     * @see javax.jcr.Repository#getDescriptorKeys()
+     */
+    void checkSupportedOption(String option) throws UnsupportedRepositoryOperationException, RepositoryException {
+        if (!isSupportedOption(option)) {
+            throw new UnsupportedRepositoryOperationException(option + " is not supported by this repository.");
+        }
+    }
+
+    /**
+     * Checks if this nodes session has pending changes.
+     *
+     * @throws InvalidItemStateException if this nodes session has pending changes
+     * @throws RepositoryException
+     */
+    void checkHasPendingChanges() throws RepositoryException {
+        // check for pending changes
+        if (hasPendingChanges()) {
+            String msg = "Unable to perform operation. Session has pending changes.";
+            log.debug(msg);
+            throw new InvalidItemStateException(msg);
+        }
+    }
+
+    /**
+     * Check if the the workspace with the given name exists and is accessible
+     * for this <code>Session</code>.
+     *
+     * @param workspaceName
+     * @throws NoSuchWorkspaceException
+     * @throws RepositoryException
+     */
+    void checkAccessibleWorkspace(String workspaceName) throws NoSuchWorkspaceException, RepositoryException {
+        String[] wsps = workspace.getAccessibleWorkspaceNames();
+        boolean accessible = false;
+        for (int i = 0; i < wsps.length && !accessible; i++) {
+            accessible = wsps[i].equals(workspaceName);
+        }
+
+        if (!accessible) {
+            throw new NoSuchWorkspaceException("Unknown workspace: '" + workspaceName + "'.");
+        }
+    }
+}

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionListener.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionListener.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionListener.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,45 @@
+/*
+ * 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.jcr2spi;
+
+import javax.jcr.Session;
+
+/**
+ * The <code>SessionListener</code> interface allows an implementing
+ * object to be informed about changes on a <code>Session</code>.
+ *
+ * @see SessionImpl#addListener
+ */
+public interface SessionListener {
+
+    /**
+     * Called when a <code>Session</code> is about to be 'closed' by
+     * calling <code>{@link javax.jcr.Session#logout()}</code. At this
+     * moment the session is still valid.
+     *
+     * @param session the <code>Session</code> that is about to be 'closed'
+     */
+    void loggingOut(Session session);
+
+    /**
+     * Called when a <code>Session</code> has been 'closed' by
+     * calling <code>{@link javax.jcr.Session#logout()}</code.
+     *
+     * @param session the <code>Session</code> that has been 'closed'
+     */
+    void loggedOut(Session session);
+}

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionListener.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,464 @@
+/*
+ * 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.jcr2spi;
+
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.jcr2spi.state.UpdatableItemStateManager;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateManager;
+import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.jcr2spi.query.QueryManagerImpl;
+import org.apache.jackrabbit.jcr2spi.operation.Move;
+import org.apache.jackrabbit.jcr2spi.operation.Copy;
+import org.apache.jackrabbit.jcr2spi.operation.Clone;
+import org.apache.jackrabbit.jcr2spi.operation.Operation;
+import org.apache.jackrabbit.jcr2spi.security.AccessManager;
+import org.apache.jackrabbit.jcr2spi.lock.LockManager;
+import org.apache.jackrabbit.jcr2spi.lock.LockManagerImpl;
+import org.apache.jackrabbit.jcr2spi.lock.DefaultLockManager;
+import org.apache.jackrabbit.jcr2spi.version.VersionManager;
+import org.apache.jackrabbit.jcr2spi.version.VersionManagerImpl;
+import org.apache.jackrabbit.jcr2spi.version.DefaultVersionManager;
+import org.apache.jackrabbit.jcr2spi.name.NamespaceRegistryImpl;
+import org.apache.jackrabbit.jcr2spi.observation.ObservationManagerImpl;
+import org.apache.jackrabbit.jcr2spi.xml.WorkspaceContentHandler;
+import org.apache.jackrabbit.spi.IdFactory;
+import org.apache.jackrabbit.spi.RepositoryService;
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.name.Path;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.ItemId;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+import org.xml.sax.ContentHandler;
+
+import javax.jcr.observation.ObservationManager;
+import javax.jcr.query.QueryManager;
+import javax.jcr.lock.LockException;
+import javax.jcr.version.VersionException;
+import javax.jcr.version.Version;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.Workspace;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.Repository;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.InvalidSerializedDataException;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * <code>WorkspaceImpl</code>...
+ */
+public class WorkspaceImpl implements Workspace, ManagerProvider {
+
+    private static Logger log = LoggerFactory.getLogger(WorkspaceImpl.class);
+
+    private final String name;
+    private final SessionImpl session;
+
+    private final WorkspaceManager wspManager;
+
+    /**
+     * The hierarchy manager that reflects workspace state only
+     * (i.e. that is isolated from transient changes made through
+     * the session)
+     */
+    private HierarchyManager hierManager;
+
+    private QueryManager qManager;
+    private ObservationManager obsManager;
+    private LockManager lockManager;
+    private VersionManager versionManager;
+
+    private final ItemStateValidator validator;
+
+    public WorkspaceImpl(String name, SessionImpl session, RepositoryService service, SessionInfo sessionInfo) throws RepositoryException {
+        this.name = name;
+        this.session = session;
+
+        wspManager = this.createManager(service, sessionInfo);
+        validator = new ItemStateValidator(getNodeTypeRegistry(), this);
+    }
+
+    //----------------------------------------------------------< Workspace >---
+    /**
+     * @see javax.jcr.Workspace#getSession()
+     */
+    public Session getSession() {
+        return session;
+    }
+
+    /**
+     * @see javax.jcr.Workspace#getName()
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @see javax.jcr.Workspace#copy(String, String)
+     */
+    public void copy(String srcAbsPath, String destAbsPath) throws ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
+        session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+        session.checkIsAlive();
+
+        // do intra-workspace copy
+        Path srcPath = session.getQPath(srcAbsPath);
+        Path destPath = session.getQPath(destAbsPath);
+
+        Operation op = Copy.create(srcPath, destPath, this, validator);
+        getUpdatableItemStateManager().execute(op);
+    }
+
+    /**
+     * @see javax.jcr.Workspace#copy(String, String, String)
+     */
+    public void copy(String srcWorkspace, String srcAbsPath, String destAbsPath) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
+        session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+        session.checkIsAlive();
+
+        // check workspace name
+        if (getName().equals(srcWorkspace)) {
+            // same as current workspace, delegate to intra-workspace copy method
+            copy(srcAbsPath, destAbsPath);
+            return;
+        }
+
+        // make sure the specified workspace is visible for the current session.
+        session.checkAccessibleWorkspace(srcWorkspace);
+
+        Path srcPath = session.getQPath(srcAbsPath);
+        Path destPath = session.getQPath(destAbsPath);
+
+        // copy (i.e. pull) subtree at srcAbsPath from srcWorkspace
+        // to 'this' workspace at destAbsPath
+
+        SessionImpl srcSession = null;
+        try {
+            // create session on other workspace for current subject
+            // (may throw NoSuchWorkspaceException and AccessDeniedException)
+            // DIFF JR: srcSession = rep.createSession(session.getSubject(), srcWorkspace);
+            srcSession = session.switchWorkspace(srcWorkspace);
+            WorkspaceImpl srcWsp = (WorkspaceImpl) srcSession.getWorkspace();
+
+            // do cross-workspace copy
+            Operation op = Copy.create(srcPath, destPath, srcWsp.getName(), srcWsp, validator);
+            getUpdatableItemStateManager().execute(op);
+        } finally {
+            if (srcSession != null) {
+                // we don't need the other session anymore, logout
+                srcSession.logout();
+            }
+        }
+    }
+
+    /**
+     * @see javax.jcr.Workspace#clone(String, String, String, boolean)
+     */
+    public void clone(String srcWorkspace, String srcAbsPath, String destAbsPath, boolean removeExisting) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
+        session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+        session.checkIsAlive();
+
+        // check workspace name
+        if (getName().equals(srcWorkspace)) {
+            // same as current workspace
+            String msg = srcWorkspace + ": illegal workspace (same as current)";
+            log.debug(msg);
+            throw new RepositoryException(msg);
+        }
+
+        // make sure the specified workspace is visible for the current session.
+        session.checkAccessibleWorkspace(srcWorkspace);
+
+        Path srcPath = session.getQPath(srcAbsPath);
+        Path destPath = session.getQPath(destAbsPath);
+
+        // clone (i.e. pull) subtree at srcAbsPath from srcWorkspace
+        // to 'this' workspace at destAbsPath
+
+        SessionImpl srcSession = null;
+        try {
+            // create session on other workspace for current subject
+            // (may throw NoSuchWorkspaceException and AccessDeniedException)
+            // DIFF JR: srcSession = rep.createSession(session.getSubject(), srcWorkspace);
+            srcSession = session.switchWorkspace(srcWorkspace);
+            WorkspaceImpl srcWsp = (WorkspaceImpl) srcSession.getWorkspace();
+
+            // do clone
+            Operation op = Clone.create(srcPath, destPath, srcWsp.getName(), removeExisting, srcWsp, validator);
+            getUpdatableItemStateManager().execute(op);
+        } finally {
+            if (srcSession != null) {
+                // we don't need the other session anymore, logout
+                srcSession.logout();
+            }
+        }
+    }
+
+    /**
+     * @see javax.jcr.Workspace#move(String, String)
+     */
+    public void move(String srcAbsPath, String destAbsPath) throws ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
+        session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+        session.checkIsAlive();
+
+        Path srcPath = session.getQPath(srcAbsPath);
+        Path destPath = session.getQPath(destAbsPath);
+
+        Operation op = Move.create(srcPath, destPath, validator);
+        getUpdatableItemStateManager().execute(op);
+    }
+
+    /**
+     * @see javax.jcr.Workspace#restore(Version[], boolean)
+     */
+    public void restore(Version[] versions, boolean removeExisting) throws ItemExistsException, UnsupportedRepositoryOperationException, VersionException, LockException, InvalidItemStateException, RepositoryException {
+        session.checkSupportedOption(Repository.OPTION_VERSIONING_SUPPORTED);
+        session.checkHasPendingChanges();
+
+        NodeId[] versionIds = new NodeId[versions.length];
+        for (int i = 0; i < versions.length; i++) {
+            ItemId versionId = session.getHierarchyManager().getItemId(versions[i]);
+            if (versionId.denotesNode()) {
+                versionIds[i] = (NodeId) versionId;
+            } else {
+                throw new RepositoryException("Unexpected error: Failed to retrieve a valid ID for the given version " + versions[i].getPath());
+            }
+        }
+        getVersionManager().restore(versionIds, removeExisting);
+    }
+
+    /**
+     * @see javax.jcr.Workspace#getQueryManager()
+     */
+    public QueryManager getQueryManager() throws RepositoryException {
+        session.checkIsAlive();
+        if (qManager == null) {
+            qManager = new QueryManagerImpl(session, session.getNamespaceResolver(), session.getItemManager(), wspManager);
+        }
+        return qManager;
+    }
+
+    /**
+     * @see javax.jcr.Workspace#getNamespaceRegistry()
+     */
+    public NamespaceRegistry getNamespaceRegistry() throws RepositoryException {
+        session.checkIsAlive();
+        return wspManager.getNamespaceRegistryImpl();
+    }
+
+    /**
+     * @see javax.jcr.Workspace#getNodeTypeManager()
+     */
+    public NodeTypeManager getNodeTypeManager() throws RepositoryException {
+        session.checkIsAlive();
+        return session.getNodeTypeManager();
+    }
+
+    /**
+     * @see javax.jcr.Workspace#getObservationManager()
+     */
+    public ObservationManager getObservationManager() throws UnsupportedRepositoryOperationException, RepositoryException {
+        session.checkSupportedOption(Repository.OPTION_OBSERVATION_SUPPORTED);
+        session.checkIsAlive();
+        if (obsManager == null) {
+            obsManager = createObservationManager(getNamespaceResolver(), getNodeTypeRegistry());
+        }
+        return obsManager;
+    }
+
+    /**
+     * @see javax.jcr.Workspace#getAccessibleWorkspaceNames()
+     */
+    public String[] getAccessibleWorkspaceNames() throws RepositoryException {
+        session.checkIsAlive();
+        return wspManager.getWorkspaceNames();
+    }
+
+    /**
+     * @see javax.jcr.Workspace#getImportContentHandler(String, int)
+     */
+    public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior)
+        throws PathNotFoundException, ConstraintViolationException, VersionException,
+        LockException, RepositoryException {
+        session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+        session.checkIsAlive();
+
+        Path parentPath = session.getQPath(parentAbsPath);
+        ItemId parentId = getHierarchyManager().getItemId(parentPath);
+        if (parentId.denotesNode()) {
+            return new WorkspaceContentHandler(this, parentAbsPath, uuidBehavior);
+        } else {
+            throw new PathNotFoundException("No node at path " + parentAbsPath);
+        }
+    }
+
+    /**
+     * @see javax.jcr.Workspace#importXML(String, InputStream, int)
+     */
+    public void importXML(String parentAbsPath, InputStream in,
+                          int uuidBehavior)
+        throws IOException, PathNotFoundException, ItemExistsException,
+        ConstraintViolationException, InvalidSerializedDataException,
+        LockException, RepositoryException {
+
+        Path parentPath = session.getQPath(parentAbsPath);
+        ItemId parentId = getHierarchyManager().getItemId(parentPath);
+        if (parentId.denotesNode()) {
+            wspManager.importXml((NodeId) parentId, in, uuidBehavior);
+        } else {
+            throw new PathNotFoundException("No node at path " + parentAbsPath);
+        }
+    }
+
+    //----------------------------------------------------< ManagerProvider >---
+    /**
+     * @see ManagerProvider#getNamespaceResolver()
+     */
+    public NamespaceResolver getNamespaceResolver() {
+        return session.getNamespaceResolver();
+    }
+
+    /**
+     * @see ManagerProvider#getHierarchyManager()
+     */
+    public HierarchyManager getHierarchyManager() {
+        if (hierManager == null) {
+            hierManager = new CachingHierarchyManager(getRootNodeId(),
+                getItemStateManager(), getNamespaceResolver());
+        }
+        return hierManager;
+    }
+
+    /**
+     * @see ManagerProvider#getItemStateManager()
+     */
+    public ItemStateManager getItemStateManager() {
+        return wspManager;
+    }
+
+    /**
+     * @see ManagerProvider#getAccessManager()
+     */
+    public AccessManager getAccessManager() {
+        return wspManager;
+    }
+
+    /**
+     * @see ManagerProvider#getLockManager()
+     */
+    public LockManager getLockManager() {
+        if (lockManager == null) {
+            lockManager = createLockManager(wspManager, session.getItemManager());
+        }
+        return lockManager;
+    }
+
+    /**
+     * @see ManagerProvider#getVersionManager()
+     */
+    public VersionManager getVersionManager() {
+        if (versionManager == null) {
+            versionManager = createVersionManager(wspManager);
+        }
+        return versionManager;
+    }
+
+    //------------------------------------< implementation specific methods >---
+    IdFactory getIdFactory() {
+        return wspManager.getIdFactory();
+    }
+
+    NodeId getRootNodeId() {
+        return wspManager.getRootNodeId();
+    }
+
+    NodeTypeRegistry getNodeTypeRegistry() {
+        return wspManager.getNodeTypeRegistry();
+    }
+
+    NamespaceRegistryImpl getNamespaceRegistryImpl() {
+        return wspManager.getNamespaceRegistryImpl();
+    }
+
+    /**
+     * Returns the state manager associated with the workspace
+     * represented by <i>this</i> <code>WorkspaceImpl</code> instance.
+     *
+     * @return the state manager of this workspace
+     */
+    public UpdatableItemStateManager getUpdatableItemStateManager() {
+        return wspManager;
+    }
+    //-----------------------------------------------------< initialization >---
+    /**
+     * Create the workspace state manager. May be overridden by subclasses.
+     *
+     * @param service the RepositoryService
+     * @return state manager
+     */
+    protected WorkspaceManager createManager(RepositoryService service, SessionInfo sessionInfo) throws RepositoryException {
+        return new WorkspaceManager(service, sessionInfo);
+    }
+
+    /**
+     *
+     * @param wspManager
+     * @param itemManager
+     * @return
+     */
+    protected LockManager createLockManager(WorkspaceManager wspManager, ItemManager itemManager) {
+        if (session.isSupportedOption(Repository.OPTION_LOCKING_SUPPORTED)) {
+            LockManager lMgr = new LockManagerImpl(wspManager, itemManager);
+            session.addListener((LockManagerImpl) lMgr);
+            return lMgr;
+        } else {
+            return new DefaultLockManager();
+        }
+    }
+
+    /**
+     *
+     * @param stateMgr
+     * @return
+     */
+    protected VersionManager createVersionManager(UpdatableItemStateManager stateMgr) {
+        if (session.isSupportedOption(Repository.OPTION_VERSIONING_SUPPORTED)) {
+            return new VersionManagerImpl(stateMgr);
+        } else {
+            return new DefaultVersionManager();
+        }
+    }
+
+    /**
+     *
+     * @return
+     */
+    protected ObservationManager createObservationManager(NamespaceResolver nsResolver, NodeTypeRegistry ntRegistry) {
+        ObservationManagerImpl obsMgr = new ObservationManagerImpl(nsResolver, ntRegistry);
+        wspManager.addEventListener(obsMgr);
+        return obsMgr;
+    }
+}

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url