You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by dc...@apache.org on 2010/02/16 17:04:07 UTC

svn commit: r910572 [7/36] - in /incubator/chemistry/trunk/opencmis: ./ _dev/ opencmis-client/ opencmis-client/opencmis-client-api/ opencmis-client/opencmis-client-api/src/ opencmis-client/opencmis-client-api/src/main/ opencmis-client/opencmis-client-a...

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/CmisAtomPubSpi.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/DiscoveryServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/DiscoveryServiceImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/DiscoveryServiceImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/DiscoveryServiceImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,201 @@
+/*
+ * 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.opencmis.client.provider.spi.atompub;
+
+import static org.apache.opencmis.commons.impl.Converter.convert;
+
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomElement;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomEntry;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomFeed;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomLink;
+import org.apache.opencmis.commons.api.ExtensionsData;
+import org.apache.opencmis.commons.enums.IncludeRelationships;
+import org.apache.opencmis.commons.exceptions.CmisObjectNotFoundException;
+import org.apache.opencmis.commons.impl.Constants;
+import org.apache.opencmis.commons.impl.JaxBHelper;
+import org.apache.opencmis.commons.impl.UrlBuilder;
+import org.apache.opencmis.commons.impl.dataobjects.ObjectListImpl;
+import org.apache.opencmis.commons.impl.jaxb.CmisObjectType;
+import org.apache.opencmis.commons.impl.jaxb.CmisQueryType;
+import org.apache.opencmis.commons.impl.jaxb.EnumIncludeRelationships;
+import org.apache.opencmis.commons.provider.DiscoveryService;
+import org.apache.opencmis.commons.provider.Holder;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.commons.provider.ObjectList;
+
+/**
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class DiscoveryServiceImpl extends AbstractAtomPubService implements DiscoveryService {
+
+  /**
+   * Constructor.
+   */
+  public DiscoveryServiceImpl(Session session) {
+    setSession(session);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.DiscoveryService#getContentChanges(java.lang.String,
+   * org.apache.opencmis.client.provider.Holder, java.lang.Boolean, java.lang.String, java.lang.Boolean,
+   * java.lang.Boolean, java.math.BigInteger, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public ObjectList getContentChanges(String repositoryId, Holder<String> changeLogToken,
+      Boolean includeProperties, String filter, Boolean includePolicyIds, Boolean includeACL,
+      BigInteger maxItems, ExtensionsData extension) {
+    ObjectListImpl result = new ObjectListImpl();
+
+    // find the link
+    String link = loadRepositoryLink(repositoryId, Constants.REP_REL_CHANGES);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or content changes not supported!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_CHANGE_LOG_TOKEN, (changeLogToken == null ? null
+        : changeLogToken.getValue()));
+    url.addParameter(Constants.PARAM_PROPERTIES, includeProperties);
+    url.addParameter(Constants.PARAM_FILTER, filter);
+    url.addParameter(Constants.PARAM_POLICY_IDS, includePolicyIds);
+    url.addParameter(Constants.PARAM_ACL, includeACL);
+    url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+    AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
+
+    // handle top level
+    for (AtomElement element : feed.getElements()) {
+      if (element.getObject() instanceof AtomLink) {
+        if (isNextLink(element)) {
+          result.setHasMoreItems(Boolean.TRUE);
+        }
+      }
+      else if (isInt(NAME_NUM_ITEMS, element)) {
+        result.setNumItems((BigInteger) element.getObject());
+      }
+    }
+
+    // get the changes
+    if (!feed.getEntries().isEmpty()) {
+      result.setObjects(new ArrayList<ObjectData>(feed.getEntries().size()));
+
+      for (AtomEntry entry : feed.getEntries()) {
+        ObjectData hit = null;
+
+        // walk through the entry
+        for (AtomElement element : entry.getElements()) {
+          if (element.getObject() instanceof CmisObjectType) {
+            hit = convert((CmisObjectType) element.getObject());
+          }
+        }
+
+        if (hit != null) {
+          result.getObjects().add(hit);
+        }
+      }
+    }
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.DiscoveryService#query(java.lang.String, java.lang.String,
+   * java.lang.Boolean, java.lang.Boolean, org.apache.opencmis.commons.enums.IncludeRelationships,
+   * java.lang.String, java.math.BigInteger, java.math.BigInteger,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public ObjectList query(String repositoryId, String statement, Boolean searchAllVersions,
+      Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+      String renditionFilter, BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
+    ObjectListImpl result = new ObjectListImpl();
+
+    // find the link
+    String link = loadCollection(repositoryId, Constants.COLLECTION_QUERY);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or query not supported!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+
+    // compile query request
+    final CmisQueryType query = new CmisQueryType();
+    query.setStatement(statement);
+    query.setSearchAllVersions(searchAllVersions);
+    query.setIncludeAllowableActions(includeAllowableActions);
+    query.setIncludeRelationships(convert(EnumIncludeRelationships.class, includeRelationships));
+    query.setRenditionFilter(renditionFilter);
+    query.setMaxItems(maxItems);
+    query.setSkipCount(skipCount);
+
+    // post the query and parse results
+    HttpUtils.Response resp = post(url, Constants.MEDIATYPE_QUERY, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        JaxBHelper.marshal(JaxBHelper.CMIS_OBJECT_FACTORY.createQuery(query), out, false);
+      }
+    });
+    AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
+
+    // handle top level
+    for (AtomElement element : feed.getElements()) {
+      if (element.getObject() instanceof AtomLink) {
+        if (isNextLink(element)) {
+          result.setHasMoreItems(Boolean.TRUE);
+        }
+      }
+      else if (isInt(NAME_NUM_ITEMS, element)) {
+        result.setNumItems((BigInteger) element.getObject());
+      }
+    }
+
+    // get the result set
+    if (!feed.getEntries().isEmpty()) {
+      result.setObjects(new ArrayList<ObjectData>(feed.getEntries().size()));
+
+      for (AtomEntry entry : feed.getEntries()) {
+        ObjectData hit = null;
+
+        // walk through the entry
+        for (AtomElement element : entry.getElements()) {
+          if (element.getObject() instanceof CmisObjectType) {
+            hit = convert((CmisObjectType) element.getObject());
+          }
+        }
+
+        if (hit != null) {
+          result.getObjects().add(hit);
+        }
+      }
+    }
+
+    return result;
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/DiscoveryServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/HttpUtils.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/HttpUtils.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/HttpUtils.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/HttpUtils.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,253 @@
+/*
+ * 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.opencmis.client.provider.spi.atompub;
+
+import java.io.BufferedOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.opencmis.client.provider.impl.CmisProviderHelper;
+import org.apache.opencmis.client.provider.spi.AbstractAuthenticationProvider;
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.commons.exceptions.CmisConnectionException;
+import org.apache.opencmis.commons.impl.UrlBuilder;
+
+/**
+ * HTTP helper methods.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class HttpUtils {
+
+  private static final Log log = LogFactory.getLog(HttpUtils.class);
+
+  private static final int BUFFER_SIZE = 4096;
+
+  private HttpUtils() {
+  }
+
+  public static Response invokeGET(UrlBuilder url, Session session) {
+    return invoke(url, "GET", null, null, session, null, null);
+  }
+
+  public static Response invokeGET(UrlBuilder url, Session session, BigInteger offset,
+      BigInteger length) {
+    return invoke(url, "GET", null, null, session, offset, length);
+  }
+
+  public static Response invokePOST(UrlBuilder url, String contentType, Output writer,
+      Session session) {
+    return invoke(url, "POST", contentType, writer, session, null, null);
+  }
+
+  public static Response invokePUT(UrlBuilder url, String contentType, Output writer,
+      Session session) {
+    return invoke(url, "PUT", contentType, writer, session, null, null);
+  }
+
+  public static Response invokeDELETE(UrlBuilder url, Session session) {
+    return invoke(url, "DELETE", null, null, session, null, null);
+  }
+
+  private static Response invoke(UrlBuilder url, String method, String contentType, Output writer,
+      Session session, BigInteger offset, BigInteger length) {
+    try {
+      // log before connect
+      if (log.isDebugEnabled()) {
+        log.debug(method + " " + url);
+      }
+
+      // connect
+      HttpURLConnection conn = (HttpURLConnection) (new URL(url.toString())).openConnection();
+      conn.setRequestMethod(method);
+      conn.setDoInput(true);
+      conn.setDoOutput(writer != null);
+
+      // set content type
+      if (contentType != null) {
+        conn.setRequestProperty("Content-Type", contentType);
+      }
+
+      // authenticate
+      AbstractAuthenticationProvider authProvider = CmisProviderHelper
+          .getAuthenticationProvider(session);
+      if (authProvider != null) {
+        Map<String, List<String>> httpHeaders = authProvider.getHTTPHeaders(url.toString());
+        if (httpHeaders != null) {
+          for (Map.Entry<String, List<String>> header : httpHeaders.entrySet()) {
+            if (header.getValue() != null) {
+              for (String value : header.getValue()) {
+                conn.setRequestProperty(header.getKey(), value);
+              }
+            }
+          }
+        }
+      }
+
+      // range
+      if ((offset != null) || (length != null)) {
+        StringBuilder sb = new StringBuilder("bytes=");
+
+        if ((offset == null) || (offset.signum() == -1)) {
+          offset = BigInteger.ZERO;
+        }
+
+        sb.append(offset.toString());
+        sb.append("-");
+
+        if ((length != null) && (length.signum() == 1)) {
+          sb.append(offset.add(length.subtract(BigInteger.ONE)).toString());
+        }
+
+        conn.setRequestProperty("Range", sb.toString());
+      }
+
+      // send data
+      if (writer != null) {
+        OutputStream out = new BufferedOutputStream(conn.getOutputStream(), BUFFER_SIZE);
+        writer.write(out);
+        out.flush();
+      }
+
+      // connect
+      conn.connect();
+
+      // get stream, if present
+      int respCode = conn.getResponseCode();
+      InputStream inputStream = null;
+      if ((respCode == 200) || (respCode == 201) || (respCode == 203) || (respCode == 206)) {
+        inputStream = conn.getInputStream();
+      }
+
+      // get the response
+      return new Response(respCode, conn.getResponseMessage(), conn.getHeaderFields(), inputStream);
+    }
+    catch (Exception e) {
+      throw new CmisConnectionException("Cannot access " + url + ": " + e.getMessage(), e);
+    }
+  }
+
+  /**
+   * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+   * 
+   */
+  public static class Response {
+    private int fResponseCode;
+    private String fResponseMessage;
+    private Map<String, List<String>> fHeaders;
+    private InputStream fStream;
+
+    public Response(int responseCode, String responseMessage, Map<String, List<String>> headers,
+        InputStream stream) {
+      fResponseCode = responseCode;
+      fResponseMessage = responseMessage;
+      fStream = stream;
+
+      fHeaders = new HashMap<String, List<String>>();
+      if (headers != null) {
+        for (Map.Entry<String, List<String>> e : headers.entrySet()) {
+          fHeaders.put(e.getKey() == null ? null : e.getKey().toLowerCase(), e.getValue());
+        }
+      }
+    }
+
+    public int getResponseCode() {
+      return fResponseCode;
+    }
+
+    public String getResponseMessage() {
+      return fResponseMessage;
+    }
+
+    public Map<String, List<String>> getHeaders() {
+      return fHeaders;
+    }
+
+    public String getHeader(String name) {
+      List<String> list = fHeaders.get(name.toLowerCase(Locale.US));
+      if ((list == null) || (list.isEmpty())) {
+        return null;
+      }
+
+      return list.get(0);
+    }
+
+    public String getContentTypeHeader() {
+      return getHeader("Content-Type");
+    }
+
+    public BigInteger getContentLengthHeader() {
+      String lengthStr = getHeader("Content-Length");
+      if (lengthStr == null) {
+        return null;
+      }
+
+      try {
+        return new BigInteger(lengthStr);
+      }
+      catch (NumberFormatException e) {
+        return null;
+      }
+    }
+
+    public String getLocactionHeader() {
+      return getHeader("Location");
+    }
+
+    public String getContentLocactionHeader() {
+      return getHeader("Content-Location");
+    }
+
+    public BigInteger getContentLength() {
+      String lenStr = getHeader("Content-Length");
+      if (lenStr == null) {
+        return null;
+      }
+
+      try {
+        return new BigInteger(lenStr);
+      }
+      catch (NumberFormatException nfe) {
+        return null;
+      }
+    }
+
+    public InputStream getStream() {
+      return fStream;
+    }
+  }
+
+  /**
+   * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+   * 
+   */
+  public interface Output {
+    void write(OutputStream out) throws Exception;
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/HttpUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/LinkCache.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/LinkCache.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/LinkCache.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/LinkCache.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,273 @@
+/*
+ * 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.opencmis.client.provider.spi.atompub;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Map;
+
+import org.apache.opencmis.client.provider.cache.Cache;
+import org.apache.opencmis.client.provider.cache.impl.CacheImpl;
+import org.apache.opencmis.client.provider.cache.impl.ContentTypeCacheLevelImpl;
+import org.apache.opencmis.client.provider.cache.impl.LruCacheLevelImpl;
+import org.apache.opencmis.client.provider.cache.impl.MapCacheLevelImpl;
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.commons.SessionParameter;
+import org.apache.opencmis.commons.impl.UrlBuilder;
+
+/**
+ * Link cache.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class LinkCache implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final int CACHE_SIZE_REPOSITORIES = 10;
+  private static final int CACHE_SIZE_TYPES = 100;
+  private static final int CACHE_SIZE_OBJECTS = 400;
+
+  private Cache fLinkCache;
+  private Cache fTypeLinkCache;
+  private Cache fCollectionLinkCache;
+  private Cache fTemplateCache;
+  private Cache fRepositoryLinkCache;
+
+  /**
+   * Constructor.
+   */
+  public LinkCache(Session session) {
+    int repCount = session.get(SessionParameter.CACHE_SIZE_REPOSITORIES, CACHE_SIZE_REPOSITORIES);
+    if (repCount < 1) {
+      repCount = CACHE_SIZE_REPOSITORIES;
+    }
+
+    int typeCount = session.get(SessionParameter.CACHE_SIZE_TYPES, CACHE_SIZE_TYPES);
+    if (typeCount < 1) {
+      typeCount = CACHE_SIZE_TYPES;
+    }
+
+    int objCount = session.get(SessionParameter.CACHE_SIZE_OBJECTS, CACHE_SIZE_OBJECTS);
+    if (objCount < 1) {
+      objCount = CACHE_SIZE_OBJECTS;
+    }
+
+    fLinkCache = new CacheImpl("Link Cache");
+    fLinkCache.initialize(new String[] {
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
+        LruCacheLevelImpl.class.getName() + " " + LruCacheLevelImpl.MAX_ENTRIES + "=" + objCount, // id
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=16", // rel
+        ContentTypeCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=3,"
+            + MapCacheLevelImpl.SINGLE_VALUE + "=true" // type
+    });
+
+    fTypeLinkCache = new CacheImpl("Type Link Cache");
+    fTypeLinkCache.initialize(new String[] {
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
+        LruCacheLevelImpl.class.getName() + " " + LruCacheLevelImpl.MAX_ENTRIES + "=" + typeCount, // id
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=16", // rel
+        ContentTypeCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=3,"
+            + MapCacheLevelImpl.SINGLE_VALUE + "=true"// type
+    });
+
+    fCollectionLinkCache = new CacheImpl("Collection Link Cache");
+    fCollectionLinkCache.initialize(new String[] {
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=8" // collection
+    });
+
+    fTemplateCache = new CacheImpl("URI Template Cache");
+    fTemplateCache.initialize(new String[] {
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=6" // type
+    });
+
+    fRepositoryLinkCache = new CacheImpl("Repository Link Cache");
+    fRepositoryLinkCache.initialize(new String[] {
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=6" // rel
+    });
+  }
+
+  /**
+   * Adds a link.
+   */
+  public void addLink(String repositoryId, String id, String rel, String type, String link) {
+    fLinkCache.put(link, repositoryId, id, rel, type);
+  }
+
+  /**
+   * Removes all links of an object.
+   */
+  public void removeLinks(String repositoryId, String id) {
+    fLinkCache.remove(repositoryId, id);
+  }
+
+  /**
+   * Gets a link.
+   */
+  public String getLink(String repositoryId, String id, String rel, String type) {
+    return (String) fLinkCache.get(repositoryId, id, rel, type);
+  }
+
+  /**
+   * Gets a link.
+   */
+  public String getLink(String repositoryId, String id, String rel) {
+    return getLink(repositoryId, id, rel, null);
+  }
+
+  /**
+   * Adds a type link.
+   */
+  public void addTypeLink(String repositoryId, String id, String rel, String type, String link) {
+    fTypeLinkCache.put(link, repositoryId, id, rel, type);
+  }
+
+  /**
+   * Removes all links of a type.
+   */
+  public void removeTypeLinks(String repositoryId, String id) {
+    fTypeLinkCache.remove(repositoryId, id);
+  }
+
+  /**
+   * Gets a type link.
+   */
+  public String getTypeLink(String repositoryId, String id, String rel, String type) {
+    return (String) fTypeLinkCache.get(repositoryId, id, rel, type);
+  }
+
+  /**
+   * Gets a type link.
+   */
+  public String getTypeLink(String repositoryId, String id, String rel) {
+    return getLink(repositoryId, id, rel, null);
+  }
+
+  /**
+   * Adds a collection.
+   */
+  public void addCollection(String repositoryId, String collection, String link) {
+    fCollectionLinkCache.put(link, repositoryId, collection);
+  }
+
+  /**
+   * Gets a collection.
+   */
+  public String getCollection(String repositoryId, String collection) {
+    return (String) fCollectionLinkCache.get(repositoryId, collection);
+  }
+
+  /**
+   * Adds an URI template.
+   */
+  public void addTemplate(String repositoryId, String type, String link) {
+    fTemplateCache.put(link, repositoryId, type);
+  }
+
+  /**
+   * Gets an URI template and replaces place holders with the given parameters.
+   */
+  public String getTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
+    String template = (String) fTemplateCache.get(repositoryId, type);
+    if (template == null) {
+      return null;
+    }
+
+    StringBuilder result = new StringBuilder();
+    StringBuilder param = new StringBuilder();
+
+    boolean paramMode = false;
+    for (int i = 0; i < template.length(); i++) {
+      char c = template.charAt(i);
+
+      if (paramMode) {
+        if (c == '}') {
+          paramMode = false;
+
+          String paramValue = UrlBuilder.normalizeParameter(parameters.get(param.toString()));
+          if (paramValue != null) {
+            try {
+              result.append(URLEncoder.encode(paramValue, "UTF-8"));
+            }
+            catch (UnsupportedEncodingException e) {
+              result.append(paramValue);
+            }
+          }
+
+          param = new StringBuilder();
+        }
+        else {
+          param.append(c);
+        }
+      }
+      else {
+        if (c == '{') {
+          paramMode = true;
+        }
+        else {
+          result.append(c);
+        }
+      }
+    }
+
+    return result.toString();
+  }
+
+  /**
+   * Adds a collection.
+   */
+  public void addRepositoryLink(String repositoryId, String rel, String link) {
+    fRepositoryLinkCache.put(link, repositoryId, rel);
+  }
+
+  /**
+   * Gets a collection.
+   */
+  public String getRepositoryLink(String repositoryId, String rel) {
+    return (String) fRepositoryLinkCache.get(repositoryId, rel);
+  }
+
+  /**
+   * Removes all entries of the given repository from the caches.
+   */
+  public void clearRepository(String repositoryId) {
+    fLinkCache.remove(repositoryId);
+    fTypeLinkCache.remove(repositoryId);
+    fCollectionLinkCache.remove(repositoryId);
+    fTemplateCache.remove(repositoryId);
+    fRepositoryLinkCache.remove(repositoryId);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see java.lang.Object#toString()
+   */
+  @Override
+  public String toString() {
+    return "Link Cache [link cache=" + fLinkCache + ", type link cache=" + fTypeLinkCache
+        + ", collection link cache=" + fCollectionLinkCache + ", repository link cache="
+        + fRepositoryLinkCache + ",  template cache=" + fTemplateCache + "]";
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/LinkCache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/MultiFilingServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/MultiFilingServiceImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/MultiFilingServiceImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/MultiFilingServiceImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,110 @@
+/*
+ * 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.opencmis.client.provider.spi.atompub;
+
+import java.io.OutputStream;
+
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.commons.api.ExtensionsData;
+import org.apache.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.opencmis.commons.exceptions.CmisObjectNotFoundException;
+import org.apache.opencmis.commons.impl.Constants;
+import org.apache.opencmis.commons.impl.UrlBuilder;
+import org.apache.opencmis.commons.provider.MultiFilingService;
+
+/**
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class MultiFilingServiceImpl extends AbstractAtomPubService implements MultiFilingService {
+
+  /**
+   * Constructor.
+   */
+  public MultiFilingServiceImpl(Session session) {
+    setSession(session);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.MultiFilingService#addObjectToFolder(java.lang.String,
+   * java.lang.String, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public void addObjectToFolder(String repositoryId, String objectId, String folderId,
+      Boolean allVersions, ExtensionsData extension) {
+    if (objectId == null) {
+      throw new CmisInvalidArgumentException("Object id must be set!");
+    }
+
+    // find the link
+    String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_ALL_VERSIONS, allVersions);
+
+    // set up object and writer
+    final AtomEntryWriter entryWriter = new AtomEntryWriter(createIdObject(objectId));
+
+    // post addObjectToFolder request
+    post(url, Constants.MEDIATYPE_ENTRY, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        entryWriter.write(out);
+      }
+    });
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.MultiFilingService#removeObjectFromFolder(java.lang.String,
+   * java.lang.String, java.lang.String, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public void removeObjectFromFolder(String repositoryId, String objectId, String folderId,
+      ExtensionsData extension) {
+    if (objectId == null) {
+      throw new CmisInvalidArgumentException("Object id must be set!");
+    }
+
+    // find the link
+    String link = loadCollection(repositoryId, Constants.COLLECTION_UNFILED);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or unfiling not supported!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_REMOVE_FROM, folderId);
+
+    // set up object and writer
+    final AtomEntryWriter entryWriter = new AtomEntryWriter(createIdObject(objectId));
+
+    // post removeObjectFromFolder request
+    post(url, Constants.MEDIATYPE_ENTRY, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        entryWriter.write(out);
+      }
+    });
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/MultiFilingServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/NavigationServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/NavigationServiceImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/NavigationServiceImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/NavigationServiceImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,491 @@
+/*
+ * 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.opencmis.client.provider.spi.atompub;
+
+import static org.apache.opencmis.commons.impl.Converter.convert;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomBase;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomElement;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomEntry;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomFeed;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomLink;
+import org.apache.opencmis.commons.api.ExtensionsData;
+import org.apache.opencmis.commons.enums.IncludeRelationships;
+import org.apache.opencmis.commons.exceptions.CmisObjectNotFoundException;
+import org.apache.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.opencmis.commons.impl.Constants;
+import org.apache.opencmis.commons.impl.UrlBuilder;
+import org.apache.opencmis.commons.impl.dataobjects.ObjectInFolderContainerImpl;
+import org.apache.opencmis.commons.impl.dataobjects.ObjectInFolderDataImpl;
+import org.apache.opencmis.commons.impl.dataobjects.ObjectInFolderListImpl;
+import org.apache.opencmis.commons.impl.dataobjects.ObjectListImpl;
+import org.apache.opencmis.commons.impl.dataobjects.ObjectParentDataImpl;
+import org.apache.opencmis.commons.impl.jaxb.CmisObjectType;
+import org.apache.opencmis.commons.provider.NavigationService;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.commons.provider.ObjectInFolderContainer;
+import org.apache.opencmis.commons.provider.ObjectInFolderData;
+import org.apache.opencmis.commons.provider.ObjectInFolderList;
+import org.apache.opencmis.commons.provider.ObjectList;
+import org.apache.opencmis.commons.provider.ObjectParentData;
+
+/**
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class NavigationServiceImpl extends AbstractAtomPubService implements NavigationService {
+
+  /**
+   * Constructor.
+   */
+  public NavigationServiceImpl(Session session) {
+    setSession(session);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.NavigationService#getChildren(java.lang.String,
+   * java.lang.String, java.lang.String, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.commons.enums.IncludeRelationships, java.lang.String, java.lang.Boolean,
+   * java.math.BigInteger, java.math.BigInteger, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public ObjectInFolderList getChildren(String repositoryId, String folderId, String filter,
+      String orderBy, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+      String renditionFilter, Boolean includePathSegment, BigInteger maxItems,
+      BigInteger skipCount, ExtensionsData extension) {
+    ObjectInFolderListImpl result = new ObjectInFolderListImpl();
+
+    // find the link
+    String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or folder!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_FILTER, filter);
+    url.addParameter(Constants.PARAM_ORDER_BY, orderBy);
+    url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+    url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+    url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
+    url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
+    url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+    url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+    AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
+
+    // handle top level
+    for (AtomElement element : feed.getElements()) {
+      if (element.getObject() instanceof AtomLink) {
+        if (isNextLink(element)) {
+          result.setHasMoreItems(Boolean.TRUE);
+        }
+      }
+      else if (isInt(NAME_NUM_ITEMS, element)) {
+        result.setNumItems((BigInteger) element.getObject());
+      }
+    }
+
+    // get the children
+    if (!feed.getEntries().isEmpty()) {
+      result.setObjects(new ArrayList<ObjectInFolderData>(feed.getEntries().size()));
+
+      for (AtomEntry entry : feed.getEntries()) {
+        ObjectInFolderDataImpl child = null;
+        String pathSegment = null;
+
+        // clean up cache
+        removeLinks(repositoryId, entry.getId());
+
+        // walk through the entry
+        for (AtomElement element : entry.getElements()) {
+          if (element.getObject() instanceof AtomLink) {
+            addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+          }
+          else if (isStr(NAME_PATH_SEGMENT, element)) {
+            pathSegment = (String) element.getObject();
+          }
+          else if (element.getObject() instanceof CmisObjectType) {
+            child = new ObjectInFolderDataImpl();
+            child.setObject(convert((CmisObjectType) element.getObject()));
+          }
+        }
+
+        if (child != null) {
+          child.setPathSegment(pathSegment);
+          result.getObjects().add(child);
+        }
+      }
+    }
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.NavigationService#getDescendants(java.lang.String,
+   * java.lang.String, java.math.BigInteger, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.commons.enums.IncludeRelationships, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public List<ObjectInFolderContainer> getDescendants(String repositoryId, String folderId,
+      BigInteger depth, String filter, Boolean includeAllowableActions,
+      IncludeRelationships includeRelationships, String renditionFilter,
+      Boolean includePathSegment, ExtensionsData extension) {
+    List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>();
+
+    // find the link
+    String link = loadLink(repositoryId, folderId, Constants.REL_DOWN,
+        Constants.MEDIATYPE_DESCENDANTS);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or folder!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_DEPTH, depth);
+    url.addParameter(Constants.PARAM_FILTER, filter);
+    url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+    url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+    url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
+    url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+    AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
+
+    // process tree
+    addDescendantsLevel(repositoryId, feed, result);
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.NavigationService#getFolderParent(java.lang.String,
+   * java.lang.String, java.lang.String, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public ObjectData getFolderParent(String repositoryId, String folderId, String filter,
+      ExtensionsData extension) {
+    ObjectData result = null;
+
+    // find the link
+    String link = loadLink(repositoryId, folderId, Constants.REL_UP, Constants.MEDIATYPE_ENTRY);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or folder!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_FILTER, filter);
+
+    // read
+    HttpUtils.Response resp = read(url);
+
+    AtomBase base = parse(resp.getStream(), AtomBase.class);
+
+    // get the entry
+    AtomEntry entry = null;
+    if (base instanceof AtomFeed) {
+      AtomFeed feed = (AtomFeed) base;
+      if (feed.getEntries().isEmpty()) {
+        throw new CmisRuntimeException("Parent feed is empty!");
+      }
+      entry = feed.getEntries().get(0);
+    }
+    else if (base instanceof AtomEntry) {
+      entry = (AtomEntry) base;
+    }
+    else {
+      throw new CmisRuntimeException("Unexpected document!");
+    }
+
+    // clean up cache
+    removeLinks(repositoryId, entry.getId());
+
+    // walk through the entry
+    for (AtomElement element : entry.getElements()) {
+      if (element.getObject() instanceof AtomLink) {
+        addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+      }
+      else if (element.getObject() instanceof CmisObjectType) {
+        result = convert((CmisObjectType) element.getObject());
+      }
+    }
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.NavigationService#getFolderTree(java.lang.String,
+   * java.lang.String, java.math.BigInteger, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.commons.enums.IncludeRelationships, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public List<ObjectInFolderContainer> getFolderTree(String repositoryId, String folderId,
+      BigInteger depth, String filter, Boolean includeAllowableActions,
+      IncludeRelationships includeRelationships, String renditionFilter,
+      Boolean includePathSegment, ExtensionsData extension) {
+    List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>();
+
+    // find the link
+    String link = loadLink(repositoryId, folderId, Constants.REL_FOLDERTREE,
+        Constants.MEDIATYPE_DESCENDANTS);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or folder!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_DEPTH, depth);
+    url.addParameter(Constants.PARAM_FILTER, filter);
+    url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+    url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+    url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
+    url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+    AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
+
+    // process tree
+    addDescendantsLevel(repositoryId, feed, result);
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.NavigationService#getObjectParents(java.lang.String,
+   * java.lang.String, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.commons.enums.IncludeRelationships, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public List<ObjectParentData> getObjectParents(String repositoryId, String objectId,
+      String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+      String renditionFilter, Boolean includeRelativePathSegment, ExtensionsData extension) {
+    List<ObjectParentData> result = new ArrayList<ObjectParentData>();
+
+    // find the link
+    String link = loadLink(repositoryId, objectId, Constants.REL_UP, Constants.MEDIATYPE_FEED);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or folder!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_FILTER, filter);
+    url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+    url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+    url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
+    url.addParameter(Constants.PARAM_RELATIVE_PATH_SEGMENT, includeRelativePathSegment);
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+
+    AtomBase base = parse(resp.getStream(), AtomBase.class);
+
+    if (base instanceof AtomFeed) {
+      // it's a feed
+      AtomFeed feed = (AtomFeed) base;
+
+      // walk through the feed
+      for (AtomEntry entry : feed.getEntries()) {
+        ObjectParentDataImpl objectParent = processParentEntry(entry, repositoryId);
+
+        if (objectParent != null) {
+          result.add(objectParent);
+        }
+      }
+    }
+    else if (base instanceof AtomEntry) {
+      // it's an entry
+      AtomEntry entry = (AtomEntry) base;
+
+      ObjectParentDataImpl objectParent = processParentEntry(entry, repositoryId);
+
+      if (objectParent != null) {
+        result.add(objectParent);
+      }
+    }
+
+    return result;
+  }
+
+  private ObjectParentDataImpl processParentEntry(AtomEntry entry, String repositoryId) {
+    ObjectParentDataImpl result = null;
+    String relativePathSegment = null;
+
+    // clean up cache
+    removeLinks(repositoryId, entry.getId());
+
+    // walk through the entry
+    for (AtomElement element : entry.getElements()) {
+      if (element.getObject() instanceof AtomLink) {
+        addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+      }
+      else if (element.getObject() instanceof CmisObjectType) {
+        result = new ObjectParentDataImpl(convert((CmisObjectType) element.getObject()));
+      }
+      else if (is(NAME_RELATIVE_PATH_SEGMENT, element)) {
+        relativePathSegment = (String) element.getObject();
+      }
+    }
+
+    if (result != null) {
+      result.setRelativePathSegment(relativePathSegment);
+    }
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.NavigationService#getCheckedOutDocs(java.lang.String,
+   * java.lang.String, java.lang.String, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.commons.enums.IncludeRelationships, java.lang.String, java.math.BigInteger,
+   * java.math.BigInteger, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public ObjectList getCheckedOutDocs(String repositoryId, String folderId, String filter,
+      String orderBy, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+      String renditionFilter, BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
+    ObjectListImpl result = new ObjectListImpl();
+
+    // find the link
+    String link = loadCollection(repositoryId, Constants.COLLECTION_CHECKEDOUT);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException(
+          "Unknown repository or checkedout collection not supported!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_FOLDER_ID, folderId);
+    url.addParameter(Constants.PARAM_FILTER, filter);
+    url.addParameter(Constants.PARAM_ORDER_BY, orderBy);
+    url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+    url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+    url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
+    url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+    url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+    AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
+
+    // handle top level
+    for (AtomElement element : feed.getElements()) {
+      if (element.getObject() instanceof AtomLink) {
+        if (isNextLink(element)) {
+          result.setHasMoreItems(Boolean.TRUE);
+        }
+      }
+      else if (isInt(NAME_NUM_ITEMS, element)) {
+        result.setNumItems((BigInteger) element.getObject());
+      }
+    }
+
+    // get the documents
+    if (!feed.getEntries().isEmpty()) {
+      result.setObjects(new ArrayList<ObjectData>(feed.getEntries().size()));
+
+      for (AtomEntry entry : feed.getEntries()) {
+        ObjectData child = null;
+
+        // clean up cache
+        removeLinks(repositoryId, entry.getId());
+
+        // walk through the entry
+        for (AtomElement element : entry.getElements()) {
+          if (element.getObject() instanceof AtomLink) {
+            addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+          }
+          else if (element.getObject() instanceof CmisObjectType) {
+            child = convert((CmisObjectType) element.getObject());
+          }
+        }
+
+        if (child != null) {
+          result.getObjects().add(child);
+        }
+      }
+    }
+
+    return result;
+  }
+
+  // ---- internal ----
+
+  /**
+   * Adds descendants level recursively.
+   */
+  private void addDescendantsLevel(String repositoryId, AtomFeed feed,
+      List<ObjectInFolderContainer> containerList) {
+    if ((feed == null) || (feed.getEntries().isEmpty())) {
+      return;
+    }
+
+    // walk through the feed
+    for (AtomEntry entry : feed.getEntries()) {
+      ObjectInFolderDataImpl objectInFolder = null;
+      String pathSegment = null;
+      List<ObjectInFolderContainer> childContainerList = new ArrayList<ObjectInFolderContainer>();
+
+      // clean up cache
+      removeLinks(repositoryId, entry.getId());
+
+      // walk through the entry
+      for (AtomElement element : entry.getElements()) {
+        if (element.getObject() instanceof AtomLink) {
+          addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+        }
+        else if (element.getObject() instanceof CmisObjectType) {
+          objectInFolder = new ObjectInFolderDataImpl(convert((CmisObjectType) element.getObject()));
+        }
+        else if (is(NAME_PATH_SEGMENT, element)) {
+          pathSegment = (String) element.getObject();
+        }
+        else if (element.getObject() instanceof AtomFeed) {
+          addDescendantsLevel(repositoryId, (AtomFeed) element.getObject(), childContainerList);
+        }
+      }
+
+      if (objectInFolder != null) {
+        objectInFolder.setPathSegment(pathSegment);
+        ObjectInFolderContainerImpl childContainer = new ObjectInFolderContainerImpl(objectInFolder);
+        childContainer.setChildren(childContainerList);
+        containerList.add(childContainer);
+      }
+    }
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/NavigationServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/ObjectServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/ObjectServiceImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/ObjectServiceImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/ObjectServiceImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,755 @@
+/*
+ * 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.opencmis.client.provider.spi.atompub;
+
+import static org.apache.opencmis.commons.impl.Converter.convert;
+import static org.apache.opencmis.commons.impl.Converter.convertPolicyIds;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.List;
+
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AllowableActions;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomElement;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomEntry;
+import org.apache.opencmis.client.provider.spi.atompub.objects.AtomLink;
+import org.apache.opencmis.commons.PropertyIds;
+import org.apache.opencmis.commons.api.ExtensionsData;
+import org.apache.opencmis.commons.enums.IncludeRelationships;
+import org.apache.opencmis.commons.enums.UnfileObjects;
+import org.apache.opencmis.commons.enums.VersioningState;
+import org.apache.opencmis.commons.exceptions.CmisConnectionException;
+import org.apache.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.opencmis.commons.exceptions.CmisNotSupportedException;
+import org.apache.opencmis.commons.exceptions.CmisObjectNotFoundException;
+import org.apache.opencmis.commons.impl.Constants;
+import org.apache.opencmis.commons.impl.ReturnVersion;
+import org.apache.opencmis.commons.impl.UrlBuilder;
+import org.apache.opencmis.commons.impl.dataobjects.ContentStreamDataImpl;
+import org.apache.opencmis.commons.impl.dataobjects.FailedToDeleteDataImpl;
+import org.apache.opencmis.commons.impl.jaxb.CmisObjectType;
+import org.apache.opencmis.commons.impl.jaxb.CmisProperty;
+import org.apache.opencmis.commons.impl.jaxb.CmisPropertyString;
+import org.apache.opencmis.commons.provider.AccessControlList;
+import org.apache.opencmis.commons.provider.AllowableActionsData;
+import org.apache.opencmis.commons.provider.ContentStreamData;
+import org.apache.opencmis.commons.provider.FailedToDeleteData;
+import org.apache.opencmis.commons.provider.Holder;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.commons.provider.ObjectService;
+import org.apache.opencmis.commons.provider.PropertiesData;
+import org.apache.opencmis.commons.provider.PropertyData;
+import org.apache.opencmis.commons.provider.PropertyIdData;
+import org.apache.opencmis.commons.provider.RenditionData;
+
+/**
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class ObjectServiceImpl extends AbstractAtomPubService implements ObjectService {
+
+  /**
+   * Constructor.
+   */
+  public ObjectServiceImpl(Session session) {
+    setSession(session);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#createDocument(java.lang.String,
+   * org.apache.opencmis.client.provider.PropertiesData, java.lang.String,
+   * org.apache.opencmis.client.provider.ContentStreamData, org.apache.opencmis.commons.enums.VersioningState,
+   * java.util.List, org.apache.opencmis.client.provider.AccessControlList,
+   * org.apache.opencmis.client.provider.AccessControlList, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public String createDocument(String repositoryId, PropertiesData properties, String folderId,
+      ContentStreamData contentStream, VersioningState versioningState, List<String> policies,
+      AccessControlList addAces, AccessControlList removeAces, ExtensionsData extension) {
+    checkCreateProperties(properties);
+
+    // find the link
+    String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_VERSIONIG_STATE, versioningState);
+
+    // set up object and writer
+    CmisObjectType object = new CmisObjectType();
+    object.setProperties(convert(properties));
+    object.setPolicyIds(convertPolicyIds(policies));
+
+    String mediaType = null;
+    InputStream stream = null;
+
+    if (contentStream != null) {
+      mediaType = contentStream.getMimeType();
+      stream = contentStream.getStream();
+    }
+
+    final AtomEntryWriter entryWriter = new AtomEntryWriter(object, mediaType, stream);
+
+    // post the new folder object
+    HttpUtils.Response resp = post(url, Constants.MEDIATYPE_ENTRY, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        entryWriter.write(out);
+      }
+    });
+
+    // parse the response
+    AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+    // handle ACL modifications
+    handleAclModifications(repositoryId, entry, addAces, removeAces);
+
+    return entry.getId();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#createDocumentFromSource(java.lang.String,
+   * java.lang.String, org.apache.opencmis.client.provider.PropertiesData, java.lang.String,
+   * org.apache.opencmis.commons.enums.VersioningState, java.util.List,
+   * org.apache.opencmis.client.provider.AccessControlList, org.apache.opencmis.client.provider.AccessControlList,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public String createDocumentFromSource(String repositoryId, String sourceId,
+      PropertiesData properties, String folderId, VersioningState versioningState,
+      List<String> policies, AccessControlList addACEs, AccessControlList removeACEs,
+      ExtensionsData extension) {
+    throw new CmisNotSupportedException(
+        "createDocumentFromSource is not supported by the AtomPub binding!");
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#createFolder(java.lang.String,
+   * org.apache.opencmis.client.provider.PropertiesData, java.lang.String, java.util.List,
+   * org.apache.opencmis.client.provider.AccessControlList, org.apache.opencmis.client.provider.AccessControlList,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public String createFolder(String repositoryId, PropertiesData properties, String folderId,
+      List<String> policies, AccessControlList addAces, AccessControlList removeAces,
+      ExtensionsData extension) {
+    checkCreateProperties(properties);
+
+    // find the link
+    String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+
+    // set up object and writer
+    CmisObjectType object = new CmisObjectType();
+    object.setProperties(convert(properties));
+    object.setPolicyIds(convertPolicyIds(policies));
+
+    final AtomEntryWriter entryWriter = new AtomEntryWriter(object);
+
+    // post the new folder object
+    HttpUtils.Response resp = post(url, Constants.MEDIATYPE_ENTRY, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        entryWriter.write(out);
+      }
+    });
+
+    // parse the response
+    AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+    // handle ACL modifications
+    handleAclModifications(repositoryId, entry, addAces, removeAces);
+
+    return entry.getId();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#createPolicy(java.lang.String,
+   * org.apache.opencmis.client.provider.PropertiesData, java.lang.String, java.util.List,
+   * org.apache.opencmis.client.provider.AccessControlList, org.apache.opencmis.client.provider.AccessControlList,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public String createPolicy(String repositoryId, PropertiesData properties, String folderId,
+      List<String> policies, AccessControlList addAces, AccessControlList removeAces,
+      ExtensionsData extension) {
+    checkCreateProperties(properties);
+
+    // find the link
+    String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+
+    // set up object and writer
+    CmisObjectType object = new CmisObjectType();
+    object.setProperties(convert(properties));
+    object.setPolicyIds(convertPolicyIds(policies));
+
+    final AtomEntryWriter entryWriter = new AtomEntryWriter(object);
+
+    // post the new folder object
+    HttpUtils.Response resp = post(url, Constants.MEDIATYPE_ENTRY, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        entryWriter.write(out);
+      }
+    });
+
+    // parse the response
+    AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+    // handle ACL modifications
+    handleAclModifications(repositoryId, entry, addAces, removeAces);
+
+    return entry.getId();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#createRelationship(java.lang.String,
+   * org.apache.opencmis.client.provider.PropertiesData, java.util.List,
+   * org.apache.opencmis.client.provider.AccessControlList, org.apache.opencmis.client.provider.AccessControlList,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public String createRelationship(String repositoryId, PropertiesData properties,
+      List<String> policies, AccessControlList addAces, AccessControlList removeAces,
+      ExtensionsData extension) {
+    checkCreateProperties(properties);
+
+    // find source id
+    PropertyData<?> sourceIdProperty = properties.getProperties().get(PropertyIds.CMIS_SOURCE_ID);
+    if (!(sourceIdProperty instanceof PropertyIdData)) {
+      throw new CmisInvalidArgumentException("Source Id is not set!");
+    }
+
+    String sourceId = ((PropertyIdData) sourceIdProperty).getFirstValue();
+    if (sourceId == null) {
+      throw new CmisInvalidArgumentException("Source Id is not set!");
+    }
+
+    // find the link
+    String link = loadLink(repositoryId, sourceId, Constants.REL_RELATIONSHIPS,
+        Constants.MEDIATYPE_FEED);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or source object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+
+    // set up object and writer
+    CmisObjectType object = new CmisObjectType();
+    object.setProperties(convert(properties));
+    object.setPolicyIds(convertPolicyIds(policies));
+
+    final AtomEntryWriter entryWriter = new AtomEntryWriter(object);
+
+    // post the new folder object
+    HttpUtils.Response resp = post(url, Constants.MEDIATYPE_ENTRY, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        entryWriter.write(out);
+      }
+    });
+
+    // parse the response
+    AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+    // handle ACL modifications
+    handleAclModifications(repositoryId, entry, addAces, removeAces);
+
+    return entry.getId();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#updateProperties(java.lang.String,
+   * org.apache.opencmis.client.provider.Holder, org.apache.opencmis.client.provider.Holder,
+   * org.apache.opencmis.client.provider.PropertiesData, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public void updateProperties(String repositoryId, Holder<String> objectId,
+      Holder<String> changeToken, PropertiesData properties, ExtensionsData extension) {
+    // we need an object id
+    if ((objectId == null) || (objectId.getValue() == null) || (objectId.getValue().length() == 0)) {
+      throw new CmisInvalidArgumentException("Object id must be set!");
+    }
+
+    // find the link
+    String link = loadLink(repositoryId, objectId.getValue(), Constants.REL_SELF,
+        Constants.MEDIATYPE_ENTRY);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    if (changeToken != null) {
+      url.addParameter(Constants.PARAM_CHANGE_TOKEN, changeToken.getValue());
+    }
+
+    // set up object and writer
+    CmisObjectType object = new CmisObjectType();
+    object.setProperties(convert(properties));
+
+    final AtomEntryWriter entryWriter = new AtomEntryWriter(object);
+
+    // update
+    HttpUtils.Response resp = put(url, Constants.MEDIATYPE_ENTRY, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        entryWriter.write(out);
+      }
+    });
+
+    // parse new entry
+    AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+    // we expect a CMIS entry
+    if (entry.getId() == null) {
+      throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
+    }
+
+    // set object id
+    objectId.setValue(entry.getId());
+
+    if (changeToken != null) {
+      changeToken.setValue(null); // just in case
+    }
+
+    // clean up cache
+    removeLinks(repositoryId, entry.getId());
+
+    // walk through the entry
+    for (AtomElement element : entry.getElements()) {
+      if (element.getObject() instanceof AtomLink) {
+        addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+      }
+      else if (element.getObject() instanceof CmisObjectType) {
+        // extract new change token
+        if (changeToken != null) {
+          object = (CmisObjectType) element.getObject();
+
+          if (object.getProperties() != null) {
+            for (CmisProperty property : object.getProperties().getProperty()) {
+              if (PropertyIds.CMIS_CHANGE_TOKEN.equals(property.getPropertyDefinitionId())
+                  && (property instanceof CmisPropertyString)) {
+
+                CmisPropertyString changeTokenProperty = (CmisPropertyString) property;
+                if (!changeTokenProperty.getValue().isEmpty()) {
+                  changeToken.setValue(changeTokenProperty.getValue().get(0));
+                }
+
+                break;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#deleteObject(java.lang.String,
+   * java.lang.String, java.lang.Boolean, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public void deleteObject(String repositoryId, String objectId, Boolean allVersions,
+      ExtensionsData extension) {
+
+    // find the link
+    String link = loadLink(repositoryId, objectId, Constants.REL_SELF, Constants.MEDIATYPE_ENTRY);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_ALL_VERSIONS, allVersions);
+
+    delete(url);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#deleteTree(java.lang.String, java.lang.String,
+   * java.lang.Boolean, org.apache.opencmis.commons.enums.UnfileObject, java.lang.Boolean,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public FailedToDeleteData deleteTree(String repositoryId, String folderId, Boolean allVersions,
+      UnfileObjects unfileObjects, Boolean continueOnFailure, ExtensionsData extension) {
+
+    // find the link
+    String link = loadLink(repositoryId, folderId, Constants.REL_DOWN,
+        Constants.MEDIATYPE_DESCENDANTS);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or folder!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_ALL_VERSIONS, allVersions);
+    url.addParameter(Constants.PARAM_UNFILE_OBJECTS, unfileObjects);
+    url.addParameter(Constants.PARAM_CONTINUE_ON_FAILURE, continueOnFailure);
+
+    // make the call
+    HttpUtils.Response resp = HttpUtils.invokeDELETE(url, getSession());
+
+    // check response code
+    if ((resp.getResponseCode() == 200) || (resp.getResponseCode() == 202)
+        || (resp.getResponseCode() == 204)) {
+      return new FailedToDeleteDataImpl();
+    }
+
+    throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), null);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#getAllowableActions(java.lang.String,
+   * java.lang.String, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public AllowableActionsData getAllowableActions(String repositoryId, String objectId,
+      ExtensionsData extension) {
+    // find the link
+    String link = loadLink(repositoryId, objectId, Constants.REL_ALLOWABLEACTIONS,
+        Constants.MEDIATYPE_ALLOWABLEACTION);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+    AllowableActions allowableActions = parse(resp.getStream(), AllowableActions.class);
+
+    return convert(allowableActions.getAllowableActions());
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#getContentStream(java.lang.String,
+   * java.lang.String, java.lang.String, java.math.BigInteger, java.math.BigInteger,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public ContentStreamData getContentStream(String repositoryId, String objectId, String streamId,
+      BigInteger offset, BigInteger length, ExtensionsData extension) {
+    ContentStreamDataImpl result = new ContentStreamDataImpl();
+
+    // find the link
+    String link = loadLink(repositoryId, objectId, AtomPubParser.LINK_REL_CONTENT, null);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_STREAM_ID, streamId);
+
+    // get the content
+    HttpUtils.Response resp = HttpUtils.invokeGET(url, getSession(), offset, length);
+
+    // check response code
+    if ((resp.getResponseCode() != 200) && (resp.getResponseCode() != 206)) {
+      throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), null);
+    }
+
+    result.setFilename(null);
+    result.setLength(resp.getContentLength());
+    result.setMimeType(resp.getContentTypeHeader());
+    result.setStream(resp.getStream());
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#getObject(java.lang.String, java.lang.String,
+   * java.lang.String, java.lang.Boolean, org.apache.opencmis.commons.enums.IncludeRelationships,
+   * java.lang.String, java.lang.Boolean, java.lang.Boolean,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public ObjectData getObject(String repositoryId, String objectId, String filter,
+      Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+      String renditionFilter, Boolean includePolicyIds, Boolean includeACL, ExtensionsData extension) {
+
+    return getObjectInternal(repositoryId, IdentifierType.ID, objectId, ReturnVersion.THIS, filter,
+        includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds,
+        includeACL, extension);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#getObjectByPath(java.lang.String,
+   * java.lang.String, java.lang.String, java.lang.Boolean,
+   * org.apache.opencmis.commons.enums.IncludeRelationships, java.lang.String, java.lang.Boolean,
+   * java.lang.Boolean, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public ObjectData getObjectByPath(String repositoryId, String path, String filter,
+      Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+      String renditionFilter, Boolean includePolicyIds, Boolean includeACL, ExtensionsData extension) {
+
+    return getObjectInternal(repositoryId, IdentifierType.PATH, path, ReturnVersion.THIS, filter,
+        includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds,
+        includeACL, extension);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#getProperties(java.lang.String,
+   * java.lang.String, java.lang.String, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public PropertiesData getProperties(String repositoryId, String objectId, String filter,
+      ExtensionsData extension) {
+    ObjectData object = getObjectInternal(repositoryId, IdentifierType.ID, objectId,
+        ReturnVersion.THIS, filter, Boolean.FALSE, IncludeRelationships.NONE, "cmis:none",
+        Boolean.FALSE, Boolean.FALSE, extension);
+
+    return object.getProperties();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#getRenditions(java.lang.String,
+   * java.lang.String, java.lang.String, java.math.BigInteger, java.math.BigInteger,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public List<RenditionData> getRenditions(String repositoryId, String objectId,
+      String renditionFilter, BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
+    ObjectData object = getObjectInternal(repositoryId, IdentifierType.ID, objectId,
+        ReturnVersion.THIS, PropertyIds.CMIS_OBJECT_ID, Boolean.FALSE, IncludeRelationships.NONE,
+        renditionFilter, Boolean.FALSE, Boolean.FALSE, extension);
+
+    return object.getRenditions();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#moveObject(java.lang.String,
+   * org.apache.opencmis.client.provider.Holder, java.lang.String, java.lang.String,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public void moveObject(String repositoryId, Holder<String> objectId, String targetFolderId,
+      String sourceFolderId, ExtensionsData extension) {
+    if ((objectId == null) || (objectId.getValue() == null) || (objectId.getValue().length() == 0)) {
+      throw new CmisInvalidArgumentException("Object id must be set!");
+    }
+
+    if ((targetFolderId == null) || (targetFolderId.length() == 0) || (sourceFolderId == null)
+        || (sourceFolderId.length() == 0)) {
+      throw new CmisInvalidArgumentException("Source and target folder must be set!");
+    }
+
+    // find the link
+    String link = loadLink(repositoryId, targetFolderId, Constants.REL_DOWN,
+        Constants.MEDIATYPE_CHILDREN);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_SOURCE_FOLDER_ID, sourceFolderId);
+
+    // set up object and writer
+    final AtomEntryWriter entryWriter = new AtomEntryWriter(createIdObject(objectId.getValue()));
+
+    // post move request
+    HttpUtils.Response resp = post(url, Constants.MEDIATYPE_ENTRY, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        entryWriter.write(out);
+      }
+    });
+
+    // parse the response
+    AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+    objectId.setValue(entry.getId());
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#setContentStream(java.lang.String,
+   * org.apache.opencmis.client.provider.Holder, java.lang.Boolean, org.apache.opencmis.client.provider.Holder,
+   * org.apache.opencmis.client.provider.ContentStreamData, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public void setContentStream(String repositoryId, Holder<String> objectId, Boolean overwriteFlag,
+      Holder<String> changeToken, ContentStreamData contentStream, ExtensionsData extension) {
+    // we need an object id
+    if ((objectId == null) || (objectId.getValue() == null)) {
+      throw new CmisInvalidArgumentException("Object ID must be set!");
+    }
+
+    // we need content
+    if ((contentStream == null) || (contentStream.getStream() == null)
+        || (contentStream.getMimeType() == null)) {
+      throw new CmisInvalidArgumentException("Content must be set!");
+    }
+
+    // find the link
+    String link = loadLink(repositoryId, objectId.getValue(), Constants.REL_EDITMEDIA, null);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    if (changeToken != null) {
+      url.addParameter(Constants.PARAM_CHANGE_TOKEN, changeToken.getValue());
+    }
+    url.addParameter(Constants.PARAM_OVERWRITE_FLAG, overwriteFlag);
+
+    final InputStream stream = contentStream.getStream();
+
+    // send content
+    HttpUtils.Response resp = HttpUtils.invokePUT(url, contentStream.getMimeType(),
+        new HttpUtils.Output() {
+          public void write(OutputStream out) throws Exception {
+            int b;
+            byte[] buffer = new byte[4096];
+
+            while ((b = stream.read(buffer)) > -1) {
+              out.write(buffer, 0, b);
+            }
+
+            stream.close();
+          }
+        }, getSession());
+
+    // check response code
+    if ((resp.getResponseCode() != 200) && (resp.getResponseCode() != 201)
+        && (resp.getResponseCode() != 204)) {
+      throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), null);
+    }
+
+    objectId.setValue(null);
+    if (changeToken != null) {
+      changeToken.setValue(null);
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ObjectService#deleteContentStream(java.lang.String,
+   * org.apache.opencmis.client.provider.Holder, org.apache.opencmis.client.provider.Holder,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public void deleteContentStream(String repositoryId, Holder<String> objectId,
+      Holder<String> changeToken, ExtensionsData extension) {
+    // we need an object id
+    if ((objectId == null) || (objectId.getValue() == null)) {
+      throw new CmisInvalidArgumentException("Object ID must be set!");
+    }
+
+    // find the link
+    String link = loadLink(repositoryId, objectId.getValue(), Constants.REL_EDITMEDIA, null);
+
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository or object!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    if (changeToken != null) {
+      url.addParameter(Constants.PARAM_CHANGE_TOKEN, changeToken.getValue());
+    }
+
+    delete(url);
+
+    objectId.setValue(null);
+    if (changeToken != null) {
+      changeToken.setValue(null);
+    }
+  }
+
+  // ---- internal ----
+
+  private void checkCreateProperties(PropertiesData properties) {
+    if ((properties == null) || (properties.getProperties() == null)) {
+      throw new CmisInvalidArgumentException("Properties must be set!");
+    }
+
+    if (!properties.getProperties().containsKey(PropertyIds.CMIS_OBJECT_TYPE_ID)) {
+      throw new CmisInvalidArgumentException("Property " + PropertyIds.CMIS_OBJECT_TYPE_ID
+          + " must be set!");
+    }
+
+    if (properties.getProperties().containsKey(PropertyIds.CMIS_OBJECT_ID)) {
+      throw new CmisInvalidArgumentException("Property " + PropertyIds.CMIS_OBJECT_ID
+          + " must not be set!");
+    }
+  }
+
+  /**
+   * Handles ACL modifications of newly created objects.
+   */
+  private void handleAclModifications(String repositoryId, AtomEntry entry,
+      AccessControlList addAces, AccessControlList removeAces) {
+    if (!isAclMergeRequired(addAces, removeAces)) {
+      return;
+    }
+
+    AccessControlList originalAces = null;
+
+    // walk through the entry and find the current ACL
+    for (AtomElement element : entry.getElements()) {
+      if (element.getObject() instanceof CmisObjectType) {
+        // extract current ACL
+        CmisObjectType object = (CmisObjectType) element.getObject();
+        originalAces = convert(object.getAcl(), object.isExactACL());
+
+        break;
+      }
+    }
+
+    if (originalAces != null) {
+      // merge and update ACL
+      AccessControlList newACL = mergeAcls(originalAces, addAces, removeAces);
+      if (newACL != null) {
+        updateAcl(repositoryId, entry.getId(), newACL, null);
+      }
+    }
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/spi/atompub/ObjectServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native