chemistry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dcaru...@apache.org
Subject svn commit: r910572 [24/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-...
Date Tue, 16 Feb 2010 16:04:07 GMT
Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/CmisAtomPubServlet.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/CmisAtomPubServlet.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/CmisAtomPubServlet.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/CmisAtomPubServlet.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,354 @@
+/*
+ * 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.server.impl.atompub;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Map;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.opencmis.commons.exceptions.CmisBaseException;
+import org.apache.opencmis.commons.exceptions.CmisConstraintException;
+import org.apache.opencmis.commons.exceptions.CmisContentAlreadyExistsException;
+import org.apache.opencmis.commons.exceptions.CmisFilterNotValidException;
+import org.apache.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.opencmis.commons.exceptions.CmisNameConstraintViolationException;
+import org.apache.opencmis.commons.exceptions.CmisNotSupportedException;
+import org.apache.opencmis.commons.exceptions.CmisObjectNotFoundException;
+import org.apache.opencmis.commons.exceptions.CmisPermissionDeniedException;
+import org.apache.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.opencmis.commons.exceptions.CmisStorageException;
+import org.apache.opencmis.commons.exceptions.CmisStreamNotSupportedException;
+import org.apache.opencmis.commons.exceptions.CmisUpdateConflictException;
+import org.apache.opencmis.commons.exceptions.CmisVersioningException;
+import org.apache.opencmis.server.impl.CallContextImpl;
+import org.apache.opencmis.server.impl.CmisRepositoryContextListener;
+import org.apache.opencmis.server.spi.AbstractServicesFactory;
+import org.apache.opencmis.server.spi.CallContext;
+
+/**
+ * CMIS AtomPub servlet.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class CmisAtomPubServlet extends HttpServlet {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final String PARAM_CALL_CONTEXT_HANDLER = "callContextHandler";
+
+  private static final String METHOD_GET = "GET";
+  private static final String METHOD_POST = "POST";
+  private static final String METHOD_PUT = "PUT";
+  private static final String METHOD_DELETE = "DELETE";
+
+  private static final Log LOG = LogFactory.getLog(CmisAtomPubServlet.class.getName());
+
+  private Dispatcher fDispatcher;
+  private CallContextHandler fCallContextHandler;
+
+  @Override
+  public void init(ServletConfig config) throws ServletException {
+    super.init(config);
+
+    // initialize the call context handler
+    fCallContextHandler = null;
+    String callContextHandlerClass = config.getInitParameter(PARAM_CALL_CONTEXT_HANDLER);
+    if (callContextHandlerClass != null) {
+      try {
+        fCallContextHandler = (CallContextHandler) Class.forName(callContextHandlerClass)
+            .newInstance();
+      }
+      catch (Exception e) {
+        throw new ServletException("Could not load call context handler: " + e, e);
+      }
+    }
+
+    // initialize the dispatcher
+    fDispatcher = new Dispatcher();
+
+    try {
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_TYPES, METHOD_GET, RepositoryService.class,
+          "getTypeChildren");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_TYPESDESC, METHOD_GET, RepositoryService.class,
+          "getTypeDescendants");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_TYPE, METHOD_GET, RepositoryService.class,
+          "getTypeDefinition");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_CHILDREN, METHOD_GET, NavigationService.class,
+          "getChildren");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_DESCENDANTS, METHOD_GET,
+          NavigationService.class, "getDescendants");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_FOLDERTREE, METHOD_GET,
+          NavigationService.class, "getFolderTree");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_PARENTS, METHOD_GET, NavigationService.class,
+          "getObjectParents");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_CHECKEDOUT, METHOD_GET,
+          NavigationService.class, "getCheckedOutDocs");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_ENTRY, METHOD_GET, ObjectService.class,
+          "getObject");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_OBJECTBYID, METHOD_GET, ObjectService.class,
+          "getObject");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_OBJECTBYPATH, METHOD_GET, ObjectService.class,
+          "getObjectByPath");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_ALLOWABLEACIONS, METHOD_GET,
+          ObjectService.class, "getAllowableActions");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_CONTENT, METHOD_GET, ObjectService.class,
+          "getContentStream");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_CONTENT, METHOD_PUT, ObjectService.class,
+          "setContentStream");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_CONTENT, METHOD_DELETE, ObjectService.class,
+          "deleteContentStream");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_CHILDREN, METHOD_POST, ObjectService.class,
+          "create");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_RELATIONSHIPS, METHOD_POST,
+          ObjectService.class, "createRelationship");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_ENTRY, METHOD_PUT, ObjectService.class,
+          "updateProperties");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_ENTRY, METHOD_DELETE, ObjectService.class,
+          "deleteObject");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_DESCENDANTS, METHOD_DELETE,
+          ObjectService.class, "deleteTree");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_CHECKEDOUT, METHOD_POST,
+          VersioningService.class, "checkOut");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_VERSIONS, METHOD_GET, VersioningService.class,
+          "getAllVersions");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_VERSIONS, METHOD_DELETE,
+          VersioningService.class, "deleteAllVersions");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_QUERY, METHOD_GET, DiscoveryService.class,
+          "query");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_QUERY, METHOD_POST, DiscoveryService.class,
+          "query");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_CHANGES, METHOD_GET, DiscoveryService.class,
+          "getContentChanges");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_RELATIONSHIPS, METHOD_GET,
+          RelationshipService.class, "getObjectRelationships");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_UNFILED, METHOD_POST, MultiFilingService.class,
+          "removeObjectFromFolder");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_ACL, METHOD_GET, AclService.class, "getAcl");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_ACL, METHOD_PUT, AclService.class, "applyAcl");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_POLICIES, METHOD_GET, PolicyService.class,
+          "getAppliedPolicies");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_POLICIES, METHOD_POST, PolicyService.class,
+          "applyPolicy");
+      fDispatcher.addResource(AtomPubUtils.RESOURCE_POLICIES, METHOD_DELETE, PolicyService.class,
+          "removePolicy");
+    }
+    catch (NoSuchMethodException e) {
+      LOG.error("Cannot initialize dispatcher!", e);
+    }
+  }
+
+  @Override
+  protected void service(HttpServletRequest request, HttpServletResponse response)
+      throws ServletException, IOException {
+
+    // create a context object
+    CallContext context = null;
+    try {
+      context = createContext(request);
+    }
+    catch (Exception e) {
+      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Context creation failed: "
+          + e.getMessage());
+      return;
+    }
+
+    // dispatch and handle exceptions
+    try {
+      dispatch(context, request, response);
+    }
+    catch (Exception e) {
+      if (e instanceof CmisPermissionDeniedException) {
+        if (context.getUsername() == null) {
+          response.setHeader("WWW-Authenticate", "Basic realm=\"CMIS\"");
+          response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization Required");
+        }
+        else {
+          response.sendError(getErrorCode((CmisPermissionDeniedException) e), e.getMessage());
+        }
+      }
+      else if (e instanceof CmisRuntimeException) {
+        LOG.error(e.getMessage(), e);
+        response.sendError(getErrorCode((CmisRuntimeException) e), e.getMessage());
+      }
+      else if (e instanceof CmisBaseException) {
+        response.sendError(getErrorCode((CmisBaseException) e), e.getMessage());
+      }
+      else {
+        LOG.error(e.getMessage(), e);
+        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+      }
+    }
+
+    // we are done.
+    response.flushBuffer();
+  }
+
+  /**
+   * Dispatches to feed, entry or whatever.
+   */
+  private void dispatch(CallContext context, HttpServletRequest request,
+      HttpServletResponse response) throws Exception {
+
+    // get services factory
+    AbstractServicesFactory servicesFactory = (AbstractServicesFactory) getServletContext()
+        .getAttribute(CmisRepositoryContextListener.SERVICES_FACTORY);
+
+    // analyze the path
+    String[] pathFragments = splitPath(request);
+
+    if (pathFragments.length < 2) {
+      // root -> service document
+      RepositoryService.getRepositories(context, servicesFactory, request, response);
+      return;
+    }
+
+    String method = request.getMethod();
+    String repositoryId = pathFragments[0];
+    String resource = pathFragments[1];
+
+    // dispatch
+    boolean methodFound = fDispatcher.dispatch(resource, method, context, servicesFactory,
+        repositoryId, request, response);
+
+    // if the dispatcher couldn't find a matching method, return an error message
+    if (!methodFound) {
+      response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Unknown operation");
+    }
+  }
+
+  /**
+   * Decodes basic auth and creates a {@link CallContext} object.
+   */
+  protected CallContext createContext(HttpServletRequest request) {
+    CallContextImpl context = new CallContextImpl(CallContext.BINDING_ATOMPUB);
+
+    // call call text handler
+    if (fCallContextHandler != null) {
+      Map<String, String> callContextMap = fCallContextHandler.getCallContextMap(request);
+      if (callContextMap != null) {
+        for (Map.Entry<String, String> e : callContextMap.entrySet()) {
+          context.put(e.getKey(), e.getValue());
+        }
+      }
+    }
+
+    // decode range
+    String rangeHeader = request.getHeader("Range");
+    if (rangeHeader != null) {
+      rangeHeader = rangeHeader.trim();
+      BigInteger offset = null;
+      BigInteger length = null;
+
+      int eq = rangeHeader.indexOf('=');
+      int ds = rangeHeader.indexOf('-');
+      if ((eq > 0) && (ds > eq)) {
+        String offsetStr = rangeHeader.substring(eq + 1, ds).trim();
+        if (offsetStr.length() > 0) {
+          offset = new BigInteger(offsetStr);
+        }
+
+        if (ds < rangeHeader.length()) {
+          String lengthStr = rangeHeader.substring(ds + 1).trim();
+          if (lengthStr.length() > 0) {
+            if (offset == null) {
+              length = new BigInteger(lengthStr);
+            }
+            else {
+              length = (new BigInteger(lengthStr)).subtract(offset);
+            }
+          }
+
+          if (offset != null) {
+            context.put(CallContext.OFFSET, offset.toString());
+          }
+          if (length != null) {
+            context.put(CallContext.LENGTH, length.toString());
+          }
+        }
+      }
+    }
+
+    return context;
+  }
+
+  /**
+   * Splits the path into its fragments.
+   */
+  private String[] splitPath(HttpServletRequest request) {
+    String p = request.getPathInfo();
+    if (p == null) {
+      return new String[0];
+    }
+
+    return p.substring(1).split("/");
+  }
+
+  /**
+   * Translates an exception in an appropriate HTTP error code.
+   */
+  private int getErrorCode(CmisBaseException ex) {
+    if (ex instanceof CmisConstraintException) {
+      return 409;
+    }
+    else if (ex instanceof CmisContentAlreadyExistsException) {
+      return 409;
+    }
+    else if (ex instanceof CmisFilterNotValidException) {
+      return 400;
+    }
+    else if (ex instanceof CmisInvalidArgumentException) {
+      return 400;
+    }
+    else if (ex instanceof CmisNameConstraintViolationException) {
+      return 409;
+    }
+    else if (ex instanceof CmisNotSupportedException) {
+      return 405;
+    }
+    else if (ex instanceof CmisObjectNotFoundException) {
+      return 404;
+    }
+    else if (ex instanceof CmisPermissionDeniedException) {
+      return 403;
+    }
+    else if (ex instanceof CmisStorageException) {
+      return 500;
+    }
+    else if (ex instanceof CmisStreamNotSupportedException) {
+      return 403;
+    }
+    else if (ex instanceof CmisUpdateConflictException) {
+      return 409;
+    }
+    else if (ex instanceof CmisVersioningException) {
+      return 409;
+    }
+
+    return 500;
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/CmisAtomPubServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/DiscoveryService.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/DiscoveryService.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/DiscoveryService.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/DiscoveryService.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,291 @@
+/*
+ * 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.server.impl.atompub;
+
+import static org.apache.opencmis.commons.impl.Converter.convert;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CHANGES;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_QUERY;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.compileBaseUrl;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.compileUrlBuilder;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getBigIntegerParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getBooleanParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getEnumParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getStringParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.writeObjectEntry;
+
+import java.math.BigInteger;
+import java.util.GregorianCalendar;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.opencmis.commons.enums.IncludeRelationships;
+import org.apache.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.opencmis.commons.exceptions.CmisRuntimeException;
+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.jaxb.CmisObjectType;
+import org.apache.opencmis.commons.impl.jaxb.CmisQueryType;
+import org.apache.opencmis.commons.provider.Holder;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.commons.provider.ObjectList;
+import org.apache.opencmis.server.impl.ObjectInfoHolderImpl;
+import org.apache.opencmis.server.spi.AbstractServicesFactory;
+import org.apache.opencmis.server.spi.CallContext;
+import org.apache.opencmis.server.spi.CmisDiscoveryService;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+
+/**
+ * Discovery Service operations.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class DiscoveryService {
+
+  private static final String METHOD_GET = "GET";
+  private static final String METHOD_POST = "POST";
+
+  /**
+   * Query.
+   */
+  public static void query(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisDiscoveryService service = factory.getDiscoveryService();
+
+    // get parameters
+    String statement = null;
+    Boolean searchAllVersions = null;
+    Boolean includeAllowableActions = null;
+    IncludeRelationships includeRelationships = null;
+    String renditionFilter = null;
+    BigInteger maxItems = null;
+    BigInteger skipCount = null;
+
+    int statusCode = 0;
+
+    if (METHOD_POST.equals(request.getMethod())) {
+      // POST -> read from stream
+      Object queryRequest = null;
+      try {
+        Unmarshaller u = JaxBHelper.createUnmarshaller();
+        queryRequest = u.unmarshal(request.getInputStream());
+      }
+      catch (Exception e) {
+        throw new CmisInvalidArgumentException("Invalid query request: " + e, e);
+      }
+
+      if (!(queryRequest instanceof JAXBElement<?>)) {
+        throw new CmisInvalidArgumentException("Not a query document!");
+      }
+
+      if (!(((JAXBElement<?>) queryRequest).getValue() instanceof CmisQueryType)) {
+        throw new CmisInvalidArgumentException("Not a query document!");
+      }
+
+      CmisQueryType queryType = (CmisQueryType) ((JAXBElement<?>) queryRequest).getValue();
+
+      statement = queryType.getStatement();
+      searchAllVersions = queryType.isSearchAllVersions();
+      includeAllowableActions = queryType.isIncludeAllowableActions();
+      includeRelationships = convert(IncludeRelationships.class, queryType
+          .getIncludeRelationships());
+      renditionFilter = queryType.getRenditionFilter();
+      maxItems = queryType.getMaxItems();
+      skipCount = queryType.getSkipCount();
+
+      statusCode = HttpServletResponse.SC_CREATED;
+    }
+    else if (METHOD_GET.equals(request.getMethod())) {
+      // GET -> parameters
+      statement = getStringParameter(request, Constants.PARAM_Q);
+      searchAllVersions = getBooleanParameter(request, Constants.PARAM_SEARCH_ALL_VERSIONS);
+      includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
+      includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
+          IncludeRelationships.class);
+      renditionFilter = null;
+      maxItems = getBigIntegerParameter(request, Constants.PARAM_MAX_ITEMS);
+      skipCount = getBigIntegerParameter(request, Constants.PARAM_SKIP_COUNT);
+
+      statusCode = HttpServletResponse.SC_OK;
+    }
+    else {
+      throw new CmisRuntimeException("Invalid HTTP method!");
+    }
+
+    // execute
+    ObjectList results = service.query(context, repositoryId, statement, searchAllVersions,
+        includeAllowableActions, includeRelationships, renditionFilter, maxItems, skipCount, null);
+
+    if (results == null) {
+      throw new CmisRuntimeException("Results are null!");
+    }
+
+    // set headers
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    UrlBuilder pagingUrl = compileUrlBuilder(baseUrl, RESOURCE_QUERY, null);
+    pagingUrl.addParameter(Constants.PARAM_Q, statement);
+    pagingUrl.addParameter(Constants.PARAM_SEARCH_ALL_VERSIONS, searchAllVersions);
+    pagingUrl.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+    pagingUrl.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+
+    UrlBuilder location = new UrlBuilder(pagingUrl);
+    location.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+    location.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
+
+    response.setStatus(statusCode);
+    response.setContentType(Constants.MEDIATYPE_FEED);
+    response.setHeader("Content-Location", location.toString());
+    response.setHeader("Location", location.toString());
+
+    // write XML
+    AtomFeed feed = new AtomFeed();
+    feed.startDocument(response.getOutputStream());
+    feed.startFeed(true);
+
+    // write basic Atom feed elements
+    GregorianCalendar now = new GregorianCalendar();
+    feed.writeFeedElements("query", "", "Query", now, null, results.getNumItems());
+
+    // write links
+    feed.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    feed.writePagingLinks(pagingUrl, maxItems, skipCount, results.getNumItems(), results
+        .hasMoreItems(), AtomPubUtils.PAGE_SIZE);
+
+    if (results.getObjects() != null) {
+      AtomEntry entry = new AtomEntry(feed.getWriter());
+      int idCounter = 0;
+      for (ObjectData result : results.getObjects()) {
+        if (result == null) {
+          continue;
+        }
+        idCounter++;
+        writeQueryResultEntry(entry, result, "id-" + idCounter, now);
+      }
+    }
+
+    // we are done
+    feed.endFeed();
+    feed.endDocument();
+  }
+
+  private static void writeQueryResultEntry(AtomEntry entry, ObjectData result, String id,
+      GregorianCalendar now) throws Exception {
+    CmisObjectType resultJaxb = convert(result);
+    if (resultJaxb == null) {
+      return;
+    }
+
+    // start
+    entry.startEntry(false);
+
+    // write Atom base tags
+    entry.writeAuthor("");
+    entry.writeId(entry.generateAtomId(id));
+    entry.writePublished(now);
+    entry.writeTitle("Query Result " + id);
+    entry.writeUpdated(now);
+
+    // write query result object
+    JaxBHelper.marshal(JaxBHelper.CMIS_EXTRA_OBJECT_FACTORY.createObject(resultJaxb), entry
+        .getWriter(), true);
+
+    // we are done
+    entry.endEntry();
+  }
+
+  /**
+   * Get content changes.
+   */
+  public static void getContentChanges(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisDiscoveryService service = factory.getDiscoveryService();
+
+    // get parameters
+    String changeLogToken = getStringParameter(request, Constants.PARAM_CHANGE_LOG_TOKEN);
+    Boolean includeProperties = getBooleanParameter(request, Constants.PARAM_PROPERTIES);
+    String filter = getStringParameter(request, Constants.PARAM_FILTER);
+    Boolean includePolicyIds = getBooleanParameter(request, Constants.PARAM_POLICY_IDS);
+    Boolean includeAcl = getBooleanParameter(request, Constants.PARAM_ACL);
+    BigInteger maxItems = getBigIntegerParameter(request, Constants.PARAM_MAX_ITEMS);
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    Holder<String> changeLogTokenHolder = new Holder<String>(changeLogToken);
+    ObjectList changes = service.getContentChanges(context, repositoryId, changeLogTokenHolder,
+        includeProperties, filter, includePolicyIds, includeAcl, maxItems, null, objectInfoHolder);
+
+    if (changes == null) {
+      throw new CmisRuntimeException("Changes are null!");
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_FEED);
+
+    // write XML
+    AtomFeed feed = new AtomFeed();
+    feed.startDocument(response.getOutputStream());
+    feed.startFeed(true);
+
+    // write basic Atom feed elements
+    GregorianCalendar now = new GregorianCalendar();
+    feed
+        .writeFeedElements("contentChanges", "", "Content Change", now, null, changes.getNumItems());
+
+    // write links
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    feed.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    if (changeLogTokenHolder.getValue() != null) {
+      UrlBuilder nextLink = compileUrlBuilder(baseUrl, RESOURCE_CHANGES, null);
+      nextLink.addParameter(Constants.PARAM_CHANGE_LOG_TOKEN, changeLogTokenHolder.getValue());
+      nextLink.addParameter(Constants.PARAM_PROPERTIES, includeProperties);
+      nextLink.addParameter(Constants.PARAM_FILTER, filter);
+      nextLink.addParameter(Constants.PARAM_POLICY_IDS, includePolicyIds);
+      nextLink.addParameter(Constants.PARAM_ACL, includeAcl);
+      nextLink.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+      feed.writeNextLink(nextLink.toString());
+    }
+
+    // write entries
+    if (changes.getObjects() != null) {
+      AtomEntry entry = new AtomEntry(feed.getWriter());
+      for (ObjectData object : changes.getObjects()) {
+        if (object == null) {
+          continue;
+        }
+        writeObjectEntry(entry, object, objectInfoHolder, null, repositoryId, null, null, baseUrl,
+            false);
+      }
+    }
+
+    // we are done
+    feed.endFeed();
+    feed.endDocument();
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/DiscoveryService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/Dispatcher.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/Dispatcher.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/Dispatcher.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/Dispatcher.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,108 @@
+/*
+ * 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.server.impl.atompub;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.opencmis.commons.exceptions.CmisBaseException;
+import org.apache.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.opencmis.server.spi.AbstractServicesFactory;
+import org.apache.opencmis.server.spi.CallContext;
+
+/**
+ * Dispatcher for the AtomPub servlet.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class Dispatcher {
+
+  private static final Log LOG = LogFactory.getLog(Dispatcher.class.getName());
+
+  private Map<String, Method> fMethodMap = new HashMap<String, Method>();
+
+  public Dispatcher() {
+  }
+
+  /**
+   * Connects a resource and HTTP method with a class and a class method.
+   */
+  public synchronized void addResource(String resource, String httpMethod, Class<?> clazz,
+      String classmethod) throws NoSuchMethodException {
+
+    Method m = clazz.getMethod(classmethod, CallContext.class, AbstractServicesFactory.class,
+        String.class, HttpServletRequest.class, HttpServletResponse.class);
+
+    fMethodMap.put(getKey(resource, httpMethod), m);
+  }
+
+  /**
+   * Find the appropriate method an call it.
+   * 
+   * @return <code>true</code> if the method was found, <code>false</code> otherwise.
+   */
+  public boolean dispatch(String resource, String httpMethod, CallContext context,
+      AbstractServicesFactory factory, String repositoryId, HttpServletRequest request,
+      HttpServletResponse response) {
+
+    Method m = fMethodMap.get(getKey(resource, httpMethod));
+    if (m == null) {
+      return false;
+    }
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug(repositoryId + " / " + resource + ", " + httpMethod + " -> " + m.getName());
+    }
+
+    try {
+      m.invoke(null, context, factory, repositoryId, request, response);
+    }
+    catch (IllegalArgumentException e) {
+      throw e;
+    }
+    catch (IllegalAccessException e) {
+      throw new CmisRuntimeException("Internal error!", e);
+    }
+    catch (InvocationTargetException e) {
+      if (e.getCause() instanceof CmisBaseException) {
+        throw (CmisBaseException) e.getCause();
+      }
+      else {
+        throw new CmisRuntimeException(e.getMessage(), e);
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Generates a map key from a resource and an HTTP method.
+   */
+  private String getKey(String resource, String httpMethod) {
+    return resource + "/" + httpMethod;
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/Dispatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/MultiFilingService.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/MultiFilingService.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/MultiFilingService.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/MultiFilingService.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,88 @@
+/*
+ * 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.server.impl.atompub;
+
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_ENTRY;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.compileBaseUrl;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.compileUrl;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getStringParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.writeObjectEntry;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+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.provider.ObjectData;
+import org.apache.opencmis.server.impl.ObjectInfoHolderImpl;
+import org.apache.opencmis.server.spi.AbstractServicesFactory;
+import org.apache.opencmis.server.spi.CallContext;
+import org.apache.opencmis.server.spi.CmisMultiFilingService;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+
+/**
+ * MultiFiling Service operations.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class MultiFilingService {
+
+  /**
+   * Remove object from folder.
+   */
+  public static void removeObjectFromFolder(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisMultiFilingService service = factory.getMultiFilingService();
+
+    // get parameters
+    String removeFrom = getStringParameter(request, Constants.PARAM_REMOVE_FROM);
+
+    AtomEntryParser parser = new AtomEntryParser(request.getInputStream());
+    String objectId = parser.getId();
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    ObjectData object = service.removeObjectFromFolder(context, repositoryId, objectId, removeFrom,
+        null, objectInfoHolder);
+
+    if (object == null) {
+      throw new CmisRuntimeException("Object is null!");
+    }
+
+    if (object.getId() == null) {
+      throw new CmisRuntimeException("Object Id is null!");
+    }
+
+    // set headers
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    response.setStatus(HttpServletResponse.SC_CREATED);
+    response.setContentType(Constants.MEDIATYPE_ENTRY);
+    response.setHeader("Location", compileUrl(baseUrl, RESOURCE_ENTRY, object.getId()));
+
+    // write XML
+    AtomEntry entry = new AtomEntry();
+    entry.startDocument(response.getOutputStream());
+    writeObjectEntry(entry, object, objectInfoHolder, null, repositoryId, null, null, baseUrl, true);
+    entry.endDocument();
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/MultiFilingService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/NavigationService.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/NavigationService.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/NavigationService.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/NavigationService.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,544 @@
+/*
+ * 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.server.impl.atompub;
+
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_ACL;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_ALLOWABLEACIONS;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CHECKEDOUT;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CHILDREN;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CONTENT;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_DESCENDANTS;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_ENTRY;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_FOLDERTREE;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_PARENTS;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_POLICIES;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_RELATIONSHIPS;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_TYPE;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.compileBaseUrl;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.compileUrl;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.compileUrlBuilder;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getBigIntegerParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getBooleanParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getEnumParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getStringParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.writeObjectEntry;
+
+import java.math.BigInteger;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.opencmis.commons.enums.IncludeRelationships;
+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.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;
+import org.apache.opencmis.server.impl.ObjectInfoHolderImpl;
+import org.apache.opencmis.server.spi.AbstractServicesFactory;
+import org.apache.opencmis.server.spi.CallContext;
+import org.apache.opencmis.server.spi.CmisNavigationService;
+import org.apache.opencmis.server.spi.ObjectInfo;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+import org.apache.opencmis.server.spi.ObjectInfoImpl;
+import org.apache.opencmis.server.spi.RenditionInfo;
+
+/**
+ * Navigation Service operations.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public final class NavigationService {
+
+  /**
+   * Children Collection GET.
+   */
+  public static void getChildren(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisNavigationService service = factory.getNavigationService();
+
+    // get parameters
+    String folderId = getStringParameter(request, Constants.PARAM_ID);
+    String filter = getStringParameter(request, Constants.PARAM_FILTER);
+    String orderBy = getStringParameter(request, Constants.PARAM_ORDER_BY);
+    Boolean includeAllowableActions = getBooleanParameter(request,
+        Constants.PARAM_ALLOWABLE_ACTIONS);
+    IncludeRelationships includeRelationships = getEnumParameter(request,
+        Constants.PARAM_RELATIONSHIPS, IncludeRelationships.class);
+    String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+    Boolean includePathSegment = getBooleanParameter(request, Constants.PARAM_PATH_SEGMENT);
+    BigInteger maxItems = getBigIntegerParameter(request, Constants.PARAM_MAX_ITEMS);
+    BigInteger skipCount = getBigIntegerParameter(request, Constants.PARAM_SKIP_COUNT);
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    ObjectInFolderList children = service.getChildren(context, repositoryId, folderId, filter,
+        orderBy, includeAllowableActions, includeRelationships, renditionFilter,
+        includePathSegment, maxItems, skipCount, null, objectInfoHolder);
+
+    if (children == null) {
+      throw new CmisRuntimeException("Children are null!");
+    }
+
+    ObjectInfo folderInfo = objectInfoHolder.getObjectInfo(folderId);
+    if (folderInfo == null) {
+      throw new CmisRuntimeException("Folder Object Info is missing!");
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_FEED);
+
+    // write XML
+    AtomFeed feed = new AtomFeed();
+    feed.startDocument(response.getOutputStream());
+    feed.startFeed(true);
+
+    // write basic Atom feed elements
+    feed.writeFeedElements(folderInfo.getId(), folderInfo.getCreatedBy(), folderInfo.getName(),
+        folderInfo.getLastModificationDate(), null, children.getNumItems());
+
+    // write links
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    feed.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()), null);
+
+    feed.writeDescribedByLink(compileUrl(baseUrl, RESOURCE_TYPE, folderInfo.getTypeId()));
+
+    feed
+        .writeAllowableActionsLink(compileUrl(baseUrl, RESOURCE_ALLOWABLEACIONS, folderInfo.getId()));
+
+    feed.writeDownLink(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()),
+        Constants.MEDIATYPE_FEED);
+
+    if (folderInfo.supportsDescendants()) {
+      feed.writeDownLink(compileUrl(baseUrl, RESOURCE_DESCENDANTS, folderInfo.getId()),
+          Constants.MEDIATYPE_DESCENDANTS);
+    }
+
+    if (folderInfo.supportsFolderTree()) {
+      feed.writeFolderTreeLink(compileUrl(baseUrl, RESOURCE_FOLDERTREE, folderInfo.getId()));
+    }
+
+    if (folderInfo.hasParent()) {
+      feed.writeUpLink(compileUrl(baseUrl, RESOURCE_PARENTS, folderInfo.getId()),
+          Constants.MEDIATYPE_FEED);
+    }
+
+    if (folderInfo.getRenditionInfos() != null) {
+      for (RenditionInfo ri : folderInfo.getRenditionInfos()) {
+        feed.writeAlternateLink(compileUrl(baseUrl, RESOURCE_CONTENT, ri.getId()), ri
+            .getContenType(), ri.getKind(), ri.getTitle(), ri.getLength());
+      }
+    }
+
+    if (folderInfo.hasAcl()) {
+      feed.writeAclLink(compileUrl(baseUrl, RESOURCE_ACL, folderInfo.getId()));
+    }
+
+    if (folderInfo.supportsPolicies()) {
+      feed.writeAclLink(compileUrl(baseUrl, RESOURCE_POLICIES, folderInfo.getId()));
+    }
+
+    if (folderInfo.supportsRelationships()) {
+      feed.writeRelationshipsLink(compileUrl(baseUrl, RESOURCE_RELATIONSHIPS, folderInfo.getId()));
+    }
+
+    UrlBuilder pagingUrl = new UrlBuilder(compileUrlBuilder(baseUrl, RESOURCE_CHILDREN, folderInfo
+        .getId()));
+    pagingUrl.addParameter(Constants.PARAM_FILTER, filter);
+    pagingUrl.addParameter(Constants.PARAM_ORDER_BY, orderBy);
+    pagingUrl.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+    pagingUrl.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+    pagingUrl.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
+    pagingUrl.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
+    feed.writePagingLinks(pagingUrl, maxItems, skipCount, children.getNumItems(), children
+        .hasMoreItems(), AtomPubUtils.PAGE_SIZE);
+
+    // write collection
+    feed.writeCollection(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()), null,
+        "Folder collection", Constants.MEDIATYPE_CMISATOM);
+
+    // write entries
+    if (children.getObjects() != null) {
+      AtomEntry entry = new AtomEntry(feed.getWriter());
+      for (ObjectInFolderData object : children.getObjects()) {
+        if ((object == null) || (object.getObject() == null)) {
+          continue;
+        }
+        writeObjectEntry(entry, object.getObject(), objectInfoHolder, null, repositoryId, object
+            .getPathSegment(), null, baseUrl, false);
+      }
+    }
+
+    // we are done
+    feed.endFeed();
+    feed.endDocument();
+  }
+
+  /**
+   * Descendants feed GET.
+   */
+  public static void getDescendants(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisNavigationService service = factory.getNavigationService();
+
+    // get parameters
+    String folderId = getStringParameter(request, Constants.PARAM_ID);
+    BigInteger depth = getBigIntegerParameter(request, Constants.PARAM_DEPTH);
+    String filter = getStringParameter(request, Constants.PARAM_FILTER);
+    Boolean includeAllowableActions = getBooleanParameter(request,
+        Constants.PARAM_ALLOWABLE_ACTIONS);
+    IncludeRelationships includeRelationships = getEnumParameter(request,
+        Constants.PARAM_RELATIONSHIPS, IncludeRelationships.class);
+    String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+    Boolean includePathSegment = getBooleanParameter(request, Constants.PARAM_PATH_SEGMENT);
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    List<ObjectInFolderContainer> descendants = service.getDescendants(context, repositoryId,
+        folderId, depth, filter, includeAllowableActions, includeRelationships, renditionFilter,
+        includePathSegment, null, objectInfoHolder);
+
+    if (descendants == null) {
+      throw new CmisRuntimeException("Descendants are null!");
+    }
+
+    ObjectInfo folderInfo = objectInfoHolder.getObjectInfo(folderId);
+    if (folderInfo == null) {
+      throw new CmisRuntimeException("Folder Object Info is missing!");
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_FEED);
+
+    // write XML
+    AtomFeed feed = new AtomFeed();
+    feed.startDocument(response.getOutputStream());
+    feed.startFeed(true);
+
+    // write basic Atom feed elements
+    feed.writeFeedElements(folderInfo.getId(), folderInfo.getCreatedBy(), folderInfo.getName(),
+        folderInfo.getLastModificationDate(), null, null);
+
+    // write links
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    feed.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_DESCENDANTS, folderInfo.getId()), null);
+
+    feed.writeViaLink(compileUrl(baseUrl, RESOURCE_ENTRY, folderInfo.getId()));
+
+    feed.writeDownLink(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()),
+        Constants.MEDIATYPE_FEED);
+
+    if (folderInfo.supportsFolderTree()) {
+      feed.writeFolderTreeLink(compileUrl(baseUrl, RESOURCE_FOLDERTREE, folderInfo.getId()));
+    }
+
+    if (folderInfo.hasParent()) {
+      feed.writeUpLink(compileUrl(baseUrl, RESOURCE_PARENTS, folderInfo.getId()),
+          Constants.MEDIATYPE_FEED);
+    }
+
+    // write entries
+    AtomEntry entry = new AtomEntry(feed.getWriter());
+    for (ObjectInFolderContainer container : descendants) {
+      if ((container == null) || (container.getObject() == null)
+          || (container.getObject().getObject() == null)) {
+        continue;
+      }
+      writeObjectEntry(entry, container.getObject().getObject(), objectInfoHolder, container
+          .getChildren(), repositoryId, container.getObject().getPathSegment(), null, baseUrl,
+          false);
+    }
+
+    // we are done
+    feed.endFeed();
+    feed.endDocument();
+  }
+
+  /**
+   * Folder tree feed GET.
+   */
+  public static void getFolderTree(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisNavigationService service = factory.getNavigationService();
+
+    // get parameters
+    String folderId = getStringParameter(request, Constants.PARAM_ID);
+    BigInteger depth = getBigIntegerParameter(request, Constants.PARAM_DEPTH);
+    String filter = getStringParameter(request, Constants.PARAM_FILTER);
+    Boolean includeAllowableActions = getBooleanParameter(request,
+        Constants.PARAM_ALLOWABLE_ACTIONS);
+    IncludeRelationships includeRelationships = getEnumParameter(request,
+        Constants.PARAM_RELATIONSHIPS, IncludeRelationships.class);
+    String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+    Boolean includePathSegment = getBooleanParameter(request, Constants.PARAM_PATH_SEGMENT);
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    List<ObjectInFolderContainer> folderTree = service.getFolderTree(context, repositoryId,
+        folderId, depth, filter, includeAllowableActions, includeRelationships, renditionFilter,
+        includePathSegment, null, objectInfoHolder);
+
+    if (folderTree == null) {
+      throw new CmisRuntimeException("Folder tree is null!");
+    }
+
+    ObjectInfo folderInfo = objectInfoHolder.getObjectInfo(folderId);
+    if (folderInfo == null) {
+      throw new CmisRuntimeException("Folder Object Info is missing!");
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_FEED);
+
+    // write XML
+    AtomFeed feed = new AtomFeed();
+    feed.startDocument(response.getOutputStream());
+    feed.startFeed(true);
+
+    // write basic Atom feed elements
+    feed.writeFeedElements(folderInfo.getId(), folderInfo.getCreatedBy(), folderInfo.getName(),
+        folderInfo.getLastModificationDate(), null, null);
+
+    // write links
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    feed.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_DESCENDANTS, folderInfo.getId()), null);
+
+    feed.writeViaLink(compileUrl(baseUrl, RESOURCE_ENTRY, folderInfo.getId()));
+
+    feed.writeDownLink(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()),
+        Constants.MEDIATYPE_FEED);
+
+    if (folderInfo.supportsDescendants()) {
+      feed.writeDownLink(compileUrl(baseUrl, RESOURCE_DESCENDANTS, folderInfo.getId()),
+          Constants.MEDIATYPE_DESCENDANTS);
+    }
+
+    if (folderInfo.hasParent()) {
+      feed.writeUpLink(compileUrl(baseUrl, RESOURCE_PARENTS, folderInfo.getId()),
+          Constants.MEDIATYPE_FEED);
+    }
+
+    // write entries
+    AtomEntry entry = new AtomEntry(feed.getWriter());
+    for (ObjectInFolderContainer container : folderTree) {
+      if ((container == null) || (container.getObject() == null)
+          || (container.getObject().getObject() == null)) {
+        continue;
+      }
+      writeObjectEntry(entry, container.getObject().getObject(), objectInfoHolder, container
+          .getChildren(), repositoryId, container.getObject().getPathSegment(), null, baseUrl,
+          false);
+    }
+
+    // we are done
+    feed.endFeed();
+    feed.endDocument();
+  }
+
+  /**
+   * Object parents feed GET.
+   */
+  public static void getObjectParents(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisNavigationService service = factory.getNavigationService();
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+    String filter = getStringParameter(request, Constants.PARAM_FILTER);
+    Boolean includeAllowableActions = getBooleanParameter(request,
+        Constants.PARAM_ALLOWABLE_ACTIONS);
+    IncludeRelationships includeRelationships = getEnumParameter(request,
+        Constants.PARAM_RELATIONSHIPS, IncludeRelationships.class);
+    String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+    Boolean includeRelativePathSegment = getBooleanParameter(request,
+        Constants.PARAM_RELATIVE_PATH_SEGMENT);
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    List<ObjectParentData> parents = service.getObjectParents(context, repositoryId, objectId,
+        filter, includeAllowableActions, includeRelationships, renditionFilter,
+        includeRelativePathSegment, null, objectInfoHolder);
+
+    if (parents == null) {
+      throw new CmisRuntimeException("Parents are null!");
+    }
+
+    ObjectInfo objectInfo = objectInfoHolder.getObjectInfo(objectId);
+    if (objectInfo == null) {
+      throw new CmisRuntimeException("Object Info is missing!");
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_FEED);
+
+    // write XML
+    AtomFeed feed = new AtomFeed();
+    feed.startDocument(response.getOutputStream());
+    feed.startFeed(true);
+
+    // write basic Atom feed elements
+    feed.writeFeedElements(objectInfo.getId(), objectInfo.getCreatedBy(), objectInfo.getName(),
+        objectInfo.getLastModificationDate(), null, null);
+
+    // write links
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    feed.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_PARENTS, objectInfo.getId()), null);
+
+    // write entries
+    if (parents != null) {
+      AtomEntry entry = new AtomEntry(feed.getWriter());
+      for (ObjectParentData object : parents) {
+        if ((object == null) || (object.getObject() == null)) {
+          continue;
+        }
+        writeObjectEntry(entry, object.getObject(), objectInfoHolder, null, repositoryId, null,
+            object.getRelativePathSegment(), baseUrl, false);
+      }
+    }
+
+    // we are done
+    feed.endFeed();
+    feed.endDocument();
+  }
+
+  /**
+   * Checked Out Collection GET.
+   */
+  public static void getCheckedOutDocs(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisNavigationService service = factory.getNavigationService();
+
+    // get parameters
+    String folderId = getStringParameter(request, Constants.PARAM_ID);
+    String filter = getStringParameter(request, Constants.PARAM_FILTER);
+    String orderBy = getStringParameter(request, Constants.PARAM_ORDER_BY);
+    Boolean includeAllowableActions = getBooleanParameter(request,
+        Constants.PARAM_ALLOWABLE_ACTIONS);
+    IncludeRelationships includeRelationships = getEnumParameter(request,
+        Constants.PARAM_RELATIONSHIPS, IncludeRelationships.class);
+    String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+    BigInteger maxItems = getBigIntegerParameter(request, Constants.PARAM_MAX_ITEMS);
+    BigInteger skipCount = getBigIntegerParameter(request, Constants.PARAM_SKIP_COUNT);
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    ObjectList checkedOut = service.getCheckedOutDocs(context, repositoryId, folderId, filter,
+        orderBy, includeAllowableActions, includeRelationships, renditionFilter, maxItems,
+        skipCount, null, objectInfoHolder);
+
+    if (checkedOut == null) {
+      throw new CmisRuntimeException("Checked Out list is null!");
+    }
+
+    ObjectInfo folderInfo = null;
+    if (folderId != null) {
+      folderInfo = objectInfoHolder.getObjectInfo(folderId);
+      if (folderInfo == null) {
+        throw new CmisRuntimeException("Folder Object Info is missing!");
+      }
+    }
+    else {
+      folderInfo = new ObjectInfoImpl();
+      GregorianCalendar now = new GregorianCalendar();
+
+      ((ObjectInfoImpl) folderInfo).setId("uri:x-checkedout");
+      ((ObjectInfoImpl) folderInfo).setName("Checked Out");
+      ((ObjectInfoImpl) folderInfo).setCreatedBy("");
+      ((ObjectInfoImpl) folderInfo).setCreationDate(now);
+      ((ObjectInfoImpl) folderInfo).setLastModificationDate(now);
+      ((ObjectInfoImpl) folderInfo).setHasParent(false);
+      ((ObjectInfoImpl) folderInfo).setSupportsDescendants(false);
+      ((ObjectInfoImpl) folderInfo).setSupportsFolderTree(false);
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_FEED);
+
+    // write XML
+    AtomFeed feed = new AtomFeed();
+    feed.startDocument(response.getOutputStream());
+    feed.startFeed(true);
+
+    // write basic Atom feed elements
+    feed.writeFeedElements(folderInfo.getId(), folderInfo.getCreatedBy(), folderInfo.getName(),
+        folderInfo.getLastModificationDate(), null, checkedOut.getNumItems());
+
+    // write links
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    feed.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_CHECKEDOUT, folderInfo.getId()), null);
+
+    UrlBuilder pagingUrl = new UrlBuilder(compileUrlBuilder(baseUrl, RESOURCE_CHECKEDOUT,
+        folderInfo.getId()));
+    pagingUrl.addParameter(Constants.PARAM_FILTER, filter);
+    pagingUrl.addParameter(Constants.PARAM_ORDER_BY, orderBy);
+    pagingUrl.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+    pagingUrl.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+    pagingUrl.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
+    feed.writePagingLinks(pagingUrl, maxItems, skipCount, checkedOut.getNumItems(), checkedOut
+        .hasMoreItems(), AtomPubUtils.PAGE_SIZE);
+
+    // write entries
+    if (checkedOut.getObjects() != null) {
+      AtomEntry entry = new AtomEntry(feed.getWriter());
+      for (ObjectData object : checkedOut.getObjects()) {
+        if (object == null) {
+          continue;
+        }
+        writeObjectEntry(entry, object, objectInfoHolder, null, repositoryId, null, null, baseUrl,
+            false);
+      }
+    }
+
+    // we are done
+    feed.endFeed();
+    feed.endDocument();
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/NavigationService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/ObjectService.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/ObjectService.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/ObjectService.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/ObjectService.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,562 @@
+/*
+ * 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.server.impl.atompub;
+
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CONTENT;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_ENTRY;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.compileBaseUrl;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.compileUrl;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getBooleanParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getEnumParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getStringParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.writeObjectEntry;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.opencmis.commons.PropertyIds;
+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.CmisRuntimeException;
+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.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.PropertiesData;
+import org.apache.opencmis.commons.provider.PropertyData;
+import org.apache.opencmis.commons.provider.PropertyStringData;
+import org.apache.opencmis.server.impl.ObjectInfoHolderImpl;
+import org.apache.opencmis.server.spi.AbstractServicesFactory;
+import org.apache.opencmis.server.spi.CallContext;
+import org.apache.opencmis.server.spi.CmisMultiFilingService;
+import org.apache.opencmis.server.spi.CmisObjectService;
+import org.apache.opencmis.server.spi.CmisVersioningService;
+import org.apache.opencmis.server.spi.ObjectInfo;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+
+/**
+ * Object Service operations.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public final class ObjectService {
+
+  private static final int BUFFER_SIZE = 64 * 1024;
+
+  /**
+   * Create*.
+   */
+  public static void create(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+
+    // get parameters
+    String folderId = getStringParameter(request, Constants.PARAM_ID);
+    String sourceFolderId = getStringParameter(request, Constants.PARAM_SOURCE_FOLDER_ID);
+    VersioningState versioningState = getEnumParameter(request, Constants.PARAM_VERSIONIG_STATE,
+        VersioningState.class);
+
+    AtomEntryParser parser = new AtomEntryParser(request.getInputStream());
+    String objectId = parser.getId();
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    ObjectData object = null;
+
+    if (objectId == null) {
+      // create
+      CmisObjectService service = factory.getObjectService();
+      object = service.create(context, repositoryId, parser.getProperties(), folderId, parser
+          .getContentStream(), versioningState, parser.getPolicyIds(), null, objectInfoHolder);
+    }
+    else {
+      if ((sourceFolderId == null) || (sourceFolderId.trim().length() == 0)) {
+        // addObjectToFolder
+        CmisMultiFilingService service = factory.getMultiFilingService();
+        object = service.addObjectToFolder(context, repositoryId, objectId, sourceFolderId, null,
+            null, objectInfoHolder);
+      }
+      else {
+        // move
+        CmisObjectService service = factory.getObjectService();
+        object = service.moveObject(context, repositoryId, new Holder<String>(objectId), folderId,
+            sourceFolderId, null, objectInfoHolder);
+      }
+    }
+
+    if (object == null) {
+      throw new CmisRuntimeException("Object is null!");
+    }
+
+    if (object.getId() == null) {
+      throw new CmisRuntimeException("Object Id is null!");
+    }
+
+    // set headers
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    response.setStatus(HttpServletResponse.SC_CREATED);
+    response.setContentType(Constants.MEDIATYPE_ENTRY);
+    response.setHeader("Location", compileUrl(baseUrl, RESOURCE_ENTRY, object.getId()));
+
+    // write XML
+    AtomEntry entry = new AtomEntry();
+    entry.startDocument(response.getOutputStream());
+    writeObjectEntry(entry, object, objectInfoHolder, null, repositoryId, null, null, baseUrl, true);
+    entry.endDocument();
+  }
+
+  /**
+   * Create relationship.
+   */
+  public static void createRelationship(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisObjectService service = factory.getObjectService();
+
+    // get parameters
+    AtomEntryParser parser = new AtomEntryParser(request.getInputStream());
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    ObjectData object = service.create(context, repositoryId, parser.getProperties(), null, null,
+        null, parser.getPolicyIds(), null, objectInfoHolder);
+
+    // set headers
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    response.setStatus(HttpServletResponse.SC_CREATED);
+    response.setContentType(Constants.MEDIATYPE_ENTRY);
+    response.setHeader("Location", compileUrl(baseUrl, RESOURCE_ENTRY, object.getId()));
+
+    // write XML
+    AtomEntry entry = new AtomEntry();
+    entry.startDocument(response.getOutputStream());
+    writeObjectEntry(entry, object, objectInfoHolder, null, repositoryId, null, null, baseUrl, true);
+    entry.endDocument();
+  }
+
+  /**
+   * Delete object.
+   */
+  public static void deleteObject(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisObjectService service = factory.getObjectService();
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+    Boolean allVersions = getBooleanParameter(request, Constants.PARAM_ALL_VERSIONS);
+
+    // execute
+    service.deleteObjectOrCancelCheckOut(context, repositoryId, objectId, allVersions, null);
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_NO_CONTENT);
+  }
+
+  /**
+   * Delete content stream.
+   */
+  public static void deleteContentStream(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisObjectService service = factory.getObjectService();
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+    String changeToken = getStringParameter(request, Constants.PARAM_CHANGE_TOKEN);
+
+    // execute
+    service.deleteContentStream(context, repositoryId, new Holder<String>(objectId),
+        changeToken == null ? null : new Holder<String>(changeToken), null);
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_NO_CONTENT);
+  }
+
+  /**
+   * Set content stream.
+   */
+  public static void setContentStream(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisObjectService service = factory.getObjectService();
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+    String changeToken = getStringParameter(request, Constants.PARAM_CHANGE_TOKEN);
+    Boolean overwriteFlag = getBooleanParameter(request, Constants.PARAM_OVERWRITE_FLAG);
+
+    ContentStreamDataImpl contentStream = new ContentStreamDataImpl();
+    contentStream.setStream(request.getInputStream());
+    contentStream.setMimeType(request.getHeader("Content-Type"));
+    String lengthStr = request.getHeader("Content-Length");
+    if (lengthStr != null) {
+      try {
+        contentStream.setLength(new BigInteger(lengthStr));
+      }
+      catch (NumberFormatException e) {
+      }
+    }
+
+    // execute
+    Holder<String> objectIdHolder = new Holder<String>(objectId);
+    service.setContentStream(context, repositoryId, objectIdHolder, overwriteFlag,
+        changeToken == null ? null : new Holder<String>(changeToken), contentStream, null);
+
+    // set headers
+    String newObjectId = (objectIdHolder.getValue() == null ? objectId : objectIdHolder.getValue());
+    String location = compileUrl(compileBaseUrl(request, repositoryId), RESOURCE_CONTENT,
+        newObjectId);
+
+    response.setStatus(HttpServletResponse.SC_CREATED);
+    response.setHeader("Content-Location", location);
+    response.setHeader("Location", location);
+  }
+
+  /**
+   * Delete tree.
+   */
+  public static void deleteTree(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisObjectService service = factory.getObjectService();
+
+    // get parameters
+    String folderId = getStringParameter(request, Constants.PARAM_ID);
+    Boolean allVersions = getBooleanParameter(request, Constants.PARAM_ALL_VERSIONS);
+    UnfileObjects unfileObjects = getEnumParameter(request, Constants.PARAM_UNFILE_OBJECTS,
+        UnfileObjects.class);
+    Boolean continueOnFailure = getBooleanParameter(request, Constants.PARAM_CONTINUE_ON_FAILURE);
+
+    // execute
+    FailedToDeleteData ftd = service.deleteTree(context, repositoryId, folderId, allVersions,
+        unfileObjects, continueOnFailure, null);
+
+    if ((ftd != null) && (ftd.getIds() != null) && (ftd.getIds().size() > 0)) {
+      // print ids that could not be deleted
+      response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+      response.setContentType("text/plain");
+
+      PrintWriter pw = response.getWriter();
+
+      pw.println("Failed to delete the following objects:");
+      for (String id : ftd.getIds()) {
+        pw.println(id);
+      }
+
+      pw.flush();
+
+      return;
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_NO_CONTENT);
+  }
+
+  /**
+   * getObject.
+   */
+  public static void getObject(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+    ReturnVersion returnVersion = getEnumParameter(request, Constants.PARAM_RETURN_VERSION,
+        ReturnVersion.class);
+    String filter = getStringParameter(request, Constants.PARAM_FILTER);
+    Boolean includeAllowableActions = getBooleanParameter(request,
+        Constants.PARAM_ALLOWABLE_ACTIONS);
+    IncludeRelationships includeRelationships = getEnumParameter(request,
+        Constants.PARAM_RELATIONSHIPS, IncludeRelationships.class);
+    String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+    Boolean includePolicyIds = getBooleanParameter(request, Constants.PARAM_POLICY_IDS);
+    Boolean includeAcl = getBooleanParameter(request, Constants.PARAM_ACL);
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    ObjectData object = null;
+
+    if ((returnVersion == ReturnVersion.LATEST) || (returnVersion == ReturnVersion.LASTESTMAJOR)) {
+      CmisVersioningService service = factory.getVersioningService();
+      object = service.getObjectOfLatestVersion(context, repositoryId, objectId,
+          returnVersion == ReturnVersion.LASTESTMAJOR, filter, includeAllowableActions,
+          includeRelationships, renditionFilter, includePolicyIds, includeAcl, null,
+          objectInfoHolder);
+    }
+    else {
+      CmisObjectService service = factory.getObjectService();
+      object = service.getObject(context, repositoryId, objectId, filter, includeAllowableActions,
+          includeRelationships, renditionFilter, includePolicyIds, includeAcl, null,
+          objectInfoHolder);
+    }
+
+    if (object == null) {
+      throw new CmisRuntimeException("Object is null!");
+    }
+
+    ObjectInfo objectInfo = objectInfoHolder.getObjectInfo(object.getId());
+    if (objectInfo == null) {
+      throw new CmisRuntimeException("Object Info is missing!");
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_ENTRY);
+
+    // write XML
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    AtomEntry entry = new AtomEntry();
+    entry.startDocument(response.getOutputStream());
+    writeObjectEntry(entry, object, objectInfoHolder, null, repositoryId, null, null, baseUrl, true);
+    entry.endDocument();
+  }
+
+  /**
+   * objectByPath URI template.
+   */
+  public static void getObjectByPath(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisObjectService service = factory.getObjectService();
+
+    // get parameters
+    String path = getStringParameter(request, Constants.PARAM_PATH);
+    String filter = getStringParameter(request, Constants.PARAM_FILTER);
+    Boolean includeAllowableActions = getBooleanParameter(request,
+        Constants.PARAM_ALLOWABLE_ACTIONS);
+    IncludeRelationships includeRelationships = getEnumParameter(request,
+        Constants.PARAM_RELATIONSHIPS, IncludeRelationships.class);
+    String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+    Boolean includePolicyIds = getBooleanParameter(request, Constants.PARAM_POLICY_IDS);
+    Boolean includeAcl = getBooleanParameter(request, Constants.PARAM_ACL);
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    ObjectData object = service.getObjectByPath(context, repositoryId, path, filter,
+        includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds,
+        includeAcl, null, objectInfoHolder);
+
+    if (object == null) {
+      throw new CmisRuntimeException("Object is null!");
+    }
+
+    ObjectInfo objectInfo = objectInfoHolder.getObjectInfo(object.getId());
+    if (objectInfo == null) {
+      throw new CmisRuntimeException("Object Info is missing!");
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_ENTRY);
+
+    // write XML
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+
+    AtomEntry entry = new AtomEntry();
+    entry.startDocument(response.getOutputStream());
+    writeObjectEntry(entry, object, objectInfoHolder, null, repositoryId, null, null, baseUrl, true);
+    entry.endDocument();
+  }
+
+  /**
+   * Allowable Actions.
+   */
+  public static void getAllowableActions(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisObjectService service = factory.getObjectService();
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+
+    // execute
+    AllowableActionsData allowableActions = service.getAllowableActions(context, repositoryId,
+        objectId, null);
+
+    if (allowableActions == null) {
+      throw new CmisRuntimeException("Allowable Actions is null!");
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_ALLOWABLEACTION);
+
+    // write XML
+    AllowableActionsDocument allowableActionsDocument = new AllowableActionsDocument();
+    allowableActionsDocument.writeAllowableActions(allowableActions, response.getOutputStream());
+  }
+
+  /**
+   * getContentStream.
+   */
+  public static void getContentStream(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisObjectService service = factory.getObjectService();
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+    String streamId = getStringParameter(request, Constants.PARAM_STREAM_ID);
+
+    BigInteger offset = null;
+    String offsetStr = context.get(CallContext.OFFSET);
+    if (offsetStr != null) {
+      offset = new BigInteger(offsetStr);
+    }
+
+    BigInteger length = null;
+    String lengthStr = context.get(CallContext.LENGTH);
+    if (lengthStr != null) {
+      length = new BigInteger(offsetStr);
+    }
+
+    // execute
+    ContentStreamData content = service.getContentStream(context, repositoryId, objectId, streamId,
+        offset, length, null);
+
+    if ((content == null) || (content.getStream() == null)) {
+      throw new CmisRuntimeException("Content stream is null!");
+    }
+
+    String contentType = content.getMimeType();
+    if (contentType == null) {
+      contentType = Constants.MEDIATYPE_OCTETSTREAM;
+    }
+
+    // set headers
+    if ((offset == null) && (length == null)) {
+      response.setStatus(HttpServletResponse.SC_OK);
+    }
+    else {
+      response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
+    }
+    response.setContentType(contentType);
+
+    // send content
+    InputStream in = new BufferedInputStream(content.getStream(), BUFFER_SIZE);
+    OutputStream out = new BufferedOutputStream(response.getOutputStream());
+
+    byte[] buffer = new byte[BUFFER_SIZE];
+    int b;
+    while ((b = in.read(buffer)) > -1) {
+      out.write(buffer, 0, b);
+    }
+
+    in.close();
+    out.flush();
+  }
+
+  /**
+   * UpdateProperties.
+   */
+  public static void updateProperties(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+    Boolean checkin = getBooleanParameter(request, Constants.PARAM_CHECK_IN);
+    String checkinComment = getStringParameter(request, Constants.PARAM_CHECKIN_COMMENT);
+    Boolean major = getBooleanParameter(request, Constants.PARAM_MAJOR);
+
+    AtomEntryParser parser = new AtomEntryParser(request.getInputStream());
+
+    // execute
+    ObjectInfoHolder objectInfoHolder = new ObjectInfoHolderImpl();
+    ObjectData object = null;
+
+    if ((checkin != null) && (checkin.booleanValue())) {
+      CmisVersioningService service = factory.getVersioningService();
+      object = service.checkIn(context, repositoryId, new Holder<String>(objectId), major, parser
+          .getProperties(), parser.getContentStream(), checkinComment, parser.getPolicyIds(), null,
+          null, null, objectInfoHolder);
+    }
+    else {
+      String changeToken = extractChangeToken(parser.getProperties());
+
+      CmisObjectService service = factory.getObjectService();
+      object = service.updateProperties(context, repositoryId, new Holder<String>(objectId),
+          changeToken == null ? null : new Holder<String>(changeToken), parser.getProperties(),
+          parser.getAcl(), null, objectInfoHolder);
+    }
+
+    if (object == null) {
+      throw new CmisRuntimeException("Object is null!");
+    }
+
+    if (object.getId() == null) {
+      throw new CmisRuntimeException("Object Id is null!");
+    }
+
+    // set headers
+    UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
+    String location = compileUrl(baseUrl, RESOURCE_ENTRY, object.getId());
+
+    response.setStatus(HttpServletResponse.SC_CREATED);
+    response.setContentType(Constants.MEDIATYPE_ENTRY);
+    response.setHeader("Content-Location", location);
+    response.setHeader("Location", location);
+
+    // write XML
+    AtomEntry entry = new AtomEntry();
+    entry.startDocument(response.getOutputStream());
+    writeObjectEntry(entry, object, objectInfoHolder, null, repositoryId, null, null, baseUrl, true);
+    entry.endDocument();
+  }
+
+  /**
+   * Gets the change token from a property set.
+   */
+  private static String extractChangeToken(PropertiesData properties) {
+    if (properties == null) {
+      return null;
+    }
+
+    Map<String, PropertyData<?>> propertiesMap = properties.getProperties();
+    if (propertiesMap == null) {
+      return null;
+    }
+
+    PropertyData<?> changeLogProperty = propertiesMap.get(PropertyIds.CMIS_CHANGE_TOKEN);
+    if (!(changeLogProperty instanceof PropertyStringData)) {
+      return null;
+    }
+
+    return ((PropertyStringData) changeLogProperty).getFirstValue();
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/ObjectService.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message