You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fm...@apache.org on 2010/03/23 10:44:55 UTC

svn commit: r926511 - in /incubator/chemistry/trunk/opencmis/opencmis-client: opencmis-client-api/src/main/java/org/apache/opencmis/client/api/ opencmis-client-api/src/main/java/org/apache/opencmis/client/api/repository/ opencmis-client-impl/src/main/j...

Author: fmui
Date: Tue Mar 23 09:44:54 2010
New Revision: 926511

URL: http://svn.apache.org/viewvc?rev=926511&view=rev
Log:
fixed a problem with updateProperties
first steps to make the client API tread-safe

Modified:
    incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/CmisObject.java
    incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/repository/ObjectFactory.java
    incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/AbstractPersistentCmisObject.java
    incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentDocumentImpl.java
    incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentFolderImpl.java
    incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentRelationshipImpl.java
    incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentSessionImpl.java
    incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/cache/CacheImpl.java
    incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/repository/PersistentObjectFactoryImpl.java

Modified: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/CmisObject.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/CmisObject.java?rev=926511&r1=926510&r2=926511&view=diff
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/CmisObject.java (original)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/CmisObject.java Tue Mar 23 09:44:54 2010
@@ -114,7 +114,7 @@ public interface CmisObject extends Obje
 
   void delete(boolean allVersions);
 
-  void updateProperties();
+  ObjectId updateProperties();
 
   // relationship service
 

Modified: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/repository/ObjectFactory.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/repository/ObjectFactory.java?rev=926511&r1=926510&r2=926511&view=diff
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/repository/ObjectFactory.java (original)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-api/src/main/java/org/apache/opencmis/client/api/repository/ObjectFactory.java Tue Mar 23 09:44:54 2010
@@ -22,6 +22,7 @@ import java.io.InputStream;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.opencmis.client.api.Ace;
 import org.apache.opencmis.client.api.Acl;
@@ -37,6 +38,7 @@ import org.apache.opencmis.client.api.Re
 import org.apache.opencmis.client.api.objecttype.ObjectType;
 import org.apache.opencmis.commons.api.PropertyDefinition;
 import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.enums.Updatability;
 import org.apache.opencmis.commons.provider.AccessControlList;
 import org.apache.opencmis.commons.provider.AllowableActionsData;
 import org.apache.opencmis.commons.provider.ContentStreamData;
