jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r901449 [1/2] - in /jackrabbit/sandbox/jackrabbit-spi2cmis: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/jackrabbit/ src/main/java/org/apache/jackrabbit/spi2cmis/ src/main/resources/...
Date Thu, 21 Jan 2010 00:03:48 GMT
Author: mduerig
Date: Thu Jan 21 00:03:47 2010
New Revision: 901449

URL: http://svn.apache.org/viewvc?rev=901449&view=rev
Log:
SPI implementation for CMIS

Added:
    jackrabbit/sandbox/jackrabbit-spi2cmis/
    jackrabbit/sandbox/jackrabbit-spi2cmis/README.txt   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/pom.xml   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/IdTransformer.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/NameTransformer.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Spi2cmisRepositoryServiceFactory.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/SuppressWarning.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Util.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/AbstractTestCase.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/ReadTest.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/Spi2cmisFactoryTest.java   (with props)
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/resources/
    jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/resources/log4j.xml

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/README.txt
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/README.txt?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/README.txt (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/README.txt Thu Jan 21 00:03:47 2010
@@ -0,0 +1,58 @@
+Jackrabbit SPI to CMIS -- spi2cmis
+
+Introduction
+------------
+This is an experimental implementation of a bridge from JCR to the 
+emerging Content Management Interoperability Services standard (CMIS). 
+Visit http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=cmis 
+for more information on CMIS.
+
+This implementation depends on Apache Jackrabbit SPI on the JCR side 
+and on Apache Chemistry on the CMIS side. See 
+http://jackrabbit.apache.org/jackrabbit-spi.html for more information 
+on Apache Jackrabbit SPI and  http://incubator.apache.org/chemistry/
+for more information on Apache Chemistry.  
+
+
+Features
+--------
+* Exposing meta data from a CMIS repository as JCR hierarchy.
+
+* Mapping CMIS object types to JCR node and property types.
+
+* Interoperable with Apache Chemistry's CMIS implementation, Nuxeo's 
+  CMIS demo at http://cmis.demo.nuxeo.org/nuxeo/site/cmis/repository 
+  and with Alfresco's CMIS Repository at 
+  http://cmis.alfresco.com/service/cmis.    
+
+
+Not (yet) implemented
+--------------------- 
+* Content streams: currently there is no way to access the content  
+  stream of a CMIS document. 
+ 
+* Mapping to nt:folder, nt:file: cmis:folder and cmis:document should 
+  map to nt:folder and nt:file in JCR. 
+  
+* Query support
+
+* Access control support
+
+* Multi-filing support
+
+* Support for relationships
+
+* Support for policies
+
+* Support for versioning
+
+
+Getting started 
+---------------
+You can build spi2cmis with Maven 2.2.1 and Java 5:
+
+    mvn clean install
+
+Please refer to the tests in /src/test for basic usage information
+of the spi2cmis module.  
+ 
\ No newline at end of file

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/README.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/pom.xml?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/pom.xml (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/pom.xml Thu Jan 21 00:03:47 2010
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" 
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+         
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>spi2cmis</artifactId>
+    <name>Jackrabbit SPI to CMIS</name>
+    <description>Jackrabbit SPI implementation for CMIS backends</description>
+    <version>1.0-SNAPSHOT</version>
+
+    <parent>
+        <groupId>org.apache.jackrabbit</groupId>
+        <artifactId>jackrabbit-parent</artifactId>
+        <version>2.1-SNAPSHOT</version>
+    </parent>
+    
+    <repositories>
+        <repository>
+            <id>apache-incubating</id>
+            <name>Apache Incubating Repository</name>
+            <url>http://people.apache.org/repo/m2-incubating-repository</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-spi</artifactId>
+            <version>2.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-spi-commons</artifactId>
+            <version>2.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-jcr-commons</artifactId>
+            <version>2.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-jcr2spi</artifactId>
+            <version>2.1-SNAPSHOT</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.apache.chemistry</groupId>
+            <artifactId>chemistry-api</artifactId>
+            <version>0.5-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.chemistry</groupId>
+            <artifactId>chemistry-tests</artifactId>
+            <version>0.5-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.chemistry</groupId>
+            <artifactId>chemistry-atompub-client</artifactId>
+            <version>0.5-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.14</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.jcr</groupId>
+            <artifactId>jcr</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+        	<groupId>commons-collections</groupId>
+        	<artifactId>commons-collections</artifactId>
+        	<version>3.2.1</version>
+        </dependency>
+        <dependency>
+        	<groupId>xml-apis</groupId>
+        	<artifactId>xml-apis</artifactId>
+        	<version>1.3.02</version>
+        </dependency>
+        <dependency>
+        	<groupId>stax</groupId>
+        	<artifactId>stax-api</artifactId>
+        	<version>1.0.1</version>
+        </dependency>
+
+    </dependencies>
+
+</project>

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,363 @@
+/*
+ * 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.spi2cmis;
+
+
+import static org.apache.jackrabbit.spi2cmis.SuppressWarning.unchecked;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.jcr.Credentials;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+
+import org.apache.chemistry.BaseType;
+import org.apache.chemistry.CMIS;
+import org.apache.chemistry.CMISObject;
+import org.apache.chemistry.Connection;
+import org.apache.chemistry.Folder;
+import org.apache.chemistry.ListPage;
+import org.apache.chemistry.ObjectEntry;
+import org.apache.chemistry.ObjectId;
+import org.apache.chemistry.Property;
+import org.apache.chemistry.Repository;
+import org.apache.chemistry.RepositoryCapabilities;
+import org.apache.chemistry.RepositoryInfo;
+import org.apache.chemistry.Type;
+import org.apache.commons.collections.Transformer;
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.commons.collections.iterators.SingletonIterator;
+import org.apache.commons.collections.iterators.TransformIterator;
+import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
+import org.apache.jackrabbit.commons.cnd.ParseException;
+import org.apache.jackrabbit.spi.ChildInfo;
+import org.apache.jackrabbit.spi.ItemId;
+import org.apache.jackrabbit.spi.ItemInfo;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.NodeInfo;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.spi.PropertyInfo;
+import org.apache.jackrabbit.spi.QNodeDefinition;
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.QValueFactory;
+import org.apache.jackrabbit.spi.RepositoryService;
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.commons.AbstractRepositoryService;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
+import org.apache.jackrabbit.spi.commons.nodetype.QDefinitionBuilderFactory;
+import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+/**
+ * {@link RepositoryService} implementation for CMIS.
+ * Implements a direct mapping of CMIS types to JCR types and of the CMIS content structure
+ * to a JCR content structure.
+ * <ul>
+ *   <li>todo implement: expose cmis:folder as nt:folder and cmis:document as nt:file
+ *   </li>
+ *   <li>todo implement: expose content streams
+ *   </li>
+ *   <li>todo implement: implement query support
+ *   </li>
+ *   <li>todo implement: access control
+ *   </li>
+ *   <li>todo implement: support multi-filing
+ *   </li>
+ *   <li>todo implement: support relationships
+ *   </li>
+ *   <li>todo implement: support policies
+ *   </li>
+ *   <li>todo implement: support versioning
+ *   </li>
+ * </ul>
+ */
+public class CmisRepositoryService extends AbstractRepositoryService {
+    private static final Logger log = LoggerFactory.getLogger(CmisRepositoryService.class);
+
+    /** The underlying CMIS repository */
+    private final Repository cmisRepository;
+
+    /** We maintain a CMIS connection for each JCR session */
+    private final Map<SessionInfo, Connection> cmisConnections = new HashMap<SessionInfo, Connection>();
+
+    /**
+     * Create a new instance for a underlying CMIS repository.
+     * This constructor initializes the {@link javax.jcr.Repository#getDescriptorKeys() descriptors}
+     * and registers the JCR node types by a one to one {@link TypeTransformer translation} of the
+     * CMIS types.
+     * @param cmisRepository  the underlying CMIS repository
+     * @throws RepositoryException
+     */
+    protected CmisRepositoryService(Repository cmisRepository) throws RepositoryException {
+        super();
+        this.cmisRepository = cmisRepository;
+
+        initRepositoryDescriptors(descriptors, cmisRepository.getInfo());
+
+        // Register node types and name spaces mandated by JCR
+        InputStream is = getClass().getResourceAsStream("/nodetypes.cnd");
+        Reader sr = new InputStreamReader(is);
+        CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping> cndReader;
+        try {
+            cndReader = new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(
+                sr, "(internal)", new NamespaceMapping(namespaces), new QDefinitionBuilderFactory());
+        }
+        catch (ParseException e) {
+            String msg = "Internal error while registering node types";
+            log.error(msg, e);
+            throw new RepositoryException(msg, e);
+        }
+        finally {
+            close(sr);
+        }
+
+        // Register JCR related node types
+        for (QNodeTypeDefinition ntd : cndReader.getNodeTypeDefinitions()) {
+            nodeTypeDefs.registerNodeTypes(new QNodeTypeDefinition[] { ntd }, true);
+        }
+
+        // Register JCR related name spaces
+        Map<String, String> prefix2Uri = cndReader.getNamespaceMapping().getPrefixToURIMapping();
+        for (String prefix : prefix2Uri.keySet()) {
+            namespaces.setMapping(prefix, prefix2Uri.get(prefix));
+        }
+
+        // Register node types of the CMIS repository
+        Collection<Type> cmisTypes = cmisRepository.getTypes();
+        QNodeTypeDefinition[] ntds = new QNodeTypeDefinition[cmisTypes.size()];
+        int k = 0;
+        for (Type cmisType : cmisTypes) {
+            ntds[k++] = TypeTransformer.jcrNodeTypeDef(cmisRepository, cmisType, namespaces);
+        }
+        nodeTypeDefs.registerNodeTypes(ntds, true);
+    }
+
+    private static void initRepositoryDescriptors(Map<String, QValue[]> descriptors, RepositoryInfo info)
+            throws ValueFormatException, RepositoryException {
+
+        QValueFactory qvf = QValueFactoryImpl.getInstance();
+
+        descriptors.put(CMIS.DESCRIPTION.toString(), qValue(info.getDescription(), qvf));
+        descriptors.put(CMIS.VENDOR_NAME.toString(), qValue(info.getVendorName(), qvf));
+        descriptors.put(CMIS.PRODUCT_NAME.toString(), qValue(info.getProductName(), qvf));
+        descriptors.put(CMIS.PRODUCT_VERSION.toString(), qValue(info.getProductVersion(), qvf));
+        descriptors.put(CMIS.VERSION_SUPPORTED.toString(), qValue(info.getVersionSupported(), qvf));
+
+        Document repoSpecific = info.getRepositorySpecificInformation();
+        if (repoSpecific != null) {
+            descriptors.put(CMIS.REPOSITORY_SPECIFIC_INFORMATION.toString(), qValue(repoSpecific.toString(), qvf));
+        }
+
+        RepositoryCapabilities caps = info.getCapabilities();
+        descriptors.put(CMIS.CAPABILITY_MULTIFILING.toString(), qValue(caps.hasMultifiling(), qvf));
+        descriptors.put(CMIS.CAPABILITY_UNFILING.toString(), qValue(caps.hasUnfiling() , qvf));
+        descriptors.put(CMIS.CAPABILITY_VERSION_SPECIFIC_FILING.toString(), qValue(caps.hasVersionSpecificFiling(), qvf));
+        descriptors.put(CMIS.CAPABILITY_PWC_UPDATABLE.toString(), qValue(caps.isPWCUpdatable(), qvf));
+        descriptors.put(CMIS.CAPABILITY_PWC_SEARCHABLE.toString(), qValue(caps.isPWCSearchable() , qvf));
+        descriptors.put(CMIS.CAPABILITY_ALL_VERSIONS_SEARCHABLE.toString(), qValue(caps.isAllVersionsSearchable() , qvf));
+        descriptors.put(CMIS.CAPABILITY_CAN_GET_DESCENDANTS.toString(), qValue(caps.hasGetDescendants() , qvf));
+        descriptors.put(CMIS.CAPABILITY_CAN_GET_FOLDER_TREE.toString(), qValue(caps.hasGetFolderTree(), qvf));
+        descriptors.put(CMIS.CAPABILITY_CONTENT_STREAM_UPDATABILITY.toString(), qValue(caps.isContentStreamUpdatableAnytime() , qvf));
+
+        descriptors.put(CMIS.CAPABILITY_QUERY.toString(), qValue(caps.getQueryCapability(), qvf));
+        descriptors.put(CMIS.CAPABILITY_JOIN.toString(), qValue(caps.getJoinCapability(), qvf));
+        descriptors.put(CMIS.CAPABILITY_RENDITIONS.toString(), qValue(caps.getRenditionCapability(), qvf));
+        descriptors.put(CMIS.CAPABILITY_CHANGES.toString(), qValue(caps.getChangeCapability(), qvf));
+        descriptors.put(CMIS.CAPABILITY_ACL.toString(), qValue(caps.getACLCapability(), qvf));
+    }
+
+    private static QValue[] qValue(String value, QValueFactory factory) throws RepositoryException {
+        return new QValue[] { factory.create(value, PropertyType.STRING) };
+    }
+
+    private static QValue[] qValue(boolean value, QValueFactory factory) throws RepositoryException {
+        return new QValue[] { factory.create(value) };
+    }
+
+    private static QValue[] qValue(Enum<?> value, QValueFactory factory) throws RepositoryException {
+        return qValue(value.toString(), factory);
+    }
+
+    private static void close(Reader sr) {
+        try {
+            sr.close();
+        }
+        catch (IOException e) {
+            log.warn("Error closing stream", e);
+        }
+    }
+
+    @Override
+    protected SessionInfo createSessionInfo(Credentials credentials, String workspaceName)
+            throws RepositoryException {
+
+        SessionInfo sessionInfo = super.createSessionInfo(credentials, workspaceName);
+        cmisConnections.put(sessionInfo, cmisRepository.getConnection(null));
+        return sessionInfo ;
+    }
+
+    @Override
+    public void dispose(SessionInfo sessionInfo) throws RepositoryException {
+        cmisConnections.remove(sessionInfo);
+    }
+
+    @Override
+    protected QNodeDefinition createRootNodeDefinition(SessionInfo sessionInfo) throws RepositoryException {
+        Connection conn = getCmisConnection(sessionInfo);
+        Folder root = conn.getRootFolder();
+        return TypeTransformer.jcrNodeDef(NameConstants.NT_BASE, root.getType(), namespaces);
+    }
+
+    // -----------------------------------------------------< Workspaces >---
+
+    /**
+     * Supports only a single workspace corresponding to the current CMIS repository
+     */
+    public String[] getWorkspaceNames(SessionInfo sessionInfo) throws RepositoryException {
+        return new String[] { sessionInfo.getWorkspaceName() };
+    }
+
+    //-----------------------------------------------------< Access Control >---
+
+    public boolean isGranted(SessionInfo sessionInfo, ItemId itemId, String[] actions)
+            throws RepositoryException {
+
+        // todo implement: isGranted
+        return true;
+    }
+
+    //------------------------------------------------------< Reading items >---
+
+    public NodeInfo getNodeInfo(SessionInfo sessionInfo, NodeId nodeId) throws RepositoryException {
+        Connection conn = cmisConnections.get(sessionInfo);
+        CMISObject obj = getCMISObject(conn, nodeId);
+        return ItemTransformer.jcrNode(obj, namespaces);
+    }
+
+    public Iterator<? extends ItemInfo> getItemInfos(SessionInfo sessionInfo, NodeId nodeId)
+            throws RepositoryException {
+
+        // todo implement: batch reading
+        return unchecked(new SingletonIterator(getNodeInfo(sessionInfo, nodeId)));
+    }
+
+    public Iterator<ChildInfo> getChildInfos(SessionInfo sessionInfo, NodeId parentId)
+            throws RepositoryException {
+
+        final Connection conn = cmisConnections.get(sessionInfo);
+        CMISObject parent = getCMISObject(conn, parentId);
+
+        // If parentId refers to a folder...
+        if (BaseType.FOLDER == parent.getBaseType()) {
+            // ... retrieve children and transform them into ChildInfos
+            ListPage<ObjectEntry> children = conn.getSPI().getChildren(parent, null, null, null); // todo fix: specify inclusions
+            return unchecked(new TransformIterator(children.iterator(), new Transformer() {
+                public Object transform(Object entry) {
+                    CMISObject obj = conn.getObject((ObjectId) entry);
+                    return ItemTransformer.jcrChildInfo(obj, namespaces);
+                }
+            }));
+        }
+        else {
+            return unchecked(EmptyIterator.INSTANCE);
+        }
+    }
+
+    public Iterator<PropertyId> getReferences(SessionInfo sessionInfo, NodeId nodeId, Name propertyName,
+            boolean weakReferences) throws RepositoryException {
+
+        // todo implement: getReferences
+        return unchecked(EmptyIterator.INSTANCE);
+    }
+
+    public PropertyInfo getPropertyInfo(SessionInfo sessionInfo, PropertyId propertyId)
+            throws RepositoryException {
+
+        NodeId parentId = propertyId.getParentId();
+        Connection conn = getCmisConnection(sessionInfo);
+        CMISObject parent = getCMISObject(conn, parentId);
+        Property prop = parent.getProperty(IdTransformer.cmisId(propertyId.getName(), namespaces));
+        return ItemTransformer.jcrPropertyInfo(parent, prop, namespaces);
+    }
+
+    // -----------------------------------------------------< private >---
+
+    /**
+     * Extract the CMIS connection from the session.
+     */
+    private Connection getCmisConnection(SessionInfo sessionInfo) throws RepositoryException {
+        Connection conn = cmisConnections.get(sessionInfo);
+        if (conn == null) {
+            String msg = "Invalid session: connection lookup resulted failed";
+            log.debug(msg);
+            throw new RepositoryException(msg);
+        }
+        else {
+            return conn;
+        }
+    }
+
+    /**
+     * Retrieve the CMIS object identified by the given nodeId from a CMIS connection.
+     */
+    private CMISObject getCMISObject(Connection conn, NodeId nodeId) throws RepositoryException {
+        String uuid = nodeId.getUniqueID();
+        Path path = nodeId.getPath();
+
+        assert uuid != null || path != null;
+
+        // If we have an UUID we need to traverse the remaining path down from there.
+        // Otherwise we need to traverse the path down all the way from the root.
+        CMISObject o = uuid == null
+            ? conn.getRootFolder()
+            : conn.getObject(IdTransformer.cmisId(uuid));
+
+        // If there is no path left, we are there already.
+        if (path == null || path.denotesRoot()) {
+            return o;
+        }
+
+        // Otherwise construct the full CMIS path from an absolute part and a relative part.
+        String abs = uuid == null
+            ? ""
+            : PathTransformer.cmisPath(o) + '/';
+
+        String rel = PathTransformer.cmisPath(path);
+
+        ObjectEntry entry = conn.getSPI().getObjectByPath(abs + rel, null); // todo fix: specify inclusions
+        if (entry == null) {
+            throw new PathNotFoundException();
+        }
+        return conn.getObject(entry);
+    }
+
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/IdTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/IdTransformer.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/IdTransformer.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/IdTransformer.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,104 @@
+/*
+ * 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.spi2cmis;
+
+import javax.jcr.NamespaceException;
+
+import org.apache.chemistry.ObjectId;
+import org.apache.chemistry.Property;
+import org.apache.jackrabbit.spi.IdFactory;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.spi.commons.identifier.IdFactoryImpl;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
+
+/**
+ * Utility class to transform JCR identifiers to CMIS identifiers and vice versa.
+ */
+public class IdTransformer {
+    public static final IdFactory ID_FACTORY = IdFactoryImpl.getInstance();
+
+    private IdTransformer() {
+        super();
+    }
+
+    /**
+     * Transform a JCR uuid into an CMIS {@link ObjectId}.
+     * @param uuid  JCR uuid
+     * @return  CMIS {@link ObjectId}
+     */
+    public static ObjectId cmisId(final String uuid) {
+        return new ObjectId() {
+            public String getId() {
+                return uuid;
+            }
+        };
+    }
+
+    /**
+     * Transform a JCR {@link Name} into and CMIS identifier with respect to a name space
+     * mapping.
+     * @param name  JCR {@link Name}
+     * @param namespaces  name space mapping
+     * @return  CMIS identifier
+     * @throws NamespaceException
+     */
+    public static String cmisId(Name name, NamespaceMapping namespaces) throws NamespaceException {
+        String nsURI = name.getNamespaceURI();
+        String prefix = nsURI == null
+            ? ""
+            : namespaces.getPrefix(nsURI);
+
+        return "".equals(prefix)
+            ? name.getLocalName()
+            : prefix + ":" + name.getLocalName();
+    }
+
+    /**
+     * Transform a CMIS {@link ObjectId} into a JCR {@link NodeId}.
+     * @param objectId  CMIS {@link ObjectId}
+     * @return  JCR {@link NodeId}
+     */
+    public static NodeId jcrId(ObjectId objectId) {
+        return ID_FACTORY.createNodeId(objectId.getId());
+    }
+
+    /**
+     * Transform a CMIS {@link ObjectId} into a JCR uuid.
+     * @param cmisObject  CMIS {@link ObjectId}
+     * @return  JCR uuid
+     */
+    public static String jcrUuid(ObjectId cmisObject) {
+        return cmisObject.getId();
+    }
+
+    /**
+     * Create a JCR {@link PropertyId} from a CMIS {@link ObjectId} and a CMIS {@link Property} with
+     * respect to a name space mapping.
+     * @param parentCmisId  {@link ObjectId} of the parent CMIS object
+     * @param cmisProperty  CMIS {@link Property}
+     * @param namespaces  name space mapping
+     * @return  JCR {@link PropertyId}
+     */
+    public static PropertyId jcrId(ObjectId parentCmisId, Property cmisProperty, NamespaceMapping namespaces) {
+        NodeId parentId = jcrId(parentCmisId);
+        Name propertyName = NameTransformer.jcrName(cmisProperty.getDefinition(), namespaces);
+        return ID_FACTORY.createPropertyId(parentId, propertyName);
+    }
+
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/IdTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,131 @@
+/*
+ * 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.spi2cmis;
+
+import static org.apache.jackrabbit.spi2cmis.SuppressWarning.unchecked;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.jcr.Item;
+import javax.jcr.RepositoryException;
+
+import org.apache.chemistry.CMISObject;
+import org.apache.chemistry.Property;
+import org.apache.chemistry.PropertyDefinition;
+import org.apache.chemistry.Type;
+import org.apache.commons.collections.Predicate;
+import org.apache.commons.collections.Transformer;
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.commons.collections.iterators.FilterIterator;
+import org.apache.commons.collections.iterators.TransformIterator;
+import org.apache.jackrabbit.spi.ChildInfo;
+import org.apache.jackrabbit.spi.IdFactory;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.NodeInfo;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.spi.PropertyInfo;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.commons.ChildInfoImpl;
+import org.apache.jackrabbit.spi.commons.NodeInfoImpl;
+import org.apache.jackrabbit.spi.commons.PropertyInfoImpl;
+import org.apache.jackrabbit.spi.commons.identifier.IdFactoryImpl;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
+
+/**
+ * Utility class to transform {@link CMISObject}s to JCR {@link Item}s.
+ */
+public class ItemTransformer {
+
+    private static final IdFactory ID_FACTORY = IdFactoryImpl.getInstance();
+
+    private ItemTransformer() {
+        super();
+    }
+
+    /**
+     * Transform a {@link CMISObject} into a {@link NodeInfo} with respect to a name space mapping.
+     * @param cmidObject  {@link CMISObject}
+     * @param namespaces  name space mapping
+     * @return  JCR {@link NodeInfo}
+     */
+    public static NodeInfo jcrNode(CMISObject cmidObject, final NamespaceMapping namespaces) {
+        Path path = PathTransformer.jcrPath(cmidObject, namespaces);
+        final NodeId nodeId = IdTransformer.jcrId(cmidObject);
+
+        Type type = cmidObject.getType();
+        Name primaryTypeName = NameTransformer.jcrName(type.getId(), namespaces);
+
+        // todo implement: include references
+        Iterator<PropertyId> references = unchecked(EmptyIterator.INSTANCE);
+
+        // From all properties...
+        final Map<String, Property> properties = cmidObject.getProperties();
+
+        // ... filter out the ones having null values
+        FilterIterator nonNullProperties = new FilterIterator(properties.keySet().iterator(), new Predicate() {
+            public boolean evaluate(Object id) {
+                return properties.get(id).getValue() != null;
+            }
+        });
+
+        // ... and transform them into valid JCR names
+        Iterator<PropertyId> propertyIds = unchecked(new TransformIterator(nonNullProperties, new Transformer() {
+            public Object transform(Object id) {
+                Name propertyName = NameTransformer.jcrName((String) id, namespaces);
+                return ID_FACTORY.createPropertyId(nodeId, propertyName);
+            }
+        }));
+
+        return new NodeInfoImpl(path, nodeId, 0, primaryTypeName, new Name[0], references, propertyIds, null);
+    }
+
+    /**
+     * Transform a {@link CMISObject} into a JCR {@link ChildInfo} with respect to name space mapping.
+     * @param cmisObject  {@link CMISObject}
+     * @param namespaces  name space mapping
+     * @return  JCR {@link ChildInfo}
+     */
+    public static ChildInfo jcrChildInfo(CMISObject cmisObject, NamespaceMapping namespaces) {
+        Name name = NameTransformer.jcrName(cmisObject.getName(), namespaces);
+        return new ChildInfoImpl(name, IdTransformer.jcrUuid(cmisObject), Path.INDEX_DEFAULT);
+    }
+
+    /**
+     * Transform a {@link CMISObject} and a CMIS {@link Property} into a JCR {@link PropertyInfo} with
+     * respect to a name space mapping.
+     * @param parent  parent of the <code>cmisProperty</code>
+     * @param cmisProperty  CMIS {@link Property}
+     * @param namespaces  name space mapping
+     * @return  JCR {@link PropertyInfo}
+     * @throws RepositoryException
+     */
+    public static PropertyInfo jcrPropertyInfo(CMISObject parent, Property cmisProperty,
+            NamespaceMapping namespaces) throws RepositoryException {
+
+        PropertyDefinition def = cmisProperty.getDefinition();
+        Path path = PathTransformer.jcrPath(parent, cmisProperty, namespaces);
+        PropertyId id = IdTransformer.jcrId(parent, cmisProperty, namespaces);
+        int type = TypeTransformer.jcrPropertyType(def.getType());
+        boolean isMultiValued = def.isMultiValued();
+        QValue[] values = ValueTransformer.jcrValue(cmisProperty);
+        return new PropertyInfoImpl(path, id, type, isMultiValued, values);
+    }
+
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/NameTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/NameTransformer.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/NameTransformer.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/NameTransformer.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,82 @@
+/*
+ * 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.spi2cmis;
+
+import javax.jcr.NamespaceException;
+
+import org.apache.chemistry.PropertyDefinition;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NameFactory;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
+
+/**
+ * Utility class to transform CMIS names to JCR {@link Name}s.
+ */
+public class NameTransformer {
+    private static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
+
+    private NameTransformer() {
+        super();
+    }
+
+    /**
+     * Transform a CMIS name to a JCR {@link Name} with respect to a name space mapping.
+     * @param name  CMIS name
+     * @param namespaces  name space mapping
+     * @return  JCR {@link Name}
+     */
+    public static Name jcrName(String name, NamespaceMapping namespaces) {
+        int k = name.lastIndexOf(':');
+        if (k == -1) {
+            return NAME_FACTORY.create("{}" + name);
+        }
+        else {
+            String prefix = name.substring(0, k).replace(':', '-');
+            String local = name.substring(k + 1);
+            return NAME_FACTORY.create(prefixToURI(prefix, namespaces), local);
+        }
+    }
+
+    /**
+     * Transform the name of a CMIS {@link PropertyDefinition} to a JCR {@link Name} with respect to
+     * a name space mapping.
+     * @param cmisPropertyDefinition  CMIS {@link PropertyDefinition}
+     * @param namespaces  name space mapping
+     * @return  JCR {@link Name}
+     */
+    public static Name jcrName(PropertyDefinition cmisPropertyDefinition, NamespaceMapping namespaces) {
+        return jcrName(cmisPropertyDefinition.getId(), namespaces);
+    }
+
+    // -----------------------------------------------------< private >---
+
+    private static String prefixToURI(String prefix, NamespaceMapping namespaces) {
+        try {
+            return namespaces.getURI(prefix);
+        }
+        catch (NamespaceException e) {
+            try {
+                namespaces.setMapping(prefix, prefix);
+            }
+            catch (NamespaceException ignore) {
+                assert false;
+            }
+            return prefix;
+        }
+    }
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/NameTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,133 @@
+/*
+ * 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.spi2cmis;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.chemistry.CMISObject;
+import org.apache.chemistry.Folder;
+import org.apache.chemistry.Property;
+import org.apache.chemistry.PropertyDefinition;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.PathFactory;
+import org.apache.jackrabbit.spi.Path.Element;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
+
+/**
+ * Utility class to transform CMIS paths to JCR {@link Path}s and vice versa.
+ */
+public class PathTransformer {
+    private static final PathFactory PATH_FACTORY = PathFactoryImpl.getInstance();
+
+    private PathTransformer() {
+        super();
+    }
+
+    /**
+     * Transform a JCR {@link Path} to a CMIS path.
+     * @param path  JCR {@link Path}
+     * @return  CMIS path
+     * @throws RepositoryException
+     */
+    public static String cmisPath(Path path) throws RepositoryException {
+        StringBuilder s = new StringBuilder();
+        boolean first = true;
+        for (Path.Element element : path.getNormalizedPath().getElements()) {
+            if (element.denotesRoot()) {
+                s.append('/');
+            }
+            else {
+                if (!first) {
+                    s.append('/');
+                }
+                s.append(element.getName().getLocalName());
+                first = false;
+            }
+        }
+
+        return s.toString();
+    }
+
+    /**
+     * Calculate the CMIS path of a {@link CMISObject}.
+     * @param cmisObject  {@link CMISObject}
+     * @return  the CMIS path of <code>cmisObject</code>
+     */
+    public static String cmisPath(CMISObject cmisObject) {
+        if (cmisObject instanceof Folder) {
+            return ((Folder) cmisObject).getString(Property.PATH);
+        }
+        else {
+            Folder parent = cmisObject.getParent();
+            String parentPath = parent.getString(Property.PATH);
+            return parentPath + '/' + cmisObject.getName();
+        }
+    }
+
+    /**
+     * Calculate the JCR path of a {@link CMISObject} with respect to a name space mapping.
+     * @param cmisObject  {@link CMISObject}
+     * @param namespaces  name space mapping
+     * @return  the JCR path of <code>cmisObject</code>
+     */
+    public static Path jcrPath(CMISObject cmisObject, NamespaceMapping namespaces) {
+        List<Element> elements = new ArrayList<Path.Element>();
+        String path = cmisPath(cmisObject);
+
+        elements.add(PATH_FACTORY.getRootElement());
+        int j = 1;
+        int k = path.indexOf('/', j);
+        if (k == -1) {
+            k = path.length();
+        }
+        while (j < k) {
+            String pathSegment = path.substring(j, k);
+            Name name = NameTransformer.jcrName(pathSegment, namespaces);
+            elements.add(PATH_FACTORY.createElement(name));
+            j = k + 1;
+            k = path.indexOf('/', j);
+            if (k == -1) {
+                k = path.length();
+            }
+        }
+
+        return PATH_FACTORY.create(elements.toArray(new Element[elements.size()]));
+    }
+
+    /**
+     * Calculate the JCR path of a CMIS {@link Property} with respect to a name space mapping.
+     * @param parent  parent {@link CMISObject} of <code>cmisProperty</code>
+     * @param cmisProperty  CMIS {@link Property}
+     * @param namespaces  name space mapping
+     * @return  the JCR path of <code>cmisProperty</code>
+     * @throws RepositoryException
+     */
+    public static Path jcrPath(CMISObject parent, Property cmisProperty, NamespaceMapping namespaces)
+            throws RepositoryException {
+
+        Path parentPath = jcrPath(parent, namespaces);
+        PropertyDefinition def = cmisProperty.getDefinition();
+        Name name = NameTransformer.jcrName(def, namespaces);
+        return PATH_FACTORY.create(parentPath, name, false);
+    }
+
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Spi2cmisRepositoryServiceFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Spi2cmisRepositoryServiceFactory.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Spi2cmisRepositoryServiceFactory.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Spi2cmisRepositoryServiceFactory.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,125 @@
+/*
+ * 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.spi2cmis;
+
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.chemistry.Repository;
+import org.apache.chemistry.atompub.client.APPContentManager;
+import org.apache.chemistry.atompub.client.ContentManager;
+import org.apache.jackrabbit.spi.RepositoryService;
+import org.apache.jackrabbit.spi.RepositoryServiceFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link RepositoryServiceFactory} for creating {@link CmisRepositoryService} instances.
+ * This implementation recognizes the following parameters:
+ * <ul>
+ * <li> {@link #PARAM_CMIS_REPOSITORY}: an instance of {@link Repository} representing the underlying
+ *      CMIS repository. If this parameter is present, all other parameters are ignored.</li>
+ * <li> {@link #PARAM_CMIS_REPOSITORY_URL}: the URL of the CMIS repository to connect to. <b>Note:</b>
+ *      Currently only supports Atom Pub bindings.</li>
+ * <li> {@link #PARAM_CMIS_REPOSITORY_ID}: id of the repository to connect to. If no id is specified,
+ *      the default repository is returned.</li>
+ * <li> {@link #PARAM_CMIS_USERNAME}: user name used to log into the repository.</li>
+ * <li> {@link #PARAM_CMIS_PASSWORD}: password used to log into the repository.</li>
+ * </ul>
+ */
+public class Spi2cmisRepositoryServiceFactory implements RepositoryServiceFactory {
+    private static final Logger log = LoggerFactory.getLogger(Spi2cmisRepositoryServiceFactory.class);
+
+    public static final String PARAM_CMIS_REPOSITORY = "org.apache.jackrabbit.spi2cmis.CMISRepository";
+    public static final String PARAM_CMIS_REPOSITORY_URL = "org.apache.jackrabbit.spi2cmis.CMISRepositoryUrl";
+    public static final String PARAM_CMIS_REPOSITORY_ID = "org.apache.jackrabbit.spi2cmis.CMISRepositoryId";
+    public static final String PARAM_CMIS_USERNAME = "org.apache.jackrabbit.spi2cmis.Username";
+    public static final String PARAM_CMIS_PASSWORD = "org.apache.jackrabbit.spi2cmis.Password";
+
+    public RepositoryService createRepositoryService(Map<?, ?> parameters) throws RepositoryException {
+        if (parameters == null) {
+            log.warn("Missing arguments. Cannot acquire CMIS repository");
+            return null;
+        }
+
+        Repository cmisRepo;
+        try {
+            if (parameters.containsKey(PARAM_CMIS_REPOSITORY)) {
+                Object v = parameters.get(PARAM_CMIS_REPOSITORY);
+                log.info("Using CMIS repository instance \"{}\"", v);
+                if (v instanceof Repository) {
+                    cmisRepo = (Repository) v;
+                }
+                else {
+                    log.error("Invalid value for {}", PARAM_CMIS_REPOSITORY);
+                    log.error("{} is not an instance of {}", v, Repository.class);
+                    return null;
+                }
+            }
+
+            else if (parameters.containsKey(PARAM_CMIS_REPOSITORY_URL)) {
+                String serverUrl = parameters.get(PARAM_CMIS_REPOSITORY_URL).toString();
+                log.info("Connecting to repository at {}", serverUrl);
+                ContentManager cm = new APPContentManager(serverUrl);
+
+                String username = parameters.containsKey(PARAM_CMIS_USERNAME)
+                    ? parameters.get(PARAM_CMIS_USERNAME).toString()
+                    : null;
+
+                String password = parameters.containsKey(PARAM_CMIS_PASSWORD)
+                    ? parameters.get(PARAM_CMIS_PASSWORD).toString()
+                    : null;
+
+                if (username != null && password != null) {
+                    log.debug("Login in with user {}", username);
+                    cm.login(username, password);
+                }
+
+                if (parameters.containsKey(PARAM_CMIS_REPOSITORY_ID)) {
+                    String repositoryId = parameters.get(PARAM_CMIS_REPOSITORY_ID).toString();
+                    log.info("Selecting repository \"{}\"", repositoryId);
+                    cmisRepo = cm.getRepository(repositoryId);
+                }
+                else {
+                    log.info("Selecting default repository");
+                    cmisRepo = cm.getDefaultRepository();
+                }
+            }
+
+            // todo implement: Support WS bindings
+            else {
+                return null;
+            }
+        }
+        catch (Exception e) {
+            log.error("Error acquiring CMIS repositor", e);
+            return null;
+        }
+
+        if (cmisRepo == null) {
+            log.error("Error acquiring CMIS repositor");
+            return null;
+        }
+        else {
+            log.info("Acquired CMIS repository \"{}\"", cmisRepo.getName());
+            return new CmisRepositoryService(cmisRepo);
+        }
+    }
+
+}
+

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Spi2cmisRepositoryServiceFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/SuppressWarning.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/SuppressWarning.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/SuppressWarning.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/SuppressWarning.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,36 @@
+/*
+ * 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.spi2cmis;
+
+/**
+ * Utility class which can be used instead of the <code>@SuppressWarnings("unchecked")</code>
+ * annotation to suppress unchecked warnings when dealing with legacy collection classes.
+ * The advantage over the <code>@SuppressWarnings</code> annotation is the more limited
+ * scope of the {@link #unchecked(Object)} method.
+ */
+public class SuppressWarning {
+
+    private SuppressWarning() {
+        super();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <S, T> S unchecked(T x) {
+        return (S) x;
+    }
+
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/SuppressWarning.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,215 @@
+/*
+ * 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.spi2cmis;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.version.OnParentVersionAction;
+
+import org.apache.chemistry.BaseType;
+import org.apache.chemistry.PropertyDefinition;
+import org.apache.chemistry.PropertyType;
+import org.apache.chemistry.Repository;
+import org.apache.chemistry.Type;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QNodeDefinition;
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.QValueConstraint;
+import org.apache.jackrabbit.spi.commons.QNodeDefinitionImpl;
+import org.apache.jackrabbit.spi.commons.QNodeTypeDefinitionImpl;
+import org.apache.jackrabbit.spi.commons.QPropertyDefinitionImpl;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
+
+/**
+ * Utility class to transform CMIS {@link Type}s to JCR {@link QNodeTypeDefinition}s.
+ */
+public class TypeTransformer {
+
+    private TypeTransformer() {
+        super();
+    }
+
+    /**
+     * Transform a CMIS {@link Type} to a JCR {@link QNodeTypeDefinition} with respect to a
+     * name space mapping and a CMIS {@link Repository}.
+     * @param cmisRepository  CMIS {@link Repository}
+     * @param cmisType  CMIS {@link Type}
+     * @param namespaces  name space mapping
+     * @return  JCR {@link QNodeTypeDefinition}
+     * @throws RepositoryException
+     */
+    public static QNodeTypeDefinition jcrNodeTypeDef(Repository cmisRepository, Type cmisType,
+            NamespaceMapping namespaces) throws RepositoryException {
+
+        Name name = NameTransformer.jcrName(cmisType.getId(), namespaces);
+
+        String parentId = cmisType.getParentId();
+        Name[] supertypes = parentId == null
+            ? Name.EMPTY_ARRAY
+            : new Name[] { NameTransformer.jcrName(parentId, namespaces) };
+
+        Name[] supportedMixins = Name.EMPTY_ARRAY;
+        boolean isMixin = false;
+        boolean isAbstract = false;
+        boolean isQueryable = cmisType.isQueryable();
+        boolean hasOrderableChildNodes = false;
+        Name primaryItemName = null;
+
+        Set<String> superTypeProperties = getSuperTypeProperties(cmisRepository, cmisType);
+        Collection<PropertyDefinition> cmisPropDefs = cmisType.getPropertyDefinitions();
+        List<QPropertyDefinition> dpd = new ArrayList<QPropertyDefinition>(cmisPropDefs.size());
+        for (PropertyDefinition def : cmisPropDefs) {
+            // Only include properties which are not present on a super type
+            if (!superTypeProperties.contains(def.getId())) {
+                dpd.add(jcrPropDef(name, cmisType, def, namespaces));
+            }
+        }
+
+        QPropertyDefinition[] declaredPropDefs = dpd.toArray(new QPropertyDefinition[dpd.size()]);
+
+        QNodeDefinition[] declaredNodeDefs;
+        if (BaseType.FOLDER.getId().equals(cmisType.getId())) {
+            declaredNodeDefs = new QNodeDefinition[] { createResidualNodeDef(name) };
+        }
+        else {
+            declaredNodeDefs = QNodeDefinition.EMPTY_ARRAY;
+        }
+
+        return new QNodeTypeDefinitionImpl(name, supertypes, supportedMixins, isMixin, isAbstract,
+                isQueryable, hasOrderableChildNodes, primaryItemName, declaredPropDefs, declaredNodeDefs);
+    }
+
+    /**
+     * Transform a CMIS {@link Type} to a JCR {@link QNodeDefinition} with respect to a
+     * name space mapping and a declaring node type.
+     * @param declaringNodeType  {@link Name} of the declaring node type
+     * @param cmisType  CMIS {@link Type}
+     * @param namespaces  name space mapping
+     * @return  JCR {@link QNodeDefinition}
+     */
+    public static QNodeDefinition jcrNodeDef(Name declaringNodeType, Type cmisType,
+            NamespaceMapping namespaces) {
+
+        Name name = NameTransformer.jcrName(cmisType.getId(), namespaces);
+        boolean isAutoCreated = false;
+        boolean isMandatory = false;
+        int onParentVersion = OnParentVersionAction.IGNORE;
+        boolean isProtected = false;
+        Name defaultPrimaryType = NameTransformer.jcrName(cmisType.getId(), namespaces);
+        Name[] requiredPrimaryTypes = { NameTransformer.jcrName(cmisType.getBaseType().getId(), namespaces) };
+        boolean allowsSameNameSiblings = false;
+
+        return new QNodeDefinitionImpl(name, declaringNodeType, isAutoCreated, isMandatory, onParentVersion,
+                isProtected, defaultPrimaryType, requiredPrimaryTypes, allowsSameNameSiblings);
+    }
+
+    /**
+     * Transform a CMIS {@link PropertyDefinition} to a JCR {@link QPropertyDefinition} with respect
+     * to a name space mapping and declaring node type.
+     * @param declaringNodeType  {@link Name} of the declaring node type
+     * @param declaringCmisType  CMIS {@link Type} of the declaring node
+     * @param cmisPropDef  CMIS {@link PropertyDefinition}
+     * @param namespaces  name space mapping
+     * @return  JCR {@link QPropertyDefinition}
+     * @throws RepositoryException
+     */
+    public static QPropertyDefinition jcrPropDef(Name declaringNodeType, Type declaringCmisType,
+            PropertyDefinition cmisPropDef, NamespaceMapping namespaces) throws RepositoryException {
+
+        Name name = NameTransformer.jcrName(cmisPropDef, namespaces);
+        boolean isAutoCreated = false;
+        boolean isMandatory = cmisPropDef.isRequired();
+        int onParentVersion = OnParentVersionAction.IGNORE;
+        boolean isProtected = false;
+
+        Serializable defaults = cmisPropDef.getDefaultValue();
+        QValue[] defaultValues = defaults == null
+            ? QValue.EMPTY_ARRAY
+            : ValueTransformer.jcrValue(defaults, cmisPropDef.getType());
+
+        boolean isMultiple = cmisPropDef.isMultiValued();
+        int requiredType = jcrPropertyType(cmisPropDef.getType());
+        QValueConstraint[] valueConstraints = {};
+        String[] availableQueryOperators = {}; // todo implement: availableQueryOperators
+        boolean isFullTextSearchable = declaringCmisType.isFulltextIndexed();
+        boolean isQueryOrderable = cmisPropDef.isOrderable();
+
+        return new QPropertyDefinitionImpl(name, declaringNodeType, isAutoCreated, isMandatory,
+                onParentVersion, isProtected, defaultValues, isMultiple, requiredType, valueConstraints,
+                availableQueryOperators, isFullTextSearchable, isQueryOrderable);
+    }
+
+    /**
+     * Transform a CMIS {@link PropertyType} to a JCR {@link javax.jcr.PropertyType}
+     * @param cmisPropertyType  CMIS {@link PropertyType}
+     * @return  JCR {@link javax.jcr.PropertyType}
+     */
+    public static int jcrPropertyType(org.apache.chemistry.PropertyType cmisPropertyType) {
+        return ValueTransformer.getValueTransformer(cmisPropertyType).getJcrPropertyType();
+    }
+
+    // -----------------------------------------------------<  >---
+
+    private static Set<String> getSuperTypeProperties(Repository cmisRepository, Type cmisType) {
+        Set<String> ids = new HashSet<String>();
+
+        // Add properties from base type if this is not a base type itself
+        String baseTypeId = cmisType.getBaseType().getId();
+        if (!baseTypeId.equals(cmisType.getId())) {
+            Type baseType = cmisRepository.getType(baseTypeId);
+            for (PropertyDefinition pd : baseType.getPropertyDefinitions()) {
+                ids.add(pd.getId());
+            }
+        }
+
+        // Add properties from super type hierarchy
+        String parentTypeId = cmisType.getParentId();
+        while (parentTypeId != null) {
+            Type parentType = cmisRepository.getType(parentTypeId);
+            for (PropertyDefinition pd : parentType.getPropertyDefinitions()) {
+                ids.add(pd.getId());
+            }
+
+            parentTypeId = parentType.getParentId();
+        }
+
+        return ids;
+    }
+
+    private static QNodeDefinitionImpl createResidualNodeDef(Name declaringNodeType) {
+        Name name = NameConstants.ANY_NAME;
+        boolean isAutoCreated = false;
+        boolean isMandatory = false;
+        int onParentVersion = OnParentVersionAction.IGNORE;
+        boolean isProtected = false;
+        Name defaultPrimaryType = NameConstants.NT_BASE;
+        Name[] requiredPrimaryTypes = { NameConstants.NT_BASE };
+        boolean allowsSameNameSiblings = false;
+        return new QNodeDefinitionImpl(name, declaringNodeType, isAutoCreated, isMandatory, onParentVersion,
+                isProtected, defaultPrimaryType, requiredPrimaryTypes, allowsSameNameSiblings);
+    }
+
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Util.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Util.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Util.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Util.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,30 @@
+/*
+ * 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.spi2cmis;
+
+public class Util {
+
+    private Util() {
+        super();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <S, T> S unchecked(T x) {
+        return (S) x;
+    }
+
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Util.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,387 @@
+/*
+ * 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.spi2cmis;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.apache.chemistry.Property;
+import org.apache.chemistry.PropertyDefinition;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.QValueFactory;
+import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility class to transform CMIS Values to JCR {@link QValue}s.
+ */
+public abstract class ValueTransformer {
+    private static final Logger log = LoggerFactory.getLogger(ValueTransformer.class);
+
+    /**
+     * {@link ValueTransformer} from CMIS {@link org.apache.chemistry.PropertyType#DECIMAL} to
+     * JCR {@link PropertyType#DECIMAL}.
+     */
+    public static final ValueTransformer DECIMAL_VALUE_TRANSFORMER = new DecimalValueTransformer();
+
+    /**
+     * {@link ValueTransformer} from CMIS {@link org.apache.chemistry.PropertyType#INTEGER} to
+     * JCR {@link PropertyType#LONG}.
+     */
+    public static final ValueTransformer INTEGER_VALUE_TRANSFORMER = new IntegerValueTransformer();
+
+    /**
+     * {@link ValueTransformer} from CMIS {@link org.apache.chemistry.PropertyType#BOOLEAN} to
+     * JCR {@link PropertyType#BOOLEAN}.
+     */
+    public static final ValueTransformer BOOLEAN_VALUE_TRANSFORMER = new BooleanValueTransformer();
+
+    /**
+     * {@link ValueTransformer} from CMIS {@link org.apache.chemistry.PropertyType#DATETIME} to
+     * JCR {@link PropertyType#DATE}.
+     */
+    public static final ValueTransformer DATE_TIME_VALUE_TRANSFORMER = new DateTimeValueTransformer();
+
+    /**
+     * {@link ValueTransformer} from CMIS {@link org.apache.chemistry.PropertyType#URI} to
+     * JCR {@link PropertyType#URI}.
+     */
+    public static final ValueTransformer URI_VALUE_TRANSFORMER = new UriValueTransformer();
+
+    /**
+     * {@link ValueTransformer} from CMIS {@link org.apache.chemistry.PropertyType#ID} to
+     * JCR {@link PropertyType#WEAKREFERENCE}.
+     */
+    public static final ValueTransformer ID_VALUE_TRANSFORMER = new IdValueTransformer();
+
+    /**
+     * {@link ValueTransformer} from CMIS {@link org.apache.chemistry.PropertyType#STRING} to
+     * JCR {@link PropertyType#STRING}.
+     */
+    public static final ValueTransformer STRING_VALUE_TRANSFORMER = new StringValueTransformer();
+
+    /**
+     * {@link ValueTransformer} from CMIS {@link org.apache.chemistry.PropertyType#HTML} to
+     * JCR {@link PropertyType#STRING}.
+     */
+    public static final ValueTransformer HTML_VALUE_TRANSFORMER = new HtmlValueTransformer();
+
+    private static final Map<org.apache.chemistry.PropertyType, ValueTransformer> VALUE_TRANSFORMERS =
+        new HashMap<org.apache.chemistry.PropertyType, ValueTransformer>();
+
+    static {
+        for (ValueTransformer t : Arrays.asList(
+                DECIMAL_VALUE_TRANSFORMER, INTEGER_VALUE_TRANSFORMER, BOOLEAN_VALUE_TRANSFORMER,
+                DATE_TIME_VALUE_TRANSFORMER, URI_VALUE_TRANSFORMER, ID_VALUE_TRANSFORMER,
+                STRING_VALUE_TRANSFORMER, HTML_VALUE_TRANSFORMER
+        )) {
+            VALUE_TRANSFORMERS.put(t.getCmisPropertyType(), t);
+        }
+    }
+
+    private static final QValueFactory QVALUE_FACTORY = QValueFactoryImpl.getInstance();
+
+    private ValueTransformer() {
+        super();
+    }
+
+    /**
+     * Transforms a CMIS {@link Property} to a JCR {@link QValue}.
+     * @param cmisProperty  CMIS {@link Property}
+     * @return  JCR {@link QValue}
+     * @throws RepositoryException
+     */
+    public static QValue[] jcrValue(Property cmisProperty) throws RepositoryException {
+        PropertyDefinition def = cmisProperty.getDefinition();
+        Serializable val = cmisProperty.getValue();
+        return jcrValue(val, def.getType());
+    }
+
+    /**
+     * Transforms a CMIS value to a JCR {@link QValue}.
+     * @param cmisValue  CMIS value
+     * @param cmisPropertyType  CMIS {@link org.apache.chemistry.PropertyType}
+     * @return  JCR {@link QValue}
+     * @throws RepositoryException
+     */
+    public static QValue[] jcrValue(Serializable cmisValue, org.apache.chemistry.PropertyType cmisPropertyType)
+            throws RepositoryException {
+
+        if (cmisValue.getClass().isArray()) {
+            Serializable[] values = (Serializable[]) cmisValue;
+            QValue[] qValues = new QValue[values.length];
+            int k = 0;
+            for (Serializable v : values) {
+                qValues[k++] = getValueTransformer(cmisPropertyType).getQValue(v);
+            }
+            return qValues;
+        }
+        else {
+            return new QValue[] { getValueTransformer(cmisPropertyType).getQValue(cmisValue) };
+        }
+    }
+
+    /**
+     * Provides {@link ValueTransformer}s for a given CMIS {@link org.apache.chemistry.PropertyType}.
+     * @param cmisPropertyType  CMIS {@link org.apache.chemistry.PropertyType}
+     * @return  {@link ValueTransformer}
+     */
+    public static ValueTransformer getValueTransformer(org.apache.chemistry.PropertyType cmisPropertyType) {
+        ValueTransformer valueTransformer = VALUE_TRANSFORMERS.get(cmisPropertyType);
+        if (valueTransformer == null) {
+            String msg = "Unknown property type " + cmisPropertyType;
+            log.error(msg);
+            throw new IllegalArgumentException(msg);
+        }
+        else {
+            return valueTransformer;
+        }
+    }
+
+    /**
+     * The CMIS {@link org.apache.chemistry.PropertyType} this {@link ValueTransformer} is
+     * mapping from.
+     * @return  CMIS {@link org.apache.chemistry.PropertyType}
+     */
+    public abstract org.apache.chemistry.PropertyType getCmisPropertyType();
+
+    /**
+     * The JCR {@link PropertyType} this {@link ValueTransformer} is mapping to.
+     * @return  JCR {@link PropertyType}
+     */
+    public abstract int getJcrPropertyType();
+
+    /**
+     * Transforms a CMIS value to a JCR {@link QValue}.
+     * @param cmisValue  CMIS value
+     * @return  JCR {@link QValue}
+     * @throws RepositoryException
+     */
+    public abstract QValue getQValue(Serializable cmisValue) throws RepositoryException;
+
+    // -----------------------------------------------------< private >---
+
+    private static class DecimalValueTransformer extends ValueTransformer {
+
+        @Override
+        public int getJcrPropertyType() {
+            return PropertyType.DECIMAL;
+        }
+
+        @Override
+        public QValue getQValue(Serializable cmisValue) throws RepositoryException {
+            if (cmisValue instanceof BigDecimal) {
+                return QVALUE_FACTORY.create((BigDecimal) cmisValue);
+            }
+            else {
+                String msg = "Expected BigDecimal, got " + cmisValue.getClass();
+                log.error(msg);
+                throw new RepositoryException(msg);
+            }
+        }
+
+        @Override
+        public org.apache.chemistry.PropertyType getCmisPropertyType() {
+            return org.apache.chemistry.PropertyType.DECIMAL;
+        }
+
+    }
+
+    private static class IntegerValueTransformer extends ValueTransformer {
+
+        @Override
+        public int getJcrPropertyType() {
+            return PropertyType.LONG;
+        }
+
+        @Override
+        public QValue getQValue(Serializable cmisValue) throws RepositoryException {
+            if (cmisValue instanceof Integer) {
+                return QVALUE_FACTORY.create((Integer) cmisValue);
+            }
+            else {
+                String msg = "Expected Integer, got " + cmisValue.getClass();
+                log.error(msg);
+                throw new RepositoryException(msg);
+            }
+        }
+
+        @Override
+        public org.apache.chemistry.PropertyType getCmisPropertyType() {
+            return org.apache.chemistry.PropertyType.INTEGER;
+        }
+
+    }
+
+    private static class BooleanValueTransformer extends ValueTransformer {
+
+        @Override
+        public int getJcrPropertyType() {
+            return PropertyType.BOOLEAN;
+        }
+
+        @Override
+        public QValue getQValue(Serializable cmisValue) throws RepositoryException {
+            if (cmisValue instanceof Boolean) {
+                return QVALUE_FACTORY.create((Boolean) cmisValue);
+            }
+            else {
+                String msg = "Expected Boolean, got " + cmisValue.getClass();
+                log.error(msg);
+                throw new RepositoryException(msg);
+            }
+        }
+
+        @Override
+        public org.apache.chemistry.PropertyType getCmisPropertyType() {
+            return org.apache.chemistry.PropertyType.BOOLEAN;
+        }
+
+    }
+
+    private static class DateTimeValueTransformer extends ValueTransformer {
+
+        @Override
+        public int getJcrPropertyType() {
+            return PropertyType.DATE;
+        }
+
+        @Override
+        public QValue getQValue(Serializable cmisValue) throws RepositoryException {
+            if (cmisValue instanceof Calendar) {
+                return QVALUE_FACTORY.create((Calendar) cmisValue);
+            }
+            else if (cmisValue instanceof Date){
+                Calendar c = Calendar.getInstance();
+                c.setTime((Date) cmisValue);
+                return QVALUE_FACTORY.create(c);
+            }
+            else {
+                String msg = "Expected either Calendar or Date, got " + cmisValue.getClass();
+                log.error(msg);
+                throw new RepositoryException(msg);
+            }
+        }
+
+        @Override
+        public org.apache.chemistry.PropertyType getCmisPropertyType() {
+            return org.apache.chemistry.PropertyType.DATETIME;
+        }
+
+    }
+
+    private static class UriValueTransformer extends ValueTransformer {
+
+        @Override
+        public int getJcrPropertyType() {
+            return PropertyType.URI;
+        }
+
+        @Override
+        public QValue getQValue(Serializable cmisValue) throws RepositoryException {
+            if (cmisValue instanceof URI) {
+                return QVALUE_FACTORY.create((URI) cmisValue);
+            }
+            else {
+                try {
+                    URI uri = new URI(cmisValue.toString());
+                    return QVALUE_FACTORY.create(uri);
+                }
+                catch (URISyntaxException e) {
+                    String msg = "Not an URI: " + cmisValue;
+                    log.error(msg);
+                    throw new RepositoryException(msg, e);
+                }
+            }
+        }
+
+        @Override
+        public org.apache.chemistry.PropertyType getCmisPropertyType() {
+            return org.apache.chemistry.PropertyType.URI;
+        }
+
+    }
+
+    private static class IdValueTransformer extends ValueTransformer {
+
+        @Override
+        public int getJcrPropertyType() {
+            return PropertyType.WEAKREFERENCE;
+        }
+
+        @Override
+        public QValue getQValue(Serializable cmisValue) throws RepositoryException {
+            return QVALUE_FACTORY.create(cmisValue.toString(), PropertyType.WEAKREFERENCE);
+        }
+
+        @Override
+        public org.apache.chemistry.PropertyType getCmisPropertyType() {
+            return org.apache.chemistry.PropertyType.ID;
+        }
+
+    }
+
+    private static class StringValueTransformer extends ValueTransformer {
+
+        @Override
+        public int getJcrPropertyType() {
+            return PropertyType.STRING;
+        }
+
+        @Override
+        public QValue getQValue(Serializable cmisValue) throws RepositoryException {
+            return QVALUE_FACTORY.create(cmisValue.toString(), PropertyType.STRING);
+        }
+
+        @Override
+        public org.apache.chemistry.PropertyType getCmisPropertyType() {
+            return org.apache.chemistry.PropertyType.STRING;
+        }
+
+    }
+
+    private static class HtmlValueTransformer extends ValueTransformer {
+
+        @Override
+        public int getJcrPropertyType() {
+            return PropertyType.STRING;
+        }
+
+        @Override
+        public QValue getQValue(Serializable cmisValue) throws RepositoryException {
+            return QVALUE_FACTORY.create(cmisValue.toString(), PropertyType.STRING);
+        }
+
+        @Override
+        public org.apache.chemistry.PropertyType getCmisPropertyType() {
+            return org.apache.chemistry.PropertyType.HTML;
+        }
+
+    }
+
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd Thu Jan 21 00:03:47 2010
@@ -0,0 +1,27 @@
+/*
+ * Licensed 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.
+ */
+
+<''=''>
+<rep='internal'>
+<jcr='http://www.jcp.org/jcr/1.0'>
+<xs='http://www.w3.org/2001/XMLSchema'>
+<nt='http://www.jcp.org/jcr/nt/1.0'>
+<mix='http://www.jcp.org/jcr/mix/1.0'>
+<crx='http://www.day.com/crx/1.0'>
+<sv='http://www.jcp.org/jcr/sv/1.0'>
+<xml='http://www.w3.org/XML/1998/namespace'>
+
+[nt:base]
+- jcr:primaryType (NAME) autocreated mandatory protected COMPUTE
+- jcr:mixinTypes  (NAME) autocreated mandatory protected multiple COMPUTE
\ No newline at end of file

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/AbstractTestCase.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/AbstractTestCase.java?rev=901449&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/AbstractTestCase.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/AbstractTestCase.java Thu Jan 21 00:03:47 2010
@@ -0,0 +1,84 @@
+/*
+ * 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.spi2cmis;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+
+import junit.framework.TestCase;
+
+import org.apache.chemistry.test.BasicHelper;
+import org.apache.jackrabbit.jcr2spi.Jcr2spiRepositoryFactory;
+
+public abstract class AbstractTestCase extends TestCase {
+
+    protected Repository repository;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.repository = createJcrRepository();
+    }
+
+    protected Repository createJcrRepository() throws RepositoryException {
+        try {
+            Map<String, Object> parameters = new HashMap<String, Object>();
+            parameters.put(
+                    Jcr2spiRepositoryFactory.PARAM_REPOSITORY_SERVICE_FACTORY,
+                    Spi2cmisRepositoryServiceFactory.class.getName());
+
+            simpleParameters(parameters);
+//            nuxeoParameters(parameters);
+//            alfrescoParameters(parameters);
+
+            return new Jcr2spiRepositoryFactory().getRepository(parameters);
+        }
+        catch (Exception e) {
+            throw new RepositoryException(e);
+        }
+    }
+
+    protected org.apache.chemistry.Repository createSimpleRepository() throws Exception {
+        org.apache.chemistry.Repository cmisRepo = BasicHelper.makeSimpleRepository("spi2cmis test");
+        BasicHelper.populateRepository(cmisRepo);
+        return cmisRepo;
+    }
+
+    private void simpleParameters(Map<String, Object> parameters) throws Exception {
+        parameters.put(Spi2cmisRepositoryServiceFactory.PARAM_CMIS_REPOSITORY, createSimpleRepository());
+    }
+
+    @SuppressWarnings("unused")
+    private static void nuxeoParameters(Map<String, Object> parameters) {
+        parameters.put(Spi2cmisRepositoryServiceFactory.PARAM_CMIS_REPOSITORY_URL,
+                "http://cmis.demo.nuxeo.org/nuxeo/site/cmis/repository");
+        parameters.put(Spi2cmisRepositoryServiceFactory.PARAM_CMIS_USERNAME, "Administrator");
+        parameters.put(Spi2cmisRepositoryServiceFactory.PARAM_CMIS_PASSWORD, "Administrator");
+    }
+
+    @SuppressWarnings("unused")
+    private static void alfrescoParameters(Map<String, Object> parameters) {
+        parameters.put(Spi2cmisRepositoryServiceFactory.PARAM_CMIS_REPOSITORY_URL,
+                "http://cmis.alfresco.com/service/cmis");
+        parameters.put(Spi2cmisRepositoryServiceFactory.PARAM_CMIS_USERNAME, "admin");
+        parameters.put(Spi2cmisRepositoryServiceFactory.PARAM_CMIS_PASSWORD, "admin");
+    }
+
+}

Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/AbstractTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message