You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fg...@apache.org on 2010/04/15 12:33:51 UTC

svn commit: r934361 [2/9] - in /incubator/chemistry/opencmis/trunk: chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/ chemistry-opencmis-client/chemistry-opencmis-client-bindings/s...

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/RepositoryServiceImpl.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/RepositoryServiceImpl.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/RepositoryServiceImpl.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,185 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.impl;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.util.List;
+
+import org.apache.chemistry.opencmis.client.bindings.spi.CmisSpi;
+import org.apache.chemistry.opencmis.client.bindings.spi.Session;
+import org.apache.chemistry.opencmis.commons.api.ExtensionsData;
+import org.apache.chemistry.opencmis.commons.api.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.api.TypeDefinitionContainer;
+import org.apache.chemistry.opencmis.commons.api.TypeDefinitionList;
+import org.apache.chemistry.opencmis.commons.provider.RepositoryInfoData;
+import org.apache.chemistry.opencmis.commons.provider.RepositoryService;
+
+/**
+ * Repository Service implementation.
+ * 
+ * Passes requests to the SPI and handles caching.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class RepositoryServiceImpl implements RepositoryService, Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private final Session fSession;
+
+  /**
+   * Constructor.
+   */
+  public RepositoryServiceImpl(Session session) {
+    fSession = session;
+  }
+
+  public RepositoryInfoData getRepositoryInfo(String repositoryId, ExtensionsData extension) {
+    RepositoryInfoData result = null;
+    boolean hasExtension = (extension != null) && (!extension.getExtensions().isEmpty());
+
+    RepositoryInfoCache cache = CmisBindingsHelper.getRepositoryInfoCache(fSession);
+
+    // if extension is not set, check the cache first
+    if (!hasExtension) {
+      result = cache.get(repositoryId);
+      if (result != null) {
+        return result;
+      }
+    }
+
+    // it was not in the cache -> get the SPI and fetch the repository info
+    CmisSpi spi = CmisBindingsHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getRepositoryInfo(repositoryId, extension);
+
+    // put it into the cache
+    if (!hasExtension) {
+      cache.put(result);
+    }
+
+    return result;
+  }
+
+  public List<RepositoryInfoData> getRepositoryInfos(ExtensionsData extension) {
+    List<RepositoryInfoData> result = null;
+    boolean hasExtension = (extension != null) && (!extension.getExtensions().isEmpty());
+
+    // get the SPI and fetch the repository infos
+    CmisSpi spi = CmisBindingsHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getRepositoryInfos(extension);
+
+    // put it into the cache
+    if (!hasExtension && (result != null)) {
+      RepositoryInfoCache cache = CmisBindingsHelper.getRepositoryInfoCache(fSession);
+      for (RepositoryInfoData rid : result) {
+        cache.put(rid);
+      }
+    }
+
+    return result;
+  }
+
+  public TypeDefinitionList getTypeChildren(String repositoryId, String typeId,
+      Boolean includePropertyDefinitions, BigInteger maxItems, BigInteger skipCount,
+      ExtensionsData extension) {
+    TypeDefinitionList result = null;
+    boolean hasExtension = (extension != null) && (!extension.getExtensions().isEmpty());
+    boolean propDefs = (includePropertyDefinitions == null ? false : includePropertyDefinitions
+        .booleanValue());
+
+    // get the SPI and fetch the type definitions
+    CmisSpi spi = CmisBindingsHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getTypeChildren(repositoryId, typeId,
+        includePropertyDefinitions, maxItems, skipCount, extension);
+
+    // put it into the cache
+    if (!hasExtension && propDefs && (result != null)) {
+      TypeDefinitionCache cache = CmisBindingsHelper.getTypeDefinitionCache(fSession);
+
+      for (TypeDefinition tdd : result.getList()) {
+        cache.put(repositoryId, tdd);
+      }
+    }
+
+    return result;
+  }
+
+  public TypeDefinition getTypeDefinition(String repositoryId, String typeId,
+      ExtensionsData extension) {
+    TypeDefinition result = null;
+    boolean hasExtension = (extension != null) && (!extension.getExtensions().isEmpty());
+
+    TypeDefinitionCache cache = CmisBindingsHelper.getTypeDefinitionCache(fSession);
+
+    // if extension is not set, check the cache first
+    if (!hasExtension) {
+      result = cache.get(repositoryId, typeId);
+      if (result != null) {
+        return result;
+      }
+    }
+
+    // it was not in the cache -> get the SPI and fetch the type definition
+    CmisSpi spi = CmisBindingsHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getTypeDefinition(repositoryId, typeId, extension);
+
+    // put it into the cache
+    if (!hasExtension && (result != null)) {
+      cache.put(repositoryId, result);
+    }
+
+    return result;
+  }
+
+  public List<TypeDefinitionContainer> getTypeDescendants(String repositoryId, String typeId,
+      BigInteger depth, Boolean includePropertyDefinitions, ExtensionsData extension) {
+    List<TypeDefinitionContainer> result = null;
+    boolean hasExtension = (extension != null) && (!extension.getExtensions().isEmpty());
+    boolean propDefs = (includePropertyDefinitions == null ? false : includePropertyDefinitions
+        .booleanValue());
+
+    // get the SPI and fetch the type definitions
+    CmisSpi spi = CmisBindingsHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getTypeDescendants(repositoryId, typeId, depth,
+        includePropertyDefinitions, extension);
+
+    // put it into the cache
+    if (!hasExtension && propDefs && (result != null)) {
+      TypeDefinitionCache cache = CmisBindingsHelper.getTypeDefinitionCache(fSession);
+      addToTypeCache(cache, repositoryId, result);
+    }
+
+    return result;
+  }
+
+  private void addToTypeCache(TypeDefinitionCache cache, String repositoryId,
+      List<TypeDefinitionContainer> containers) {
+    if (containers == null) {
+      return;
+    }
+
+    for (TypeDefinitionContainer container : containers) {
+      cache.put(repositoryId, container.getTypeDefinition());
+      addToTypeCache(cache, repositoryId, container.getChildren());
+    }
+  }
+}

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

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/RepositoryServiceImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/RepositoryServiceImpl.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/SessionImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/SessionImpl.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/SessionImpl.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/SessionImpl.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,145 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.impl;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.chemistry.opencmis.client.bindings.spi.Session;
+
+/**
+ * CMIS binding session implementation.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class SessionImpl implements Session {
+
+  private static final long serialVersionUID = 1L;
+
+  private Map<String, Object> fData;
+
+  private final ReentrantReadWriteLock fLock = new ReentrantReadWriteLock();
+
+  /**
+   * Constructor.
+   */
+  public SessionImpl() {
+    fData = new HashMap<String, Object>();
+  }
+
+  public Object get(String key) {
+    Object value = null;
+
+    fLock.readLock().lock();
+    try {
+      value = fData.get(key);
+    }
+    finally {
+      fLock.readLock().unlock();
+    }
+
+    if (value instanceof TransientWrapper) {
+      return ((TransientWrapper) value).getObject();
+    }
+
+    return value;
+  }
+
+  public Object get(String key, Object defValue) {
+    Object value = get(key);
+    return (value == null ? defValue : value);
+  }
+
+  public int get(String key, int defValue) {
+    Object value = get(key);
+    int intValue = defValue;
+
+    if (value instanceof Integer) {
+      intValue = ((Integer) value).intValue();
+    }
+    else if (value instanceof String) {
+      try {
+        intValue = Integer.valueOf((String) value);
+      }
+      catch (NumberFormatException e) {
+      }
+    }
+
+    return intValue;
+  }
+
+  public void put(String key, Serializable obj) {
+    fLock.writeLock().lock();
+    try {
+      fData.put(key, obj);
+    }
+    finally {
+      fLock.writeLock().unlock();
+    }
+  }
+
+  public void put(String key, Object obj, boolean isTransient) {
+    Object value = (isTransient ? new TransientWrapper(obj) : obj);
+    if (!(value instanceof Serializable)) {
+      throw new IllegalArgumentException("Object must be serializable!");
+    }
+
+    fLock.writeLock().lock();
+    try {
+      fData.put(key, value);
+    }
+    finally {
+      fLock.writeLock().unlock();
+    }
+  }
+
+  public void remove(String key) {
+    fLock.writeLock().lock();
+    try {
+      fData.remove(key);
+    }
+    finally {
+      fLock.writeLock().unlock();
+    }
+  }
+
+  public void readLock() {
+    fLock.readLock().lock();
+  }
+
+  public void readUnlock() {
+    fLock.readLock().unlock();
+  }
+
+  public void writeLock() {
+    fLock.writeLock().lock();
+  }
+
+  public void writeUnlock() {
+    fLock.writeLock().unlock();
+  }
+
+  @Override
+  public String toString() {
+    return fData.toString();
+  }
+}

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

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/SessionImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/SessionImpl.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TransientWrapper.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TransientWrapper.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TransientWrapper.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TransientWrapper.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,46 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.impl;
+
+import java.io.Serializable;
+
+/**
+ * Wrapper for transient objects in a cache.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class TransientWrapper implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+  private transient Object fObject = null;
+
+  public TransientWrapper(Object object) {
+    fObject = object;
+  }
+
+  public Object getObject() {
+    return fObject;
+  }
+
+  @Override
+  public String toString() {
+    return (fObject == null ? "(no object)" : "(transient) " + fObject.toString());
+  }
+}

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

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TransientWrapper.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TransientWrapper.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TypeDefinitionCache.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TypeDefinitionCache.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TypeDefinitionCache.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TypeDefinitionCache.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.chemistry.opencmis.client.bindings.impl;
+
+import java.io.Serializable;
+
+import org.apache.chemistry.opencmis.client.bindings.cache.Cache;
+import org.apache.chemistry.opencmis.client.bindings.cache.impl.CacheImpl;
+import org.apache.chemistry.opencmis.client.bindings.cache.impl.LruCacheLevelImpl;
+import org.apache.chemistry.opencmis.client.bindings.cache.impl.MapCacheLevelImpl;
+import org.apache.chemistry.opencmis.client.bindings.spi.Session;
+import org.apache.chemistry.opencmis.commons.SessionParameter;
+import org.apache.chemistry.opencmis.commons.api.TypeDefinition;
+
+/**
+ * A cache for type definition objects.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class TypeDefinitionCache implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final int CACHE_SIZE_REPOSITORIES = 10;
+  private static final int CACHE_SIZE_TYPES = 100;
+
+  private Cache fCache;
+
+  /**
+   * Constructor.
+   * 
+   * @param session
+   *          the session object
+   */
+  public TypeDefinitionCache(Session session) {
+    int repCount = session.get(SessionParameter.CACHE_SIZE_REPOSITORIES, CACHE_SIZE_REPOSITORIES);
+    if (repCount < 1) {
+      repCount = CACHE_SIZE_REPOSITORIES;
+    }
+
+    int typeCount = session.get(SessionParameter.CACHE_SIZE_TYPES, CACHE_SIZE_TYPES);
+    if (typeCount < 1) {
+      typeCount = CACHE_SIZE_TYPES;
+    }
+
+    fCache = new CacheImpl("Type Definition Cache");
+    fCache.initialize(new String[] {
+        MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
+        LruCacheLevelImpl.class.getName() + " " + LruCacheLevelImpl.MAX_ENTRIES + "=" + typeCount // type
+    });
+  }
+
+  /**
+   * Adds a type definition object to the cache.
+   * 
+   * @param repositoryId
+   *          the repository id
+   * @param typeDefinition
+   *          the type definition object
+   */
+  public void put(String repositoryId, TypeDefinition typeDefinition) {
+    if ((typeDefinition == null) || (typeDefinition.getId() == null)) {
+      return;
+    }
+
+    fCache.put(typeDefinition, repositoryId, typeDefinition.getId());
+  }
+
+  /**
+   * Retrieves a type definition object from the cache.
+   * 
+   * @param repositoryId
+   *          the repository id
+   * @param typeId
+   *          the type id
+   * @return the type definition object or <code>null</code> if the object is not in the cache
+   */
+  public TypeDefinition get(String repositoryId, String typeId) {
+    return (TypeDefinition) fCache.get(repositoryId, typeId);
+  }
+
+  /**
+   * Removes a type definition object from the cache.
+   * 
+   * @param repositoryId
+   *          the repository id
+   * @param typeId
+   *          the type id
+   */
+  public void remove(String repositoryId, String typeId) {
+    fCache.remove(repositoryId, typeId);
+  }
+
+  /**
+   * Removes all type definition objects of a repository from the cache.
+   * 
+   * @param repositoryId
+   *          the repository id
+   */
+  public void remove(String repositoryId) {
+    fCache.remove(repositoryId);
+  }
+
+  @Override
+  public String toString() {
+    return fCache.toString();
+  }
+}

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

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TypeDefinitionCache.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/impl/TypeDefinitionCache.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,107 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.spi;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.chemistry.opencmis.commons.SessionParameter;
+import org.w3c.dom.Element;
+
+/**
+ * Authentication provider class.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public abstract class AbstractAuthenticationProvider implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private Session fSession;
+
+  /**
+   * Sets the {@link Session} the authentication provider lives in.
+   */
+  public void setSession(Session session) {
+    fSession = session;
+  }
+
+  /**
+   * Returns {@link Session}.
+   */
+  public Session getSession() {
+    return fSession;
+  }
+
+  /**
+   * Returns a set of HTTP headers (key-value pairs) that should be added to a HTTP call. This will
+   * be called by the AtomPub and the Web Services binding. You might want to check the binding in
+   * use before you set the headers.
+   * 
+   * @param url
+   *          the URL of the HTTP call
+   * 
+   * @return the HTTP headers or <code>null</code> if no additional headers should be set
+   */
+  public Map<String, List<String>> getHTTPHeaders(String url) {
+    return null;
+  }
+
+  /**
+   * Returns a SOAP header that should be added to a Web Services call.
+   * 
+   * @param portObject
+   *          the port object
+   * 
+   * @return the SOAP headers or <code>null</code> if no additional headers should be set
+   */
+  public Element getSOAPHeaders(Object portObject) {
+    return null;
+  }
+
+  /**
+   * Gets the user name from the session.
+   * 
+   * @return the user name or <code>null</code> if the user name is not set
+   */
+  protected String getUser() {
+    Object userObject = getSession().get(SessionParameter.USER);
+    if (userObject instanceof String) {
+      return (String) userObject;
+    }
+
+    return null;
+  }
+
+  /**
+   * Gets the password from the session.
+   * 
+   * @return the password or <code>null</code> if the password is not set
+   */
+  protected String getPassword() {
+    Object passwordObject = getSession().get(SessionParameter.PASSWORD);
+    if (passwordObject instanceof String) {
+      return (String) passwordObject;
+    }
+
+    return null;
+  }
+}

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpi.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpi.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpi.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpi.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,96 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.spi;
+
+import org.apache.chemistry.opencmis.commons.provider.AclService;
+import org.apache.chemistry.opencmis.commons.provider.DiscoveryService;
+import org.apache.chemistry.opencmis.commons.provider.MultiFilingService;
+import org.apache.chemistry.opencmis.commons.provider.NavigationService;
+import org.apache.chemistry.opencmis.commons.provider.ObjectService;
+import org.apache.chemistry.opencmis.commons.provider.PolicyService;
+import org.apache.chemistry.opencmis.commons.provider.RelationshipService;
+import org.apache.chemistry.opencmis.commons.provider.RepositoryService;
+import org.apache.chemistry.opencmis.commons.provider.VersioningService;
+
+/**
+ * CMIS SPI interface.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public interface CmisSpi {
+  /**
+   * Gets a Repository Service interface object.
+   */
+  RepositoryService getRepositoryService();
+
+  /**
+   * Gets a Navigation Service interface object.
+   */
+  NavigationService getNavigationService();
+
+  /**
+   * Gets an Object Service interface object.
+   */
+  ObjectService getObjectService();
+
+  /**
+   * Gets a Versioning Service interface object.
+   */
+  VersioningService getVersioningService();
+
+  /**
+   * Gets a Relationship Service interface object.
+   */
+  RelationshipService getRelationshipService();
+
+  /**
+   * Gets a Discovery Service interface object.
+   */
+  DiscoveryService getDiscoveryService();
+
+  /**
+   * Gets a Multifiling Service interface object.
+   */
+  MultiFilingService getMultiFilingService();
+
+  /**
+   * Gets an ACL Service interface object.
+   */
+  AclService getAclService();
+
+  /**
+   * Gets a Policy Service interface object.
+   */
+  PolicyService getPolicyService();
+
+  /**
+   * Clears all caches of the current session.
+   */
+  void clearAllCaches();
+
+  /**
+   * Clears all caches of the current session that are related to the given repository.
+   * 
+   * @param repositoryId
+   *          the repository id
+   */
+  void clearRepositoryCache(String repositoryId);
+
+}

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpi.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpi.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpi.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpiFactory.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpiFactory.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpiFactory.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpiFactory.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,35 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.spi;
+
+/**
+ * CMIS SPI factory interface.
+ * 
+ * <p>
+ * A class implementing this interface MUST provide a default constructor.
+ * </p>
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public interface CmisSpiFactory {
+
+  CmisSpi getSpiInstance(Session session);
+
+}

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpiFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpiFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/CmisSpiFactory.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/Session.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/Session.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/Session.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/Session.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,80 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.spi;
+
+import java.io.Serializable;
+
+/**
+ * CMIS provider session interface.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public interface Session extends Serializable {
+
+  /**
+   * Gets a session value.
+   */
+  Object get(String key);
+
+  /**
+   * Returns a session value or the default value if the key doesn't exist.
+   */
+  Object get(String key, Object defValue);
+
+  /**
+   * Returns a session value or the default value if the key doesn't exist.
+   */
+  int get(String key, int defValue);
+
+  /**
+   * Adds a non-transient session value.
+   */
+  void put(String key, Serializable object);
+
+  /**
+   * Adds a session value.
+   */
+  void put(String key, Object object, boolean isTransient);
+
+  /**
+   * Removes a session value.
+   */
+  void remove(String key);
+
+  /**
+   * Acquires a read lock.
+   */
+  void readLock();
+
+  /**
+   * Releases a read lock.
+   */
+  void readUnlock();
+
+  /**
+   * Acquires a write lock.
+   */
+  void writeLock();
+
+  /**
+   * Releases a write lock.
+   */
+  void writeUnlock();
+}

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/Session.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/Session.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/Session.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,179 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.spi;
+
+import java.io.UnsupportedEncodingException;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.chemistry.opencmis.commons.SessionParameter;
+import org.apache.commons.codec.binary.Base64;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Standard authentication provider class.
+ * 
+ * Adds a basic authentication HTTP header and a WS-Security UsernameToken SOAP header.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class StandardAuthenticationProvider extends AbstractAuthenticationProvider {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final String WSSE_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
+  private static final String WSU_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
+
+  @Override
+  public Map<String, List<String>> getHTTPHeaders(String url) {
+    Map<String, List<String>> result = null;
+
+    // only send HTTP header if configured
+    if (!isTrue(SessionParameter.AUTH_HTTP_BASIC)) {
+      return null;
+    }
+
+    // get user and password
+    String user = getUser();
+    String password = getPassword();
+
+    // if no user is set, don't create HTTP headers
+    if (user == null) {
+      return null;
+    }
+
+    if (password == null) {
+      password = "";
+    }
+
+    String authHeader = "";
+    try {
+      authHeader = "Basic "
+          + new String(Base64.encodeBase64((user + ":" + password).getBytes("ISO-8859-1")),
+              "ISO-8859-1");
+    }
+    catch (UnsupportedEncodingException e) {
+      // shouldn't happen...
+      return null;
+    }
+
+    result = new HashMap<String, List<String>>();
+    result.put("Authorization", Collections.singletonList(authHeader));
+
+    return result;
+  }
+
+  @Override
+  public Element getSOAPHeaders(Object portObject) {
+    // get user and password
+    String user = getUser();
+    String password = getPassword();
+
+    // only send SOAP header if configured
+    if (!isTrue(SessionParameter.AUTH_SOAP_USERNAMETOKEN)) {
+      return null;
+    }
+
+    // if no user is set, don't create SOAP header
+    if (user == null) {
+      return null;
+    }
+
+    if (password == null) {
+      password = "";
+    }
+
+    // set time
+    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+    long created = System.currentTimeMillis();
+    long expires = created + 24 * 60 * 60 * 1000; // 24 hours
+
+    // create the SOAP header
+    try {
+      Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+
+      Element wsseSecurityElement = document.createElementNS(WSSE_NAMESPACE, "Security");
+
+      Element wsuTimestampElement = document.createElementNS(WSU_NAMESPACE, "Timestamp");
+      wsseSecurityElement.appendChild(wsuTimestampElement);
+
+      Element tsCreatedElement = document.createElementNS(WSU_NAMESPACE, "Created");
+      tsCreatedElement.setTextContent(sdf.format(created));
+      wsuTimestampElement.appendChild(tsCreatedElement);
+
+      Element tsExpiresElement = document.createElementNS(WSU_NAMESPACE, "Expires");
+      tsExpiresElement.setTextContent(sdf.format(expires));
+      wsuTimestampElement.appendChild(tsExpiresElement);
+
+      Element usernameTokenElement = document.createElementNS(WSSE_NAMESPACE, "UsernameToken");
+      wsseSecurityElement.appendChild(usernameTokenElement);
+
+      Element usernameElement = document.createElementNS(WSSE_NAMESPACE, "Username");
+      usernameElement.setTextContent(user);
+      usernameTokenElement.appendChild(usernameElement);
+
+      Element passwordElement = document.createElementNS(WSSE_NAMESPACE, "Password");
+      passwordElement.setTextContent(password);
+      passwordElement
+          .setAttribute("Type",
+              "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
+      usernameTokenElement.appendChild(passwordElement);
+
+      Element createdElement = document.createElementNS(WSU_NAMESPACE, "Created");
+      createdElement.setTextContent(sdf.format(created));
+      usernameTokenElement.appendChild(createdElement);
+
+      return wsseSecurityElement;
+    }
+    catch (ParserConfigurationException e) {
+      // shouldn't happen...
+      e.printStackTrace();
+    }
+
+    return null;
+  }
+
+  /**
+   * Returns <code>true</code> if the given parameter exists in the session and is set to true,
+   * <code>false</code> otherwise.
+   */
+  private boolean isTrue(String parameterName) {
+    Object value = getSession().get(parameterName);
+
+    if (value instanceof Boolean) {
+      return ((Boolean) value).booleanValue();
+    }
+
+    if (value instanceof String) {
+      return Boolean.parseBoolean((String) value);
+    }
+
+    return false;
+  }
+}

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,806 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.spi.atompub;
+
+import static org.apache.chemistry.opencmis.commons.impl.Converter.convert;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.chemistry.opencmis.client.bindings.spi.Session;
+import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.Acl;
+import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomBase;
+import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomElement;
+import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomEntry;
+import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomLink;
+import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.RepositoryWorkspace;
+import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.ServiceDoc;
+import org.apache.chemistry.opencmis.commons.PropertyIds;
+import org.apache.chemistry.opencmis.commons.SessionParameter;
+import org.apache.chemistry.opencmis.commons.api.ExtensionsData;
+import org.apache.chemistry.opencmis.commons.api.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
+import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.chemistry.opencmis.commons.impl.Constants;
+import org.apache.chemistry.opencmis.commons.impl.JaxBHelper;
+import org.apache.chemistry.opencmis.commons.impl.ReturnVersion;
+import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlEntryImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlListImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlPrincipalDataImpl;
+import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisAccessControlListType;
+import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisObjectType;
+import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisPropertiesType;
+import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisPropertyId;
+import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisRepositoryInfoType;
+import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisTypeDefinitionType;
+import org.apache.chemistry.opencmis.commons.provider.AccessControlEntry;
+import org.apache.chemistry.opencmis.commons.provider.AccessControlList;
+import org.apache.chemistry.opencmis.commons.provider.ObjectData;
+import org.apache.chemistry.opencmis.commons.provider.RepositoryInfoData;
+
+/**
+ * Base class for all AtomPub clients.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class AbstractAtomPubService {
+
+  protected enum IdentifierType {
+    ID, PATH
+  };
+
+  protected static final String NAME_COLLECTION = "collection";
+  protected static final String NAME_URI_TEMPLATE = "uritemplate";
+  protected static final String NAME_PATH_SEGMENT = "pathSegment";
+  protected static final String NAME_RELATIVE_PATH_SEGMENT = "relativePathSegment";
+  protected static final String NAME_NUM_ITEMS = "numItems";
+
+  private Session fSession;
+
+  /**
+   * Sets the current session.
+   */
+  protected void setSession(Session session) {
+    fSession = session;
+  }
+
+  /**
+   * Gets the current session.
+   */
+  protected Session getSession() {
+    return fSession;
+  }
+
+  /**
+   * Returns the service document URL of this session.
+   */
+  protected String getServiceDocURL() {
+    Object url = fSession.get(SessionParameter.ATOMPUB_URL);
+    if (url instanceof String) {
+      return (String) url;
+    }
+
+    return null;
+  }
+
+  // ---- link cache ----
+
+  /**
+   * Returns the link cache or creates a new cache if it doesn't exist.
+   */
+  protected LinkCache getLinkCache() {
+    LinkCache linkCache = (LinkCache) getSession().get(SpiSessionParameter.LINK_CACHE);
+    if (linkCache == null) {
+      linkCache = new LinkCache(getSession());
+      getSession().put(SpiSessionParameter.LINK_CACHE, linkCache);
+    }
+
+    return linkCache;
+  }
+
+  /**
+   * Gets a link from the cache.
+   */
+  protected String getLink(String repositoryId, String id, String rel, String type) {
+    if (repositoryId == null) {
+      throw new CmisInvalidArgumentException("Repository id must be set!");
+    }
+
+    if (id == null) {
+      throw new CmisInvalidArgumentException("Object id must be set!");
+    }
+
+    return getLinkCache().getLink(repositoryId, id, rel, type);
+  }
+
+  /**
+   * Gets a link from the cache.
+   */
+  protected String getLink(String repositoryId, String id, String rel) {
+    return getLink(repositoryId, id, rel, null);
+  }
+
+  /**
+   * Gets a link from the cache if it is there or loads it into the cache if it is not there.
+   */
+  protected String loadLink(String repositoryId, String id, String rel, String type) {
+    String link = getLink(repositoryId, id, rel, type);
+    if (link == null) {
+      getObjectInternal(repositoryId, IdentifierType.ID, id, ReturnVersion.THIS, null, null, null,
+          null, null, null, null);
+      link = getLink(repositoryId, id, rel, type);
+    }
+
+    return link;
+  }
+
+  /**
+   * Adds a link to the cache.
+   */
+  protected void addLink(String repositoryId, String id, String rel, String type, String link) {
+    getLinkCache().addLink(repositoryId, id, rel, type, link);
+  }
+
+  /**
+   * Adds a link to the cache.
+   */
+  protected void addLink(String repositoryId, String id, AtomLink link) {
+    getLinkCache().addLink(repositoryId, id, link.getRel(), link.getType(), link.getHref());
+  }
+
+  /**
+   * Removes all links of an object.
+   */
+  protected void removeLinks(String repositoryId, String id) {
+    getLinkCache().removeLinks(repositoryId, id);
+  }
+
+  /**
+   * Locks the link cache.
+   */
+  protected void lockLinks() {
+    getLinkCache().lockLinks();
+  }
+
+  /**
+   * Unlocks the link cache.
+   */
+  protected void unlockLinks() {
+    getLinkCache().unlockLinks();
+  }
+
+  /**
+   * Checks a link throw an appropriate exception.
+   */
+  protected void throwLinkException(String repositoryId, String id, String rel, String type) {
+    int index = getLinkCache().checkLink(repositoryId, id, rel, type);
+
+    switch (index) {
+    case 0:
+      throw new CmisObjectNotFoundException("Unknown repository!");
+    case 1:
+      throw new CmisObjectNotFoundException("Unknown object!");
+    case 2:
+      throw new CmisNotSupportedException(
+          "Operation not supported by the repository for this object!");
+    case 3:
+      throw new CmisNotSupportedException("No link with matching media type!");
+    case 4:
+      throw new CmisRuntimeException("Nothing wrong! Either this is a bug or threading issue.");
+    default:
+      throw new CmisRuntimeException("Unknown error!");
+    }
+  }
+
+  /**
+   * Gets a type link from the cache.
+   */
+  protected String getTypeLink(String repositoryId, String typeId, String rel, String type) {
+    if (repositoryId == null) {
+      throw new CmisInvalidArgumentException("Repository id must be set!");
+    }
+
+    if (typeId == null) {
+      throw new CmisInvalidArgumentException("Type id must be set!");
+    }
+
+    return getLinkCache().getTypeLink(repositoryId, typeId, rel, type);
+  }
+
+  /**
+   * Gets a type link from the cache.
+   */
+  protected String getTypeLink(String repositoryId, String typeId, String rel) {
+    return getTypeLink(repositoryId, typeId, rel, null);
+  }
+
+  /**
+   * Gets a link from the cache if it is there or loads it into the cache if it is not there.
+   */
+  protected String loadTypeLink(String repositoryId, String typeId, String rel, String type) {
+    String link = getTypeLink(repositoryId, typeId, rel, type);
+    if (link == null) {
+      getTypeDefinitionInternal(repositoryId, typeId);
+      link = getTypeLink(repositoryId, typeId, rel, type);
+    }
+
+    return link;
+  }
+
+  /**
+   * Adds a type link to the cache.
+   */
+  protected void addTypeLink(String repositoryId, String typeId, String rel, String type,
+      String link) {
+    getLinkCache().addTypeLink(repositoryId, typeId, rel, type, link);
+  }
+
+  /**
+   * Adds a type link to the cache.
+   */
+  protected void addTypeLink(String repositoryId, String typeId, AtomLink link) {
+    getLinkCache().addTypeLink(repositoryId, typeId, link.getRel(), link.getType(), link.getHref());
+  }
+
+  /**
+   * Removes all links of a type.
+   */
+  protected void removeTypeLinks(String repositoryId, String id) {
+    getLinkCache().removeTypeLinks(repositoryId, id);
+  }
+
+  /**
+   * Locks the type link cache.
+   */
+  protected void lockTypeLinks() {
+    getLinkCache().lockTypeLinks();
+  }
+
+  /**
+   * Unlocks the type link cache.
+   */
+  protected void unlockTypeLinks() {
+    getLinkCache().unlockTypeLinks();
+  }
+
+  /**
+   * Gets a collection from the cache.
+   */
+  protected String getCollection(String repositoryId, String collection) {
+    return getLinkCache().getCollection(repositoryId, collection);
+  }
+
+  /**
+   * Gets a collection from the cache if it is there or loads it into the cache if it is not there.
+   */
+  protected String loadCollection(String repositoryId, String collection) {
+    String link = getCollection(repositoryId, collection);
+    if (link == null) {
+      // cache repository info
+      getRepositoriesInternal(repositoryId);
+      link = getCollection(repositoryId, collection);
+    }
+
+    return link;
+  }
+
+  /**
+   * Adds a collection to the cache.
+   */
+  protected void addCollection(String repositoryId, String collection, String link) {
+    getLinkCache().addCollection(repositoryId, collection, link);
+  }
+
+  /**
+   * Gets a repository link from the cache.
+   */
+  protected String getRepositoryLink(String repositoryId, String rel) {
+    return getLinkCache().getRepositoryLink(repositoryId, rel);
+  }
+
+  /**
+   * Gets a repository link from the cache if it is there or loads it into the cache if it is not
+   * there.
+   */
+  protected String loadRepositoryLink(String repositoryId, String rel) {
+    String link = getRepositoryLink(repositoryId, rel);
+    if (link == null) {
+      // cache repository info
+      getRepositoriesInternal(repositoryId);
+      link = getRepositoryLink(repositoryId, rel);
+    }
+
+    return link;
+  }
+
+  /**
+   * Adds a repository link to the cache.
+   */
+  protected void addRepositoryLink(String repositoryId, String rel, String link) {
+    getLinkCache().addRepositoryLink(repositoryId, rel, link);
+  }
+
+  /**
+   * Adds a repository link to the cache.
+   */
+  protected void addRepositoryLink(String repositoryId, AtomLink link) {
+    addRepositoryLink(repositoryId, link.getRel(), link.getHref());
+  }
+
+  /**
+   * Gets an URI template from the cache.
+   */
+  protected String getTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
+    return getLinkCache().getTemplateLink(repositoryId, type, parameters);
+  }
+
+  /**
+   * Gets a template link from the cache if it is there or loads it into the cache if it is not
+   * there.
+   */
+  protected String loadTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
+    String link = getTemplateLink(repositoryId, type, parameters);
+    if (link == null) {
+      // cache repository info
+      getRepositoriesInternal(repositoryId);
+      link = getTemplateLink(repositoryId, type, parameters);
+    }
+
+    return link;
+  }
+
+  /**
+   * Adds an URI template to the cache.
+   */
+  protected void addTemplate(String repositoryId, String type, String link) {
+    getLinkCache().addTemplate(repositoryId, type, link);
+  }
+
+  // ---- exceptions ----
+
+  /**
+   * Converts a HTTP status code into an Exception.
+   */
+  protected CmisBaseException convertStatusCode(int code, String message, String errorContent,
+      Throwable t) {
+    switch (code) {
+    case 400:
+      return new CmisInvalidArgumentException(message, errorContent, t);
+    case 404:
+      return new CmisObjectNotFoundException(message, errorContent, t);
+    case 403:
+      return new CmisPermissionDeniedException(message, errorContent, t);
+    case 405:
+      return new CmisNotSupportedException(message, errorContent, t);
+    case 409:
+      return new CmisConstraintException(message, errorContent, t);
+    default:
+      return new CmisRuntimeException(message, errorContent, t);
+    }
+  }
+
+  // ---- helpers ----
+
+  protected boolean is(String name, AtomElement element) {
+    return name.equals(element.getName().getLocalPart());
+  }
+
+  protected boolean isStr(String name, AtomElement element) {
+    return is(name, element) && (element.getObject() instanceof String);
+  }
+
+  protected boolean isInt(String name, AtomElement element) {
+    return is(name, element) && (element.getObject() instanceof BigInteger);
+  }
+
+  protected boolean isNextLink(AtomElement element) {
+    return Constants.REL_NEXT.equals(((AtomLink) element.getObject()).getRel());
+  }
+
+  /**
+   * Creates a CMIS object that only contains an id in the property list.
+   */
+  protected CmisObjectType createIdObject(String objectId) {
+    CmisObjectType object = new CmisObjectType();
+
+    CmisPropertiesType properties = new CmisPropertiesType();
+    object.setProperties(properties);
+
+    CmisPropertyId idProperty = new CmisPropertyId();
+    properties.getProperty().add(idProperty);
+    idProperty.setPropertyDefinitionId(PropertyIds.CMIS_OBJECT_ID);
+    idProperty.getValue().add(objectId);
+
+    return object;
+  }
+
+  /**
+   * Parses an input stream.
+   */
+  @SuppressWarnings("unchecked")
+  protected <T extends AtomBase> T parse(InputStream stream, Class<T> clazz) {
+    AtomPubParser parser = new AtomPubParser(stream);
+
+    try {
+      parser.parse();
+    }
+    catch (Exception e) {
+      throw new CmisConnectionException("Parsing exception!", e);
+    }
+
+    AtomBase parseResult = parser.getResults();
+
+    if (!clazz.isInstance(parseResult)) {
+      throw new CmisConnectionException("Unexpected document! Received "
+          + (parseResult == null ? "something unknown" : parseResult.getType()) + "!");
+    }
+
+    return (T) parseResult;
+  }
+
+  /**
+   * Performs a GET on an URL, checks the response code and returns the result.
+   */
+  protected HttpUtils.Response read(UrlBuilder url) {
+    // make the call
+    HttpUtils.Response resp = HttpUtils.invokeGET(url, fSession);
+
+    // check response code
+    if (resp.getResponseCode() != 200) {
+      throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp
+          .getErrorContent(), null);
+    }
+
+    return resp;
+  }
+
+  /**
+   * Performs a POST on an URL, checks the response code and returns the result.
+   */
+  protected HttpUtils.Response post(UrlBuilder url, String contentType, HttpUtils.Output writer) {
+    // make the call
+    HttpUtils.Response resp = HttpUtils.invokePOST(url, contentType, writer, fSession);
+
+    // check response code
+    if (resp.getResponseCode() != 201) {
+      throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp
+          .getErrorContent(), null);
+    }
+
+    return resp;
+  }
+
+  /**
+   * Performs a PUT on an URL, checks the response code and returns the result.
+   */
+  protected HttpUtils.Response put(UrlBuilder url, String contentType, HttpUtils.Output writer) {
+    // make the call
+    HttpUtils.Response resp = HttpUtils.invokePUT(url, contentType, writer, fSession);
+
+    // check response code
+    if ((resp.getResponseCode() < 200) || (resp.getResponseCode() > 299)) {
+      throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp
+          .getErrorContent(), null);
+    }
+
+    return resp;
+  }
+
+  /**
+   * Performs a DELETE on an URL, checks the response code and returns the result.
+   */
+  protected void delete(UrlBuilder url) {
+    // make the call
+    HttpUtils.Response resp = HttpUtils.invokeDELETE(url, fSession);
+
+    // check response code
+    if (resp.getResponseCode() != 204) {
+      throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp
+          .getErrorContent(), null);
+    }
+  }
+
+  // ---- common operations ----
+
+  /**
+   * Checks if at least one ACE list is not empty.
+   */
+  protected boolean isAclMergeRequired(AccessControlList addAces, AccessControlList removeAces) {
+    return (addAces != null && addAces.getAces() != null && !addAces.getAces().isEmpty())
+        || (removeAces != null && removeAces.getAces() != null && !removeAces.getAces().isEmpty());
+  }
+
+  /**
+   * Merges the new ACL from original, add and remove ACEs lists.
+   */
+  protected AccessControlList mergeAcls(AccessControlList originalAces, AccessControlList addAces,
+      AccessControlList removeAces) {
+    Map<String, Set<String>> originals = convertAclToMap(originalAces);
+    Map<String, Set<String>> adds = convertAclToMap(addAces);
+    Map<String, Set<String>> removes = convertAclToMap(removeAces);
+    List<AccessControlEntry> newACEs = new ArrayList<AccessControlEntry>();
+
+    // iterate through the original ACEs
+    for (Map.Entry<String, Set<String>> ace : originals.entrySet()) {
+
+      // add permissions
+      Set<String> addPermissions = adds.get(ace.getKey());
+      if (addPermissions != null) {
+        ace.getValue().addAll(addPermissions);
+      }
+
+      // remove permissions
+      Set<String> removePermissions = removes.get(ace.getKey());
+      if (removePermissions != null) {
+        ace.getValue().removeAll(removePermissions);
+      }
+
+      // create new ACE
+      if (!ace.getValue().isEmpty()) {
+        newACEs.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(ace.getKey()),
+            new ArrayList<String>(ace.getValue())));
+      }
+    }
+
+    // find all ACEs that should be added but are not in the original ACE list
+    for (Map.Entry<String, Set<String>> ace : adds.entrySet()) {
+      if (!originals.containsKey(ace.getKey()) && !ace.getValue().isEmpty()) {
+        newACEs.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(ace.getKey()),
+            new ArrayList<String>(ace.getValue())));
+      }
+    }
+
+    return new AccessControlListImpl(newACEs);
+  }
+
+  /**
+   * Converts a list of ACEs into Map for better handling.
+   */
+  private Map<String, Set<String>> convertAclToMap(AccessControlList acl) {
+    Map<String, Set<String>> result = new HashMap<String, Set<String>>();
+
+    if ((acl == null) || (acl.getAces() == null)) {
+      return result;
+    }
+
+    for (AccessControlEntry ace : acl.getAces()) {
+      // don't consider indirect ACEs - we can't change them
+      if (!ace.isDirect()) {
+        // ignore
+        continue;
+      }
+
+      // although a principal must not be null, check it
+      if ((ace.getPrincipal() == null) || (ace.getPrincipal().getPrincipalId() == null)) {
+        // ignore
+        continue;
+      }
+
+      Set<String> permissions = new HashSet<String>();
+      if (ace.getPermissions() != null) {
+        permissions.addAll(ace.getPermissions());
+      }
+
+      result.put(ace.getPrincipal().getPrincipalId(), permissions);
+    }
+
+    return result;
+  }
+
+  /**
+   * Retrieves the Service Document from the server and caches the repository info objects,
+   * collections, links, URI templates, etc.
+   */
+  @SuppressWarnings("unchecked")
+  protected List<RepositoryInfoData> getRepositoriesInternal(String repositoryId) {
+    List<RepositoryInfoData> repInfos = new ArrayList<RepositoryInfoData>();
+
+    // retrieve service doc
+    UrlBuilder url = new UrlBuilder(getServiceDocURL());
+    url.addParameter(Constants.PARAM_REPOSITORY_ID, repositoryId);
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+    ServiceDoc serviceDoc = parse(resp.getStream(), ServiceDoc.class);
+
+    // walk through the workspaces
+    for (RepositoryWorkspace ws : serviceDoc.getWorkspaces()) {
+      if (ws.getId() == null) {
+        // found a non-CMIS workspace
+        continue;
+      }
+
+      for (AtomElement element : ws.getElements()) {
+        if (is(NAME_COLLECTION, element)) {
+          Map<String, String> colMap = (Map<String, String>) element.getObject();
+          addCollection(ws.getId(), colMap.get("collectionType"), colMap.get("href"));
+        }
+        else if (element.getObject() instanceof AtomLink) {
+          addRepositoryLink(ws.getId(), (AtomLink) element.getObject());
+        }
+        else if (is(NAME_URI_TEMPLATE, element)) {
+          Map<String, String> tempMap = (Map<String, String>) element.getObject();
+          addTemplate(ws.getId(), tempMap.get("type"), tempMap.get("template"));
+        }
+        else if (element.getObject() instanceof CmisRepositoryInfoType) {
+          repInfos.add(convert((CmisRepositoryInfoType) element.getObject()));
+        }
+      }
+    }
+
+    return repInfos;
+  }
+
+  /**
+   * Retrieves an object from the server and caches the links.
+   */
+  protected ObjectData getObjectInternal(String repositoryId, IdentifierType idOrPath,
+      String objectIdOrPath, ReturnVersion returnVersion, String filter,
+      Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+      String renditionFilter, Boolean includePolicyIds, Boolean includeAcl, ExtensionsData extension) {
+    ObjectData result = null;
+
+    Map<String, Object> parameters = new HashMap<String, Object>();
+    parameters.put(Constants.PARAM_ID, objectIdOrPath);
+    parameters.put(Constants.PARAM_PATH, objectIdOrPath);
+    parameters.put(Constants.PARAM_RETURN_VERSION, returnVersion);
+    parameters.put(Constants.PARAM_FILTER, filter);
+    parameters.put(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
+    parameters.put(Constants.PARAM_ACL, includeAcl);
+    parameters.put(Constants.PARAM_POLICY_IDS, includePolicyIds);
+    parameters.put(Constants.PARAM_RELATIONSHIPS, includeRelationships);
+    parameters.put(Constants.PARAM_RENDITION_FILTER, renditionFilter);
+
+    String link = loadTemplateLink(repositoryId,
+        (idOrPath == IdentifierType.ID ? Constants.TEMPLATE_OBJECT_BY_ID
+            : Constants.TEMPLATE_OBJECT_BY_PATH), parameters);
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository!");
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    // workaround for missing template parameter in the CMIS spec
+    if ((returnVersion != null) && (returnVersion != ReturnVersion.THIS)) {
+      url.addParameter(Constants.PARAM_RETURN_VERSION, returnVersion);
+    }
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+    AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+    // we expect a CMIS entry
+    if (entry.getId() == null) {
+      throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
+    }
+
+    lockLinks();
+    try {
+      // clean up cache
+      removeLinks(repositoryId, entry.getId());
+
+      // walk through the entry
+      for (AtomElement element : entry.getElements()) {
+        if (element.getObject() instanceof AtomLink) {
+          addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+        }
+        else if (element.getObject() instanceof CmisObjectType) {
+          result = convert((CmisObjectType) element.getObject());
+        }
+      }
+    }
+    finally {
+      unlockLinks();
+    }
+
+    return result;
+  }
+
+  /**
+   * Retrieves a type definition.
+   */
+  protected TypeDefinition getTypeDefinitionInternal(String repositoryId, String typeId) {
+    TypeDefinition result = null;
+
+    Map<String, Object> parameters = new HashMap<String, Object>();
+    parameters.put(Constants.PARAM_ID, typeId);
+
+    String link = loadTemplateLink(repositoryId, Constants.TEMPLATE_TYPE_BY_ID, parameters);
+    if (link == null) {
+      throw new CmisObjectNotFoundException("Unknown repository!");
+    }
+
+    // read and parse
+    HttpUtils.Response resp = read(new UrlBuilder(link));
+    AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
+
+    // we expect a CMIS entry
+    if (entry.getId() == null) {
+      throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
+    }
+
+    lockTypeLinks();
+    try {
+      // clean up cache
+      removeTypeLinks(repositoryId, entry.getId());
+
+      // walk through the entry
+      for (AtomElement element : entry.getElements()) {
+        if (element.getObject() instanceof AtomLink) {
+          addTypeLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
+        }
+        else if (element.getObject() instanceof CmisTypeDefinitionType) {
+          result = convert((CmisTypeDefinitionType) element.getObject());
+        }
+      }
+    }
+    finally {
+      unlockTypeLinks();
+    }
+
+    return result;
+  }
+
+  /**
+   * Updates the ACL of an object.
+   */
+  protected Acl updateAcl(String repositoryId, String objectId, AccessControlList acl,
+      AclPropagation aclPropagation) {
+
+    // find the link
+    String link = loadLink(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
+
+    if (link == null) {
+      throwLinkException(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
+    }
+
+    UrlBuilder aclUrl = new UrlBuilder(link);
+    aclUrl.addParameter(Constants.PARAM_ACL_PROPAGATION, aclPropagation);
+
+    // set up object and writer
+    final CmisAccessControlListType aclJaxb = convert(acl);
+
+    // update
+    HttpUtils.Response resp = put(aclUrl, Constants.MEDIATYPE_ACL, new HttpUtils.Output() {
+      public void write(OutputStream out) throws Exception {
+        JaxBHelper.marshal(JaxBHelper.CMIS_OBJECT_FACTORY.createAcl(aclJaxb), out, false);
+      }
+    });
+
+    // parse new entry
+    return parse(resp.getStream(), Acl.class);
+  }
+
+}

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

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AbstractAtomPubService.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java?rev=934361&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java Thu Apr 15 10:33:49 2010
@@ -0,0 +1,105 @@
+/*
+ * 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.chemistry.opencmis.client.bindings.spi.atompub;
+
+import static org.apache.chemistry.opencmis.commons.impl.Converter.convert;
+
+import org.apache.chemistry.opencmis.client.bindings.spi.Session;
+import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.Acl;
+import org.apache.chemistry.opencmis.commons.api.ExtensionsData;
+import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
+import org.apache.chemistry.opencmis.commons.impl.Constants;
+import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
+import org.apache.chemistry.opencmis.commons.provider.AccessControlList;
+import org.apache.chemistry.opencmis.commons.provider.AclService;
+
+/**
+ * ACL Service AtomPub client.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class AclServiceImpl extends AbstractAtomPubService implements AclService {
+
+  /**
+   * Constructor.
+   */
+  public AclServiceImpl(Session session) {
+    setSession(session);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ACLService#applyACL(java.lang.String,
+   * java.lang.String, org.apache.opencmis.client.provider.AccessControlList,
+   * org.apache.opencmis.client.provider.AccessControlList,
+   * org.apache.opencmis.commons.enums.ACLPropagation,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public AccessControlList applyAcl(String repositoryId, String objectId,
+      AccessControlList addAces, AccessControlList removeAces, AclPropagation aclPropagation,
+      ExtensionsData extension) {
+    AccessControlList result = null;
+
+    // fetch the current ACL
+    AccessControlList originalAces = getAcl(repositoryId, objectId, false, null);
+
+    // if no changes required, just return the ACL
+    if (!isAclMergeRequired(addAces, removeAces)) {
+      return originalAces;
+    }
+
+    // merge ACLs
+    AccessControlList newACL = mergeAcls(originalAces, addAces, removeAces);
+
+    // update ACL
+    Acl acl = updateAcl(repositoryId, objectId, newACL, aclPropagation);
+    result = convert(acl.getACL(), null);
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.ACLService#getACL(java.lang.String, java.lang.String,
+   * java.lang.Boolean, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public AccessControlList getAcl(String repositoryId, String objectId,
+      Boolean onlyBasicPermissions, ExtensionsData extension) {
+
+    // find the link
+    String link = loadLink(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
+
+    if (link == null) {
+      throwLinkException(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
+    }
+
+    UrlBuilder url = new UrlBuilder(link);
+    url.addParameter(Constants.PARAM_ONLY_BASIC_PERMISSIONS, onlyBasicPermissions);
+
+    // read and parse
+    HttpUtils.Response resp = read(url);
+    Acl acl = parse(resp.getStream(), Acl.class);
+
+    return convert(acl.getACL(), null);
+  }
+
+}

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

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/AclServiceImpl.java
------------------------------------------------------------------------------
    svn:keywords = Id