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

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/java/org/apache/opencmis/test/suite/otx/OtxWebServiceCmisTestSuite.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/java/org/apache/opencmis/test/suite/otx/OtxWebServiceCmisTestSuite.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/java/org/apache/opencmis/test/suite/otx/OtxWebServiceCmisTestSuite.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/java/org/apache/opencmis/test/suite/otx/OtxWebServiceCmisTestSuite.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.test.suite.otx;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite.SuiteClasses;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.RunnerBuilder;
+import org.apache.opencmis.test.Fixture;
+import org.apache.opencmis.test.ReadOnlyAclCapabilityTest;
+import org.apache.opencmis.test.ReadOnlyCreateSessionTest;
+import org.apache.opencmis.test.ReadOnlyObjectTest;
+import org.apache.opencmis.test.ReadOnlyRepositoryInfoTest;
+import org.apache.opencmis.test.suite.AbstractCmisTestSuite;
+
+/**
+ * Test suite to run OTX SOAP binding.
+ */
+
+@RunWith(OtxWebServiceCmisTestSuite.class)
+@SuiteClasses( { ReadOnlyCreateSessionTest.class, ReadOnlyRepositoryInfoTest.class,
+    ReadOnlyAclCapabilityTest.class, ReadOnlyObjectTest.class })
+public class OtxWebServiceCmisTestSuite extends AbstractCmisTestSuite {
+
+  public OtxWebServiceCmisTestSuite(Class<?> klass, RunnerBuilder r) throws InitializationError {
+    super(klass, r);
+  }
+
+  @Override
+  protected void initializeFixture() {
+    Map<String, String> parameter = new HashMap<String, String>();
+    // parameter.put(Session.URL, "http://pwdf6227:8080/cmis/services");
+    // parameter.put(Session.USER, "test");
+    // parameter.put(Session.PASSWORD, "test");
+    // parameter.put(Session.BINDING, "webservice");
+    // parameter.put(Session.PROVIDER, "otx");
+    // parameter.put(Session.REPOSITORY_ID, "myRepository");
+
+    Fixture.setParamter(parameter);
+    Fixture.setSessionFactory(null);
+  }
+
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/java/org/apache/opencmis/test/suite/otx/OtxWebServiceCmisTestSuite.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/resources/log4j.properties?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/resources/log4j.properties (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/resources/log4j.properties Tue Feb 16 16:03:38 2010
@@ -0,0 +1,22 @@
+#sample log4j.properties
+
+log4j.rootCategory=DEBUG, R, O
+
+# Stdout
+log4j.appender.O=org.apache.log4j.ConsoleAppender
+
+# File
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=log4j.log
+
+# Control the maximum log file size
+log4j.appender.R.MaxFileSize=100KB
+
+# Archive log files (one backup file here)
+log4j.appender.R.MaxBackupIndex=1
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.O.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c: %m%n
+log4j.appender.O.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c: %m%n
+
+log4j.logger.org.apache.opencmis.client.provider.spi=O
\ No newline at end of file

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-client-impl/src/test/resources/log4j.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Tue Feb 16 16:03:38 2010
@@ -0,0 +1,6 @@
+bin
+target
+*.iws
+*.ipr
+*.iml
+.*

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/pom.xml
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/pom.xml?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/pom.xml (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/pom.xml Tue Feb 16 16:03:38 2010
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                             http://maven.apache.org/maven-v4_0_0.xsd">
+                             
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.opencmis</groupId>
+    <artifactId>opencmis</artifactId>
+    <version>0.1-SNAPSHOT</version>
+	<relativePath>../../pom.xml</relativePath>
+  </parent>
+  
+  <artifactId>opencmis-provider-impl</artifactId>
+  <name>OpenCMIS Provider Implementation</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opencmis</groupId>
+      <artifactId>opencmis-commons-api</artifactId>
+      <version>${version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opencmis</groupId>
+      <artifactId>opencmis-commons-impl</artifactId>
+      <version>${version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.xml.ws</groupId>
+      <artifactId>jaxws-rt</artifactId>
+      <version>2.1.7</version>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+
+  <repositories>
+    <repository>
+      <id>maven-repository.dev.java.net</id>
+      <name>Java.net Repository for Maven 1</name>
+      <url>http://download.java.net/maven/1/</url>
+      <layout>legacy</layout>
+    </repository>
+    <repository>
+      <id>maven2-repository.dev.java.net</id>
+      <name>Java.net Repository for Maven 2</name>
+      <url>http://download.java.net/maven/2/</url>
+    </repository>
+  </repositories>
+  
+  <pluginRepositories>
+    <pluginRepository>
+      <id>maven2-repository.dev.java.net</id>
+      <url>http://download.java.net/maven/2/</url>
+    </pluginRepository>
+  </pluginRepositories>  
+</project>

Propchange: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/Cache.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/Cache.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/Cache.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/Cache.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.cache;
+
+import java.io.Serializable;
+
+/**
+ * An interface for an hierarchical cache.
+ * 
+ * <p>
+ * Each level of the hierarchy could use a different caching strategy. The cache is initialize by
+ * defining the classes that handle the caching for one level. These classes must implement the
+ * {@link CacheLevel} interface.<br/>
+ * <br/>
+ * Level configuration string format: "
+ * <code>&lt;class name&gt; [param1=value1,param2=value2,...]</code>".<br/>
+ * For example: <code>org.apache.opencmis.client.provider.cache.impl.MapCacheLevelImpl capacity=10</code><br/>
+ * </p>
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ * @see CacheLevel
+ */
+public interface Cache extends Serializable {
+
+  /**
+   * Initializes the cache.
+   * 
+   * @param cacheLevelConfig
+   *          the level configuration strings from the root to the leafs
+   */
+  void initialize(String[] cacheLevelConfig);
+
+  /**
+   * Adds an object to the cache.
+   * 
+   * @param value
+   *          the object
+   * @param keys
+   *          the keys for this object
+   */
+  void put(Object value, String... keys);
+
+  /**
+   * Retrieves an object from the cache
+   * 
+   * @param keys
+   *          the keys
+   * @return the object or <code>null<code> if the branch or leaf doesn't exist
+   */
+  Object get(String... keys);
+
+  /**
+   * Removes a branch or leaf from the cache.
+   * 
+   * @param keys
+   *          the keys of the branch or leaf
+   */
+  void remove(String... keys);
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/CacheLevel.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/CacheLevel.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/CacheLevel.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/CacheLevel.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.cache;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * Interface for a level of an hierarchical cache.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ * @see Cache
+ */
+public interface CacheLevel extends Serializable {
+
+  /**
+   * Initialize the cache level.
+   * 
+   * @param parameters
+   *          level parameters
+   */
+  void initialize(Map<String, String> parameters);
+
+  /**
+   * Adds an object to the cache level.
+   * 
+   * @param value
+   *          the object
+   * @param key
+   *          the key at this level
+   */
+  void put(Object value, String key);
+
+  /**
+   * Retrieves an object from the cache level.
+   * 
+   * @param key
+   *          the key at this cache level
+   * @return the object or <code>null</code> if the object doesn't exist
+   */
+  Object get(String key);
+
+  /**
+   * Removes an object from this cache level.
+   * 
+   * @param key
+   *          the key at this cache level
+   */
+  void remove(String key);
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/AbstractMapCacheLevel.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/AbstractMapCacheLevel.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/AbstractMapCacheLevel.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/AbstractMapCacheLevel.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.cache.impl;
+
+import java.util.Map;
+
+import org.apache.opencmis.client.provider.cache.CacheLevel;
+
+/**
+ * Abstract Map cache.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public abstract class AbstractMapCacheLevel implements CacheLevel {
+
+  private static final long serialVersionUID = 1L;
+
+  private Map<String, Object> fMap;
+  private boolean fFallbackEnabled = false;
+  private String fFallbackKey = null;
+  private boolean fSingleValueEnabled = false;
+
+  public abstract void initialize(Map<String, String> parameters);
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.cache.CacheLevel#get(java.lang.String)
+   */
+  public Object get(String key) {
+    Object value = fMap.get(key);
+
+    if ((value == null) && fFallbackEnabled) {
+      value = fMap.get(fFallbackKey);
+    }
+
+    if ((value == null) && fSingleValueEnabled) {
+      if (fMap.size() == 1) {
+        value = fMap.values().iterator().next();
+      }
+    }
+
+    return value;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.cache.CacheLevel#put(java.lang.Object, java.lang.String)
+   */
+  public void put(Object value, String key) {
+    fMap.put(key, value);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.cache.CacheLevel#remove(java.lang.String)
+   */
+  public void remove(String key) {
+    fMap.remove(key);
+  }
+
+  /**
+   * Returns the internal map.
+   */
+  protected Map<String, Object> getMap() {
+    return fMap;
+  }
+
+  /**
+   * Sets the internal map.
+   */
+  protected void setMap(Map<String, Object> map) {
+    fMap = map;
+  }
+
+  /**
+   * Enables a fallback key if no value was found for a requested key.
+   */
+  protected void enableKeyFallback(String key) {
+    fFallbackKey = key;
+    fFallbackEnabled = true;
+  }
+
+  /**
+   * Disables the fallback key.
+   */
+  protected void disableKeyFallback() {
+    fFallbackEnabled = false;
+  }
+
+  /**
+   * Enables the single value fallback.
+   */
+  protected void enableSingeValueFallback() {
+    fSingleValueEnabled = true;
+  }
+
+  /**
+   * Disables the single value fallback.
+   */
+  protected void disableSingeValueFallback() {
+    fSingleValueEnabled = false;
+  }
+
+  /**
+   * Extracts an integer parameter from the parameters.
+   * 
+   * @param parameters
+   *          the parameter map
+   * @param name
+   *          the parameter name
+   * @param defValue
+   *          the default value if the parameter can't be found
+   */
+  protected int getIntParameter(Map<String, String> parameters, String name, int defValue) {
+    if (parameters == null) {
+      return defValue;
+    }
+
+    String value = parameters.get(name);
+    if ((value == null) || (value.trim().length() == 0)) {
+      return defValue;
+    }
+
+    try {
+      return Integer.valueOf(value);
+    }
+    catch (NumberFormatException e) {
+      return defValue;
+    }
+  }
+
+  /**
+   * Extracts a float parameter from the parameters.
+   * 
+   * @param parameters
+   *          the parameter map
+   * @param name
+   *          the parameter name
+   * @param defValue
+   *          the default value if the parameter can't be found
+   */
+  protected float getFloatParameter(Map<String, String> parameters, String name, float defValue) {
+    if (parameters == null) {
+      return defValue;
+    }
+
+    String value = parameters.get(name);
+    if ((value == null) || (value.trim().length() == 0)) {
+      return defValue;
+    }
+
+    try {
+      return Float.valueOf(value);
+    }
+    catch (NumberFormatException e) {
+      return defValue;
+    }
+  }
+
+  /**
+   * Extracts a boolean parameter from the parameters.
+   * 
+   * @param parameters
+   *          the parameter map
+   * @param name
+   *          the parameter name
+   * @param defValue
+   *          the default value if the parameter can't be found
+   */
+  protected boolean getBooleanParameter(Map<String, String> parameters, String name,
+      boolean defValue) {
+    if (parameters == null) {
+      return defValue;
+    }
+
+    String value = parameters.get(name);
+    if ((value == null) || (value.trim().length() == 0)) {
+      return defValue;
+    }
+
+    return Boolean.parseBoolean(value);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see java.lang.Object#toString()
+   */
+  @Override
+  public String toString() {
+    return (fMap == null ? "[no map]" : fMap.toString());
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/CacheImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/CacheImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/CacheImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/CacheImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,284 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.cache.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.opencmis.client.provider.cache.Cache;
+import org.apache.opencmis.client.provider.cache.CacheLevel;
+
+/**
+ * Default cache implementation.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class CacheImpl implements Cache {
+
+  private static Log log = LogFactory.getLog(CacheImpl.class);
+
+  private static final long serialVersionUID = 1L;
+
+  private List<Class<?>> fLevels;
+  private List<Map<String, String>> fLevelParameters;
+
+  private String fName;
+
+  private CacheLevel fRoot;
+
+  /**
+   * Constructor.
+   */
+  public CacheImpl() {
+    fName = "Cache";
+  }
+
+  /**
+   * Constructor.
+   */
+  public CacheImpl(String name) {
+    fName = name;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.cache.Cache#initialize(java.lang.String[])
+   */
+  public void initialize(String[] cacheLevelConfig) {
+    if (fLevels != null) {
+      throw new IllegalStateException("Cache already initialize!");
+    }
+
+    if ((cacheLevelConfig == null) || (cacheLevelConfig.length == 0)) {
+      throw new IllegalArgumentException("Cache config must not be empty!");
+    }
+
+    fLevels = new ArrayList<Class<?>>();
+    fLevelParameters = new ArrayList<Map<String, String>>();
+
+    // build level lists
+    for (String config : cacheLevelConfig) {
+      int x = config.indexOf(' ');
+      if (x == -1) {
+        addLevel(config, null);
+      }
+      else {
+        addLevel(config.substring(0, x), config.substring(x + 1));
+      }
+    }
+
+    // create root
+    fRoot = createCacheLevel(0);
+  }
+
+  private void addLevel(String className, String parameters) {
+    // get the class
+    Class<?> clazz;
+    try {
+      clazz = Class.forName(className);
+    }
+    catch (ClassNotFoundException e) {
+      throw new IllegalArgumentException("Class '" + className + "' not found!", e);
+    }
+
+    // check the class
+    if (!CacheLevel.class.isAssignableFrom(clazz)) {
+      throw new IllegalArgumentException("Class '" + className
+          + "' does not implement the CacheLevel interface!");
+    }
+
+    fLevels.add(clazz);
+
+    // process parameters
+    if (parameters == null) {
+      fLevelParameters.add(null);
+    }
+    else {
+      Map<String, String> parameterMap = new HashMap<String, String>();
+      fLevelParameters.add(parameterMap);
+
+      for (String pair : parameters.split(",")) {
+        String[] keyValue = pair.split("=");
+        if (keyValue.length == 1) {
+          parameterMap.put(keyValue[0], "");
+        }
+        else {
+          parameterMap.put(keyValue[0], keyValue[1]);
+        }
+      }
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.cache.Cache#get(java.lang.String[])
+   */
+  public Object get(String... keys) {
+    // check keys
+    if (keys == null) {
+      return null;
+    }
+
+    // check level depth
+    if (fLevels.size() != keys.length) {
+      throw new IllegalArgumentException("Wrong number of keys!");
+    }
+
+    CacheLevel cacheLevel = fRoot;
+
+    // follow the branch
+    for (int i = 0; i < keys.length - 1; i++) {
+      Object level = cacheLevel.get(keys[i]);
+
+      // does the branch exist?
+      if (level == null) {
+        return null;
+      }
+
+      // next level
+      cacheLevel = (CacheLevel) level;
+    }
+
+    // get the value and return
+    return cacheLevel.get(keys[keys.length - 1]);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.cache.Cache#put(java.lang.Object, java.lang.String[])
+   */
+  public void put(Object value, String... keys) {
+    // check keys
+    if (keys == null) {
+      return;
+    }
+
+    // check level depth
+    if (fLevels.size() != keys.length) {
+      throw new IllegalArgumentException("Wrong number of keys!");
+    }
+
+    CacheLevel cacheLevel = fRoot;
+
+    // follow the branch
+    for (int i = 0; i < keys.length - 1; i++) {
+      Object level = cacheLevel.get(keys[i]);
+
+      // does the branch exist?
+      if (level == null) {
+        level = createCacheLevel(i + 1);
+        cacheLevel.put(level, keys[i]);
+      }
+
+      // next level
+      cacheLevel = (CacheLevel) level;
+    }
+
+    cacheLevel.put(value, keys[keys.length - 1]);
+
+    if (log.isDebugEnabled()) {
+      log.debug(fName + ": put [" + getFormattedKeys(keys) + "] = " + value);
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.cache.Cache#remove(java.lang.String[])
+   */
+  public void remove(String... keys) {
+    if (keys == null) {
+      return;
+    }
+
+    CacheLevel cacheLevel = fRoot;
+
+    // follow the branch
+    for (int i = 0; i < keys.length - 1; i++) {
+      Object level = cacheLevel.get(keys[i]);
+
+      // does the branch exist?
+      if (level == null) {
+        return;
+      }
+
+      // next level
+      cacheLevel = (CacheLevel) level;
+    }
+
+    cacheLevel.remove(keys[keys.length - 1]);
+
+    if (log.isDebugEnabled()) {
+      log.debug(fName + ": removed [" + getFormattedKeys(keys) + "]");
+    }
+  }
+
+  // ---- internal ----
+
+  /**
+   * Creates a cache level object.
+   */
+  private CacheLevel createCacheLevel(int level) {
+    if ((level < 0) || (level >= fLevels.size())) {
+      throw new IllegalArgumentException("Cache level doesn't fit the configuration!");
+    }
+
+    // get the class and create an instance
+    Class<?> clazz = fLevels.get(level);
+    CacheLevel cacheLevel = null;
+    try {
+      cacheLevel = (CacheLevel) clazz.newInstance();
+    }
+    catch (Exception e) {
+      throw new IllegalArgumentException("Cache level problem?!", e);
+    }
+
+    // initialize it
+    cacheLevel.initialize(fLevelParameters.get(level));
+
+    return cacheLevel;
+  }
+
+  @Override
+  public String toString() {
+    return (fRoot == null ? "(no cache root)" : fRoot.toString());
+  }
+
+  // ---- internal ----
+
+  private String getFormattedKeys(String[] keys) {
+    StringBuilder sb = new StringBuilder();
+    for (String k : keys) {
+      if (sb.length() > 0) {
+        sb.append(", ");
+      }
+      sb.append(k);
+    }
+
+    return sb.toString();
+  }
+}
\ No newline at end of file

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/ContentTypeCacheLevelImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/ContentTypeCacheLevelImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/ContentTypeCacheLevelImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/ContentTypeCacheLevelImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.cache.impl;
+
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * Content type cache.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class ContentTypeCacheLevelImpl extends MapCacheLevelImpl {
+
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * Constructor.
+   */
+  public ContentTypeCacheLevelImpl() {
+    enableKeyFallback(null);
+  }
+
+  @Override
+  public Object get(String key) {
+    return super.get(normalize(key));
+  }
+
+  @Override
+  public void put(Object value, String key) {
+    super.put(value, normalize(key));
+  }
+
+  @Override
+  public void remove(String key) {
+    super.remove(normalize(key));
+  }
+
+  /**
+   * Normalizes the key which should be a content type. It's quite simple at the moment but should
+   * cover most cases.
+   */
+  private String normalize(String key) {
+    if (key == null) {
+      return null;
+    }
+
+    StringBuilder sb = new StringBuilder();
+    int parameterStart = 0;
+
+    // first, get the MIME type
+    for (int i = 0; i < key.length(); i++) {
+      char c = key.charAt(i);
+
+      if (Character.isWhitespace(c)) {
+        continue;
+      }
+      else if (c == ';') {
+        parameterStart = i;
+        break;
+      }
+
+      sb.append(Character.toLowerCase(c));
+    }
+
+    // if parameters have been found, gather them
+    if (parameterStart > 0) {
+      SortedMap<String, String> parameter = new TreeMap<String, String>();
+      StringBuilder ksb = new StringBuilder();
+      StringBuilder vsb = new StringBuilder();
+      boolean isKey = true;
+
+      for (int i = parameterStart + 1; i < key.length(); i++) {
+        char c = key.charAt(i);
+        if (Character.isWhitespace(c)) {
+          continue;
+        }
+
+        if (isKey) {
+          if (c == '=') {
+            // value start
+            isKey = false;
+            continue;
+          }
+
+          ksb.append(Character.toLowerCase(c));
+        }
+        else {
+          if (c == ';') {
+            // next key
+            isKey = true;
+
+            parameter.put(ksb.toString(), vsb.toString());
+
+            ksb = new StringBuilder();
+            vsb = new StringBuilder();
+
+            continue;
+          }
+          else if (c == '"') {
+            // filter quotes
+            continue;
+          }
+
+          vsb.append(Character.toLowerCase(c));
+        }
+      }
+
+      // add last parameter
+      if (ksb.length() > 0) {
+        parameter.put(ksb.toString(), vsb.toString());
+      }
+
+      // write parameters sorted by key
+      for (Map.Entry<String, String> entry : parameter.entrySet()) {
+        sb.append(";");
+        sb.append(entry.getKey());
+        sb.append("=");
+        sb.append(entry.getValue());
+      }
+    }
+
+    return sb.toString();
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/LruCacheLevelImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/LruCacheLevelImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/LruCacheLevelImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/LruCacheLevelImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.cache.impl;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * LRU cache.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class LruCacheLevelImpl extends AbstractMapCacheLevel {
+
+  private static final long serialVersionUID = 1L;
+
+  public final static String MAX_ENTRIES = "maxEntries";
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.cache.CacheLevel#initialize(java.util.Map)
+   */
+  public void initialize(Map<String, String> parameters) {
+    final int maxEntries = getIntParameter(parameters, MAX_ENTRIES, 100);
+
+    setMap(new LinkedHashMap<String, Object>(maxEntries + 1, 0.70f, true) {
+      private static final long serialVersionUID = 1L;
+
+      @Override
+      public boolean removeEldestEntry(Map.Entry<String, Object> eldest) {
+        return size() > maxEntries;
+      }
+    });
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/MapCacheLevelImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/MapCacheLevelImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/MapCacheLevelImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/cache/impl/MapCacheLevelImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.cache.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Map cache.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class MapCacheLevelImpl extends AbstractMapCacheLevel {
+
+  private static final long serialVersionUID = 1L;
+
+  public final static String CAPACITY = "capacity";
+  public final static String LOAD_FACTOR = "loadFactor";
+  public final static String SINGLE_VALUE = "singleValue";
+
+  /**
+   * Constructor.
+   */
+  public MapCacheLevelImpl() {
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.cache.CacheLevel#initialize(java.util.Map)
+   */
+  public void initialize(Map<String, String> parameters) {
+    int initialCapacity = getIntParameter(parameters, CAPACITY, 32);
+    float loadFactor = getFloatParameter(parameters, LOAD_FACTOR, 0.75f);
+    boolean singleValue = getBooleanParameter(parameters, SINGLE_VALUE, false);
+
+    setMap(new HashMap<String, Object>(initialCapacity, loadFactor));
+    disableKeyFallback();
+    if (singleValue) {
+      enableSingeValueFallback();
+    }
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/factory/CmisProviderFactory.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/factory/CmisProviderFactory.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/factory/CmisProviderFactory.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/factory/CmisProviderFactory.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.factory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.opencmis.client.provider.impl.CmisProviderImpl;
+import org.apache.opencmis.commons.SessionParameter;
+import org.apache.opencmis.commons.provider.CmisProvider;
+
+/**
+ * Default factory for a CMIS provider instance.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public final class CmisProviderFactory {
+
+  /** Default CMIS AtomPub provider SPI implementation */
+  public static final String BINDING_SPI_ATOMPUB = "org.apache.opencmis.client.provider.spi.atompub.CmisAtomPubSpi";
+  /** Default CMIS Web Services provider SPI implementation */
+  public static final String BINDING_SPI_WEBSERVICES = "org.apache.opencmis.client.provider.spi.webservices.CmisWebServicesSpi";
+  /** CMIS In Memory provider SPI implementation (for testing only!) */
+  public static final String BINDING_SPI_INMEMORY = "org.apache.opencmis.inmemory.clientprovider.CmisInMemorySpiFactory";
+
+  /** Standard authentication provider class */
+  public static final String STANDARD_AUTHENTICATION_PROVIDER = "org.apache.opencmis.client.provider.spi.StandardAuthenticationProvider";
+
+  private Map<String, String> fDefaults;
+
+  /**
+   * Private constructor -- it's a factory.
+   */
+  private CmisProviderFactory() {
+    fDefaults = createNewDefaultParameters();
+  }
+
+  /**
+   * Creates a new factory instance.
+   */
+  public static CmisProviderFactory newInstance() {
+    return new CmisProviderFactory();
+  }
+
+  /**
+   * Returns the default session parameters.
+   */
+  public Map<String, String> getDefaultSessionParameters() {
+    return fDefaults;
+  }
+
+  /**
+   * Sets the default session parameters.
+   */
+  public void setDefaultSessionParameters(Map<String, String> sessionParameters) {
+    if (sessionParameters == null) {
+      fDefaults = createNewDefaultParameters();
+    }
+    else {
+      fDefaults = sessionParameters;
+    }
+  }
+
+  /**
+   * Creates a CMIS provider instance. A binding class has to be provided in the session parameters.
+   */
+  public CmisProvider createCmisProvider(Map<String, String> sessionParameters) {
+    checkSessionParameters(sessionParameters, true);
+
+    addDefaultParameters(sessionParameters);
+
+    return new CmisProviderImpl(sessionParameters);
+  }
+
+  /**
+   * Creates a default CMIS AtomPub provider instance.
+   */
+  public CmisProvider createCmisAtomPubProvider(Map<String, String> sessionParameters) {
+    checkSessionParameters(sessionParameters, false);
+
+    sessionParameters.put(SessionParameter.BINDING_SPI_CLASS, BINDING_SPI_ATOMPUB);
+    sessionParameters.put(SessionParameter.AUTHENTICATION_PROVIDER_CLASS,
+        STANDARD_AUTHENTICATION_PROVIDER);
+    sessionParameters.put(SessionParameter.AUTH_HTTP_BASIC, "true");
+    sessionParameters.put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, "false");
+    addDefaultParameters(sessionParameters);
+
+    check(sessionParameters, SessionParameter.ATOMPUB_URL);
+
+    return new CmisProviderImpl(sessionParameters);
+  }
+
+  /**
+   * Creates a default CMIS Web Services provider instance.
+   */
+  public CmisProvider createCmisWebServicesProvider(Map<String, String> sessionParameters) {
+    checkSessionParameters(sessionParameters, false);
+
+    sessionParameters.put(SessionParameter.BINDING_SPI_CLASS, BINDING_SPI_WEBSERVICES);
+    sessionParameters.put(SessionParameter.AUTHENTICATION_PROVIDER_CLASS,
+        STANDARD_AUTHENTICATION_PROVIDER);
+    sessionParameters.put(SessionParameter.AUTH_HTTP_BASIC, "true");
+    sessionParameters.put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, "true");
+    addDefaultParameters(sessionParameters);
+
+    check(sessionParameters, SessionParameter.WEBSERVICES_ACL_SERVICE);
+    check(sessionParameters, SessionParameter.WEBSERVICES_DISCOVERY_SERVICE);
+    check(sessionParameters, SessionParameter.WEBSERVICES_MULTIFILING_SERVICE);
+    check(sessionParameters, SessionParameter.WEBSERVICES_NAVIGATION_SERVICE);
+    check(sessionParameters, SessionParameter.WEBSERVICES_OBJECT_SERVICE);
+    check(sessionParameters, SessionParameter.WEBSERVICES_POLICY_SERVICE);
+    check(sessionParameters, SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE);
+    check(sessionParameters, SessionParameter.WEBSERVICES_REPOSITORY_SERVICE);
+    check(sessionParameters, SessionParameter.WEBSERVICES_VERSIONING_SERVICE);
+
+    return new CmisProviderImpl(sessionParameters);
+  }
+
+  // ---- internal ----
+
+  /**
+   * Checks the passed session parameters.
+   */
+  private void checkSessionParameters(Map<String, String> sessionParameters, boolean mustContainSPI) {
+    // don't accept null
+    if (sessionParameters == null) {
+      throw new IllegalArgumentException("Session parameter map not set!");
+    }
+
+    // check binding entry
+    String SPIClass = sessionParameters.get(SessionParameter.BINDING_SPI_CLASS);
+    if (mustContainSPI) {
+      if ((SPIClass == null) || (SPIClass.trim().length() == 0)) {
+        throw new IllegalArgumentException("SPI class entry (" + SessionParameter.BINDING_SPI_CLASS
+            + ") is missing!");
+      }
+    }
+  }
+
+  /**
+   * Checks if the given parameter is present. If not, throw an
+   * <code>IllegalArgumentException</code>.
+   */
+  private void check(Map<String, String> sessionParameters, String parameter) {
+    if (!sessionParameters.containsKey(parameter)) {
+      throw new IllegalArgumentException("Parameter '" + parameter + "' is missing!");
+    }
+  }
+
+  /**
+   * Add the default session parameters to the given map without override existing entries.
+   */
+  private void addDefaultParameters(Map<String, String> sessionParameters) {
+    for (String key : fDefaults.keySet()) {
+      if (!sessionParameters.containsKey(key)) {
+        sessionParameters.put(key, fDefaults.get(key));
+      }
+    }
+  }
+
+  /**
+   * Creates a default session parameters map with some reasonable defaults.
+   */
+  private Map<String, String> createNewDefaultParameters() {
+    Map<String, String> result = new HashMap<String, String>();
+
+    result.put(SessionParameter.CACHE_SIZE_REPOSITORIES, "10");
+    result.put(SessionParameter.CACHE_SIZE_TYPES, "100");
+    result.put(SessionParameter.CACHE_SIZE_OBJECTS, "400");
+
+    return result;
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/CmisProviderHelper.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/CmisProviderHelper.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/CmisProviderHelper.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/CmisProviderHelper.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.impl;
+
+import org.apache.opencmis.client.provider.spi.AbstractAuthenticationProvider;
+import org.apache.opencmis.client.provider.spi.CmisSpi;
+import org.apache.opencmis.client.provider.spi.CmisSpiFactory;
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.commons.SessionParameter;
+import org.apache.opencmis.commons.exceptions.CmisBaseException;
+import org.apache.opencmis.commons.exceptions.CmisRuntimeException;
+
+/**
+ * A collection of static methods that are used in multiple places within the provider
+ * implementation.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public final class CmisProviderHelper {
+
+  public static final String REPOSITORY_INFO_CACHE = "org.apache.opencmis.provider.repositoryInfoCache";
+  public static final String TYPE_DEFINTION_CACHE = "org.apache.opencmis.provider.typeDefintionCache";
+  public static final String SPI_OBJECT = "org.apache.opencmis.provider.spi.object";
+  public static final String AUTHENTICATION_PROVIDER_OBJECT = "org.apache.opencmis.provider.auth.object";
+
+  /**
+   * Private constructor.
+   */
+  private CmisProviderHelper() {
+  }
+
+  /**
+   * Gets the SPI object for the given session. If there is already a SPI object in the session it
+   * will be returned. If there is no SPI object it will be created and put into the session.
+   * 
+   * @param session
+   *          the session object
+   * 
+   * @return the SPI object
+   */
+  public static CmisSpi getSPI(Session session) {
+    // fetch from session
+    CmisSpi spi = (CmisSpi) session.get(SPI_OBJECT);
+    if (spi != null) {
+      return spi;
+    }
+
+    // ok, we have to create it...
+    try {
+      String spiFactoryName = (String) session.get(SessionParameter.BINDING_SPI_CLASS);
+      Class<?> spiFactoryClass = Class.forName(spiFactoryName);
+      Object spiFactory = spiFactoryClass.newInstance();
+
+      if (!(spiFactory instanceof CmisSpiFactory)) {
+        throw new CmisRuntimeException("Not a CMISSPIFactory class!");
+      }
+
+      spi = ((CmisSpiFactory) spiFactory).getSpiInstance(session);
+      if (spi == null) {
+        throw new CmisRuntimeException("SPI factory returned null!");
+      }
+    }
+    catch (CmisBaseException e) {
+      throw e;
+    }
+    catch (Exception e) {
+      throw new CmisRuntimeException("SPI cannot be initialized: " + e.getMessage(), e);
+    }
+
+    // we have a SPI object -> put it into the session
+    session.put(SPI_OBJECT, spi, true);
+
+    return spi;
+  }
+
+  /**
+   * Returns the authentication provider from the session or <code>null</code> if no authentication
+   * provider is set.
+   */
+  public static AbstractAuthenticationProvider getAuthenticationProvider(Session session) {
+    return (AbstractAuthenticationProvider) session.get(AUTHENTICATION_PROVIDER_OBJECT);
+  }
+
+  /**
+   * Returns the repository info cache from the session.
+   */
+  public static RepositoryInfoCache getRepositoryInfoCache(Session session) {
+    return (RepositoryInfoCache) session.get(REPOSITORY_INFO_CACHE);
+  }
+
+  /**
+   * Returns the type definition cache from the session.
+   */
+  public static TypeDefinitionCache getTypeDefinitionCache(Session session) {
+    return (TypeDefinitionCache) session.get(TYPE_DEFINTION_CACHE);
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/CmisProviderImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/CmisProviderImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/CmisProviderImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/CmisProviderImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,244 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.impl;
+
+import java.util.Map;
+
+import org.apache.opencmis.client.provider.spi.AbstractAuthenticationProvider;
+import org.apache.opencmis.client.provider.spi.CmisSpi;
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.commons.SessionParameter;
+import org.apache.opencmis.commons.impl.dataobjects.ProviderObjectFactoryImpl;
+import org.apache.opencmis.commons.provider.AclService;
+import org.apache.opencmis.commons.provider.CmisProvider;
+import org.apache.opencmis.commons.provider.DiscoveryService;
+import org.apache.opencmis.commons.provider.MultiFilingService;
+import org.apache.opencmis.commons.provider.NavigationService;
+import org.apache.opencmis.commons.provider.ObjectService;
+import org.apache.opencmis.commons.provider.PolicyService;
+import org.apache.opencmis.commons.provider.ProviderObjectFactory;
+import org.apache.opencmis.commons.provider.RelationshipService;
+import org.apache.opencmis.commons.provider.RepositoryService;
+import org.apache.opencmis.commons.provider.VersioningService;
+
+/**
+ * CMIS provider implementation.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class CmisProviderImpl implements CmisProvider {
+
+  private static final long serialVersionUID = 1L;
+
+  private Session fSession;
+  private transient ProviderObjectFactory fObjectFactory;
+  private transient RepositoryService fRepositoryService;
+
+  /**
+   * Constructor.
+   * 
+   * @param sessionParameters
+   *          the session parameters
+   */
+  public CmisProviderImpl(Map<String, String> sessionParameters) {
+    // some checks first
+    if (sessionParameters == null) {
+      throw new IllegalArgumentException("Session parameters must be set!");
+    }
+    if (!sessionParameters.containsKey(SessionParameter.BINDING_SPI_CLASS)) {
+      throw new IllegalArgumentException("Session parameters do not contain a SPI class name!");
+    }
+
+    // initialize session
+    fSession = new SessionImpl();
+    for (Map.Entry<String, String> entry : sessionParameters.entrySet()) {
+      fSession.put(entry.getKey(), entry.getValue());
+    }
+
+    // create authentication provider and add it session
+    String authProvider = sessionParameters.get(SessionParameter.AUTHENTICATION_PROVIDER_CLASS);
+    if (authProvider != null) {
+      Object authProviderObj = null;
+
+      try {
+        authProviderObj = Class.forName(authProvider).newInstance();
+      }
+      catch (Exception e) {
+        throw new IllegalArgumentException("Could not load authentication provider: " + e, e);
+      }
+
+      if (!(authProviderObj instanceof AbstractAuthenticationProvider)) {
+        throw new IllegalArgumentException(
+            "Authentication provider does not extend AbstractAuthenticationProvider!");
+      }
+
+      fSession.put(CmisProviderHelper.AUTHENTICATION_PROVIDER_OBJECT,
+          (AbstractAuthenticationProvider) authProviderObj);
+      ((AbstractAuthenticationProvider) authProviderObj).setSession(fSession);
+    }
+
+    // set up caches
+    clearAllCaches();
+
+    // initialize the SPI
+    CmisProviderHelper.getSPI(fSession);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getRepositoryService()
+   */
+  public RepositoryService getRepositoryService() {
+    if (fRepositoryService == null) {
+      fRepositoryService = new RepositoryServiceImpl(fSession);
+    }
+
+    return fRepositoryService;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getNavigationService()
+   */
+  public NavigationService getNavigationService() {
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    return spi.getNavigationService();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getObjectService()
+   */
+  public ObjectService getObjectService() {
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    return spi.getObjectService();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getDiscoveryService()
+   */
+  public DiscoveryService getDiscoveryService() {
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    return spi.getDiscoveryService();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getRelationshipService()
+   */
+  public RelationshipService getRelationshipService() {
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    return spi.getRelationshipService();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getVersioningService()
+   */
+  public VersioningService getVersioningService() {
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    return spi.getVersioningService();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getACLService()
+   */
+  public AclService getAclService() {
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    return spi.getAclService();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getMultiFilingService()
+   */
+  public MultiFilingService getMultiFilingService() {
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    return spi.getMultiFilingService();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getPolicyService()
+   */
+  public PolicyService getPolicyService() {
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    return spi.getPolicyService();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#getObjectFactory()
+   */
+  public ProviderObjectFactory getObjectFactory() {
+    if (fObjectFactory == null) {
+      fObjectFactory = new ProviderObjectFactoryImpl();
+    }
+
+    return fObjectFactory;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#clearAllCaches()
+   */
+  public void clearAllCaches() {
+    fSession.put(CmisProviderHelper.REPOSITORY_INFO_CACHE, new RepositoryInfoCache(fSession));
+    fSession.put(CmisProviderHelper.TYPE_DEFINTION_CACHE, new TypeDefinitionCache(fSession));
+
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    spi.clearAllCaches();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.CMISProvider#clearRepositoryCache(java.lang.String)
+   */
+  public void clearRepositoryCache(String repositoryId) {
+    if (repositoryId == null) {
+      return;
+    }
+
+    RepositoryInfoCache repInfoCache = (RepositoryInfoCache) fSession
+        .get(CmisProviderHelper.REPOSITORY_INFO_CACHE);
+    repInfoCache.remove(repositoryId);
+
+    TypeDefinitionCache typeDefCache = (TypeDefinitionCache) fSession
+        .get(CmisProviderHelper.TYPE_DEFINTION_CACHE);
+    typeDefCache.remove(repositoryId);
+
+    CmisSpi spi = CmisProviderHelper.getSPI(fSession);
+    spi.clearRepositoryCache(repositoryId);
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryInfoCache.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryInfoCache.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryInfoCache.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryInfoCache.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.opencmis.client.provider.impl;
+
+import java.io.Serializable;
+
+import org.apache.opencmis.client.provider.cache.Cache;
+import org.apache.opencmis.client.provider.cache.impl.CacheImpl;
+import org.apache.opencmis.client.provider.cache.impl.MapCacheLevelImpl;
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.commons.SessionParameter;
+import org.apache.opencmis.commons.provider.RepositoryInfoData;
+
+/**
+ * A cache for repository info objects.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public class RepositoryInfoCache implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final int CACHE_SIZE_REPOSITORIES = 10;
+
+  private Cache fCache;
+
+  /**
+   * Constructor.
+   * 
+   * @param session
+   *          the session object
+   */
+  public RepositoryInfoCache(Session session) {
+    int repCount = session.get(SessionParameter.CACHE_SIZE_REPOSITORIES, CACHE_SIZE_REPOSITORIES);
+    if (repCount < 1) {
+      repCount = CACHE_SIZE_REPOSITORIES;
+    }
+
+    fCache = new CacheImpl("Repository Info Cache");
+    fCache.initialize(new String[] { MapCacheLevelImpl.class.getName() + " "
+        + MapCacheLevelImpl.CAPACITY + "=" + repCount });
+  }
+
+  /**
+   * Adds a repository info object to the cache.
+   * 
+   * @param repositoryInfo
+   *          the repository info object
+   */
+  public void put(RepositoryInfoData repositoryInfo) {
+    if ((repositoryInfo == null) || (repositoryInfo.getRepositoryId() == null)) {
+      return;
+    }
+
+    fCache.put(repositoryInfo, repositoryInfo.getRepositoryId());
+  }
+
+  /**
+   * Retrieves a repository info object from the cache.
+   * 
+   * @param repositoryId
+   *          the repository id
+   * @return the repository info object or <code>null</code> if the object is not in the cache
+   */
+  public RepositoryInfoData get(String repositoryId) {
+    return (RepositoryInfoData) fCache.get(repositoryId);
+  }
+
+  /**
+   * Removes a repository info object 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/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryInfoCache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryServiceImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryServiceImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryServiceImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.opencmis.client.provider.impl;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.apache.opencmis.client.provider.spi.CmisSpi;
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.commons.api.ExtensionsData;
+import org.apache.opencmis.commons.api.TypeDefinitionContainer;
+import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.api.TypeDefinitionList;
+import org.apache.opencmis.commons.provider.RepositoryInfoData;
+import org.apache.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 {
+
+  private Session fSession;
+
+  /**
+   * Constructor.
+   */
+  public RepositoryServiceImpl(Session session) {
+    fSession = session;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.RepositoryService#getRepositoryInfo(java.lang.String,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public RepositoryInfoData getRepositoryInfo(String repositoryId, ExtensionsData extension) {
+    RepositoryInfoData result = null;
+    boolean hasExtension = (extension != null) && (!extension.getExtensions().isEmpty());
+
+    RepositoryInfoCache cache = CmisProviderHelper.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 = CmisProviderHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getRepositoryInfo(repositoryId, extension);
+
+    // put it into the cache
+    if (!hasExtension) {
+      cache.put(result);
+    }
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.opencmis.client.provider.RepositoryService#getRepositoryInfos(org.apache.opencmis.client.provider
+   * .ExtensionsData)
+   */
+  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 = CmisProviderHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getRepositoryInfos(extension);
+
+    // put it into the cache
+    if (!hasExtension && (result != null)) {
+      RepositoryInfoCache cache = CmisProviderHelper.getRepositoryInfoCache(fSession);
+      for (RepositoryInfoData rid : result) {
+        cache.put(rid);
+      }
+    }
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.RepositoryService#getTypeChildren(java.lang.String,
+   * java.lang.String, java.lang.Boolean, java.math.BigInteger, java.math.BigInteger,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  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 = CmisProviderHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getTypeChildren(repositoryId, typeId,
+        includePropertyDefinitions, maxItems, skipCount, extension);
+
+    // put it into the cache
+    if (!hasExtension && propDefs && (result != null)) {
+      TypeDefinitionCache cache = CmisProviderHelper.getTypeDefinitionCache(fSession);
+
+      for (TypeDefinition tdd : result.getList()) {
+        cache.put(repositoryId, tdd);
+      }
+    }
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.RepositoryService#getTypeDefinition(java.lang.String,
+   * java.lang.String, org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  public TypeDefinition getTypeDefinition(String repositoryId, String typeId,
+      ExtensionsData extension) {
+    TypeDefinition result = null;
+    boolean hasExtension = (extension != null) && (!extension.getExtensions().isEmpty());
+
+    TypeDefinitionCache cache = CmisProviderHelper.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 = CmisProviderHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getTypeDefinition(repositoryId, typeId, extension);
+
+    // put it into the cache
+    if (!hasExtension && (result != null)) {
+      cache.put(repositoryId, result);
+    }
+
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.RepositoryService#getTypeDescendants(java.lang.String,
+   * java.lang.String, java.math.BigInteger, java.lang.Boolean,
+   * org.apache.opencmis.client.provider.ExtensionsData)
+   */
+  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 = CmisProviderHelper.getSPI(fSession);
+    result = spi.getRepositoryService().getTypeDescendants(repositoryId, typeId, depth,
+        includePropertyDefinitions, extension);
+
+    // put it into the cache
+    if (!hasExtension && propDefs && (result != null)) {
+      TypeDefinitionCache cache = CmisProviderHelper.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/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/RepositoryServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/SessionImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/SessionImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/SessionImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/SessionImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.client.provider.impl;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.opencmis.client.provider.spi.Session;
+
+/**
+ * CMIS provider 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;
+
+  /**
+   * Constructor.
+   */
+  public SessionImpl() {
+    fData = new HashMap<String, Object>();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.Session#get(java.lang.String)
+   */
+  public Object get(String key) {
+    Object value = fData.get(key);
+
+    if (value instanceof TransientWrapper) {
+      return ((TransientWrapper) value).getObject();
+    }
+
+    return value;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.Session#get(java.lang.String, java.lang.Object)
+   */
+  public Object get(String key, Object defValue) {
+    Object value = get(key);
+    return (value == null ? defValue : value);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.Session#get(java.lang.String, int)
+   */
+  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;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.Session#put(java.lang.String, java.io.Serializable)
+   */
+  public void put(String key, Serializable obj) {
+    fData.put(key, obj);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.Session#put(java.lang.String, java.lang.Object, boolean)
+   */
+  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!");
+    }
+
+    fData.put(key, value);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.Session#remove(java.lang.String)
+   */
+  public void remove(String key) {
+    fData.remove(key);
+  }
+
+  @Override
+  public String toString() {
+    return fData.toString();
+  }
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TransientWrapper.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TransientWrapper.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TransientWrapper.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TransientWrapper.java Tue Feb 16 16:03:38 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.opencmis.client.provider.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/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TransientWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TypeDefinitionCache.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TypeDefinitionCache.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TypeDefinitionCache.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TypeDefinitionCache.java Tue Feb 16 16:03:38 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.opencmis.client.provider.impl;
+
+import java.io.Serializable;
+
+import org.apache.opencmis.client.provider.cache.Cache;
+import org.apache.opencmis.client.provider.cache.impl.CacheImpl;
+import org.apache.opencmis.client.provider.cache.impl.LruCacheLevelImpl;
+import org.apache.opencmis.client.provider.cache.impl.MapCacheLevelImpl;
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.commons.SessionParameter;
+import org.apache.opencmis.commons.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/trunk/opencmis/opencmis-client/opencmis-provider-impl/src/main/java/org/apache/opencmis/client/provider/impl/TypeDefinitionCache.java
------------------------------------------------------------------------------
    svn:eol-style = native