You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by dp...@apache.org on 2009/04/15 12:49:35 UTC

svn commit: r765129 [3/5] - in /jackrabbit/sandbox/chemistry: ./ chemistry-api/ chemistry-api/src/ chemistry-api/src/main/ chemistry-api/src/main/java/ chemistry-api/src/main/java/org/ chemistry-api/src/main/java/org/apache/ chemistry-api/src/main/java...

Added: jackrabbit/sandbox/chemistry/chemistry-api/src/main/java/org/apache/chemistry/type/Type.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-api/src/main/java/org/apache/chemistry/type/Type.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-api/src/main/java/org/apache/chemistry/type/Type.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-api/src/main/java/org/apache/chemistry/type/Type.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.type;
+
+import java.util.Collection;
+
+import org.apache.chemistry.property.PropertyDefinition;
+
+/**
+ * A CMIS Type Definition.
+ *
+ * @author Florent Guillaume
+ */
+public interface Type {
+
+    /**
+     * The type ID.
+     * <p>
+     * This uniquely identifies this type in the repository.
+     *
+     * @return the type ID
+     */
+    String getId();
+
+    /**
+     * The query name.
+     * <p>
+     * This is used as a table name in a SQL query. It maybe in mixed case, but
+     * must uniquely identify this type within the repository
+     * case-insensitively.
+     *
+     * @return the type's query name
+     */
+    String getQueryName();
+
+    /**
+     * The display name.
+     * <p>
+     * This is used for presentation by the application.
+     *
+     * @return the type's display name
+     */
+    String getDisplayName();
+
+    /**
+     * The parent type's ID, or {@code null} if it's a base type.
+     *
+     * @return type parent type's ID, or {@code null}
+     */
+    String getParentId();
+
+    /**
+     * The base type.
+     * <p>
+     * This can be only {@link BaseType#DOCUMENT DOCUMENT},
+     * {@link BaseType#FOLDER FOLDER}, {@link BaseType#RELATIONSHIP
+     * RELATIONSHIP} or {@link BaseType#POLICY POLICY}.
+     */
+    BaseType getBaseType();
+
+    /**
+     * The base type's query name.
+     * <p>
+     * This can be only {@code Document}, {@code Folder}, {@code Relationship},
+     * or {@code Policy}.
+     *
+     * @return the base type's query name
+     */
+    String getBaseTypeQueryName();
+
+    /**
+     * The type's description.
+     * <p>
+     * This is an application's description of this type, such as the nature of
+     * content, or its intended use.
+     */
+    String getDescription();
+
+    /**
+     * Is the type creatable.
+     * <p>
+     * This indicates whether new objects of this type can be created. If a type
+     * is not creatable, the repository may contain objects of this type
+     * already, but it is not possible to create new objects of this type.
+     *
+     * @return {@code true} if the type is creatable
+     */
+    boolean isCreatable();
+
+    /**
+     * Is the type queryable.
+     * <p>
+     * This indicates whether or not this type is queryable. A non-queryable
+     * type is not visible through the relational view that is used for query,
+     * and can not appear in the {@code FROM} clause of a query statement.
+     * <p>
+     * If this type is non-queryable and its super-type is queried, whether or
+     * not objects of this type are included in the search scope is
+     * repository-specific.
+     * <p>
+     * Document and Folder types should be queryable. Relationship types are not
+     * queryable. Policy types may be queryable.
+     *
+     * @return {@code true} if the type is queryable
+     */
+    boolean isQueryable();
+
+    /**
+     * Is the type controllable.
+     * <p>
+     * This indicates whether or not objects of this type are controllable.
+     * Policy objects can only be applied to controllable objects.
+     * <p>
+     * All types may be controllable.
+     *
+     * @return {@code true} if the type is controllable.
+     */
+    boolean isControllable();
+
+    /**
+     * Is the type included in a query of a super-type.
+     * <p>
+     * This controls whether this type and its subtypes appear in a query of a
+     * super-type of this type.
+     *
+     * @return {@code true} if the type is included in a query of a super-type
+     */
+    boolean isIncludedInSuperTypeQuery();
+
+    /**
+     * Is the type fileable.
+     * <p>
+     * This indicates whether or not objects of this type are fileable. A
+     * fileable object is allowed to be a child object of a Folder.
+     * <p>
+     * Folder types are always fileable. Document types should be fileable, and
+     * are fileable if unfiling is not supported. Relationship types are not
+     * fileable. Policy types may be fileable.
+     *
+     * @return {@code true} if the type is fileable
+     */
+    boolean isFileable();
+
+    /**
+     * Is the type versionable.
+     * <p>
+     * This indicates whether or not objects of this type are versionable.
+     * <p>
+     * Only Document types may be versionable.
+     *
+     * @return {@code true} if the type is versionable
+     */
+    boolean isVersionable();
+
+    /**
+     * Is a content-stream allowed or required for this type.
+     * <p>
+     * This indicates whether a content-stream is not allowed, allowed, or
+     * required for objects of this type.
+     * <p>
+     * This is always {@link ContentStreamPresence#NOT_ALLOWED NOT_ALLOWED} for
+     * non-Document types.
+     */
+    ContentStreamPresence getContentStreamAllowed();
+
+    /**
+     * The allowed source types for this relationship type.
+     * <p>
+     * This is a list of type IDs. The source object of a relationship object of
+     * this type is constrained be of one of these listed types. If this is
+     * {@code null}, then the source object can be of any type.
+     * <p>
+     * This is {@code null} for non-Relationship types.
+     *
+     * @return a list of type IDs, or {@code null}
+     */
+    String[] getAllowedSourceTypes();
+
+    /**
+     * The allowed target types for this relationship type.
+     * <p>
+     * This is a list of type IDs. The target object of a relationship object of
+     * this type is constrained be of one of these listed types. If this is
+     * {@code null}, then the target object can be of any type.
+     * <p>
+     * This is {@code null} for non-Relationship types.
+     *
+     * @return a list of type IDs, or {@code null}
+     */
+    String[] getAllowedTargetTypes();
+
+    /**
+     * The property definitions for this type.
+     * <p>
+     * If this type was retrieved through a call specifying {@code
+     * returnPropertyDefinitions = false}, then this will return {@code null}.
+     *
+     * @return a collection of property definitions, or {@code null} when
+     *         omitted
+     */
+    Collection<PropertyDefinition> getPropertyDefinitions();
+
+    /**
+     * Gets one property definition.
+     * <p>
+     * If this type was retrieved through a call specifying {@code
+     * returnPropertyDefinitions = false}, then this will return {@code null}.
+     *
+     * @return a property definition, or {@code null} when omitted
+     */
+    PropertyDefinition getPropertyDefinition(String name);
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-api/src/main/java/org/apache/chemistry/type/Type.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-api/src/main/java/org/apache/chemistry/type/Type.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/README.txt
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/README.txt?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/README.txt (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/README.txt Wed Apr 15 10:49:31 2009
@@ -0,0 +1 @@
+This module contains the implementation of the AtomPub bindings for the Camaieu CMIS API.

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/README.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/pom.xml?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/pom.xml (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/pom.xml Wed Apr 15 10:49:31 2009
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   Copyright 2009 Nuxeo SA <http://nuxeo.com>
+
+   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>
+
+  <parent>
+    <groupId>org.apache.chemistry</groupId>
+    <artifactId>chemistry-parent</artifactId>
+    <version>0.1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>chemistry-atompub-server</artifactId>
+  <name>Chemistry AtomPub Server</name>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.apache.chemistry</groupId>
+      <artifactId>chemistry-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.chemistry</groupId>
+      <artifactId>chemistry-atompub</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.abdera</groupId>
+      <artifactId>abdera-server</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.abdera</groupId>
+      <artifactId>abdera-client</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.chemistry</groupId>
+      <artifactId>chemistry-commons</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mortbay.jetty</groupId>
+      <artifactId>jetty</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mortbay.jetty</groupId>
+      <artifactId>jetty-util</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub.server;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.abdera.protocol.server.ProviderHelper;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.TargetType;
+import org.apache.abdera.protocol.server.context.ResponseContextException;
+import org.apache.abdera.protocol.server.impl.AbstractEntityCollectionAdapter;
+import org.apache.chemistry.repository.Repository;
+
+/**
+ * Base abstract class for the CMIS collections.
+ *
+ * @author Florent Guillaume
+ */
+public abstract class CMISCollection<T> extends
+        AbstractEntityCollectionAdapter<T> {
+
+    protected final String type;
+
+    protected final String name;
+
+    protected final String id;
+
+    protected final Repository repository;
+
+    public CMISCollection(String type, String name, String id,
+            Repository repository) {
+        this.type = type;
+        this.name = name;
+        this.id = id;
+        this.repository = repository;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    /*
+     * ----- Transactional -----
+     */
+
+    @Override
+    public void start(RequestContext request) throws ResponseContextException {
+    }
+
+    @Override
+    public void end(RequestContext request, ResponseContext response) {
+    }
+
+    @Override
+    public void compensate(RequestContext request, Throwable t) {
+    }
+
+    /*
+     * ----- AbstractCollectionAdapter -----
+     */
+
+    // called by AbstractProvider.process if unknown TargetType
+    @Override
+    public ResponseContext extensionRequest(RequestContext request) {
+        return ProviderHelper.notallowed(request,
+                ProviderHelper.getDefaultMethods(request));
+    }
+
+    @Override
+    public String getHref(RequestContext request) {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("collection", name);
+        params.put("id", id); // id may be null
+        return request.absoluteUrlFor(TargetType.TYPE_COLLECTION, params);
+    }
+
+    @Override
+    public String[] getAccepts(RequestContext request) {
+        return new String[0];
+        // return new String[] { "application/atom+xml;type=entry" };
+    }
+
+    /*
+     * ----- Utilities -----
+     */
+
+    public String getRepositoryLink(RequestContext request) {
+        return request.absoluteUrlFor(TargetType.TYPE_SERVICE, null);
+    }
+
+    public String getTypeLink(String tid, RequestContext request) {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("entrytype", "type");
+        params.put("id", tid);
+        return request.absoluteUrlFor(TargetType.TYPE_ENTRY, params);
+    }
+
+    public String getChildrenLink(String fid, RequestContext request) {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("entrytype", "children");
+        params.put("id", fid);
+        return request.absoluteUrlFor(TargetType.TYPE_ENTRY, params);
+    }
+
+    public String getDescendantsLink(String fid, RequestContext request) {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("entrytype", "descendants");
+        params.put("id", fid);
+        return request.absoluteUrlFor(TargetType.TYPE_ENTRY, params);
+    }
+
+    public String getParentsLink(String fid, RequestContext request) {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("entrytype", "parents");
+        params.put("id", fid);
+        return request.absoluteUrlFor(TargetType.TYPE_ENTRY, params);
+    }
+
+    public String getObjectLink(String id, RequestContext request) {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("entrytype", "object");
+        params.put("id", id);
+        return request.absoluteUrlFor(TargetType.TYPE_ENTRY, params);
+    }
+
+    public String getMediaLink(String id, RequestContext request) {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("entrytype", "file");
+        params.put("id", id);
+        return request.absoluteUrlFor(TargetType.TYPE_ENTRY, params);
+    }
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForChildren.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForChildren.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForChildren.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForChildren.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.model.Person;
+import org.apache.abdera.model.Text;
+import org.apache.abdera.protocol.server.ProviderHelper;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.context.AbstractResponseContext;
+import org.apache.abdera.protocol.server.context.BaseResponseContext;
+import org.apache.abdera.protocol.server.context.ResponseContextException;
+import org.apache.chemistry.ObjectEntry;
+import org.apache.chemistry.ReturnVersion;
+import org.apache.chemistry.SPI;
+import org.apache.chemistry.atompub.CMIS;
+import org.apache.chemistry.atompub.ObjectElement;
+import org.apache.chemistry.property.Property;
+import org.apache.chemistry.repository.Repository;
+import org.apache.chemistry.type.BaseType;
+
+/**
+ * CMIS Collection for the children of a Folder.
+ *
+ * @author Florent Guillaume
+ */
+public class CMISCollectionForChildren extends CMISCollection<ObjectEntry> {
+
+    public CMISCollectionForChildren(String type, String id,
+            Repository repository) {
+        super(type, "children", id, repository);
+    }
+
+    /*
+     * ----- AbstractCollectionAdapter -----
+     */
+
+    @Override
+    protected Feed createFeedBase(RequestContext request) {
+        Factory factory = request.getAbdera().getFactory();
+        Feed feed = factory.newFeed();
+        feed.declareNS(CMIS.CMIS_NS, CMIS.CMIS_PREFIX);
+        feed.setId(getId(request));
+        feed.setTitle(getTitle(request));
+        feed.addAuthor(getAuthor(request));
+        feed.setUpdated(new Date()); // XXX
+
+        feed.addLink(getChildrenLink(id, request), "self");
+        feed.addLink(getObjectLink(id, request), CMIS.LINK_SOURCE);
+
+        // RFC 5005 paging
+
+        return feed;
+    }
+
+    @Override
+    public String getId(RequestContext request) {
+        return "urn:x-children:" + id;
+    }
+
+    public String getTitle(RequestContext request) {
+        return "Children";
+    }
+
+    @Override
+    public String getAuthor(RequestContext request) {
+        return "system";
+    }
+
+    // don't add a source
+    @Override
+    protected ResponseContext buildGetEntryResponse(RequestContext request,
+            Entry entry) throws ResponseContextException {
+        Document<Entry> entryDoc = entry.getDocument();
+        AbstractResponseContext rc = new BaseResponseContext<Document<Entry>>(
+                entryDoc);
+        rc.setEntityTag(ProviderHelper.calculateEntityTag(entry));
+        return rc;
+    }
+
+    /*
+     * ----- AbstractEntityCollectionAdapter -----
+     */
+    @Override
+    protected String addEntryDetails(RequestContext request, Entry entry,
+            IRI feedIri, ObjectEntry object) throws ResponseContextException {
+        Factory factory = request.getAbdera().getFactory();
+
+        entry.declareNS(CMIS.CMIS_NS, CMIS.CMIS_PREFIX);
+
+        entry.setId(getId(object));
+        entry.setTitle(getTitle(object));
+        entry.setUpdated(getUpdated(object));
+        List<Person> authors = getAuthors(object, request);
+        if (authors != null) {
+            for (Person a : authors) {
+                entry.addAuthor(a);
+            }
+        }
+        Text t = getSummary(object, request);
+        if (t != null) {
+            entry.setSummaryElement(t);
+        }
+
+        String link = getLink(object, feedIri, request);
+        entry.addLink(link, "self");
+        entry.addLink(link, "edit");
+        // alternate is mandated by Atom when there is no atom:content
+        entry.addLink(link, "alternate");
+        // CMIS links
+        entry.addLink(getRepositoryLink(request), CMIS.LINK_REPOSITORY);
+        entry.addLink(getTypeLink(object.getTypeId(), request), CMIS.LINK_TYPE);
+        if (object.getType().getBaseType() == BaseType.FOLDER) {
+            String oid = object.getId();
+            entry.addLink(getChildrenLink(oid, request), CMIS.LINK_CHILDREN);
+            entry.addLink(getDescendantsLink(oid, request),
+                    CMIS.LINK_DESCENDANTS);
+            entry.addLink(getParentsLink(oid, request), CMIS.LINK_PARENTS);
+            String pid = object.getId(Property.PARENT_ID);
+            if (pid != null) {
+                // TODO unclear in spec (parent vs parents)
+                entry.addLink(getObjectLink(pid, request), CMIS.LINK_PARENT);
+            }
+        }
+        // entry.addLink("XXX", CMIS.LINK_ALLOWABLE_ACTIONS);
+        // entry.addLink("XXX", CMIS.LINK_RELATIONSHIPS);
+
+        // ContentStreamUri needs to know the media link
+        String mediaLink = isMediaEntry(object) ? getMediaLink(object.getId(),
+                request) : null;
+        entry.addExtension(new ObjectElement(factory, object, mediaLink));
+
+        return link;
+    }
+
+    protected static String bool(boolean bool) {
+        return bool ? "true" : "false";
+    }
+
+    @Override
+    public Iterable<ObjectEntry> getEntries(RequestContext request)
+            throws ResponseContextException {
+        SPI spi = repository.getConnection(null).getSPI();
+        boolean[] hasMoreItems = new boolean[1];
+        List<ObjectEntry> children = spi.getChildren(id, null, null, false,
+                false, 0, 0, null, hasMoreItems);
+        return children;
+    }
+
+    @Override
+    public ObjectEntry postEntry(String title, IRI id, String summary,
+            Date updated, List<Person> authors, Content content,
+            RequestContext request) throws ResponseContextException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putEntry(ObjectEntry object, String title, Date updated,
+            List<Person> authors, String summary, Content content,
+            RequestContext request) throws ResponseContextException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void deleteEntry(String resourceName, RequestContext request)
+            throws ResponseContextException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<Person> getAuthors(ObjectEntry object, RequestContext request) {
+        String author = null;
+        try {
+            author = object.getString(Property.CREATED_BY);
+        } catch (Exception e) {
+            // no such property or bad type
+        }
+        if (author == null) {
+            author = "system";
+        }
+        Person person = request.getAbdera().getFactory().newAuthor();
+        person.setName(author);
+        return Collections.singletonList(person);
+    }
+
+    @Override
+    public boolean isMediaEntry(ObjectEntry object)
+            throws ResponseContextException {
+        return object.hasContentStream();
+    }
+
+    @Override
+    protected String addMediaContent(IRI feedIri, Entry entry,
+            ObjectEntry object, RequestContext request)
+            throws ResponseContextException {
+        String mediaLink = getMediaLink(object.getId(), request);
+        entry.setContent(new IRI(mediaLink), getContentType(object));
+        entry.addLink(mediaLink, "edit-media");
+        entry.addLink(mediaLink, "cmis-stream");
+        return mediaLink;
+    }
+
+    // called when this is not a media entry
+    @Override
+    public Object getContent(ObjectEntry object, RequestContext request)
+            throws ResponseContextException {
+        return null;
+    }
+
+    @Override
+    public String getContentType(ObjectEntry object) {
+        return object.getString(Property.CONTENT_STREAM_MIME_TYPE);
+    }
+
+    @Override
+    public ObjectEntry getEntry(String id, RequestContext request)
+            throws ResponseContextException {
+        SPI spi = repository.getConnection(null).getSPI();
+        return spi.getProperties(id, ReturnVersion.THIS, null, false, false);
+    }
+
+    @Override
+    public String getResourceName(RequestContext request) {
+        return request.getTarget().getParameter("objectid");
+    }
+
+    @Override
+    protected String getLink(ObjectEntry object, IRI feedIri,
+            RequestContext request) {
+        return getObjectLink(object.getId(), request);
+    }
+
+    @Override
+    public InputStream getMediaStream(ObjectEntry object)
+            throws ResponseContextException {
+        // TODO entry was fetched for mostly nothing...
+        SPI spi = repository.getConnection(null).getSPI();
+        try {
+            return spi.getContentStream(object.getId(), 0, -1);
+        } catch (IOException e) {
+            throw new ResponseContextException(500, e);
+        }
+    }
+
+    @Override
+    public String getName(ObjectEntry object) {
+        throw new UnsupportedOperationException(); // unused
+    }
+
+    @Override
+    public String getId(ObjectEntry object) {
+        return "urn:uuid:" + object.getId();
+    }
+
+    @Override
+    public String getTitle(ObjectEntry object) {
+        String title = null;
+        try {
+            title = object.getString("title"); // TODO improve
+        } catch (Exception e) {
+            // no such property or bad type
+        }
+        if (title == null) {
+            title = object.getName();
+        }
+        return title;
+    }
+
+    @Override
+    public Date getUpdated(ObjectEntry object) {
+        Date date = null;
+        try {
+            Calendar calendar = object.getDateTime(Property.LAST_MODIFICATION_DATE);
+            if (calendar != null) {
+                date = calendar.getTime();
+            }
+        } catch (Exception e) {
+            // no such property or bad type
+        }
+        if (date == null) {
+            date = new Date();
+        }
+        return date;
+    }
+
+    @Override
+    public Text getSummary(ObjectEntry object, RequestContext request) {
+        String summary = null;
+        try {
+            summary = object.getString("description"); // TODO improve
+        } catch (Exception e) {
+            // no such property or bad type
+        }
+        if (summary == null) {
+            return null;
+        }
+        Text text = request.getAbdera().getFactory().newSummary();
+        text.setValue(summary);
+        return text;
+    }
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForChildren.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForChildren.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForOther.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForOther.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForOther.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForOther.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub.server;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Person;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.context.ResponseContextException;
+import org.apache.chemistry.repository.Repository;
+
+/**
+ * CMIS Collection for the XXX.
+ *
+ * @author Florent Guillaume
+ */
+public class CMISCollectionForOther extends CMISCollection<Object> {
+
+    public CMISCollectionForOther(String type, String name, String id,
+            Repository repository) {
+        super(type, name, id, repository);
+    }
+
+    /*
+     * ----- AbstractCollectionAdapter -----
+     */
+
+    @Override
+    public String getId(RequestContext request) {
+        return "urn:id:1234collid";
+    }
+
+    @Override
+    public String getAuthor(RequestContext request)
+            throws ResponseContextException {
+        return "the coll author";
+    }
+
+    /*
+     * ----- CollectionInfo -----
+     */
+
+    public String getTitle(RequestContext request) {
+        return "the " + name;
+    }
+
+    /*
+     * ----- AbstractEntityCollectionAdapter -----
+     */
+
+    @Override
+    public Object postEntry(String title, IRI id, String summary, Date updated,
+            List<Person> authors, Content content, RequestContext request)
+            throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putEntry(Object entry, String title, Date updated,
+            List<Person> authors, String summary, Content content,
+            RequestContext request) throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void deleteEntry(String resourceName, RequestContext request)
+            throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Iterable<Object> getEntries(RequestContext request)
+            throws ResponseContextException {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Object getContent(Object entry, RequestContext request)
+            throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object getEntry(String resourceName, RequestContext request)
+            throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getId(Object entry) throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getName(Object entry) throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getTitle(Object entry) throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Date getUpdated(Object entry) throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForOther.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForOther.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForTypes.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForTypes.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForTypes.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForTypes.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub.server;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.model.Person;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.context.ResponseContextException;
+import org.apache.chemistry.atompub.CMIS;
+import org.apache.chemistry.repository.Repository;
+import org.apache.chemistry.type.Type;
+
+/**
+ * CMIS Collection for the Types.
+ *
+ * @author Florent Guillaume
+ */
+public class CMISCollectionForTypes extends CMISCollection<Type> {
+
+    public CMISCollectionForTypes(String type, Repository repository) {
+        super(type, "types", null, repository);
+    }
+
+    /*
+     * ----- AbstractCollectionAdapter -----
+     */
+
+    @Override
+    protected Feed createFeedBase(RequestContext request) {
+        Factory factory = request.getAbdera().getFactory();
+        Feed feed = factory.newFeed();
+        feed.declareNS(CMIS.CMIS_NS, CMIS.CMIS_PREFIX);
+        feed.setId(getId(request));
+        feed.setTitle(getTitle(request));
+        // feed.addLink("");
+        // feed.addLink("", "self");
+        feed.addAuthor(getAuthor(request));
+        feed.setUpdated(new Date()); // XXX fixed date
+        return feed;
+    }
+
+    @Override
+    public String getId(RequestContext request) {
+        return "urn:x-id:types";
+    }
+
+    public String getTitle(RequestContext request) {
+        return "Types";
+    }
+
+    @Override
+    public String getAuthor(RequestContext request) {
+        return "system";
+    }
+
+    /*
+     * ----- AbstractEntityCollectionAdapter -----
+     */
+
+    @Override
+    protected String addEntryDetails(RequestContext request, Entry entry,
+            IRI feedIri, Type type) throws ResponseContextException {
+        Factory factory = request.getAbdera().getFactory();
+
+        entry.setId(getId(type));
+        entry.setTitle(getTitle(type));
+        entry.setUpdated(getUpdated(type));
+        // no authors, feed has one
+        String summary = type.getDescription();
+        if (summary != null && summary.length() != 0) {
+            entry.setSummary(summary);
+        }
+
+        String link = getLink(type, feedIri, request);
+        entry.addLink(link, "self");
+        entry.addLink(link, "edit");
+        // alternate is mandated by Atom when there is no atom:content
+        entry.addLink(link, "alternate");
+        // CMIS links
+        entry.addLink(getRepositoryLink(request), CMIS.LINK_REPOSITORY);
+
+        // CMIS-specific
+        // TODO refactor this to be a proper ExtensibleElement
+        Element dt = factory.newElement(CMIS.DOCUMENT_TYPE, entry);
+        Element el;
+        // note: setText is called in a separate statement as JDK 5 has problems
+        // compiling when it's on one line (compiler generics bug)
+        el = factory.newElement(CMIS.TYPE_ID, dt);
+        el.setText(type.getId());
+        el = factory.newElement(CMIS.QUERY_NAME, dt);
+        el.setText(type.getQueryName());
+        el = factory.newElement(CMIS.DISPLAY_NAME, dt);
+        el.setText(type.getDisplayName());
+        el = factory.newElement(CMIS.BASE_TYPE, dt);
+        el.setText(type.getBaseType().toString());
+        el = factory.newElement(CMIS.BASE_TYPE_QUERY_NAME, dt);
+        el.setText(type.getBaseTypeQueryName());
+        el = factory.newElement(CMIS.PARENT_ID, dt);
+        el.setText(type.getParentId());
+        el = factory.newElement(CMIS.DESCRIPTION, dt);
+        el.setText(type.getDescription());
+        el = factory.newElement(CMIS.CREATABLE, dt);
+        el.setText(bool(type.isCreatable()));
+        el = factory.newElement(CMIS.FILEABLE, dt);
+        el.setText(bool(type.isFileable()));
+        el = factory.newElement(CMIS.QUERYABLE, dt);
+        el.setText(bool(type.isQueryable()));
+        el = factory.newElement(CMIS.CONTROLLABLE, dt);
+        el.setText(bool(type.isControllable()));
+        el = factory.newElement(CMIS.VERSIONABLE, dt);
+        el.setText(bool(type.isVersionable()));
+
+        return link;
+    }
+
+    protected static String bool(boolean bool) {
+        return bool ? "true" : "false";
+    }
+
+    @Override
+    public Iterable<Type> getEntries(RequestContext request)
+            throws ResponseContextException {
+        return repository.getTypes(null, true);
+    }
+
+    @Override
+    public Type postEntry(String title, IRI id, String summary, Date updated,
+            List<Person> authors, Content content, RequestContext request)
+            throws ResponseContextException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putEntry(Type type, String title, Date updated,
+            List<Person> authors, String summary, Content content,
+            RequestContext request) throws ResponseContextException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void deleteEntry(String resourceName, RequestContext request)
+            throws ResponseContextException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object getContent(Type type, RequestContext request)
+            throws ResponseContextException {
+        return null;
+    }
+
+    @Override
+    public Type getEntry(String resourceName, RequestContext request)
+            throws ResponseContextException {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected String getLink(Type type, IRI feedIri, RequestContext request) {
+        return getTypeLink(type.getId(), request);
+    }
+
+    @Override
+    public String getName(Type type) {
+        throw new UnsupportedOperationException(); // unused
+    }
+
+    @Override
+    public String getId(Type type) {
+        return "urn:x-tid:" + type.getId();
+    }
+
+    @Override
+    public String getTitle(Type type) {
+        return type.getDisplayName();
+    }
+
+    @Override
+    public Date getUpdated(Type type) {
+        // XXX TODO mandatory field
+        return new Date();
+    }
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForTypes.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollectionForTypes.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISProvider.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISProvider.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISProvider.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub.server;
+
+import org.apache.abdera.protocol.Resolver;
+import org.apache.abdera.protocol.server.CollectionInfo;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.Target;
+import org.apache.abdera.protocol.server.TargetBuilder;
+import org.apache.abdera.protocol.server.TargetType;
+import org.apache.abdera.protocol.server.WorkspaceManager;
+import org.apache.abdera.protocol.server.impl.AbstractProvider;
+import org.apache.abdera.protocol.server.impl.AbstractWorkspaceManager;
+import org.apache.abdera.protocol.server.impl.RegexTargetResolver;
+import org.apache.abdera.protocol.server.impl.SimpleWorkspaceInfo;
+import org.apache.abdera.protocol.server.impl.TemplateTargetBuilder;
+import org.apache.abdera.util.Constants;
+import org.apache.chemistry.atompub.CMIS;
+import org.apache.chemistry.repository.Repository;
+
+/**
+ * Abdera provider for the CMIS bindings used by Chemistry.
+ *
+ * @author Florent Guillaume
+ */
+public class CMISProvider extends AbstractProvider {
+
+    protected final Repository repository;
+
+    protected final AbstractWorkspaceManager workspaceManager;
+
+    protected final TemplateTargetBuilder targetBuilder;
+
+    protected final RegexTargetResolver targetResolver;
+
+    public CMISProvider(Repository repository) {
+        this.repository = repository;
+
+        targetBuilder = new TemplateTargetBuilder();
+        targetResolver = new RegexTargetResolver();
+
+        // service
+        targetBuilder.setTemplate(TargetType.TYPE_SERVICE,
+                "{target_base}/repository");
+        targetResolver.setPattern("/repository", TargetType.TYPE_SERVICE);
+
+        // entry
+        targetBuilder.setTemplate(TargetType.TYPE_ENTRY,
+                "{target_base}/{entrytype}/{id}");
+        targetResolver.setPattern("/object/([^/?]+)", TargetType.TYPE_ENTRY,
+                "objectid");
+        targetResolver.setPattern("/allowableactions/([^/?]+)",
+                TargetType.TYPE_ENTRY, "objectid"); // XXX entry?
+        targetResolver.setPattern("/type/([^/?]+)", TargetType.TYPE_ENTRY,
+                "typeid");
+
+        // media
+        targetBuilder.setTemplate(TargetType.TYPE_MEDIA,
+                "{target_base}/file/{objectid}");
+        targetResolver.setPattern("/file/([^/?]+)", TargetType.TYPE_MEDIA,
+                "objectid");
+
+        // collection
+        // global workpace collections
+        targetBuilder.setTemplate(TargetType.TYPE_COLLECTION,
+                "{target_base}/{collection}{-prefix|/|id}");
+        targetResolver.setPattern("/checkedout", TargetType.TYPE_COLLECTION);
+        targetResolver.setPattern("/unfiled", TargetType.TYPE_COLLECTION);
+        targetResolver.setPattern("/query", //
+                TargetType.TYPE_COLLECTION);
+        targetResolver.setPattern("/types", //
+                TargetType.TYPE_COLLECTION);
+        // per-object collections
+        targetResolver.setPattern("/parents/([^/?]+)",
+                TargetType.TYPE_COLLECTION, "objectid");
+        targetResolver.setPattern("/children/([^/?]+)",
+                TargetType.TYPE_COLLECTION, "objectid");
+        targetResolver.setPattern("/descendants/([^/?]+)",
+                TargetType.TYPE_COLLECTION, "objectid");
+        targetResolver.setPattern("/allversions/([^/?]+)",
+                TargetType.TYPE_COLLECTION, "objectid");
+        targetResolver.setPattern("/relationships/([^/?]+)",
+                TargetType.TYPE_COLLECTION, "objectid");
+        targetResolver.setPattern("/policies/([^/?]+)",
+                TargetType.TYPE_COLLECTION, "objectid");
+        // ?
+        targetResolver.setPattern("/types/([^/?]+)",
+                TargetType.TYPE_COLLECTION, "typeid");
+
+        // CMIS workspaces available
+
+        SimpleWorkspaceInfo workspaceInfo = new SimpleWorkspaceInfo();
+        workspaceInfo.setTitle(repository.getInfo().getName());
+        CollectionInfo ci;
+
+        workspaceInfo.addCollection(new CMISCollectionForChildren(
+                CMIS.COL_ROOT_CHILDREN, repository.getInfo().getRootFolderId(),
+                repository));
+
+        workspaceInfo.addCollection(new CMISCollectionForOther(
+                CMIS.COL_ROOT_DESCENDANTS, "descendants",
+                repository.getInfo().getRootFolderId(), repository));
+
+        workspaceInfo.addCollection(new CMISCollectionForOther(
+                CMIS.COL_UNFILED, "unfiled", null, repository));
+
+        workspaceInfo.addCollection(new CMISCollectionForOther(
+                CMIS.COL_CHECKED_OUT, "checkedout", null, repository));
+
+        ci = new CMISCollectionForTypes(CMIS.COL_TYPES_CHILDREN, repository);
+        workspaceInfo.addCollection(ci);
+
+        ci = new CMISCollectionForTypes(CMIS.COL_TYPES_DESCENDANTS, repository);
+        workspaceInfo.addCollection(ci);
+
+        workspaceInfo.addCollection(new CMISCollectionForOther(CMIS.COL_QUERY,
+                "query", null, repository));
+
+        workspaceManager = new CMISWorkspaceManager(this);
+        workspaceManager.addWorkspace(workspaceInfo);
+    }
+
+    public Repository getRepository() {
+        return repository;
+    }
+
+    @Override
+    protected TargetBuilder getTargetBuilder(RequestContext request) {
+        return targetBuilder;
+    }
+
+    @Override
+    protected Resolver<Target> getTargetResolver(RequestContext request) {
+        return targetResolver;
+    }
+
+    @Override
+    protected WorkspaceManager getWorkspaceManager(RequestContext request) {
+        return workspaceManager;
+    }
+
+    @Override
+    protected ResponseContext getServiceDocument(final RequestContext request) {
+        CMISServiceResponse response = new CMISServiceResponse(this, request);
+        response.setStatus(200);
+        response.setContentType(Constants.APP_MEDIA_TYPE);
+        return response;
+    }
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISProvider.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServiceResponse.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServiceResponse.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServiceResponse.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServiceResponse.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub.server;
+
+import java.io.IOException;
+
+import javax.xml.namespace.QName;
+
+import org.apache.abdera.parser.stax.StaxStreamWriter;
+import org.apache.abdera.protocol.server.CollectionInfo;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.WorkspaceInfo;
+import org.apache.abdera.protocol.server.context.StreamWriterResponseContext;
+import org.apache.abdera.writer.StreamWriter;
+import org.apache.chemistry.atompub.CMIS;
+import org.apache.chemistry.repository.QueryCapability;
+import org.apache.chemistry.repository.Repository;
+import org.apache.chemistry.repository.RepositoryCapabilities;
+import org.apache.chemistry.repository.RepositoryInfo;
+import org.w3c.dom.Document;
+
+/**
+ * AtomPub response for the CMIS service document. This adds CMIS-specific
+ * elements to the response.
+ *
+ * @author Florent Guillaume
+ */
+public class CMISServiceResponse extends StreamWriterResponseContext {
+
+    protected final CMISProvider provider;
+
+    protected final RequestContext request;
+
+    public CMISServiceResponse(CMISProvider provider, RequestContext request) {
+        super(request.getAbdera());
+        this.provider = provider;
+        this.request = request;
+    }
+
+    @Override
+    protected void writeTo(StreamWriter sw) throws IOException {
+        sw.startDocument();
+        sw.startService();
+        ((StaxStreamWriter) sw).writeNamespace(CMIS.CMIS_PREFIX, CMIS.CMIS_NS);
+        for (WorkspaceInfo wi : provider.getWorkspaceManager(request).getWorkspaces(
+                request)) {
+            sw.startWorkspace();
+            sw.writeTitle(wi.getTitle(request));
+            RepositoryInfoWriter.write(sw, provider);
+            for (CollectionInfo ci : wi.getCollections(request)) {
+                sw.startCollection(ci.getHref(request));
+                sw.writeAttribute(CMIS.COLLECTION_TYPE,
+                        ((CMISCollection<?>) ci).getType());
+                sw.writeTitle(ci.getTitle(request));
+                sw.writeAccepts(ci.getAccepts(request));
+                // no AtomPub categories
+                sw.endCollection();
+            }
+            sw.endWorkspace();
+        }
+        sw.endService();
+        sw.endDocument();
+    }
+
+    public static class RepositoryInfoWriter {
+
+        public final StreamWriter sw;
+
+        public final CMISProvider provider;
+
+        public RepositoryInfoWriter(StreamWriter sw, CMISProvider provider) {
+            this.sw = sw;
+            this.provider = provider;
+        }
+
+        public static void write(StreamWriter sw, CMISProvider provider)
+                throws IOException {
+            new RepositoryInfoWriter(sw, provider).write();
+        }
+
+        public void write() throws IOException {
+            Repository repository = provider.getRepository();
+            RepositoryInfo info = repository.getInfo();
+            RepositoryCapabilities cap = info.getCapabilities();
+
+            sw.startElement(CMIS.REPOSITORY_INFO);
+            write(CMIS.REPOSITORY_ID, repository.getId());
+            write(CMIS.REPOSITORY_NAME, repository.getName());
+            write(CMIS.REPOSITORY_RELATIONSHIP, "self");
+            write(CMIS.REPOSITORY_DESCRIPTION, info.getDescription());
+            write(CMIS.VENDOR_NAME, info.getVendorName());
+            write(CMIS.PRODUCT_NAME, info.getProductName());
+            write(CMIS.PRODUCT_VERSION, info.getProductVersion());
+            write(CMIS.ROOT_FOLDER_ID, info.getRootFolderId());
+
+            sw.startElement(CMIS.CAPABILITIES);
+            write(CMIS.CAPABILITY_MULTIFILING, cap.hasMultifiling());
+            write(CMIS.CAPABILITY_UNFILING, cap.hasUnfiling());
+            write(CMIS.CAPABILITY_VERSION_SPECIFIC_FILING,
+                    cap.hasVersionSpecificFiling());
+            write(CMIS.CAPABILITY_PWC_UPDATEABLE, cap.isPWCUpdatable());
+            write(CMIS.CAPABILITY_PWC_SEARCHABLE, cap.isPWCSearchable());
+            write(CMIS.CAPABILITY_ALL_VERSIONS_SEARCHABLE,
+                    cap.isAllVersionsSearchable());
+            QueryCapability qc = cap.getQueryCapability();
+            // CMIS 0.50 query/fulltext
+            String fts;
+            String qcs;
+            switch (qc) {
+            case NONE:
+            case METADATA_ONLY:
+                qcs = qc.toString();
+                fts = "none";
+                break;
+            case FULL_TEXT_ONLY:
+                qcs = qc.toString();
+                fts = "fulltextonly";
+                break;
+            case BOTH_COMBINED:
+                qcs = "both";
+                fts = "fulltext";
+                break;
+            case BOTH_SEPARATE:
+                qcs = "both";
+                fts = "fulltextonly";
+                break;
+            default:
+                throw new UnsupportedOperationException();
+            }
+            write(CMIS.CAPABILITY_QUERY, qcs); // CMIS 0.50
+            write(CMIS.CAPABILITY_JOIN, cap.getJoinCapability().toString());
+            write(CMIS.CAPABILITY_FULL_TEXT, fts); // CMIS 0.50
+            sw.endElement();
+
+            // String version = info.getVersionSupported();
+            String version = "0.5";
+            write(CMIS.VERSIONS_SUPPORTED, version);
+            write(CMIS.REPOSITORY_SPECIFIC_INFORMATION,
+                    info.getRepositorySpecificInformation());
+            sw.endElement();
+        }
+
+        protected void write(QName qname, String string) {
+            sw.startElement(qname);
+            sw.writeElementText(string);
+            sw.endElement();
+        }
+
+        protected void write(QName qname, boolean bool) {
+            sw.startElement(qname);
+            sw.writeElementText(bool ? "true" : "false");
+            sw.endElement();
+        }
+
+        private void write(QName qname, Document document) {
+            sw.startElement(qname);
+            // XXX TODO
+            sw.endElement();
+        }
+    }
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServiceResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServiceResponse.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServlet.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServlet.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServlet.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub.server;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.protocol.server.Provider;
+import org.apache.abdera.protocol.server.servlet.AbderaServlet;
+import org.apache.chemistry.repository.Repository;
+
+public class CMISServlet extends AbderaServlet {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Repository repository;
+
+    public CMISServlet(Repository repository) {
+        this.repository = repository;
+    }
+
+    @Override
+    protected Provider createProvider() {
+        Provider provider = new CMISProvider(repository);
+        Abdera abdera = new Abdera();
+        Map<String, String> properties = new HashMap<String, String>();
+        provider.init(abdera, properties);
+        return provider;
+    }
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISWorkspaceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISWorkspaceManager.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISWorkspaceManager.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISWorkspaceManager.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub.server;
+
+import org.apache.abdera.protocol.server.CollectionAdapter;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.impl.AbstractWorkspaceManager;
+
+/**
+ * Workspace manager that correctly finds the appropriate collection adapter by
+ * comparing paths, given that ci.getHref returns an absolute URI.
+ *
+ * @author Florent Guillaume
+ */
+public class CMISWorkspaceManager extends AbstractWorkspaceManager {
+
+    private final CMISProvider provider;
+
+    public CMISWorkspaceManager(CMISProvider provider) {
+        this.provider = provider;
+    }
+
+    public CollectionAdapter getCollectionAdapter(RequestContext request) {
+        String path = request.getTargetPath();
+        String paths = path + '/';
+        if (paths.startsWith("/types/")) {
+            return new CMISCollectionForTypes(null, provider.getRepository());
+        }
+        if (paths.startsWith("/children/")) {
+            return new CMISCollectionForChildren(null,
+                    request.getTarget().getParameter("objectid"),
+                    provider.getRepository());
+        }
+        if (paths.startsWith("/object/")) {
+            return new CMISCollectionForChildren(null, null,
+                    provider.getRepository());
+        }
+        if (paths.startsWith("/file/")) {
+            return new CMISCollectionForChildren(null, null,
+                    provider.getRepository());
+        }
+        if (paths.startsWith("/unfiled/")) {
+            return new CMISCollectionForOther(null, "unfiled", null,
+                    provider.getRepository());
+        }
+        return null;
+    }
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISWorkspaceManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISWorkspaceManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/java/org/apache/chemistry/atompub/server/TestAtomPubServer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/java/org/apache/chemistry/atompub/server/TestAtomPubServer.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/java/org/apache/chemistry/atompub/server/TestAtomPubServer.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/java/org/apache/chemistry/atompub/server/TestAtomPubServer.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub.server;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.servlet.Servlet;
+
+import junit.framework.TestCase;
+
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.Service;
+import org.apache.abdera.model.Workspace;
+import org.apache.abdera.protocol.client.AbderaClient;
+import org.apache.abdera.protocol.client.ClientResponse;
+import org.apache.chemistry.Connection;
+import org.apache.chemistry.ContentStream;
+import org.apache.chemistry.Document;
+import org.apache.chemistry.Folder;
+import org.apache.chemistry.atompub.CMIS;
+import org.apache.chemistry.impl.simple.SimpleContentStream;
+import org.apache.chemistry.impl.simple.SimplePropertyDefinition;
+import org.apache.chemistry.impl.simple.SimpleRepository;
+import org.apache.chemistry.impl.simple.SimpleType;
+import org.apache.chemistry.property.PropertyType;
+import org.apache.chemistry.property.Updatability;
+import org.apache.chemistry.repository.Repository;
+import org.apache.chemistry.type.BaseType;
+import org.apache.chemistry.type.ContentStreamPresence;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.ServletHolder;
+
+public class TestAtomPubServer extends TestCase {
+
+    private static final String TEST_FILE_CONTENT = "This is a test file.\nTesting, testing...\n";
+
+    protected static AbderaClient client = new AbderaClient();
+
+    protected static String doc3id;
+
+    public Server server;
+
+    public Repository repository;
+
+    protected static final int PORT = (int) (8500 + System.currentTimeMillis() % 100);
+
+    protected static final String SERVLET_PATH = "/cmis";
+
+    protected static final String CMIS_SERVICE = "/repository";
+
+    @Override
+    public void setUp() throws Exception {
+        repository = makeRepository();
+        startServer();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        stopServer();
+    }
+
+    public void startServer() throws Exception {
+        server = new Server(PORT);
+        Servlet servlet = new CMISServlet(repository);
+        ServletHolder servletHolder = new ServletHolder(servlet);
+        Context context = new Context(server, SERVLET_PATH, Context.SESSIONS);
+        context.addServlet(servletHolder, "/*");
+        server.start();
+    }
+
+    public void stopServer() throws Exception {
+        server.stop();
+    }
+
+    public static Repository makeRepository() throws IOException {
+        SimplePropertyDefinition p1 = new SimplePropertyDefinition("title",
+                "def:title", "Title", "", false, PropertyType.STRING, false,
+                null, false, false, "", Updatability.READ_WRITE, true, true, 0,
+                null, null, -1, null, null);
+        SimplePropertyDefinition p2 = new SimplePropertyDefinition(
+                "description", "def:description", "Description", "", false,
+                PropertyType.STRING, false, null, false, false, "",
+                Updatability.READ_WRITE, true, true, 0, null, null, -1, null,
+                null);
+        SimplePropertyDefinition p3 = new SimplePropertyDefinition("date",
+                "def:date", "Date", "", false, PropertyType.DATETIME, false,
+                null, false, false, null, Updatability.READ_WRITE, true, true,
+                0, null, null, -1, null, null);
+        SimpleType dt = new SimpleType("doc", "document", "Doc", "My Doc Type",
+                BaseType.DOCUMENT, "", true, true, true, true, true, true,
+                ContentStreamPresence.ALLOWED, null, null, Arrays.asList(p1,
+                        p2, p3));
+        SimpleType ft = new SimpleType("fold", "folder", "Fold",
+                "My Folder Type", BaseType.FOLDER, "", true, true, true, true,
+                false, false, ContentStreamPresence.NOT_ALLOWED, null, null,
+                Arrays.asList(p1, p2));
+        SimpleRepository repo = new SimpleRepository("test", Arrays.asList(dt,
+                ft));
+        Connection conn = repo.getConnection(null);
+        Folder root = conn.getRootFolder();
+
+        Folder folder1 = root.newFolder("fold");
+        folder1.setValue("title", "The folder 1 description");
+        folder1.setValue("description", "folder 1 title");
+        folder1.save();
+
+        Folder folder2 = folder1.newFolder("fold");
+        folder2.setValue("title", "The folder 2 description");
+        folder2.setValue("description", "folder 2 title");
+        folder2.save();
+
+        Document doc1 = folder1.newDocument("doc");
+        doc1.setValue("title", "doc 1 title");
+        doc1.setValue("description", "The doc 1 descr");
+        doc1.save();
+
+        Document doc2 = folder2.newDocument("doc");
+        doc2.setValue("title", "doc 2 title");
+        doc2.setValue("description", "The doc 2 descr");
+        doc2.save();
+
+        Document doc3 = folder2.newDocument("doc");
+        doc3.setValue("title", "doc 3 title");
+        doc3.setValue("description", "The doc 3 descr");
+        ContentStream cs = new SimpleContentStream(
+                TEST_FILE_CONTENT.getBytes("UTF-8"), "text/plain", "doc3.txt",
+                null);
+        doc3.setContentStream(cs);
+        doc3.save();
+        doc3id = doc3.getId();
+
+        conn.close();
+        return repo;
+    }
+
+    public void testConnect() throws Exception {
+        String base = "http://localhost:" + PORT + SERVLET_PATH;
+        ClientResponse resp;
+
+        resp = client.get(base + CMIS_SERVICE);
+        assertEquals(200, resp.getStatus());
+        Service root = (Service) resp.getDocument().getRoot();
+        Workspace workspace = root.getWorkspaces().get(0);
+        assertNotNull(root);
+        Element info = workspace.getFirstChild(CMIS.REPOSITORY_INFO);
+        assertNotNull(info);
+
+        resp = client.get(base + "/types");
+        assertEquals(200, resp.getStatus());
+        Element el = resp.getDocument().getRoot();
+        assertNotNull(el);
+
+        resp = client.get(base + "/children/"
+                + repository.getInfo().getRootFolderId());
+        assertEquals(200, resp.getStatus());
+        Element ch = resp.getDocument().getRoot();
+        assertNotNull(ch);
+
+        resp = client.get(base + "/object/" + doc3id);
+        assertEquals(200, resp.getStatus());
+        Element ob = resp.getDocument().getRoot();
+        assertNotNull(ob);
+
+        HttpMethod method = new GetMethod((base + "/file/" + doc3id));
+        int status = new HttpClient().executeMethod(method);
+        assertEquals(HttpStatus.SC_OK, status);
+        assertEquals("text/plain",
+                method.getResponseHeader("Content-Type").getValue());
+        byte[] body = method.getResponseBody();
+        assertEquals(TEST_FILE_CONTENT, new String(body, "UTF-8"));
+        method.releaseConnection();
+    }
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/java/org/apache/chemistry/atompub/server/TestAtomPubServer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/java/org/apache/chemistry/atompub/server/TestAtomPubServer.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/resources/log4j.properties?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/resources/log4j.properties (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/resources/log4j.properties Wed Apr 15 10:49:31 2009
@@ -0,0 +1,4 @@
+log4j.rootLogger=INFO, CONSOLE
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c{1}] %m%n

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub-server/src/test/resources/log4j.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/chemistry/chemistry-atompub/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub/pom.xml?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub/pom.xml (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub/pom.xml Wed Apr 15 10:49:31 2009
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   Copyright 2009 Nuxeo SA <http://nuxeo.com>
+
+   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>
+
+  <parent>
+    <groupId>org.apache.chemistry</groupId>
+    <artifactId>chemistry-parent</artifactId>
+    <version>0.1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>chemistry-atompub</artifactId>
+  <name>Chemistry AtomPub</name>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.apache.chemistry</groupId>
+      <artifactId>chemistry-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.abdera</groupId>
+      <artifactId>abdera-server</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.abdera</groupId>
+      <artifactId>abdera-client</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mortbay.jetty</groupId>
+      <artifactId>jetty</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mortbay.jetty</groupId>
+      <artifactId>jetty-util</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+</project>

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

Added: jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AllowableActionsElement.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AllowableActionsElement.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AllowableActionsElement.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AllowableActionsElement.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub;
+
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.model.ExtensibleElementWrapper;
+
+/**
+ * Abdera ElementWrapper for an AtomPub cmis:allowableActions element.
+ *
+ * @author Florent Guillaume
+ */
+public class AllowableActionsElement extends ExtensibleElementWrapper {
+
+    public AllowableActionsElement(Factory factory) {
+        super(factory, CMIS.ALLOWABLE_ACTIONS);
+    }
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AllowableActionsElement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AllowableActionsElement.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/CMIS.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/CMIS.java?rev=765129&view=auto
==============================================================================
--- jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/CMIS.java (added)
+++ jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/CMIS.java Wed Apr 15 10:49:31 2009
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2009 Nuxeo SA <http://nuxeo.com>
+ *
+ * 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.
+ *
+ * Authors:
+ *     Florent Guillaume
+ */
+package org.apache.chemistry.atompub;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Utility class providing CMIS constants and names for AtomPub.
+ *
+ * @author Florent Guillaume
+ */
+public class CMIS {
+
+    // utility class
+    private CMIS() {
+    }
+
+    public static QName CMISName(String localPart) {
+        return new QName(CMIS_NS, localPart, CMIS_PREFIX);
+    }
+
+    public static final String CMIS_NS = "http://www.cmis.org/2008/05";
+
+    public static final String CMIS_PREFIX = "cmis";
+
+    /*
+     * ----- XML Qualified Names -----
+     */
+
+    public static final QName REPOSITORY_INFO = CMISName("repositoryInfo");
+
+    public static final QName REPOSITORY_ID = CMISName("repositoryId");
+
+    public static final QName REPOSITORY_NAME = CMISName("repositoryName");
+
+    public static final QName REPOSITORY_RELATIONSHIP = CMISName("repositoryRelationship");
+
+    public static final QName REPOSITORY_DESCRIPTION = CMISName("repositoryDescription");
+
+    public static final QName VENDOR_NAME = CMISName("vendorName");
+
+    public static final QName PRODUCT_NAME = CMISName("productName");
+
+    public static final QName PRODUCT_VERSION = CMISName("productVersion");
+
+    public static final QName ROOT_FOLDER_ID = CMISName("rootFolderId");
+
+    public static final QName CAPABILITIES = CMISName("capabilities");
+
+    public static final QName CAPABILITY_MULTIFILING = CMISName("capabilityMultifiling");
+
+    public static final QName CAPABILITY_UNFILING = CMISName("capabilityUnfiling");
+
+    public static final QName CAPABILITY_VERSION_SPECIFIC_FILING = CMISName("capabilityVersionSpecificFiling");
+
+    public static final QName CAPABILITY_PWC_UPDATEABLE = CMISName("capabilityPWCUpdateable");
+
+    public static final QName CAPABILITY_PWC_SEARCHABLE = CMISName("capabilityPWCSearchable");
+
+    public static final QName CAPABILITY_ALL_VERSIONS_SEARCHABLE = CMISName("capabilityAllVersionsSearchable");
+
+    public static final QName CAPABILITY_QUERY = CMISName("capabilityQuery");
+
+    public static final QName CAPABILITY_JOIN = CMISName("capabilityJoin");
+
+    public static final QName CAPABILITY_FULL_TEXT = CMISName("capabilityFullText");
+
+    public static final QName VERSIONS_SUPPORTED = CMISName("cmisVersionsSupported");
+
+    public static final QName REPOSITORY_SPECIFIC_INFORMATION = CMISName("repositorySpecificInformation");
+
+    public static final QName COLLECTION_TYPE = CMISName("collectionType");
+
+    public static final QName DOCUMENT_TYPE = CMISName("documentType");
+
+    public static final QName TYPE_ID = CMISName("typeId");
+
+    public static final QName QUERY_NAME = CMISName("queryName");
+
+    public static final QName DISPLAY_NAME = CMISName("displayName");
+
+    public static final QName BASE_TYPE = CMISName("baseType");
+
+    public static final QName BASE_TYPE_QUERY_NAME = CMISName("baseTypeQueryName");
+
+    public static final QName PARENT_ID = CMISName("parentId");
+
+    public static final QName DESCRIPTION = CMISName("description");
+
+    public static final QName CREATABLE = CMISName("creatable");
+
+    public static final QName FILEABLE = CMISName("fileable");
+
+    public static final QName QUERYABLE = CMISName("queryable");
+
+    public static final QName CONTROLLABLE = CMISName("controllable");
+
+    public static final QName VERSIONABLE = CMISName("versionable");
+
+    public static final QName OBJECT = CMISName("object");
+
+    public static final QName PROPERTIES = CMISName("properties");
+
+    public static final QName PROPERTY_STRING = CMISName("propertyString");
+
+    public static final QName PROPERTY_DECIMAL = CMISName("propertyDecimal");
+
+    public static final QName PROPERTY_INTEGER = CMISName("propertyInteger");
+
+    public static final QName PROPERTY_BOOLEAN = CMISName("propertyBoolean");
+
+    public static final QName PROPERTY_DATETIME = CMISName("propertyDateTime");
+
+    public static final QName PROPERTY_URI = CMISName("propertyUri");
+
+    public static final QName PROPERTY_ID = CMISName("propertyId");
+
+    public static final QName PROPERTY_XML = CMISName("propertyXml");
+
+    public static final QName PROPERTY_HTML = CMISName("propertyHtml");
+
+    public static final QName NAME = CMISName("name");
+
+    public static final QName VALUE = CMISName("value");
+
+    public static final QName ALLOWABLE_ACTIONS = CMISName("allowableActions");
+
+    /*
+     * ----- CMIS Collection Types -----
+     */
+
+    public static final String COL_ROOT_CHILDREN = "root-children";
+
+    public static final String COL_ROOT_DESCENDANTS = "root-descendants";
+
+    public static final String COL_UNFILED = "unfiled";
+
+    public static final String COL_CHECKED_OUT = "checkedout";
+
+    public static final String COL_TYPES_CHILDREN = "types-children";
+
+    public static final String COL_TYPES_DESCENDANTS = "types-descendants";
+
+    public static final String COL_QUERY = "query";
+
+    /*
+     * ----- CMIS Link Types -----
+     */
+
+    public static final String LINK_REPOSITORY = "cmis-repository";
+
+    public static final String LINK_LATEST_VERSION = "cmis-latestversion";
+
+    public static final String LINK_PARENT = "cmis-parent";
+
+    public static final String LINK_SOURCE = "cmis-source";
+
+    public static final String LINK_TARGET = "cmis-target";
+
+    public static final String LINK_TYPE = "cmis-type";
+
+    public static final String LINK_ALLOWABLE_ACTIONS = "cmis-allowableactions";
+
+    public static final String LINK_STREAM = "cmis-stream";
+
+    public static final String LINK_PARENTS = "cmis-parents";
+
+    public static final String LINK_CHILDREN = "cmis-children";
+
+    public static final String LINK_DESCENDANTS = "cmis-descendants";
+
+    public static final String LINK_ALL_VERSIONS = "cmis-allversions";
+
+    public static final String LINK_RELATIONSHIPS = "cmis-relationships";
+
+    public static final String LINK_POLICIES = "cmis-policies";
+
+}

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/CMIS.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/CMIS.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url