@@ -96,7 +98,8 @@ public interface ObjectFactory {
 
   Map<String, Property<?>> convertProperties(ObjectType objectType, PropertiesData properties);
 
-  PropertiesData convertProperties(Collection<Property<?>> properties);
+  PropertiesData convertProperties(Collection<Property<?>> properties,
+      Set<Updatability> updatabilityFilter);
 
   List<QueryProperty<?>> convertQueryProperties(PropertiesData properties);
 

Modified: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/AbstractPersistentCmisObject.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/AbstractPersistentCmisObject.java?rev=926511&r1=926510&r2=926511&view=diff
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/AbstractPersistentCmisObject.java (original)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/AbstractPersistentCmisObject.java Tue Mar 23 09:44:54 2010
@@ -23,8 +23,11 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.GregorianCalendar;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.opencmis.client.api.Ace;
 import org.apache.opencmis.client.api.Acl;
@@ -69,6 +72,8 @@ public abstract class AbstractPersistent
   private OperationContext creationContext;
   private boolean isChanged = false;
 
+  private final ReentrantReadWriteLock fLock = new ReentrantReadWriteLock();
+
   /**
    * Initializes the object.
    */
@@ -144,6 +149,34 @@ public abstract class AbstractPersistent
   }
 
   /**
+   * Acquires a write lock.
+   */
+  protected void writeLock() {
+    fLock.writeLock().lock();
+  }
+
+  /**
+   * Releases a write lock.
+   */
+  protected void writeUnlock() {
+    fLock.writeLock().unlock();
+  }
+
+  /**
+   * Acquires a read lock.
+   */
+  protected void readLock() {
+    fLock.readLock().lock();
+  }
+
+  /**
+   * Releases a read lock.
+   */
+  protected void readUnlock() {
+    fLock.readLock().unlock();
+  }
+
+  /**
    * Returns the session object.
    */
   protected PersistentSessionImpl getSession() {
@@ -161,7 +194,13 @@ public abstract class AbstractPersistent
    * Returns the object type.
    */
   protected ObjectType getObjectType() {
-    return this.objectType;
+    readLock();
+    try {
+      return this.objectType;
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   /**
@@ -207,15 +246,37 @@ public abstract class AbstractPersistent
    * 
    * @see org.apache.opencmis.client.api.CmisObject#updateProperties()
    */
-  public void updateProperties() {
-    String objectId = getObjectId();
-    Holder<String> objectIdHolder = new Holder<String>(objectId);
+  public ObjectId updateProperties() {
+    readLock();
+    try {
+      String objectId = getObjectId();
+      Holder<String> objectIdHolder = new Holder<String>(objectId);
+
+      String changeToken = getChangeToken();
+      Holder<String> changeTokenHolder = new Holder<String>(changeToken);
+
+      Set<Updatability> updatebility = new HashSet<Updatability>();
+      updatebility.add(Updatability.READWRITE);
 
-    String changeToken = getChangeToken();
-    Holder<String> changeTokenHolder = new Holder<String>(changeToken);
+      // check if checked out
+      Boolean isCheckedOut = getPropertyValue(PropertyIds.CMIS_IS_VERSION_SERIES_CHECKED_OUT);
+      if ((isCheckedOut != null) && isCheckedOut.booleanValue()) {
+        updatebility.add(Updatability.WHENCHECKEDOUT);
+      }
+
+      getProvider().getObjectService().updateProperties(getRepositoryId(), objectIdHolder,
+          changeTokenHolder,
+          getObjectFactory().convertProperties(this.properties.values(), updatebility), null);
+
+      if (objectIdHolder.getValue() == null) {
+        return null;
+      }
 
-    getProvider().getObjectService().updateProperties(getRepositoryId(), objectIdHolder,
-        changeTokenHolder, getObjectFactory().convertProperties(properties.values()), null);
+      return getSession().createObjectId(objectIdHolder.getValue());
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   // --- properties ---
@@ -317,7 +378,13 @@ public abstract class AbstractPersistent
    * @see org.apache.opencmis.client.api.CmisObject#getProperties()
    */
   public List<Property<?>> getProperties() {
-    return new ArrayList<Property<?>>(properties.values());
+    readLock();
+    try {
+      return new ArrayList<Property<?>>(this.properties.values());
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   /*
@@ -327,7 +394,13 @@ public abstract class AbstractPersistent
    */
   @SuppressWarnings("unchecked")
   public <T> Property<T> getProperty(String id) {
-    return (Property<T>) properties.get(id);
+    readLock();
+    try {
+      return (Property<T>) this.properties.get(id);
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   /*
@@ -384,67 +457,73 @@ public abstract class AbstractPersistent
    */
   @SuppressWarnings("unchecked")
   public <T> void setPropertyMultivalue(String id, List<T> value) {
-    // get and check property type
-    PropertyDefinition<?> propertyDefinition = getObjectType().getPropertyDefintions().get(id);
-    if (propertyDefinition == null) {
-      throw new IllegalArgumentException("Unknown property!");
-    }
+    writeLock();
+    try {
+      // get and check property type
+      PropertyDefinition<?> propertyDefinition = getObjectType().getPropertyDefintions().get(id);
+      if (propertyDefinition == null) {
+        throw new IllegalArgumentException("Unknown property!");
+      }
 
-    // check updatability
-    if (propertyDefinition.getUpdatability() == Updatability.READONLY) {
-      throw new IllegalArgumentException("Property is read-only!");
-    }
+      // check updatability
+      if (propertyDefinition.getUpdatability() == Updatability.READONLY) {
+        throw new IllegalArgumentException("Property is read-only!");
+      }
 
-    boolean typeMatch = false;
+      boolean typeMatch = false;
 
-    if ((value == null) || (value.isEmpty())) {
-      typeMatch = true;
-      if (value != null) {
-        value = null;
-      }
-    }
-    else {
-      // check if list contains null values
-      for (Object o : value) {
-        if (o == null) {
-          throw new IllegalArgumentException("List contains null values!");
+      if ((value == null) || (value.isEmpty())) {
+        typeMatch = true;
+        if (value != null) {
+          value = null;
         }
       }
+      else {
+        // check if list contains null values
+        for (Object o : value) {
+          if (o == null) {
+            throw new IllegalArgumentException("List contains null values!");
+          }
+        }
 
-      // take a sample and test the data type
-      Object firstValue = value.get(0);
+        // take a sample and test the data type
+        Object firstValue = value.get(0);
 
-      switch (propertyDefinition.getPropertyType()) {
-      case STRING:
-      case ID:
-      case URI:
-      case HTML:
-        typeMatch = (firstValue instanceof String);
-        break;
-      case INTEGER:
-        typeMatch = (firstValue instanceof BigInteger);
-        break;
-      case DECIMAL:
-        typeMatch = (firstValue instanceof BigDecimal);
-        break;
-      case BOOLEAN:
-        typeMatch = (firstValue instanceof Boolean);
-        break;
-      case DATETIME:
-        typeMatch = (firstValue instanceof GregorianCalendar);
-        break;
+        switch (propertyDefinition.getPropertyType()) {
+        case STRING:
+        case ID:
+        case URI:
+        case HTML:
+          typeMatch = (firstValue instanceof String);
+          break;
+        case INTEGER:
+          typeMatch = (firstValue instanceof BigInteger);
+          break;
+        case DECIMAL:
+          typeMatch = (firstValue instanceof BigDecimal);
+          break;
+        case BOOLEAN:
+          typeMatch = (firstValue instanceof Boolean);
+          break;
+        case DATETIME:
+          typeMatch = (firstValue instanceof GregorianCalendar);
+          break;
+        }
       }
-    }
 
-    if (!typeMatch) {
-      throw new IllegalArgumentException("Value does not match property type!");
-    }
+      if (!typeMatch) {
+        throw new IllegalArgumentException("Value does not match property type!");
+      }
 
-    Property<T> newProperty = (Property<T>) getSession().getObjectFactory()
-        .createPropertyMultivalue((PropertyDefinition<T>) propertyDefinition, value);
+      Property<T> newProperty = (Property<T>) getSession().getObjectFactory()
+          .createPropertyMultivalue((PropertyDefinition<T>) propertyDefinition, value);
 
-    setChanged();
-    this.properties.put(id, newProperty);
+      setChanged();
+      this.properties.put(id, newProperty);
+    }
+    finally {
+      writeUnlock();
+    }
   }
 
   /*
@@ -453,7 +532,13 @@ public abstract class AbstractPersistent
    * @see org.apache.opencmis.client.api.CmisObject#getType()
    */
   public ObjectType getType() {
-    return this.objectType;
+    readLock();
+    try {
+      return this.objectType;
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   // --- allowable actions ---
@@ -464,7 +549,13 @@ public abstract class AbstractPersistent
    * @see org.apache.opencmis.client.api.CmisObject#getAllowableActions()
    */
   public AllowableActions getAllowableActions() {
-    return this.allowableActions;
+    readLock();
+    try {
+      return this.allowableActions;
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   // --- renditions ---
@@ -475,7 +566,13 @@ public abstract class AbstractPersistent
    * @see org.apache.opencmis.client.api.CmisObject#getRenditions()
    */
   public List<Rendition> getRenditions() {
-    return this.renditions;
+    readLock();
+    try {
+      return this.renditions;
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   // --- ACL ---
@@ -535,7 +632,13 @@ public abstract class AbstractPersistent
    * @see org.apache.opencmis.client.api.CmisObject#getAcl()
    */
   public Acl getAcl() {
-    return this.acl;
+    readLock();
+    try {
+      return this.acl;
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   // --- policies ---
@@ -578,7 +681,13 @@ public abstract class AbstractPersistent
    * @see org.apache.opencmis.client.api.CmisObject#getPolicies()
    */
   public List<Policy> getPolicies() {
-    return policies;
+    readLock();
+    try {
+      return this.policies;
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   // --- relationships ---
@@ -589,7 +698,13 @@ public abstract class AbstractPersistent
    * @see org.apache.opencmis.client.api.CmisObject#getRelationships()
    */
   public List<Relationship> getRelationships() {
-    return relationships;
+    readLock();
+    try {
+      return this.relationships;
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   /*
@@ -654,14 +769,26 @@ public abstract class AbstractPersistent
    * @see org.apache.opencmis.client.api.CmisObject#isChanged()
    */
   public boolean isChanged() {
-    return isChanged;
+    readLock();
+    try {
+      return isChanged;
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   /**
    * Sets the isChanged flag to <code>true</code>
    */
   protected void setChanged() {
-    isChanged = true;
+    writeLock();
+    try {
+      isChanged = true;
+    }
+    finally {
+      writeUnlock();
+    }
   }
 
   /*
@@ -672,17 +799,22 @@ public abstract class AbstractPersistent
    * )
    */
   public void refresh() {
-    String objectId = getObjectId();
+    writeLock();
+    try {
+      String objectId = getObjectId();
+
+      // get the latest data from the repository
+      ObjectData objectData = getSession().getProvider().getObjectService().getObject(
+          getRepositoryId(), objectId, creationContext.getFilterString(),
+          creationContext.isIncludeAllowableActions(), creationContext.getIncludeRelationships(),
+          creationContext.getRenditionFilterString(), creationContext.isIncludePolicies(),
+          creationContext.isIncludeAcls(), null);
 
-    // get the latest data from the repository
-    ObjectData objectData = getSession().getProvider().getObjectService().getObject(
-        getRepositoryId(), objectId, creationContext.getFilterString(),
-        creationContext.isIncludeAllowableActions(), creationContext.getIncludeRelationships(),
-        creationContext.getRenditionFilterString(), creationContext.isIncludePolicies(),
-        creationContext.isIncludeAcls(), null);
-
-    // reset this object
-    initialize(getSession(), getObjectType(), objectData, this.creationContext);
+      // reset this object
+      initialize(getSession(), getObjectType(), objectData, this.creationContext);
+    }
+    finally {
+      writeUnlock();
+    }
   }
-
 }

Modified: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentDocumentImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentDocumentImpl.java?rev=926511&r1=926510&r2=926511&view=diff
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentDocumentImpl.java (original)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentDocumentImpl.java Tue Mar 23 09:44:54 2010
@@ -20,7 +20,9 @@ package org.apache.opencmis.client.runti
 
 import java.math.BigInteger;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.opencmis.client.api.Ace;
 import org.apache.opencmis.client.api.CmisObject;
@@ -33,6 +35,7 @@ import org.apache.opencmis.client.api.Pr
 import org.apache.opencmis.client.api.objecttype.ObjectType;
 import org.apache.opencmis.client.api.repository.ObjectFactory;
 import org.apache.opencmis.commons.PropertyIds;
+import org.apache.opencmis.commons.enums.Updatability;
 import org.apache.opencmis.commons.enums.VersioningState;
 import org.apache.opencmis.commons.exceptions.CmisRuntimeException;
 import org.apache.opencmis.commons.provider.ContentStreamData;
@@ -169,9 +172,14 @@ public class PersistentDocumentImpl exte
 
     ObjectFactory of = getObjectFactory();
 
+    Set<Updatability> updatebility = new HashSet<Updatability>();
+    updatebility.add(Updatability.READWRITE);
+    updatebility.add(Updatability.WHENCHECKEDOUT);
+
     getProvider().getVersioningService().checkIn(getRepositoryId(), objectIdHolder, major,
-        of.convertProperties(properties), of.convertContentStream(contentStream), checkinComment,
-        of.convertPolicies(policies), of.convertAces(addAces), of.convertAces(removeAces), null);
+        of.convertProperties(properties, updatebility), of.convertContentStream(contentStream),
+        checkinComment, of.convertPolicies(policies), of.convertAces(addAces),
+        of.convertAces(removeAces), null);
 
     if (objectIdHolder.getValue() == null) {
       return null;
@@ -286,10 +294,19 @@ public class PersistentDocumentImpl exte
    * org.apache.opencmis.client.api.ContentStream)
    */
   public ObjectId setContentStream(boolean overwrite, ContentStream contentStream) {
-    String objectId = getObjectId();
-    Holder<String> objectIdHolder = new Holder<String>(objectId);
+    String objectId = null;
+    String changeToken = null;
 
-    String changeToken = getPropertyValue(PropertyIds.CMIS_CHANGE_TOKEN);
+    readLock();
+    try {
+      objectId = getObjectId();
+      changeToken = getPropertyValue(PropertyIds.CMIS_CHANGE_TOKEN);
+    }
+    finally {
+      readUnlock();
+    }
+
+    Holder<String> objectIdHolder = new Holder<String>(objectId);
     Holder<String> changeTokenHolder = new Holder<String>(changeToken);
 
     getProvider().getObjectService().setContentStream(getRepositoryId(), objectIdHolder, overwrite,
@@ -308,10 +325,19 @@ public class PersistentDocumentImpl exte
    * @see org.apache.opencmis.client.api.Document#deleteContentStream()
    */
   public ObjectId deleteContentStream() {
-    String objectId = getObjectId();
-    Holder<String> objectIdHolder = new Holder<String>(objectId);
+    String objectId = null;
+    String changeToken = null;
+
+    readLock();
+    try {
+      objectId = getObjectId();
+      changeToken = getPropertyValue(PropertyIds.CMIS_CHANGE_TOKEN);
+    }
+    finally {
+      readUnlock();
+    }
 
-    String changeToken = getPropertyValue(PropertyIds.CMIS_CHANGE_TOKEN);
+    Holder<String> objectIdHolder = new Holder<String>(objectId);
     Holder<String> changeTokenHolder = new Holder<String>(changeToken);
 
     getProvider().getObjectService().deleteContentStream(getRepositoryId(), objectIdHolder,

Modified: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentFolderImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentFolderImpl.java?rev=926511&r1=926510&r2=926511&view=diff
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentFolderImpl.java (original)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentFolderImpl.java Tue Mar 23 09:44:54 2010
@@ -21,7 +21,9 @@ package org.apache.opencmis.client.runti
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.opencmis.client.api.Ace;
 import org.apache.opencmis.client.api.CmisObject;
@@ -42,6 +44,7 @@ import org.apache.opencmis.client.runtim
 import org.apache.opencmis.commons.PropertyIds;
 import org.apache.opencmis.commons.enums.IncludeRelationships;
 import org.apache.opencmis.commons.enums.UnfileObjects;
+import org.apache.opencmis.commons.enums.Updatability;
 import org.apache.opencmis.commons.enums.VersioningState;
 import org.apache.opencmis.commons.exceptions.CmisRuntimeException;
 import org.apache.opencmis.commons.provider.FailedToDeleteData;
@@ -56,6 +59,12 @@ import org.apache.opencmis.commons.provi
 
 public class PersistentFolderImpl extends AbstractPersistentFilableCmisObject implements Folder {
 
+  private static final Set<Updatability> CREATE_UPDATABILITY = new HashSet<Updatability>();
+  static {
+    CREATE_UPDATABILITY.add(Updatability.ONCREATE);
+    CREATE_UPDATABILITY.add(Updatability.READWRITE);
+  }
+
   /**
    * Constructor.
    */
@@ -80,9 +89,9 @@ public class PersistentFolderImpl extend
     ObjectFactory of = getObjectFactory();
 
     String newId = getProvider().getObjectService().createDocument(getRepositoryId(),
-        of.convertProperties(properties), objectId, of.convertContentStream(contentStream),
-        versioningState, of.convertPolicies(policies), of.convertAces(addAces),
-        of.convertAces(removeAces), null);
+        of.convertProperties(properties, CREATE_UPDATABILITY), objectId,
+        of.convertContentStream(contentStream), versioningState, of.convertPolicies(policies),
+        of.convertAces(addAces), of.convertAces(removeAces), null);
 
     // if no context is provided the object will not be fetched
     if ((context == null) || (newId == null)) {
@@ -117,8 +126,11 @@ public class PersistentFolderImpl extend
 
     ObjectFactory of = getObjectFactory();
 
+    Set<Updatability> updatebility = new HashSet<Updatability>();
+    updatebility.add(Updatability.READWRITE);
+
     String newId = getProvider().getObjectService().createDocumentFromSource(getRepositoryId(),
-        source.getId(), of.convertProperties(properties), objectId, versioningState,
+        source.getId(), of.convertProperties(properties, updatebility), objectId, versioningState,
         of.convertPolicies(policies), of.convertAces(addAces), of.convertAces(removeAces), null);
 
     // if no context is provided the object will not be fetched
@@ -148,8 +160,8 @@ public class PersistentFolderImpl extend
     ObjectFactory of = getObjectFactory();
 
     String newId = getProvider().getObjectService().createFolder(getRepositoryId(),
-        of.convertProperties(properties), objectId, of.convertPolicies(policies),
-        of.convertAces(addAces), of.convertAces(removeAces), null);
+        of.convertProperties(properties, CREATE_UPDATABILITY), objectId,
+        of.convertPolicies(policies), of.convertAces(addAces), of.convertAces(removeAces), null);
 
     // if no context is provided the object will not be fetched
     if ((context == null) || (newId == null)) {
@@ -178,8 +190,8 @@ public class PersistentFolderImpl extend
     ObjectFactory of = getObjectFactory();
 
     String newId = getProvider().getObjectService().createPolicy(getRepositoryId(),
-        of.convertProperties(properties), objectId, of.convertPolicies(policies),
-        of.convertAces(addAces), of.convertAces(removeAces), null);
+        of.convertProperties(properties, CREATE_UPDATABILITY), objectId,
+        of.convertPolicies(policies), of.convertAces(addAces), of.convertAces(removeAces), null);
 
     // if no context is provided the object will not be fetched
     if ((context == null) || (newId == null)) {
@@ -220,13 +232,19 @@ public class PersistentFolderImpl extend
   public List<ObjectType> getAllowedChildObjectTypes() {
     List<ObjectType> result = new ArrayList<ObjectType>();
 
-    List<String> otids = getPropertyMultivalue(PropertyIds.CMIS_ALLOWED_CHILD_OBJECT_TYPE_IDS);
-    if (otids == null) {
-      return result;
-    }
+    readLock();
+    try {
+      List<String> otids = getPropertyMultivalue(PropertyIds.CMIS_ALLOWED_CHILD_OBJECT_TYPE_IDS);
+      if (otids == null) {
+        return result;
+      }
 
-    for (String otid : otids) {
-      result.add(getSession().getTypeDefinition(otid));
+      for (String otid : otids) {
+        result.add(getSession().getTypeDefinition(otid));
+      }
+    }
+    finally {
+      readUnlock();
     }
 
     return result;

Modified: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentRelationshipImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentRelationshipImpl.java?rev=926511&r1=926510&r2=926511&view=diff
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentRelationshipImpl.java (original)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentRelationshipImpl.java Tue Mar 23 09:44:54 2010
@@ -51,12 +51,18 @@ public class PersistentRelationshipImpl 
    * @see org.apache.opencmis.client.api.Relationship#getSource()
    */
   public CmisObject getSource(OperationContext context) {
-    String sourceId = getPropertyValue(PropertyIds.CMIS_SOURCE_ID);
-    if (sourceId == null) {
-      return null;
-    }
+    readLock();
+    try {
+      String sourceId = getPropertyValue(PropertyIds.CMIS_SOURCE_ID);
+      if (sourceId == null) {
+        return null;
+      }
 
-    return getSession().getObject(getSession().createObjectId(sourceId), context);
+      return getSession().getObject(getSession().createObjectId(sourceId), context);
+    }
+    finally {
+      readUnlock();
+    }
   }
 
   /*
@@ -74,12 +80,18 @@ public class PersistentRelationshipImpl 
    * @see org.apache.opencmis.client.api.Relationship#getTarget()
    */
   public CmisObject getTarget(OperationContext context) {
-    String targetId = getPropertyValue(PropertyIds.CMIS_TARGET_ID);
-    if (targetId == null) {
-      return null;
-    }
+    readLock();
+    try {
+      String targetId = getPropertyValue(PropertyIds.CMIS_TARGET_ID);
+      if (targetId == null) {
+        return null;
+      }
 
-    return getSession().getObject(getSession().createObjectId(targetId), context);
+      return getSession().getObject(getSession().createObjectId(targetId), context);
+    }
+    finally {
+      readUnlock();
+    }
   }
 
 }

Modified: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentSessionImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentSessionImpl.java?rev=926511&r1=926510&r2=926511&view=diff
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentSessionImpl.java (original)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/PersistentSessionImpl.java Tue Mar 23 09:44:54 2010
@@ -21,6 +21,7 @@ package org.apache.opencmis.client.runti
 import java.io.Serializable;
 import java.math.BigInteger;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -57,6 +58,7 @@ import org.apache.opencmis.commons.api.T
 import org.apache.opencmis.commons.api.TypeDefinitionContainer;
 import org.apache.opencmis.commons.api.TypeDefinitionList;
 import org.apache.opencmis.commons.enums.IncludeRelationships;
+import org.apache.opencmis.commons.enums.Updatability;
 import org.apache.opencmis.commons.enums.VersioningState;
 import org.apache.opencmis.commons.exceptions.CmisRuntimeException;
 import org.apache.opencmis.commons.provider.CmisProvider;
@@ -75,6 +77,12 @@ public class PersistentSessionImpl imple
   private static final OperationContext DEFAULT_CONTEXT = new OperationContextImpl(null, false,
       true, false, IncludeRelationships.NONE, null, true, null, true);
 
+  private static final Set<Updatability> CREATE_UPDATABILITY = new HashSet<Updatability>();
+  static {
+    CREATE_UPDATABILITY.add(Updatability.ONCREATE);
+    CREATE_UPDATABILITY.add(Updatability.READWRITE);
+  }
+
   private static Log log = LogFactory.getLog(PersistentSessionImpl.class);
 
   /*
@@ -280,7 +288,7 @@ public class PersistentSessionImpl imple
    * @see org.apache.opencmis.client.api.Session#getContentChanges(java.lang.String, int)
    */
   public PagingList<ChangeEvent> getContentChanges(String changeLogToken, int itemsPerPage) {
-	  throw new CmisRuntimeException("not implemented");
+    throw new CmisRuntimeException("not implemented");
   }
 
   /*
@@ -669,7 +677,8 @@ public class PersistentSessionImpl imple
     }
 
     String newId = getProvider().getObjectService().createDocument(getRepositoryId(),
-        objectFactory.convertProperties(properties), (folderId == null ? null : folderId.getId()),
+        objectFactory.convertProperties(properties, CREATE_UPDATABILITY),
+        (folderId == null ? null : folderId.getId()),
         objectFactory.convertContentStream(contentStream), versioningState,
         objectFactory.convertPolicies(policies), objectFactory.convertAces(addAces),
         objectFactory.convertAces(removeAces), null);
@@ -698,7 +707,7 @@ public class PersistentSessionImpl imple
     }
 
     String newId = getProvider().getObjectService().createDocumentFromSource(getRepositoryId(),
-        source.getId(), objectFactory.convertProperties(properties),
+        source.getId(), objectFactory.convertProperties(properties, CREATE_UPDATABILITY),
         (folderId == null ? null : folderId.getId()), versioningState,
         objectFactory.convertPolicies(policies), objectFactory.convertAces(addAces),
         objectFactory.convertAces(removeAces), null);
@@ -723,9 +732,9 @@ public class PersistentSessionImpl imple
     }
 
     String newId = getProvider().getObjectService().createFolder(getRepositoryId(),
-        objectFactory.convertProperties(properties), (folderId == null ? null : folderId.getId()),
-        objectFactory.convertPolicies(policies), objectFactory.convertAces(addAces),
-        objectFactory.convertAces(removeAces), null);
+        objectFactory.convertProperties(properties, CREATE_UPDATABILITY),
+        (folderId == null ? null : folderId.getId()), objectFactory.convertPolicies(policies),
+        objectFactory.convertAces(addAces), objectFactory.convertAces(removeAces), null);
 
     if (newId == null) {
       return null;
@@ -747,9 +756,9 @@ public class PersistentSessionImpl imple
     }
 
     String newId = getProvider().getObjectService().createPolicy(getRepositoryId(),
-        objectFactory.convertProperties(properties), (folderId == null ? null : folderId.getId()),
-        objectFactory.convertPolicies(policies), objectFactory.convertAces(addAces),
-        objectFactory.convertAces(removeAces), null);
+        objectFactory.convertProperties(properties, CREATE_UPDATABILITY),
+        (folderId == null ? null : folderId.getId()), objectFactory.convertPolicies(policies),
+        objectFactory.convertAces(addAces), objectFactory.convertAces(removeAces), null);
 
     if (newId == null) {
       return null;
@@ -767,8 +776,9 @@ public class PersistentSessionImpl imple
   public ObjectId createRelationship(List<Property<?>> properties, List<Policy> policies,
       List<Ace> addAces, List<Ace> removeAces) {
     String newId = getProvider().getObjectService().createRelationship(getRepositoryId(),
-        objectFactory.convertProperties(properties), objectFactory.convertPolicies(policies),
-        objectFactory.convertAces(addAces), objectFactory.convertAces(removeAces), null);
+        objectFactory.convertProperties(properties, CREATE_UPDATABILITY),
+        objectFactory.convertPolicies(policies), objectFactory.convertAces(addAces),
+        objectFactory.convertAces(removeAces), null);
 
     if (newId == null) {
       return null;

Modified: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/cache/CacheImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/cache/CacheImpl.java?rev=926511&r1=926510&r2=926511&view=diff
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/cache/CacheImpl.java (original)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/cache/CacheImpl.java Tue Mar 23 09:44:54 2010
@@ -22,6 +22,7 @@ import java.io.Serializable;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.opencmis.client.api.CmisObject;
 import org.apache.opencmis.commons.PropertyIds;
@@ -41,6 +42,8 @@ public class CacheImpl implements Cache,
   private LinkedHashMap<String, Map<String, CmisObject>> objectMap;
   private Map<String, String> pathToIdMap;
 
+  private final ReentrantReadWriteLock fLock = new ReentrantReadWriteLock();
+
   /**
    * Creates a new cache instance with a default size.
    */
@@ -74,22 +77,28 @@ public class CacheImpl implements Cache,
    * Sets up the internal objects.
    */
   protected void initialize() {
-    int hashTableCapacity = (int) Math.ceil(cacheSize / HASHTABLE_LOAD_FACTOR) + 1;
+    fLock.writeLock().lock();
+    try {
+      int hashTableCapacity = (int) Math.ceil(cacheSize / HASHTABLE_LOAD_FACTOR) + 1;
 
-    final int cs = cacheSize;
+      final int cs = cacheSize;
 
-    objectMap = new LinkedHashMap<String, Map<String, CmisObject>>(hashTableCapacity,
-        HASHTABLE_LOAD_FACTOR) {
+      objectMap = new LinkedHashMap<String, Map<String, CmisObject>>(hashTableCapacity,
+          HASHTABLE_LOAD_FACTOR) {
 
-      private static final long serialVersionUID = 1L;
+        private static final long serialVersionUID = 1L;
 
-      @Override
-      protected boolean removeEldestEntry(Map.Entry<String, Map<String, CmisObject>> eldest) {
-        return size() > cs;
-      }
-    };
+        @Override
+        protected boolean removeEldestEntry(Map.Entry<String, Map<String, CmisObject>> eldest) {
+          return size() > cs;
+        }
+      };
 
-    resetPathCache();
+      resetPathCache();
+    }
+    finally {
+      fLock.writeLock().unlock();
+    }
   }
 
   /*
@@ -107,7 +116,13 @@ public class CacheImpl implements Cache,
    * @see org.apache.opencmis.client.runtime.cache.Cache#resetPathCache()
    */
   public void resetPathCache() {
-    pathToIdMap = new HashMap<String, String>();
+    fLock.writeLock().lock();
+    try {
+      pathToIdMap = new HashMap<String, String>();
+    }
+    finally {
+      fLock.writeLock().unlock();
+    }
   }
 
   /*
@@ -117,11 +132,17 @@ public class CacheImpl implements Cache,
    * java.lang.String)
    */
   public boolean containsId(String objectId, String cacheKey) {
-    if (!objectMap.containsKey(objectId)) {
-      return false;
-    }
+    fLock.readLock().lock();
+    try {
+      if (!objectMap.containsKey(objectId)) {
+        return false;
+      }
 
-    return objectMap.get(objectId).containsKey(cacheKey);
+      return objectMap.get(objectId).containsKey(cacheKey);
+    }
+    finally {
+      fLock.readLock().unlock();
+    }
   }
 
   /*
@@ -131,11 +152,17 @@ public class CacheImpl implements Cache,
    * java.lang.String)
    */
   public boolean containsPath(String path, String cacheKey) {
-    if (!pathToIdMap.containsKey(path)) {
-      return false;
-    }
+    fLock.readLock().lock();
+    try {
+      if (!pathToIdMap.containsKey(path)) {
+        return false;
+      }
 
-    return containsId(pathToIdMap.get(path), cacheKey);
+      return containsId(pathToIdMap.get(path), cacheKey);
+    }
+    finally {
+      fLock.readLock().unlock();
+    }
   }
 
   /*
@@ -144,12 +171,18 @@ public class CacheImpl implements Cache,
    * @see org.apache.opencmis.client.runtime.cache.Cache#getById(java.lang.String, java.lang.String)
    */
   public CmisObject getById(String objectId, String cacheKey) {
-    Map<String, CmisObject> cacheKeyMap = objectMap.get(objectId);
-    if (cacheKeyMap == null) {
-      return null; // not found
-    }
+    fLock.readLock().lock();
+    try {
+      Map<String, CmisObject> cacheKeyMap = objectMap.get(objectId);
+      if (cacheKeyMap == null) {
+        return null; // not found
+      }
 
-    return cacheKeyMap.get(cacheKey);
+      return cacheKeyMap.get(cacheKey);
+    }
+    finally {
+      fLock.readLock().unlock();
+    }
   }
 
   /*
@@ -159,18 +192,30 @@ public class CacheImpl implements Cache,
    * java.lang.String)
    */
   public CmisObject getByPath(String path, String cacheKey) {
-    String id = pathToIdMap.get(path);
-    if (id == null) {
-      return null; // not found
-    }
+    fLock.readLock().lock();
+    try {
+      String id = pathToIdMap.get(path);
+      if (id == null) {
+        return null; // not found
+      }
 
-    CmisObject object = getById(id, cacheKey);
-    if ((object == null) && (!objectMap.containsKey(id))) {
-      // clean up
-      pathToIdMap.remove(path);
-    }
+      CmisObject object = getById(id, cacheKey);
+      if ((object == null) && (!objectMap.containsKey(id))) {
+        // clean up
+        fLock.writeLock().lock();
+        try {
+          pathToIdMap.remove(path);
+        }
+        finally {
+          fLock.writeLock().unlock();
+        }
+      }
 
-    return object;
+      return object;
+    }
+    finally {
+      fLock.readLock().unlock();
+    }
   }
 
   /*
@@ -191,20 +236,26 @@ public class CacheImpl implements Cache,
       return;
     }
 
-    // get cache key map
-    Map<String, CmisObject> cacheKeyMap = objectMap.get(object.getId());
-    if (cacheKeyMap == null) {
-      cacheKeyMap = new HashMap<String, CmisObject>();
-      objectMap.put(object.getId(), cacheKeyMap);
-    }
+    fLock.writeLock().lock();
+    try {
+      // get cache key map
+      Map<String, CmisObject> cacheKeyMap = objectMap.get(object.getId());
+      if (cacheKeyMap == null) {
+        cacheKeyMap = new HashMap<String, CmisObject>();
+        objectMap.put(object.getId(), cacheKeyMap);
+      }
 
-    // put into id cache
-    cacheKeyMap.put(cacheKey, object);
-
-    // folders may have a path, use it!
-    String path = object.getPropertyValue(PropertyIds.CMIS_PATH);
-    if (path != null) {
-      pathToIdMap.put(path, object.getId());
+      // put into id cache
+      cacheKeyMap.put(cacheKey, object);
+
+      // folders may have a path, use it!
+      String path = object.getPropertyValue(PropertyIds.CMIS_PATH);
+      if (path != null) {
+        pathToIdMap.put(path, object.getId());
+      }
+    }
+    finally {
+      fLock.writeLock().unlock();
     }
   }
 
@@ -215,10 +266,16 @@ public class CacheImpl implements Cache,
    * org.apache.opencmis.client.api.CmisObject, java.lang.String)
    */
   public void putPath(String path, CmisObject object, String cacheKey) {
-    put(object, cacheKey);
+    fLock.writeLock().lock();
+    try {
+      put(object, cacheKey);
 
-    if ((object != null) && (object.getId() != null) && (cacheKey != null)) {
-      pathToIdMap.put(path, object.getId());
+      if ((object != null) && (object.getId() != null) && (cacheKey != null)) {
+        pathToIdMap.put(path, object.getId());
+      }
+    }
+    finally {
+      fLock.writeLock().unlock();
     }
   }
 
@@ -230,5 +287,4 @@ public class CacheImpl implements Cache,
   public int getCacheSize() {
     return this.cacheSize;
   }
-
 }

Modified: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/repository/PersistentObjectFactoryImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/repository/PersistentObjectFactoryImpl.java?rev=926511&r1=926510&r2=926511&view=diff
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/repository/PersistentObjectFactoryImpl.java (original)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/main/java/org/apache/opencmis/client/runtime/repository/PersistentObjectFactoryImpl.java Tue Mar 23 09:44:54 2010
@@ -27,6 +27,7 @@ import java.util.GregorianCalendar;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.opencmis.client.api.Ace;
 import org.apache.opencmis.client.api.Acl;
@@ -73,6 +74,7 @@ import org.apache.opencmis.commons.api.P
 import org.apache.opencmis.commons.api.PropertyUriDefinition;
 import org.apache.opencmis.commons.api.RelationshipTypeDefinition;
 import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.enums.Updatability;
 import org.apache.opencmis.commons.exceptions.CmisRuntimeException;
 import org.apache.opencmis.commons.provider.AccessControlEntry;
 import org.apache.opencmis.commons.provider.AccessControlList;
@@ -441,10 +443,12 @@ public class PersistentObjectFactoryImpl
    * (non-Javadoc)
    * 
    * @see
-   * org.apache.opencmis.client.api.repository.ObjectFactory#convertProperties(java.util.Collection)
+   * org.apache.opencmis.client.api.repository.ObjectFactory#convertProperties(java.util.Collection,
+   * java.util.Set)
    */
   @SuppressWarnings("unchecked")
-  public PropertiesData convertProperties(Collection<Property<?>> properties) {
+  public PropertiesData convertProperties(Collection<Property<?>> properties,
+      Set<Updatability> updatabilityFilter) {
     // check input
     if (properties == null) {
       throw new IllegalArgumentException("Properties must be set!");
@@ -455,8 +459,23 @@ public class PersistentObjectFactoryImpl
     // iterate through properties and convert them
     List<PropertyData<?>> propertyList = new ArrayList<PropertyData<?>>();
     for (Property<?> property : properties) {
+      if (property == null) {
+        continue;
+      }
 
       PropertyDefinition<?> definition = property.getDefinition();
+      if (definition == null) {
+        throw new IllegalArgumentException("Property +'" + property.getId()
+            + "' has no property defintion!");
+      }
+
+      // check updatability
+      if (updatabilityFilter != null) {
+        if (!updatabilityFilter.contains(definition.getUpdatability())) {
+          continue;
+        }
+      }
+
       if (definition instanceof PropertyStringDefinition) {
         propertyList.add(pof.createPropertyStringData(property.getId(), (List<String>) property
             .getValues()));