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 [23/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-...

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/CmisRepositoryContextListener.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/CmisRepositoryContextListener.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/CmisRepositoryContextListener.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/CmisRepositoryContextListener.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,136 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.opencmis.server.spi.AbstractServicesFactory;
+
+/**
+ * CMIS context listener.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class CmisRepositoryContextListener implements ServletContextListener {
+
+  public static final String SERVICES_FACTORY = "org.apache.opencmis.servicesfactory";
+
+  private static final Log log = LogFactory.getLog(CmisRepositoryContextListener.class.getName());
+
+  private static final String CONFIG_FILENAME = "/repository.properties";
+  private static final String PROPERTY_CLASS = "class";
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
+   */
+  public void contextInitialized(ServletContextEvent sce) {
+    // create services factory
+    AbstractServicesFactory factory = createServicesFactory(CONFIG_FILENAME);
+
+    // set the services factory into the servlet context
+    sce.getServletContext().setAttribute(SERVICES_FACTORY, factory);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
+   */
+  public void contextDestroyed(ServletContextEvent sce) {
+    // destroy services factory
+    AbstractServicesFactory factory = (AbstractServicesFactory) sce.getServletContext()
+        .getAttribute(SERVICES_FACTORY);
+    if (factory != null) {
+      factory.destroy();
+    }
+  }
+
+  /**
+   * Creates a services factory.
+   */
+  private AbstractServicesFactory createServicesFactory(String filename) {
+    // load properties
+    InputStream stream = this.getClass().getResourceAsStream(filename);
+
+    if (stream == null) {
+      log.warn("Cannot find configuration!");
+      return null;
+    }
+
+    Properties props = new Properties();
+    try {
+      props.load(stream);
+    }
+    catch (IOException e) {
+      log.warn("Cannot load configuration: " + e, e);
+      return null;
+    }
+
+    // get 'class' property
+    String className = props.getProperty(PROPERTY_CLASS);
+    if (className == null) {
+      log.warn("Configuration doesn't contain the property 'class'!");
+      return null;
+    }
+
+    // create a factory instance
+    Object object = null;
+    try {
+      object = Class.forName(className).newInstance();
+    }
+    catch (Exception e) {
+      log.warn("Could not create a services factory instance: " + e, e);
+      return null;
+    }
+
+    if (!(object instanceof AbstractServicesFactory)) {
+      log.warn("The provided class is not a sub class of AbstractServicesFactory!");
+    }
+
+    AbstractServicesFactory factory = (AbstractServicesFactory) object;
+
+    // initialize factory instance
+    Map<String, String> parameters = new HashMap<String, String>();
+
+    for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements();) {
+      String key = (String) e.nextElement();
+      String value = props.getProperty(key);
+      parameters.put(key, value);
+    }
+
+    factory.init(parameters);
+
+    log.info("Initialized Services Factory: " + parameters);
+
+    return factory;
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/ObjectInfoHolderImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/ObjectInfoHolderImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/ObjectInfoHolderImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/ObjectInfoHolderImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,68 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.opencmis.server.spi.ObjectInfo;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+
+/**
+ * Implementation of the {@link ObjectInfo} interface.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class ObjectInfoHolderImpl implements ObjectInfoHolder {
+
+  private Map<String, ObjectInfo> fObjectInfoMap;
+
+  /**
+   * Constructor.
+   */
+  public ObjectInfoHolderImpl() {
+    fObjectInfoMap = new HashMap<String, ObjectInfo>();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.server.spi.ObjectInfoHolder#addObjectInfo(org.apache.opencmis.server.spi.ObjectInfo)
+   */
+  public void addObjectInfo(ObjectInfo info) {
+    if (info == null) {
+      throw new IllegalArgumentException("Object Info must not be null!");
+    }
+    if (info.getId() == null) {
+      throw new IllegalArgumentException("Object Info Id must not be null!");
+    }
+
+    fObjectInfoMap.put(info.getId(), info);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.server.spi.ObjectInfoHolder#getObjectInfo(java.lang.String)
+   */
+  public ObjectInfo getObjectInfo(String id) {
+    return fObjectInfoMap.get(id);
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AclDocument.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/AclDocument.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AclDocument.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AclDocument.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,58 @@
+/*
+ * 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 java.io.OutputStream;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.opencmis.commons.impl.JaxBHelper;
+import org.apache.opencmis.commons.impl.jaxb.CmisAccessControlListType;
+import org.apache.opencmis.commons.provider.AccessControlList;
+
+/**
+ * ACL document.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class AclDocument {
+
+  /**
+   * Creates an ACL document.
+   */
+  public AclDocument() {
+  }
+
+  /**
+   * Writes an object.
+   */
+  public void writeAcl(AccessControlList acl, OutputStream out) throws XMLStreamException,
+      JAXBException {
+    CmisAccessControlListType aclJaxb = convert(acl);
+    if (aclJaxb == null) {
+      return;
+    }
+
+    JaxBHelper.marshal(JaxBHelper.CMIS_OBJECT_FACTORY.createAcl(aclJaxb), out, false);
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AclService.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/AclService.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AclService.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AclService.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,124 @@
+/*
+ * 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.getBooleanParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getEnumParameter;
+import static org.apache.opencmis.server.impl.atompub.AtomPubUtils.getStringParameter;
+
+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.AclPropagation;
+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.jaxb.CmisAccessControlListType;
+import org.apache.opencmis.commons.provider.AccessControlList;
+import org.apache.opencmis.server.spi.AbstractServicesFactory;
+import org.apache.opencmis.server.spi.CallContext;
+import org.apache.opencmis.server.spi.CmisAclService;
+
+/**
+ * ACL Service operations.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class AclService {
+
+  /**
+   * Get ACL.
+   */
+  public static void getAcl(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisAclService service = factory.getAclService();
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+    Boolean onlyBasicPermissions = getBooleanParameter(request,
+        Constants.PARAM_ONLY_BASIC_PERMISSIONS);
+
+    // execute
+    AccessControlList acl = service.getAcl(context, repositoryId, objectId, onlyBasicPermissions,
+        null);
+
+    if (acl == null) {
+      throw new CmisRuntimeException("ACL is null!");
+    }
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType(Constants.MEDIATYPE_ACL);
+
+    // write XML
+    AclDocument aclDocument = new AclDocument();
+    aclDocument.writeAcl(acl, response.getOutputStream());
+  }
+
+  /**
+   * Apply ACL.
+   */
+  public static void applyAcl(CallContext context, AbstractServicesFactory factory,
+      String repositoryId, HttpServletRequest request, HttpServletResponse response)
+      throws Exception {
+    CmisAclService service = factory.getAclService();
+
+    // get parameters
+    String objectId = getStringParameter(request, Constants.PARAM_ID);
+    AclPropagation aclPropagation = getEnumParameter(request, Constants.PARAM_ACL_PROPAGATION,
+        AclPropagation.class);
+
+    Object aclRequest = null;
+    try {
+      Unmarshaller u = JaxBHelper.createUnmarshaller();
+      aclRequest = u.unmarshal(request.getInputStream());
+    }
+    catch (Exception e) {
+      throw new CmisInvalidArgumentException("Invalid ACL request: " + e, e);
+    }
+
+    if (!(aclRequest instanceof JAXBElement<?>)) {
+      throw new CmisInvalidArgumentException("Not an ACL document!");
+    }
+
+    if (!(((JAXBElement<?>) aclRequest).getValue() instanceof CmisAccessControlListType)) {
+      throw new CmisInvalidArgumentException("Not an ACL document!");
+    }
+
+    AccessControlList aces = convert((CmisAccessControlListType) ((JAXBElement<?>) aclRequest)
+        .getValue(), null);
+
+    // execute
+    AccessControlList acl = service.applyAcl(context, repositoryId, objectId, aces, aclPropagation);
+
+    // set headers
+    response.setStatus(HttpServletResponse.SC_CREATED);
+    response.setContentType(Constants.MEDIATYPE_ACL);
+
+    // write XML
+    AclDocument aclDocument = new AclDocument();
+    aclDocument.writeAcl(acl, response.getOutputStream());
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AllowableActionsDocument.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/AllowableActionsDocument.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AllowableActionsDocument.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AllowableActionsDocument.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,59 @@
+/*
+ * 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 java.io.OutputStream;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.opencmis.commons.impl.JaxBHelper;
+import org.apache.opencmis.commons.impl.jaxb.CmisAllowableActionsType;
+import org.apache.opencmis.commons.provider.AllowableActionsData;
+
+/**
+ * Allowable Actions document.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class AllowableActionsDocument {
+
+  /**
+   * Creates an Allowable Actions document.
+   */
+  public AllowableActionsDocument() {
+  }
+
+  /**
+   * Writes an object.
+   */
+  public void writeAllowableActions(AllowableActionsData allowableActions, OutputStream out)
+      throws XMLStreamException, JAXBException {
+    CmisAllowableActionsType allowableActionsJaxb = convert(allowableActions);
+    if (allowableActionsJaxb == null) {
+      return;
+    }
+
+    JaxBHelper.marshal(JaxBHelper.CMIS_OBJECT_FACTORY.createAllowableActions(allowableActionsJaxb),
+        out, false);
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomDocumentBase.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/AtomDocumentBase.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomDocumentBase.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomDocumentBase.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,355 @@
+/*
+ * 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.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.opencmis.commons.impl.Constants;
+
+/**
+ * Atom base class.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public abstract class AtomDocumentBase extends XMLDocumentBase {
+
+  private static final String ID_PREFIX = "http://opencmis.org/";
+  private static final String ID_DUMMY = "http://opencmis.org/no-id";
+
+  private SimpleDateFormat fDateFormater;
+
+  /**
+   * Formats a DateTime.
+   */
+  public String formatDate(long millis) {
+    if (fDateFormater == null) {
+      fDateFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
+      fDateFormater.setTimeZone(TimeZone.getTimeZone("UTC"));
+    }
+
+    return fDateFormater.format(millis);
+  }
+
+  /**
+   * Generates a valid Atom id.
+   */
+  public String generateAtomId(String input) {
+    if (input == null) {
+      return ID_DUMMY;
+    }
+
+    try {
+      return ID_PREFIX + (new String(Base64.encodeBase64(input.getBytes("UTF-8"))));
+    }
+    catch (UnsupportedEncodingException e) {
+      return ID_DUMMY;
+    }
+  }
+
+  /**
+   * Writes a simple tag.
+   */
+  public void writeSimpleTag(String namespace, String name, String value) throws XMLStreamException {
+    if (value == null) {
+      return;
+    }
+
+    XMLStreamWriter xsw = getWriter();
+
+    xsw.writeStartElement(namespace, name);
+    xsw.writeCharacters(value);
+    xsw.writeEndElement();
+  }
+
+  /**
+   * Writes a simple date tag.
+   */
+  public void writeSimpleDate(String namespace, String name, GregorianCalendar value)
+      throws XMLStreamException {
+    if (value == null) {
+      return;
+    }
+
+    writeSimpleTag(namespace, name, formatDate(value.getTimeInMillis()));
+  }
+
+  /**
+   * Writes a simple date tag.
+   */
+  public void writeSimpleDate(String namespace, String name, long millis) throws XMLStreamException {
+    writeSimpleTag(namespace, name, formatDate(millis));
+  }
+
+  /**
+   * Writes an Atom id tag.
+   */
+  public void writeId(String id) throws XMLStreamException {
+    writeSimpleTag(Constants.NAMESPACE_ATOM, "id", id);
+  }
+
+  /**
+   * Writes an Atom title tag.
+   */
+  public void writeTitle(String title) throws XMLStreamException {
+    writeSimpleTag(Constants.NAMESPACE_ATOM, "title", title);
+  }
+
+  /**
+   * Writes an Atom author tag.
+   */
+  public void writeAuthor(String author) throws XMLStreamException {
+    XMLStreamWriter xsw = getWriter();
+
+    xsw.writeStartElement(Constants.NAMESPACE_ATOM, "author");
+    writeSimpleTag(Constants.NAMESPACE_ATOM, "name", author);
+    xsw.writeEndElement();
+  }
+
+  /**
+   * Writes an Atom updated tag.
+   */
+  public void writeUpdated(GregorianCalendar updated) throws XMLStreamException {
+    writeSimpleDate(Constants.NAMESPACE_ATOM, "updated", updated);
+  }
+
+  /**
+   * Writes an Atom updated tag.
+   */
+  public void writeUpdated(long updated) throws XMLStreamException {
+    writeSimpleDate(Constants.NAMESPACE_ATOM, "updated", updated);
+  }
+
+  /**
+   * Writes an Atom published tag.
+   */
+  public void writePublished(GregorianCalendar published) throws XMLStreamException {
+    writeSimpleDate(Constants.NAMESPACE_ATOM, "published", published);
+  }
+
+  /**
+   * Writes an Atom published tag.
+   */
+  public void writePublished(long published) throws XMLStreamException {
+    writeSimpleDate(Constants.NAMESPACE_ATOM, "published", published);
+  }
+
+  /**
+   * Writes a CMIS pathSegment tag.
+   */
+  public void writePathSegment(String pathSegment) throws XMLStreamException {
+    writeSimpleTag(Constants.NAMESPACE_RESTATOM, "pathSegment", pathSegment);
+  }
+
+  /**
+   * Writes a CMIS relativePathSegment tag.
+   */
+  public void writeRelativePathSegment(String relativePathSegment) throws XMLStreamException {
+    writeSimpleTag(Constants.NAMESPACE_RESTATOM, "relativePathSegment", relativePathSegment);
+  }
+
+  /**
+   * Writes an Atom collection.
+   */
+  public void writeCollection(String href, String collectionType, String text, String... accept)
+      throws XMLStreamException {
+    XMLStreamWriter xsw = getWriter();
+
+    xsw.writeStartElement(Constants.NAMESPACE_APP, "collection");
+    xsw.writeAttribute("href", href);
+
+    if (collectionType != null) {
+      xsw.writeStartElement(Constants.NAMESPACE_RESTATOM, "collectionType");
+      xsw.writeCharacters(collectionType);
+      xsw.writeEndElement();
+    }
+
+    xsw.writeStartElement(Constants.NAMESPACE_ATOM, "title");
+    xsw.writeAttribute("type", text);
+    xsw.writeCharacters(text);
+    xsw.writeEndElement();
+
+    for (String ct : accept) {
+      xsw.writeStartElement(Constants.NAMESPACE_APP, "accept");
+      xsw.writeCharacters(ct);
+      xsw.writeEndElement();
+    }
+
+    xsw.writeEndElement();
+  }
+
+  /**
+   * Writes a link.
+   */
+  public void writeLink(String rel, String href, String type, String id) throws XMLStreamException {
+    XMLStreamWriter xsw = getWriter();
+
+    xsw.writeStartElement(Constants.NAMESPACE_ATOM, "link");
+
+    xsw.writeAttribute("rel", rel);
+    xsw.writeAttribute("href", href);
+    if (type != null) {
+      xsw.writeAttribute("type", type);
+    }
+    if (id != null) {
+      xsw.writeAttribute(Constants.NAMESPACE_RESTATOM, "id", id);
+    }
+
+    xsw.writeEndElement();
+  }
+
+  public void writeServiceLink(String href, String repositoryId) throws XMLStreamException {
+    try {
+      writeLink(Constants.REL_SERVICE, href + "?repositoryId="
+          + URLEncoder.encode(repositoryId, "UTF-8"), Constants.MEDIATYPE_SERVICE, null);
+    }
+    catch (UnsupportedEncodingException e) {
+    }
+  }
+
+  public void writeSelfLink(String href, String id) throws XMLStreamException {
+    writeLink(Constants.REL_SELF, href, Constants.MEDIATYPE_ENTRY, id);
+  }
+
+  public void writeEnclosureLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_ENCLOSURE, href, Constants.MEDIATYPE_ENTRY, null);
+  }
+
+  public void writeEditLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_EDIT, href, Constants.MEDIATYPE_ENTRY, null);
+  }
+
+  public void writeAlternateLink(String href, String type, String kind, String title,
+      BigInteger length) throws XMLStreamException {
+    XMLStreamWriter xsw = getWriter();
+
+    xsw.writeStartElement(Constants.NAMESPACE_ATOM, "link");
+
+    xsw.writeAttribute("rel", Constants.REL_ALTERNATE);
+    xsw.writeAttribute("href", href);
+    if (type != null) {
+      xsw.writeAttribute("type", type);
+    }
+    if (kind != null) {
+      xsw.writeAttribute(Constants.NAMESPACE_RESTATOM, "renditionKind", kind);
+    }
+    if (title != null) {
+      xsw.writeAttribute("title", title);
+    }
+    if (length != null) {
+      xsw.writeAttribute("length", length.toString());
+    }
+
+    xsw.writeEndElement();
+  }
+
+  public void writeWorkingCopyLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_WORKINGCOPY, href, Constants.MEDIATYPE_ENTRY, null);
+  }
+
+  public void writeUpLink(String href, String type) throws XMLStreamException {
+    writeLink(Constants.REL_UP, href, type, null);
+  }
+
+  public void writeDownLink(String href, String type) throws XMLStreamException {
+    writeLink(Constants.REL_DOWN, href, type, null);
+  }
+
+  public void writeVersionHistoryLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_VERSIONHISTORY, href, Constants.MEDIATYPE_FEED, null);
+  }
+
+  public void writeCurrentVerionsLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_CURRENTVERSION, href, Constants.MEDIATYPE_ENTRY, null);
+  }
+
+  public void writeEditMediaLink(String href, String type) throws XMLStreamException {
+    writeLink(Constants.REL_EDITMEDIA, href, type, null);
+  }
+
+  public void writeDescribedByLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_DESCRIBEDBY, href, Constants.MEDIATYPE_ENTRY, null);
+  }
+
+  public void writeAllowableActionsLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_ALLOWABLEACTIONS, href, Constants.MEDIATYPE_ALLOWABLEACTION, null);
+  }
+
+  public void writeAclLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_ACL, href, Constants.MEDIATYPE_ACL, null);
+  }
+
+  public void writePoliciesLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_POLICIES, href, Constants.MEDIATYPE_FEED, null);
+  }
+
+  public void writeRelationshipsLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_RELATIONSHIPS, href, Constants.MEDIATYPE_FEED, null);
+  }
+
+  public void writeRelationshipSourceLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_SOURCE, href, Constants.MEDIATYPE_ENTRY, null);
+  }
+
+  public void writeRelationshipTargetLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_TARGET, href, Constants.MEDIATYPE_ENTRY, null);
+  }
+
+  public void writeFolderTreeLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_FOLDERTREE, href, Constants.MEDIATYPE_DESCENDANTS, null);
+  }
+
+  public void writeTypeUpLink(String href, String type) throws XMLStreamException {
+    writeLink(Constants.REL_UP, href, type, null);
+  }
+
+  public void writeTypeDownLink(String href, String type) throws XMLStreamException {
+    writeLink(Constants.REL_DOWN, href, type, null);
+  }
+
+  public void writeViaLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_VIA, href, Constants.MEDIATYPE_ENTRY, null);
+  }
+
+  public void writeFirstLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_FIRST, href, Constants.MEDIATYPE_FEED, null);
+  }
+
+  public void writeLastLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_LAST, href, Constants.MEDIATYPE_FEED, null);
+  }
+
+  public void writePreviousLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_PREV, href, Constants.MEDIATYPE_FEED, null);
+  }
+
+  public void writeNextLink(String href) throws XMLStreamException {
+    writeLink(Constants.REL_NEXT, href, Constants.MEDIATYPE_FEED, null);
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomEntry.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/AtomEntry.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomEntry.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomEntry.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,144 @@
+/*
+ * 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 javax.xml.bind.JAXBException;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.impl.Constants;
+import org.apache.opencmis.commons.impl.JaxBHelper;
+import org.apache.opencmis.commons.impl.jaxb.CmisObjectType;
+import org.apache.opencmis.commons.impl.jaxb.CmisTypeDefinitionType;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.server.spi.ObjectInfo;
+
+/**
+ * Atom Entry class.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class AtomEntry extends AtomDocumentBase {
+
+  private final static String DEFAULT_AUTHOR = "unknown";
+
+  /**
+   * Creates an Atom entry document.
+   */
+  public AtomEntry() {
+  }
+
+  /**
+   * Creates an Atom entry that is embedded somewhere.
+   */
+  public AtomEntry(XMLStreamWriter writer) {
+    setWriter(writer);
+  }
+
+  /**
+   * Opens the entry tag.
+   */
+  public void startEntry(boolean isRoot) throws XMLStreamException {
+    getWriter().writeStartElement(Constants.NAMESPACE_ATOM, "entry");
+
+    if (isRoot) {
+      writeNamespace(Constants.NAMESPACE_ATOM);
+      writeNamespace(Constants.NAMESPACE_CMIS);
+      writeNamespace(Constants.NAMESPACE_RESTATOM);
+    }
+  }
+
+  /**
+   * Closes the entry tag.
+   */
+  public void endEntry() throws XMLStreamException {
+    getWriter().writeEndElement();
+  }
+
+  /**
+   * Writes an object.
+   */
+  public void writeObject(ObjectData object, ObjectInfo info, String contentSrc,
+      String contentType, String pathSegment, String relativePathSegment)
+      throws XMLStreamException, JAXBException {
+    CmisObjectType objectJaxb = convert(object);
+    if (objectJaxb == null) {
+      return;
+    }
+
+    writeAuthor(info.getCreatedBy());
+    writeId(generateAtomId(info.getId()));
+    writePublished(info.getCreationDate());
+    writeTitle(info.getName());
+    writeUpdated(info.getLastModificationDate());
+
+    writeContent(contentSrc, contentType);
+
+    JaxBHelper.marshal(JaxBHelper.CMIS_EXTRA_OBJECT_FACTORY.createObject(objectJaxb), getWriter(),
+        true);
+
+    writePathSegment(pathSegment);
+    writeRelativePathSegment(relativePathSegment);
+  }
+
+  /**
+   * Writes a type.
+   * 
+   * @throws JAXBException
+   */
+  public void writeType(TypeDefinition type) throws XMLStreamException, JAXBException {
+    CmisTypeDefinitionType typeJaxb = convert(type);
+    if (typeJaxb == null) {
+      return;
+    }
+
+    long now = System.currentTimeMillis();
+
+    writeAuthor(DEFAULT_AUTHOR);
+    writeId(generateAtomId(type.getId()));
+    writeTitle(type.getDisplayName());
+    writeUpdated(now);
+
+    JaxBHelper.marshal(JaxBHelper.CMIS_EXTRA_OBJECT_FACTORY.createTypeDefinition(typeJaxb),
+        getWriter(), true);
+  }
+
+  /**
+   * Writes a content tag.
+   */
+  public void writeContent(String src, String type) throws XMLStreamException {
+    if (src == null) {
+      return;
+    }
+
+    XMLStreamWriter xsw = getWriter();
+    xsw.writeStartElement(Constants.NAMESPACE_ATOM, "content");
+
+    xsw.writeAttribute("src", src);
+    if (type != null) {
+      xsw.writeAttribute("type", type);
+    }
+
+    xsw.writeEndElement();
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomEntryParser.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/AtomEntryParser.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomEntryParser.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomEntryParser.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,409 @@
+/*
+ * 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.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.opencmis.commons.PropertyIds;
+import org.apache.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.opencmis.commons.exceptions.CmisNotSupportedException;
+import org.apache.opencmis.commons.impl.Constants;
+import org.apache.opencmis.commons.impl.Converter;
+import org.apache.opencmis.commons.impl.JaxBHelper;
+import org.apache.opencmis.commons.impl.dataobjects.ContentStreamDataImpl;
+import org.apache.opencmis.commons.impl.jaxb.CmisObjectType;
+import org.apache.opencmis.commons.provider.AccessControlList;
+import org.apache.opencmis.commons.provider.ContentStreamData;
+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.PropertyIdData;
+
+/**
+ * Parser for Atom Entries.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class AtomEntryParser {
+
+  private final static String TAG_ENTRY = "entry";
+  private final static String TAG_OBJECT = "object";
+  private final static String TAG_CONTENT = "content";
+  private final static String TAG_BASE64 = "base64";
+  private final static String TAG_MEDIATYPE = "mediatype";
+
+  private final static String ATTR_SRC = "src";
+  private final static String ATTR_TYPE = "type";
+
+  private ObjectData fObject;
+  private ContentStreamDataImpl fAtomContentStream;
+  private ContentStreamDataImpl fCmisContentStream;
+
+  /**
+   * Constructor.
+   */
+  public AtomEntryParser() {
+  }
+
+  /**
+   * Constructor that immediately parses the given stream.
+   */
+  public AtomEntryParser(InputStream stream) throws Exception {
+    parse(stream);
+  }
+
+  /**
+   * Returns the object.
+   */
+  public ObjectData getObject() {
+    return fObject;
+  }
+
+  /**
+   * Returns the properties of the object.
+   */
+  public PropertiesData getProperties() {
+    return (fObject == null ? null : fObject.getProperties());
+  }
+
+  /**
+   * Returns the Id of the object.
+   */
+  public String getId() {
+    PropertiesData properties = getProperties();
+    if (properties == null) {
+      return null;
+    }
+
+    Map<String, PropertyData<?>> propertiesMap = properties.getProperties();
+    if (propertiesMap == null) {
+      return null;
+    }
+
+    PropertyData<?> property = propertiesMap.get(PropertyIds.CMIS_OBJECT_ID);
+    if (property instanceof PropertyIdData) {
+      return ((PropertyIdData) property).getFirstValue();
+    }
+
+    return null;
+  }
+
+  /**
+   * Returns the ACL of the object.
+   */
+  public AccessControlList getAcl() {
+    return (fObject == null ? null : fObject.getAcl());
+  }
+
+  /**
+   * Returns the policy id list of the object.
+   */
+  public List<String> getPolicyIds() {
+    if ((fObject == null) || (fObject.getPolicyIds() == null)) {
+      return null;
+    }
+
+    return fObject.getPolicyIds().getPolicyIds();
+  }
+
+  /**
+   * Returns the content stream.
+   */
+  public ContentStreamData getContentStream() {
+    return (fCmisContentStream == null ? fAtomContentStream : fCmisContentStream);
+  }
+
+  /**
+   * Parses the stream.
+   */
+  public void parse(InputStream stream) throws Exception {
+    fObject = null;
+    fAtomContentStream = null;
+    fCmisContentStream = null;
+
+    if (stream == null) {
+      return;
+    }
+
+    XMLInputFactory factory = XMLInputFactory.newInstance();
+    XMLStreamReader parser = factory.createXMLStreamReader(stream);
+
+    while (true) {
+      int event = parser.getEventType();
+      if (event == XMLStreamReader.START_ELEMENT) {
+        QName name = parser.getName();
+
+        if (Constants.NAMESPACE_ATOM.equals(name.getNamespaceURI())
+            && (TAG_ENTRY.equals(name.getLocalPart()))) {
+          parseEntry(parser);
+          break;
+        }
+        else {
+          throw new CmisInvalidArgumentException("XML is not an Atom entry!");
+        }
+      }
+
+      if (!next(parser)) {
+        break;
+      }
+    }
+
+    parser.close();
+  }
+
+  /**
+   * Parses an Atom entry.
+   */
+  private void parseEntry(XMLStreamReader parser) throws Exception {
+    next(parser);
+
+    // walk through all tags in entry
+    while (true) {
+      int event = parser.getEventType();
+      if (event == XMLStreamReader.START_ELEMENT) {
+        QName name = parser.getName();
+
+        if (Constants.NAMESPACE_RESTATOM.equals(name.getNamespaceURI())) {
+          if (TAG_OBJECT.equals(name.getLocalPart())) {
+            parseObject(parser);
+          }
+          else if (TAG_CONTENT.equals(name.getLocalPart())) {
+            parseCmisContent(parser);
+          }
+          else {
+            skip(parser);
+          }
+        }
+        else if (Constants.NAMESPACE_ATOM.equals(name.getNamespaceURI())) {
+          if (TAG_CONTENT.equals(name.getLocalPart())) {
+            parseAtomContent(parser);
+          }
+          else {
+            skip(parser);
+          }
+        }
+        else {
+          skip(parser);
+        }
+      }
+      else if (event == XMLStreamReader.END_ELEMENT) {
+        break;
+      }
+      else {
+        if (!next(parser)) {
+          break;
+        }
+      }
+    }
+  }
+
+  /**
+   * Parses a CMIS object.
+   */
+  private void parseObject(XMLStreamReader parser) throws Exception {
+    Unmarshaller u = JaxBHelper.createUnmarshaller();
+    JAXBElement<CmisObjectType> object = u.unmarshal(parser, CmisObjectType.class);
+
+    if (object != null) {
+      fObject = Converter.convert(object.getValue());
+    }
+  }
+
+  /**
+   * Extract the content stream.
+   */
+  private void parseAtomContent(XMLStreamReader parser) throws Exception {
+    fAtomContentStream = new ContentStreamDataImpl();
+
+    // read attributes
+    String type = "text";
+    for (int i = 0; i < parser.getAttributeCount(); i++) {
+      QName attrName = parser.getAttributeName(i);
+      if (ATTR_TYPE.equals(attrName.getLocalPart())) {
+        fAtomContentStream.setMimeType(parser.getAttributeValue(i));
+        if (parser.getAttributeValue(i) != null) {
+          type = parser.getAttributeValue(i).trim().toLowerCase();
+        }
+      }
+      else if (ATTR_SRC.equals(attrName.getLocalPart())) {
+        throw new CmisNotSupportedException("External content not supported!");
+      }
+    }
+
+    next(parser);
+
+    if (type.equals("text") || type.equals("html")) {
+      fAtomContentStream.setStream(new ByteArrayInputStream(readText(parser).getBytes("UTF-8")));
+    }
+    else if (type.equals("xhtml")) {
+      fAtomContentStream.setStream(copy(parser));
+    }
+    else if (type.endsWith("/xml") || type.endsWith("+xml")) {
+      fAtomContentStream.setStream(copy(parser));
+    }
+    else if (type.startsWith("text/")) {
+      fAtomContentStream.setStream(new ByteArrayInputStream(readText(parser).getBytes("UTF-8")));
+    }
+    else {
+      fAtomContentStream.setStream(new ByteArrayInputStream(Base64.decodeBase64(readText(parser))));
+    }
+  }
+
+  /**
+   * Extract the content stream.
+   */
+  private void parseCmisContent(XMLStreamReader parser) throws Exception {
+    fCmisContentStream = new ContentStreamDataImpl();
+
+    next(parser);
+
+    // walk through all tags in content
+    while (true) {
+      int event = parser.getEventType();
+      if (event == XMLStreamReader.START_ELEMENT) {
+        QName name = parser.getName();
+
+        if (Constants.NAMESPACE_RESTATOM.equals(name.getNamespaceURI())) {
+          if (TAG_MEDIATYPE.equals(name.getLocalPart())) {
+            fCmisContentStream.setMimeType(readText(parser));
+          }
+          else if (TAG_BASE64.equals(name.getLocalPart())) {
+            fCmisContentStream.setStream(new ByteArrayInputStream(Base64
+                .decodeBase64(readText(parser))));
+          }
+          else {
+            skip(parser);
+          }
+        }
+        else {
+          skip(parser);
+        }
+      }
+      else if (event == XMLStreamReader.END_ELEMENT) {
+        break;
+      }
+      else {
+        if (!next(parser)) {
+          break;
+        }
+      }
+    }
+
+    next(parser);
+  }
+
+  /**
+   * Parses a tag that contains text.
+   */
+  private String readText(XMLStreamReader parser) throws Exception {
+    StringBuilder sb = new StringBuilder();
+
+    next(parser);
+
+    while (true) {
+      int event = parser.getEventType();
+      if (event == XMLStreamReader.END_ELEMENT) {
+        break;
+      }
+      else if (event == XMLStreamReader.CHARACTERS) {
+        String s = parser.getText();
+        if (s != null) {
+          sb.append(s);
+        }
+      }
+      else if (event == XMLStreamReader.START_ELEMENT) {
+        throw new RuntimeException("Unexpected tag: " + parser.getName());
+      }
+
+      if (!next(parser)) {
+        break;
+      }
+    }
+
+    next(parser);
+
+    return sb.toString();
+  }
+
+  /**
+   * Copies a subtree into a stream.
+   */
+  private InputStream copy(XMLStreamReader parser) throws Exception {
+    // ToDo: implement copy
+
+    int level = 1;
+    while (next(parser)) {
+      int event = parser.getEventType();
+      if (event == XMLStreamReader.START_ELEMENT) {
+        level++;
+      }
+      else if (event == XMLStreamReader.END_ELEMENT) {
+        level--;
+        if (level == 0) {
+          break;
+        }
+      }
+    }
+
+    next(parser);
+
+    return null;
+  }
+
+  /**
+   * Skips a tag or subtree.
+   */
+  private void skip(XMLStreamReader parser) throws Exception {
+    int level = 1;
+    while (next(parser)) {
+      int event = parser.getEventType();
+      if (event == XMLStreamReader.START_ELEMENT) {
+        level++;
+      }
+      else if (event == XMLStreamReader.END_ELEMENT) {
+        level--;
+        if (level == 0) {
+          break;
+        }
+      }
+    }
+
+    next(parser);
+  }
+
+  private boolean next(XMLStreamReader parser) throws Exception {
+    if (parser.hasNext()) {
+      parser.next();
+      return true;
+    }
+
+    return false;
+  }
+}
\ No newline at end of file

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomFeed.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/AtomFeed.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomFeed.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomFeed.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,169 @@
+/*
+ * 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.math.BigInteger;
+import java.util.GregorianCalendar;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.opencmis.commons.impl.Constants;
+import org.apache.opencmis.commons.impl.UrlBuilder;
+
+/**
+ * Atom Feed class.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class AtomFeed extends AtomDocumentBase {
+
+  public static final BigInteger DEFAULT_PAGE_SIZE = BigInteger.valueOf(100);
+
+  /**
+   * Creates an Atom feed document.
+   */
+  public AtomFeed() {
+  }
+
+  /**
+   * Creates an Atom feed that is embedded somewhere.
+   */
+  public AtomFeed(XMLStreamWriter writer) {
+    setWriter(writer);
+  }
+
+  /**
+   * Opens the feed tag.
+   */
+  public void startFeed(boolean isRoot) throws XMLStreamException {
+    getWriter().writeStartElement(Constants.NAMESPACE_ATOM, "feed");
+
+    if (isRoot) {
+      writeNamespace(Constants.NAMESPACE_ATOM);
+      writeNamespace(Constants.NAMESPACE_CMIS);
+      writeNamespace(Constants.NAMESPACE_RESTATOM);
+      writeNamespace(Constants.NAMESPACE_APP);
+    }
+  }
+
+  /**
+   * Opens the children tag.
+   */
+  public void startChildren() throws XMLStreamException {
+    XMLStreamWriter writer = getWriter();
+    writer.writeStartElement(Constants.NAMESPACE_RESTATOM, "children");
+  }
+
+  /**
+   * Closes the feed tag.
+   */
+  public void endChildren() throws XMLStreamException {
+    getWriter().writeEndElement();
+  }
+
+  /**
+   * Closes the feed tag.
+   */
+  public void endFeed() throws XMLStreamException {
+    getWriter().writeEndElement();
+  }
+
+  /**
+   * Writes the feed elements that are required by Atom.
+   */
+  public void writeFeedElements(String id, String author, String title, GregorianCalendar updated,
+      String pathSegment, BigInteger numItems) throws XMLStreamException {
+    writeAuthor(author);
+    writeId(generateAtomId(id));
+    writeTitle(title);
+    writeUpdated(updated);
+    writePathSegment(pathSegment);
+    writeNumItems(numItems);
+  }
+
+  /**
+   * Writes a CMIS numItems tag.
+   */
+  public void writeNumItems(BigInteger numItems) throws XMLStreamException {
+    if (numItems == null) {
+      return;
+    }
+
+    writeSimpleTag(Constants.NAMESPACE_RESTATOM, "numItems", numItems.toString());
+  }
+
+  /**
+   * Writes paging links.
+   */
+  public void writePagingLinks(UrlBuilder pagingUrl, BigInteger maxItems, BigInteger skipCount,
+      BigInteger numItems, Boolean hasMoreItems, BigInteger pageSize) throws XMLStreamException {
+
+    if ((skipCount == null) || (skipCount.compareTo(BigInteger.ZERO) == -1)) {
+      skipCount = BigInteger.ZERO;
+    }
+
+    if ((maxItems == null) || (maxItems.compareTo(BigInteger.ZERO) == -1)) {
+      if ((pageSize == null) || (pageSize.compareTo(BigInteger.ZERO) == -1)) {
+        maxItems = DEFAULT_PAGE_SIZE;
+      }
+      else {
+        maxItems = pageSize;
+      }
+    }
+
+    // if not first page -> add "first" and "previous" link
+    if (skipCount.compareTo(BigInteger.ZERO) == 1) {
+      // first link
+      UrlBuilder firstLink = new UrlBuilder(pagingUrl);
+      firstLink.addParameter(Constants.PARAM_SKIP_COUNT, "0");
+      firstLink.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+      writeFirstLink(firstLink.toString());
+
+      // previous link
+      UrlBuilder previousLink = new UrlBuilder(pagingUrl);
+      previousLink.addParameter(Constants.PARAM_SKIP_COUNT, skipCount.subtract(maxItems).max(
+          BigInteger.ZERO));
+      previousLink.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+      writePreviousLink(previousLink.toString());
+    }
+
+    // if has more -> add "next" link
+    if ((hasMoreItems != null) && hasMoreItems.booleanValue()) {
+      // next link
+      UrlBuilder nextLink = new UrlBuilder(pagingUrl);
+      nextLink.addParameter(Constants.PARAM_SKIP_COUNT, skipCount.add(maxItems));
+      nextLink.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+      writeNextLink(nextLink.toString());
+    }
+
+    // if not last page -> add "last" link
+    if ((numItems != null) && (numItems.compareTo(BigInteger.ZERO) == 1)) {
+      BigInteger lastSkip = numItems.subtract(maxItems).max(BigInteger.ZERO);
+      if (lastSkip.compareTo(BigInteger.ZERO) == 1) {
+        // last link
+        UrlBuilder lastLink = new UrlBuilder(pagingUrl);
+        lastLink.addParameter(Constants.PARAM_SKIP_COUNT, lastSkip);
+        lastLink.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+        writeLastLink(lastLink.toString());
+      }
+    }
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomPubUtils.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/AtomPubUtils.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomPubUtils.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/AtomPubUtils.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,496 @@
+/*
+ * 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.Method;
+import java.math.BigInteger;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.bind.JAXBException;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.api.TypeDefinitionContainer;
+import org.apache.opencmis.commons.enums.BaseObjectTypeIds;
+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.ReturnVersion;
+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.PropertiesData;
+import org.apache.opencmis.commons.provider.PropertyData;
+import org.apache.opencmis.server.spi.ObjectInfo;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+import org.apache.opencmis.server.spi.RenditionInfo;
+
+/**
+ * This class contains operations used by all services.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public final class AtomPubUtils {
+
+  public static final String RESOURCE_CHILDREN = "children";
+  public static final String RESOURCE_DESCENDANTS = "descendants";
+  public static final String RESOURCE_FOLDERTREE = "foldertree";
+  public static final String RESOURCE_TYPE = "type";
+  public static final String RESOURCE_TYPES = "types";
+  public static final String RESOURCE_TYPESDESC = "typedesc";
+  public static final String RESOURCE_ENTRY = "entry";
+  public static final String RESOURCE_PARENTS = "parents";
+  public static final String RESOURCE_VERSIONS = "versions";
+  public static final String RESOURCE_ALLOWABLEACIONS = "allowableactions";
+  public static final String RESOURCE_ACL = "acl";
+  public static final String RESOURCE_POLICIES = "policies";
+  public static final String RESOURCE_RELATIONSHIPS = "relationships";
+  public static final String RESOURCE_OBJECTBYID = "id";
+  public static final String RESOURCE_OBJECTBYPATH = "path";
+  public static final String RESOURCE_QUERY = "query";
+  public static final String RESOURCE_CHECKEDOUT = "checkedout";
+  public static final String RESOURCE_UNFILED = "unfiled";
+  public static final String RESOURCE_CHANGES = "changes";
+  public static final String RESOURCE_CONTENT = "content";
+
+  public static final BigInteger PAGE_SIZE = BigInteger.valueOf(100);
+
+  public static final String TYPE_AUTHOR = "unknown";
+
+  /**
+   * Private constructor.
+   */
+  private AtomPubUtils() {
+  }
+
+  /**
+   * Compiles the base URL for links, collections and templates.
+   */
+  public static UrlBuilder compileBaseUrl(HttpServletRequest request, String repositoryId) {
+    UrlBuilder url = new UrlBuilder(request.getScheme(), request.getServerName(), request
+        .getServerPort(), null);
+
+    url.addPath(request.getContextPath());
+    url.addPath(request.getServletPath());
+
+    if (repositoryId != null) {
+      url.addPath(repositoryId);
+    }
+
+    return url;
+  }
+
+  /**
+   * Compiles a URL for links, collections and templates.
+   */
+  public static String compileUrl(UrlBuilder baseUrl, String resource, String id) {
+    return compileUrlBuilder(baseUrl, resource, id).toString();
+  }
+
+  /**
+   * Compiles a URL for links, collections and templates.
+   */
+  public static UrlBuilder compileUrlBuilder(UrlBuilder baseUrl, String resource, String id) {
+    UrlBuilder url = new UrlBuilder(baseUrl);
+    url.addPath(resource);
+
+    if (id != null) {
+      url.addParameter("id", id);
+    }
+
+    return url;
+  }
+
+  // -------------------------------------------------------------------------
+  // --- parameters ---
+  // -------------------------------------------------------------------------
+
+  /**
+   * Extracts a string parameter.
+   */
+  public static String getStringParameter(HttpServletRequest request, String name) {
+    return request.getParameter(name);
+  }
+
+  /**
+   * Extracts a boolean parameter (with default).
+   */
+  public static boolean getBooleanParameter(HttpServletRequest request, String name, boolean def) {
+    String value = request.getParameter(name);
+    if (value == null) {
+      return def;
+    }
+
+    return Boolean.valueOf(value);
+  }
+
+  /**
+   * Extracts a boolean parameter.
+   */
+  public static Boolean getBooleanParameter(HttpServletRequest request, String name) {
+    String value = request.getParameter(name);
+    if (value == null) {
+      return null;
+    }
+
+    return Boolean.valueOf(value);
+  }
+
+  /**
+   * Extracts an integer parameter (with default).
+   */
+  public static BigInteger getBigIntegerParameter(HttpServletRequest request, String name, long def) {
+    BigInteger result = getBigIntegerParameter(request, name);
+    if (result == null) {
+      result = BigInteger.valueOf(def);
+    }
+
+    return result;
+  }
+
+  /**
+   * Extracts an integer parameter.
+   */
+  public static BigInteger getBigIntegerParameter(HttpServletRequest request, String name) {
+    String value = request.getParameter(name);
+    if (value == null) {
+      return null;
+    }
+
+    try {
+      return new BigInteger(value);
+    }
+    catch (Exception e) {
+      throw new CmisInvalidArgumentException("Invalid parameter '" + name + "'!");
+    }
+  }
+
+  /**
+   * Extracts an enum parameter.
+   */
+  @SuppressWarnings("unchecked")
+  public static <T> T getEnumParameter(HttpServletRequest request, String name, Class<T> clazz) {
+    String value = request.getParameter(name);
+    if (value == null) {
+      return null;
+    }
+
+    try {
+      Method m = clazz.getMethod("fromValue", new Class[] { String.class });
+      return (T) m.invoke(null, new Object[] { value });
+    }
+    catch (IllegalArgumentException iae) {
+      throw new CmisInvalidArgumentException("Invalid parameter '" + name + "'!");
+    }
+    catch (Exception e) {
+      throw new CmisRuntimeException(e.getMessage(), e);
+    }
+  }
+
+  /**
+   * Extracts a property from an object.
+   */
+  @SuppressWarnings("unchecked")
+  public static <T> T getProperty(ObjectData object, String name, Class<T> clazz) {
+    if (object == null) {
+      return null;
+    }
+
+    PropertiesData propData = object.getProperties();
+    if (propData == null) {
+      return null;
+    }
+
+    Map<String, PropertyData<?>> properties = propData.getProperties();
+    if (properties == null) {
+      return null;
+    }
+
+    PropertyData<?> property = properties.get(name);
+    if (property == null) {
+      return null;
+    }
+
+    Object value = property.getFirstValue();
+    if (!clazz.isInstance(value)) {
+      return null;
+    }
+
+    return (T) value;
+  }
+
+  // -------------------------------------------------------------------------
+  // --- entry builder ---
+  // -------------------------------------------------------------------------
+
+  /**
+   * Writes the a object entry.
+   */
+  public static void writeObjectEntry(AtomEntry entry, ObjectData object,
+      ObjectInfoHolder infoHolder, List<ObjectInFolderContainer> children, String repositoryId,
+      String pathSegment, String relativePathSegment, UrlBuilder baseUrl, boolean isRoot)
+      throws XMLStreamException, JAXBException {
+    if ((object == null) || (infoHolder == null)) {
+      throw new CmisRuntimeException("Object or Object Info not set!");
+    }
+
+    ObjectInfo info = infoHolder.getObjectInfo(object.getId());
+    if (info == null) {
+      throw new CmisRuntimeException("Object Info not found!");
+    }
+
+    // start
+    entry.startEntry(isRoot);
+
+    // write object
+    String contentSrc = null;
+
+    if (info.hasContent()) {
+      UrlBuilder contentSrcBuilder = compileUrlBuilder(baseUrl, RESOURCE_CONTENT, info.getId());
+      if (info.getFileName() != null) {
+        contentSrcBuilder.addPath(info.getFileName());
+      }
+
+      contentSrc = contentSrcBuilder.toString();
+    }
+
+    entry.writeObject(object, info, contentSrc, info.getContentType(), pathSegment,
+        relativePathSegment);
+
+    // write links
+    entry.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    entry.writeSelfLink(compileUrl(baseUrl, RESOURCE_ENTRY, info.getId()), info.getId());
+    entry.writeEnclosureLink(compileUrl(baseUrl, RESOURCE_ENTRY, info.getId()));
+    entry.writeEditLink(compileUrl(baseUrl, RESOURCE_ENTRY, info.getId()));
+    entry.writeDescribedByLink(compileUrl(baseUrl, RESOURCE_TYPE, info.getTypeId()));
+    entry.writeAllowableActionsLink(compileUrl(baseUrl, RESOURCE_ALLOWABLEACIONS, info.getId()));
+
+    if (info.hasParent()) {
+      entry.writeUpLink(compileUrl(baseUrl, RESOURCE_PARENTS, info.getId()),
+          Constants.MEDIATYPE_FEED);
+    }
+
+    if (info.getBaseType() == BaseObjectTypeIds.CMIS_FOLDER) {
+      entry.writeDownLink(compileUrl(baseUrl, RESOURCE_CHILDREN, info.getId()),
+          Constants.MEDIATYPE_FEED);
+
+      if (info.supportsDescendants()) {
+        entry.writeDownLink(compileUrl(baseUrl, RESOURCE_DESCENDANTS, info.getId()),
+            Constants.MEDIATYPE_DESCENDANTS);
+      }
+
+      if (info.supportsFolderTree()) {
+        entry.writeFolderTreeLink(compileUrl(baseUrl, RESOURCE_FOLDERTREE, info.getId()));
+      }
+    }
+
+    if (info.hasVersionHistory()) {
+      entry.writeVersionHistoryLink(compileUrl(baseUrl, RESOURCE_VERSIONS, info.getId()));
+    }
+
+    if (!info.isCurrentVersion()) {
+      UrlBuilder cvUrl = compileUrlBuilder(baseUrl, RESOURCE_ENTRY, info.getId());
+      cvUrl.addParameter(Constants.PARAM_RETURN_VERSION, ReturnVersion.LATEST);
+      entry.writeEditLink(cvUrl.toString());
+    }
+
+    if (contentSrc != null) {
+      entry.writeEditMediaLink(contentSrc, info.getContentType());
+    }
+
+    if (info.getWorkingCopyId() != null) {
+      entry.writeWorkingCopyLink(compileUrl(baseUrl, RESOURCE_ENTRY, info.getWorkingCopyId()));
+    }
+
+    if (info.getWorkingCopyOriginalId() != null) {
+      entry.writeViaLink(compileUrl(baseUrl, RESOURCE_ENTRY, info.getWorkingCopyOriginalId()));
+    }
+
+    if (info.getRenditionInfos() != null) {
+      for (RenditionInfo ri : info.getRenditionInfos()) {
+        entry.writeAlternateLink(compileUrl(baseUrl, RESOURCE_CONTENT, ri.getId()), ri
+            .getContenType(), ri.getKind(), ri.getTitle(), ri.getLength());
+      }
+    }
+
+    if (info.hasAcl()) {
+      entry.writeAclLink(compileUrl(baseUrl, RESOURCE_ACL, info.getId()));
+    }
+
+    if (info.supportsPolicies()) {
+      entry.writeAclLink(compileUrl(baseUrl, RESOURCE_POLICIES, info.getId()));
+    }
+
+    if (info.supportsRelationships()) {
+      entry.writeRelationshipsLink(compileUrl(baseUrl, RESOURCE_RELATIONSHIPS, info.getId()));
+    }
+
+    if (info.getRelationshipSourceIds() != null) {
+      for (String id : info.getRelationshipSourceIds()) {
+        entry.writeRelationshipSourceLink(compileUrl(baseUrl, RESOURCE_ENTRY, id));
+      }
+    }
+
+    if (info.getRelationshipTargetIds() != null) {
+      for (String id : info.getRelationshipTargetIds()) {
+        entry.writeRelationshipTargetLink(compileUrl(baseUrl, RESOURCE_ENTRY, id));
+      }
+    }
+
+    // write children
+    if ((children != null) && (children.size() > 0)) {
+      writeObjectChildren(entry, info, children, infoHolder, repositoryId, baseUrl);
+    }
+
+    // we are done
+    entry.endEntry();
+  }
+
+  /**
+   * Writes an objects entry children feed.
+   */
+  public static void writeObjectChildren(AtomEntry entry, ObjectInfo folderInfo,
+      List<ObjectInFolderContainer> children, ObjectInfoHolder infoHolder, String repositoryId,
+      UrlBuilder baseUrl) throws XMLStreamException, JAXBException {
+
+    // start
+    AtomFeed feed = new AtomFeed(entry.getWriter());
+    feed.startChildren();
+    feed.startFeed(false);
+
+    // write basic Atom feed elements
+    feed.writeFeedElements(folderInfo.getId(), folderInfo.getCreatedBy(), folderInfo.getName(),
+        folderInfo.getLastModificationDate(), null, null);
+
+    // write links
+    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);
+
+    feed.writeDownLink(compileUrl(baseUrl, RESOURCE_FOLDERTREE, folderInfo.getId()),
+        Constants.MEDIATYPE_DESCENDANTS);
+
+    feed.writeUpLink(compileUrl(baseUrl, RESOURCE_PARENTS, folderInfo.getId()),
+        Constants.MEDIATYPE_FEED);
+
+    for (ObjectInFolderContainer container : children) {
+      if ((container != null) && (container.getObject() != null)) {
+        writeObjectEntry(entry, container.getObject().getObject(), infoHolder, container
+            .getChildren(), repositoryId, container.getObject().getPathSegment(), null, baseUrl,
+            false);
+      }
+    }
+
+    // we are done
+    feed.endFeed();
+    feed.endChildren();
+  }
+
+  /**
+   * Writes the a type entry.
+   */
+  public static void writeTypeEntry(AtomEntry entry, TypeDefinition type,
+      List<TypeDefinitionContainer> children, String repositoryId, UrlBuilder baseUrl,
+      boolean isRoot) throws XMLStreamException, JAXBException {
+
+    // start
+    entry.startEntry(isRoot);
+
+    // write type
+    entry.writeType(type);
+
+    // write links
+    entry.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    entry.writeSelfLink(compileUrl(baseUrl, RESOURCE_TYPE, type.getId()), type.getId());
+    entry.writeEnclosureLink(compileUrl(baseUrl, RESOURCE_TYPE, type.getId()));
+    if (type.getParentId() != null) {
+      entry.writeUpLink(compileUrl(baseUrl, RESOURCE_TYPE, type.getParentId()),
+          Constants.MEDIATYPE_ENTRY);
+    }
+    UrlBuilder downLink = compileUrlBuilder(baseUrl, RESOURCE_TYPES, null);
+    downLink.addParameter(Constants.PARAM_TYPE_ID, type.getId());
+    entry.writeDownLink(downLink.toString(), Constants.MEDIATYPE_CHILDREN);
+    entry.writeDescribedByLink(compileUrl(baseUrl, RESOURCE_TYPE, type.getBaseId().value()));
+
+    // write children
+    if ((children != null) && (children.size() > 0)) {
+      writeTypeChildren(entry, type, children, repositoryId, baseUrl);
+    }
+
+    // we are done
+    entry.endEntry();
+  }
+
+  /**
+   * Writes the a type entry children feed.
+   */
+  private static void writeTypeChildren(AtomEntry entry, TypeDefinition type,
+      List<TypeDefinitionContainer> children, String repositoryId, UrlBuilder baseUrl)
+      throws XMLStreamException, JAXBException {
+
+    // start
+    AtomFeed feed = new AtomFeed(entry.getWriter());
+    feed.startChildren();
+    feed.startFeed(false);
+
+    // write basic Atom feed elements
+    feed.writeFeedElements(type.getId(), TYPE_AUTHOR, type.getDisplayName(),
+        new GregorianCalendar(), null, null);
+
+    feed.writeServiceLink(baseUrl.toString(), repositoryId);
+
+    UrlBuilder selfLink = compileUrlBuilder(baseUrl, RESOURCE_TYPESDESC, null);
+    selfLink.addParameter(Constants.PARAM_TYPE_ID, type.getId());
+    feed.writeSelfLink(selfLink.toString(), type.getId());
+
+    feed.writeViaLink(compileUrl(baseUrl, RESOURCE_TYPE, type.getId()));
+
+    UrlBuilder downLink = compileUrlBuilder(baseUrl, RESOURCE_TYPES, null);
+    downLink.addParameter(Constants.PARAM_TYPE_ID, type.getId());
+    feed.writeDownLink(downLink.toString(), Constants.MEDIATYPE_FEED);
+
+    if (type.getParentId() != null) {
+      feed.writeUpLink(compileUrl(baseUrl, RESOURCE_TYPE, type.getParentId()),
+          Constants.MEDIATYPE_ENTRY);
+    }
+
+    // write tree
+    for (TypeDefinitionContainer container : children) {
+      if ((container != null) && (container.getTypeDefinition() != null)) {
+        writeTypeEntry(entry, container.getTypeDefinition(), container.getChildren(), repositoryId,
+            baseUrl, false);
+      }
+    }
+
+    // we are done
+    feed.endFeed();
+    feed.endChildren();
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/BasicAuthCallContextHandler.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/BasicAuthCallContextHandler.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/BasicAuthCallContextHandler.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/BasicAuthCallContextHandler.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,81 @@
+/*
+ * 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.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.opencmis.server.spi.CallContext;
+
+/**
+ * Call Context handler that handles basic authentication.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class BasicAuthCallContextHandler implements CallContextHandler {
+
+  /**
+   * Constructor.
+   */
+  public BasicAuthCallContextHandler() {
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @seeorg.apache.opencmis.server.impl.atompub.CallContextHandler#getCallContextMap(javax.servlet.http.
+   * HttpServletRequest)
+   */
+  public Map<String, String> getCallContextMap(HttpServletRequest request) {
+    Map<String, String> result = null;
+
+    String authHeader = request.getHeader("Authorization");
+    if ((authHeader != null) && (authHeader.trim().toLowerCase().startsWith("basic "))) {
+      int x = authHeader.lastIndexOf(' ');
+      if (x == -1) {
+        return result;
+      }
+
+      String credentials = null;
+      try {
+        credentials = new String(Base64.decodeBase64(authHeader.substring(x + 1).getBytes(
+            "ISO-8859-1")), "ISO-8859-1");
+      }
+      catch (Exception e) {
+        return result;
+      }
+
+      x = credentials.indexOf(':');
+      if (x == -1) {
+        return result;
+      }
+
+      // extract user and password and add them to map
+      result = new HashMap<String, String>();
+      result.put(CallContext.USERNAME, credentials.substring(0, x));
+      result.put(CallContext.PASSWORD, credentials.substring(x + 1));
+    }
+
+    return result;
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/CallContextHandler.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/CallContextHandler.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/CallContextHandler.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-impl/src/main/java/org/apache/opencmis/server/impl/atompub/CallContextHandler.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,39 @@
+/*
+ * 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.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.opencmis.server.spi.CallContext;
+
+/**
+ * Call Context handler interface.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public interface CallContextHandler {
+
+  /**
+   * Returns key-value pairs that will be added to the {@link CallContext}.
+   */
+  Map<String, String> getCallContextMap(HttpServletRequest request);
+}

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