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 2011/01/20 12:38:50 UTC
svn commit: r1061233 [9/15] - in /incubator/chemistry/dotcmis: branches/
tags/ trunk/ trunk/DotCMIS/ trunk/DotCMIS/Properties/ trunk/DotCMIS/Service
References/ trunk/DotCMIS/Service References/CMISWebServicesReference/
trunk/DotCMIS/binding/ trunk/Dot...
Added: incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-caches.cs
URL: http://svn.apache.org/viewvc/incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-caches.cs?rev=1061233&view=auto
==============================================================================
--- incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-caches.cs (added)
+++ incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-caches.cs Thu Jan 20 11:38:48 2011
@@ -0,0 +1,662 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using DotCMIS.Binding.Impl;
+using DotCMIS.Data;
+
+namespace DotCMIS.Binding
+{
+ // --- base cache implementation ---
+
+ internal interface ICache
+ {
+ void Initialize(string[] cacheLevelConfig);
+
+ void Put(string[] keys, object value);
+
+ object Get(string[] keys);
+
+ void Remove(string[] keys);
+
+ int Check(string[] keys);
+
+ void Lock();
+
+ void Unlock();
+ }
+
+ internal interface ICacheLevel
+ {
+ void Initialize(IDictionary<string, string> cacheLevelConfig);
+
+ object this[string key] { get; set; }
+
+ void Remove(string key);
+ }
+
+ internal class Cache : ICache
+ {
+ private IList<Type> cacheLevels;
+ private IList<IDictionary<string, string>> cacheLevelParameters;
+ private ICacheLevel root;
+ private string name;
+ private object cacheLock = new object();
+
+ public Cache()
+ : this("Cache")
+ {
+ }
+
+ public Cache(string name)
+ {
+ this.name = name;
+ }
+
+ public void Initialize(string[] cacheLevelConfig)
+ {
+ if (cacheLevels != null)
+ {
+ throw new ApplicationException("Cache already initialize!");
+ }
+
+ if ((cacheLevelConfig == null) || (cacheLevelConfig.Length == 0))
+ {
+ throw new ArgumentException("Cache config must not be empty!");
+ }
+
+ Lock();
+ try
+ {
+ cacheLevels = new List<Type>();
+ cacheLevelParameters = new List<IDictionary<string, string>>();
+
+ // build level lists
+ foreach (string config in cacheLevelConfig)
+ {
+ int x = config.IndexOf(' ');
+ if (x == -1)
+ {
+ AddLevel(config, null);
+ }
+ else
+ {
+ AddLevel(config.Substring(0, x), config.Substring(x + 1));
+ }
+ }
+
+ root = CreateCacheLevel(0);
+ }
+ finally
+ {
+ Unlock();
+ }
+ }
+
+ public void Put(string[] keys, object value)
+ {
+ if (keys == null) { return; }
+
+ if (keys.Length != cacheLevels.Count)
+ {
+ throw new ArgumentException("Wrong number of keys!");
+ }
+
+ Lock();
+ try
+ {
+ ICacheLevel cacheLevel = root;
+
+ // follow the branch
+ for (int i = 0; i < keys.Length - 1; i++)
+ {
+ object level = cacheLevel[keys[i]];
+
+ // does the branch exist?
+ if (level == null)
+ {
+ level = CreateCacheLevel(i + 1);
+ cacheLevel[keys[i]] = level;
+ }
+
+ // next level
+ cacheLevel = (ICacheLevel)level;
+ }
+
+ cacheLevel[keys[keys.Length - 1]] = value;
+
+ Trace.WriteLine(name + ": put [" + GetFormattedKeys(keys) + "] = " + value);
+ }
+ finally
+ {
+ Unlock();
+ }
+ }
+
+ public object Get(string[] keys)
+ {
+ if (keys == null) { return null; }
+
+ if (keys.Length != cacheLevels.Count)
+ {
+ throw new ArgumentException("Wrong number of keys!");
+ }
+
+ object result = null;
+
+ Lock();
+ try
+ {
+ ICacheLevel cacheLevel = root;
+
+ // follow the branch
+ for (int i = 0; i < keys.Length - 1; i++)
+ {
+ object level = cacheLevel[keys[i]];
+
+ // does the branch exist?
+ if (level == null) { return null; }
+
+ // next level
+ cacheLevel = (ICacheLevel)level;
+ }
+
+ // get the value
+ result = cacheLevel[keys[keys.Length - 1]];
+ }
+ finally
+ {
+ Unlock();
+ }
+
+ return result;
+ }
+
+ public void Remove(string[] keys)
+ {
+ if (keys == null) { return; }
+
+ Lock();
+ try
+ {
+ ICacheLevel cacheLevel = root;
+
+ // follow the branch
+ for (int i = 0; i < keys.Length - 1; i++)
+ {
+ object level = cacheLevel[keys[i]];
+
+ // does the branch exist?
+ if (level == null) { return; }
+
+ // next level
+ cacheLevel = (ICacheLevel)level;
+ }
+
+ cacheLevel.Remove(keys[keys.Length - 1]);
+
+ Trace.WriteLine(name + ": removed [" + GetFormattedKeys(keys) + "]");
+ }
+ finally
+ {
+ Unlock();
+ }
+ }
+
+ public int Check(string[] keys)
+ {
+ if (keys == null) { return -1; }
+
+ Lock();
+ try
+ {
+ ICacheLevel cacheLevel = root;
+
+ // follow the branch
+ for (int i = 0; i < keys.Length - 1; i++)
+ {
+ object level = cacheLevel[keys[i]];
+
+ // does the branch exist?
+ if (level == null) { return i; }
+
+ // next level
+ cacheLevel = (ICacheLevel)level;
+ }
+
+ return keys.Length;
+ }
+ finally
+ {
+ Unlock();
+ }
+ }
+
+ public void Lock()
+ {
+ Monitor.Enter(cacheLock);
+ }
+
+ public void Unlock()
+ {
+ Monitor.Exit(cacheLock);
+ }
+
+ // --- internal ---
+
+ private void AddLevel(string typeName, string parameters)
+ {
+ Type levelType;
+
+ try
+ {
+ levelType = Type.GetType(typeName);
+ }
+ catch (Exception e)
+ {
+ throw new ArgumentException("Class '" + typeName + "' not found!", e);
+ }
+
+ if (!typeof(ICacheLevel).IsAssignableFrom(levelType))
+ {
+ throw new ArgumentException("Class '" + typeName + "' does not implement the ICacheLevel interface!");
+ }
+
+ cacheLevels.Add(levelType);
+
+ // process parameters
+ if (parameters == null)
+ {
+ cacheLevelParameters.Add(null);
+ }
+ else
+ {
+ Dictionary<string, string> parameterDict = new Dictionary<string, string>();
+ cacheLevelParameters.Add(parameterDict);
+
+ foreach (string pair in parameters.Split(','))
+ {
+ string[] keyValue = pair.Split('=');
+ if (keyValue.Length == 1)
+ {
+ parameterDict[keyValue[0]] = "";
+ }
+ else
+ {
+ parameterDict[keyValue[0]] = keyValue[1];
+ }
+ }
+ }
+ }
+
+ private ICacheLevel CreateCacheLevel(int level)
+ {
+ if ((level < 0) || (level >= cacheLevels.Count))
+ {
+ throw new ArgumentException("Cache level doesn't fit the configuration!");
+ }
+
+ // get the class and create an instance
+ Type levelType = cacheLevels[level];
+ ICacheLevel cacheLevel = null;
+ try
+ {
+ cacheLevel = (ICacheLevel)Activator.CreateInstance(levelType);
+ }
+ catch (Exception e)
+ {
+ throw new ArgumentException("Cache level problem?!", e);
+ }
+
+ // initialize it
+ cacheLevel.Initialize(cacheLevelParameters[level]);
+
+ return cacheLevel;
+ }
+
+ private string GetFormattedKeys(string[] keys)
+ {
+ StringBuilder sb = new StringBuilder();
+ foreach (string k in keys)
+ {
+ if (sb.Length > 0)
+ {
+ sb.Append(", ");
+ }
+ sb.Append(k);
+ }
+
+ return sb.ToString();
+ }
+ }
+
+ internal abstract class AbstractDictionaryCacheLevel : ICacheLevel
+ {
+ private static string NullKey = "";
+
+ private IDictionary<string, object> dict;
+ private bool fallbackEnabled = false;
+ private string fallbackKey = null;
+ private bool singleValueEnabled = false;
+
+ public abstract void Initialize(IDictionary<string, string> cacheLevelConfig);
+
+ public virtual object this[string key]
+ {
+ get
+ {
+ object value = null;
+ if (dict.TryGetValue(key == null ? NullKey : key, out value))
+ {
+ return value;
+ }
+
+ if (fallbackEnabled && dict.TryGetValue(fallbackKey, out value))
+ {
+ return value;
+ }
+
+ if (singleValueEnabled && dict.Count == 1)
+ {
+ value = dict.Values.First();
+ }
+
+ return value;
+ }
+ set
+ {
+ if (value != null)
+ {
+ dict[key == null ? NullKey : key] = value;
+ }
+ }
+ }
+
+ public virtual void Remove(string key)
+ {
+ dict.Remove(key);
+ }
+
+ public void SetDictionary(IDictionary<string, object> dict)
+ {
+ this.dict = dict;
+ }
+
+ protected void EnableKeyFallback(string key)
+ {
+ fallbackKey = key;
+ fallbackEnabled = true;
+ }
+
+ protected void DisableKeyFallback()
+ {
+ fallbackEnabled = false;
+ }
+
+ protected void EnableSingeValueFallback()
+ {
+ singleValueEnabled = true;
+ }
+
+ protected void DisableSingeValueFallback()
+ {
+ singleValueEnabled = false;
+ }
+
+ protected int GetIntParameter(IDictionary<string, string> parameters, string name, int defValue)
+ {
+ if (parameters == null)
+ {
+ return defValue;
+ }
+
+ string value;
+ if (!parameters.TryGetValue(name, out value))
+ {
+ return defValue;
+ }
+
+ try
+ {
+ return Int32.Parse(value);
+ }
+ catch (Exception)
+ {
+ return defValue;
+ }
+ }
+
+ protected bool GetBooleanParameter(IDictionary<string, string> parameters, string name, bool defValue)
+ {
+ if (parameters == null)
+ {
+ return defValue;
+ }
+
+ string value;
+ if (!parameters.TryGetValue(name, out value))
+ {
+ return defValue;
+ }
+
+ try
+ {
+ return Boolean.Parse(value);
+ }
+ catch (Exception)
+ {
+ return defValue;
+ }
+ }
+ }
+
+ internal class DictionaryCacheLevel : AbstractDictionaryCacheLevel
+ {
+ public const string Capacity = "capacity";
+ public const string SingleValue = "singleValue";
+
+ public override void Initialize(IDictionary<string, string> parameters)
+ {
+ int initialCapacity = GetIntParameter(parameters, Capacity, 32);
+ bool singleValue = GetBooleanParameter(parameters, SingleValue, false);
+
+ SetDictionary(new Dictionary<string, object>(initialCapacity));
+ if (singleValue)
+ {
+ EnableSingeValueFallback();
+ }
+ }
+ }
+
+ internal class LruCacheLevel : AbstractDictionaryCacheLevel
+ {
+ public const string MaxEntries = "maxEntries";
+
+ private LinkedList<string> keyList;
+ private int maxEntries;
+
+ public override void Initialize(IDictionary<string, string> parameters)
+ {
+ maxEntries = GetIntParameter(parameters, MaxEntries, 100);
+ keyList = new LinkedList<string>();
+ SetDictionary(new Dictionary<string, object>(maxEntries + 1));
+ }
+
+ public override object this[string key]
+ {
+ get
+ {
+ object value = base[key];
+ if (value != null)
+ {
+ LinkedListNode<string> node = keyList.Find(key);
+ if (node == null)
+ {
+ throw new ApplicationException("Cache error!");
+ }
+ else
+ {
+ keyList.Remove(node);
+ keyList.AddFirst(node);
+ }
+ }
+
+ return value;
+ }
+ set
+ {
+ if (value == null)
+ {
+ return;
+ }
+
+ LinkedListNode<string> node = keyList.Find(key);
+ if (node == null)
+ {
+ keyList.AddFirst(key);
+ while (keyList.Count > maxEntries)
+ {
+ LinkedListNode<string> lastNode = keyList.Last;
+ base.Remove(lastNode.Value);
+ keyList.RemoveLast();
+ }
+ }
+ else
+ {
+ keyList.Remove(node);
+ keyList.AddFirst(node);
+ }
+
+ base[key] = value;
+ }
+ }
+
+ public override void Remove(string key)
+ {
+ keyList.Remove(key);
+ base.Remove(key);
+ }
+ }
+
+ // ---- Caches ----
+
+ /// <summary>
+ /// Repository Info cache.
+ /// </summary>
+ internal class RepositoryInfoCache
+ {
+ private const int CacheSizeRepositories = 10;
+
+ private ICache cache;
+
+ public RepositoryInfoCache(BindingSession session)
+ {
+ int repCount = session.GetValue(SessionParameter.CacheSizeRepositories, CacheSizeRepositories);
+ if (repCount < 1)
+ {
+ repCount = CacheSizeRepositories;
+ }
+
+ cache = new Cache("Repository Info Cache");
+ cache.Initialize(new string[] {
+ typeof(DictionaryCacheLevel).FullName + " " + DictionaryCacheLevel.Capacity + "=" + repCount });
+ }
+
+ public void Put(IRepositoryInfo repositoryInfo)
+ {
+ if ((repositoryInfo == null) || (repositoryInfo.Id == null))
+ {
+ return;
+ }
+
+ cache.Put(new string[] { repositoryInfo.Id }, repositoryInfo);
+ }
+
+ public IRepositoryInfo Get(string repositoryId)
+ {
+ return (IRepositoryInfo)cache.Get(new string[] { repositoryId });
+ }
+
+ public void Remove(string repositoryId)
+ {
+ cache.Remove(new string[] { repositoryId });
+ }
+ }
+
+ /// <summary>
+ /// Type Definition cache.
+ /// </summary>
+ internal class TypeDefinitionCache
+ {
+ private const int CacheSizeRepositories = 10;
+ private const int CacheSizeTypes = 100;
+
+ private ICache cache;
+
+ public TypeDefinitionCache(BindingSession session)
+ {
+ int repCount = session.GetValue(SessionParameter.CacheSizeRepositories, CacheSizeRepositories);
+ if (repCount < 1)
+ {
+ repCount = CacheSizeRepositories;
+ }
+
+ int typeCount = session.GetValue(SessionParameter.CacheSizeTypes, CacheSizeTypes);
+ if (typeCount < 1)
+ {
+ typeCount = CacheSizeTypes;
+ }
+
+ cache = new Cache("Type Definition Cache");
+ cache.Initialize(new string[] {
+ typeof(DictionaryCacheLevel).FullName + " " + DictionaryCacheLevel.Capacity + "=" + repCount, // repository
+ typeof(LruCacheLevel).FullName + " " + LruCacheLevel.MaxEntries + "=" + typeCount // type
+ });
+ }
+
+ public void Put(string repositoryId, ITypeDefinition typeDefinition)
+ {
+ if ((typeDefinition == null) || (typeDefinition.Id == null))
+ {
+ return;
+ }
+
+ cache.Put(new string[] { repositoryId, typeDefinition.Id }, typeDefinition);
+ }
+
+ public ITypeDefinition Get(string repositoryId, string typeId)
+ {
+ return (ITypeDefinition)cache.Get(new string[] { repositoryId, typeId });
+ }
+
+ public void Remove(string repositoryId, string typeId)
+ {
+ cache.Remove(new string[] { repositoryId, typeId });
+ }
+
+ public void Remove(string repositoryId)
+ {
+ cache.Remove(new string[] { repositoryId });
+ }
+ }
+}
Added: incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-impl.cs
URL: http://svn.apache.org/viewvc/incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-impl.cs?rev=1061233&view=auto
==============================================================================
--- incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-impl.cs (added)
+++ incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-impl.cs Thu Jan 20 11:38:48 2011
@@ -0,0 +1,604 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using DotCMIS.Binding;
+using DotCMIS.Binding.Services;
+using System.Threading;
+using DotCMIS.Exceptions;
+using DotCMIS.Data;
+using DotCMIS.Data.Extensions;
+
+namespace DotCMIS.Binding.Impl
+{
+ /// <summary>
+ /// Binding layer implementation.
+ /// </summary>
+ internal class CmisBinding : ICmisBinding
+ {
+ private BindingSession session;
+ private BindingsObjectFactory objectFactory;
+ private BindingRepositoryService repositoryServiceWrapper;
+
+ public CmisBinding(IDictionary<string, string> sessionParameters)
+ {
+ if (sessionParameters == null)
+ {
+ throw new ArgumentNullException("sessionParameters");
+ }
+
+ if (!sessionParameters.ContainsKey(SessionParameter.BindingSpiClass))
+ {
+ throw new ArgumentException("Session parameters do not contain a SPI class name!");
+ }
+
+ // initialize session
+ session = new BindingSession();
+ foreach (string key in sessionParameters.Keys)
+ {
+ session.PutValue(key, sessionParameters[key]);
+ }
+
+ // set up object factory
+ objectFactory = new BindingsObjectFactory();
+
+ // set up authentication provider
+ string authenticationProviderClass;
+ if (sessionParameters.TryGetValue(SessionParameter.AuthenticationProviderClass, out authenticationProviderClass))
+ {
+ try
+ {
+ Type authProvType = Type.GetType(authenticationProviderClass);
+ AbstractAuthenticationProvider authenticationProvider = (AbstractAuthenticationProvider)Activator.CreateInstance(authProvType);
+ authenticationProvider.Session = session;
+ session.PutValue(BindingSession.AuthenticationProvider, authenticationProvider);
+ }
+ catch (Exception e)
+ {
+ throw new CmisRuntimeException("Could not load authentictaion provider: " + e.Message, e);
+ }
+ }
+
+ // initialize the SPI
+ GetSpi();
+
+ // set up caches
+ ClearAllCaches();
+
+ // set up repository service
+ repositoryServiceWrapper = new BindingRepositoryService(session);
+ }
+
+ public IRepositoryService GetRepositoryService()
+ {
+ CheckSession();
+ return repositoryServiceWrapper;
+ }
+
+ public INavigationService GetNavigationService()
+ {
+ CheckSession();
+ ICmisSpi spi = GetSpi();
+ return spi.GetNavigationService();
+ }
+
+ public IObjectService GetObjectService()
+ {
+ CheckSession();
+ ICmisSpi spi = GetSpi();
+ return spi.GetObjectService();
+ }
+
+ public IVersioningService GetVersioningService()
+ {
+ CheckSession();
+ ICmisSpi spi = GetSpi();
+ return spi.GetVersioningService();
+ }
+
+ public IRelationshipService GetRelationshipService()
+ {
+ CheckSession();
+ ICmisSpi spi = GetSpi();
+ return spi.GetRelationshipService();
+ }
+
+ public IDiscoveryService GetDiscoveryService()
+ {
+ CheckSession();
+ ICmisSpi spi = GetSpi();
+ return spi.GetDiscoveryService();
+ }
+
+ public IMultiFilingService GetMultiFilingService()
+ {
+ CheckSession();
+ ICmisSpi spi = GetSpi();
+ return spi.GetMultiFilingService();
+ }
+
+ public IAclService GetAclService()
+ {
+ CheckSession();
+ ICmisSpi spi = GetSpi();
+ return spi.GetAclService();
+ }
+
+ public IPolicyService GetPolicyService()
+ {
+ CheckSession();
+ ICmisSpi spi = GetSpi();
+ return spi.GetPolicyService();
+ }
+
+ public IBindingsObjectFactory GetObjectFactory()
+ {
+ return objectFactory;
+ }
+
+ public void ClearAllCaches()
+ {
+ CheckSession();
+
+ session.Lock();
+ try
+ {
+ session.PutValue(BindingSession.RepositoryInfoCache, new RepositoryInfoCache(session));
+ session.PutValue(BindingSession.TypeDefinitionCache, new TypeDefinitionCache(session));
+
+ ICmisSpi spi = GetSpi();
+ spi.ClearAllCaches();
+ }
+ finally
+ {
+ session.Unlock();
+ }
+ }
+
+ public void ClearRepositoryCache(string repositoryId)
+ {
+ CheckSession();
+
+ if (repositoryId == null)
+ {
+ return;
+ }
+
+ session.Lock();
+ try
+ {
+ RepositoryInfoCache repInfoCache = session.GetRepositoryInfoCache();
+ repInfoCache.Remove(repositoryId);
+
+ TypeDefinitionCache typeDefCache = session.GetTypeDefinitionCache();
+ typeDefCache.Remove(repositoryId);
+
+ ICmisSpi spi = GetSpi();
+ spi.ClearRepositoryCache(repositoryId);
+ }
+ finally
+ {
+ session.Unlock();
+ }
+ }
+
+ public void Close()
+ {
+ CheckSession();
+
+ session.Lock();
+ try
+ {
+ GetSpi().Close();
+ }
+ finally
+ {
+ session.Unlock();
+ session = null;
+ }
+ }
+
+ private void CheckSession()
+ {
+ if (session == null)
+ {
+ throw new ApplicationException("Already closed.");
+ }
+ }
+
+ private ICmisSpi GetSpi()
+ {
+ return session.GetSpi();
+ }
+ }
+
+ /// <summary>
+ /// Session object implementation of the binding layer.
+ /// </summary>
+ internal class BindingSession : IBindingSession
+ {
+ public const string RepositoryInfoCache = "org.apache.chemistry.dotcmis.bindings.repositoryInfoCache";
+ public const string TypeDefinitionCache = "org.apache.chemistry.dotcmis.bindings.typeDefintionCache";
+ public const string AuthenticationProvider = "org.apache.chemistry.dotcmis.bindings.authenticationProvider";
+ public const string SpiObject = "org.apache.chemistry.dotcmis.bindings.spi.object";
+
+ private Dictionary<string, object> data;
+ private object sessionLock = new object();
+
+ public BindingSession()
+ {
+ data = new Dictionary<string, object>();
+ }
+
+ public object GetValue(string key)
+ {
+ return GetValue(key, null);
+ }
+
+ public object GetValue(string key, object defValue)
+ {
+ object result = null;
+
+ Lock();
+ try
+ {
+ if (data.TryGetValue(key, out result))
+ {
+ return result;
+ }
+ else
+ {
+ return defValue;
+ }
+ }
+ finally
+ {
+ Unlock();
+ }
+ }
+
+ public int GetValue(string key, int defValue)
+ {
+ object value = GetValue(key);
+
+ try
+ {
+ if (value is string)
+ {
+ return Int32.Parse((string)value);
+ }
+ else if (value is int)
+ {
+ return (int)value;
+ }
+ }
+ catch (Exception)
+ {
+ }
+
+ return defValue;
+ }
+
+ public void PutValue(string key, object value)
+ {
+ Lock();
+ try
+ {
+ data[key] = value;
+ }
+ finally
+ {
+ Unlock();
+ }
+ }
+
+ public void RemoveValue(string key)
+ {
+ Lock();
+ try
+ {
+ data.Remove(key);
+ }
+ finally
+ {
+ Unlock();
+ }
+ }
+
+ public ICmisSpi GetSpi()
+ {
+ Lock();
+ try
+ {
+ ICmisSpi spi = GetValue(SpiObject) as ICmisSpi;
+ if (spi != null)
+ {
+ return spi;
+ }
+
+
+ // ok, we have to create it...
+ try
+ {
+ object spiObject;
+ if (data.TryGetValue(SessionParameter.BindingSpiClass, out spiObject))
+ {
+ string spiClassName = spiObject as string;
+ if (spiClassName != null)
+ {
+ Type spiClass = Type.GetType(spiClassName);
+ spi = (ICmisSpi)Activator.CreateInstance(spiClass);
+ spi.initialize(this);
+ }
+ else
+ {
+ throw new CmisRuntimeException("SPI class is not set!");
+ }
+ }
+ else
+ {
+ throw new CmisRuntimeException("SPI class is not set!");
+ }
+ }
+ catch (CmisBaseException ce)
+ {
+ throw ce;
+ }
+ catch (Exception e)
+ {
+ throw new CmisRuntimeException("SPI cannot be initialized: " + e.Message, e);
+ }
+
+ // we have a SPI object -> put it into the session
+ data[SpiObject] = spi;
+
+ return spi;
+ }
+ finally
+ {
+ Unlock();
+ }
+ }
+
+ public RepositoryInfoCache GetRepositoryInfoCache()
+ {
+ return GetValue(RepositoryInfoCache) as RepositoryInfoCache;
+ }
+
+ public TypeDefinitionCache GetTypeDefinitionCache()
+ {
+ return GetValue(TypeDefinitionCache) as TypeDefinitionCache;
+ }
+
+ public AbstractAuthenticationProvider GetAuthenticationProvider()
+ {
+ return GetValue(AuthenticationProvider) as AbstractAuthenticationProvider;
+ }
+
+ public void Lock()
+ {
+ Monitor.Enter(sessionLock);
+ }
+
+ public void Unlock()
+ {
+ Monitor.Exit(sessionLock);
+ }
+
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+ }
+
+ /// <summary>
+ /// Repository service proxy that caches repository infos and type defintions.
+ /// </summary>
+ internal class BindingRepositoryService : IRepositoryService
+ {
+ private BindingSession session;
+
+ public BindingRepositoryService(BindingSession session)
+ {
+ this.session = session;
+ }
+
+ public IList<IRepositoryInfo> GetRepositoryInfos(IExtensionsData extension)
+ {
+ IList<IRepositoryInfo> result = null;
+ bool hasExtension = (extension != null) && (extension.Extensions != null) && (extension.Extensions.Count > 0);
+
+ // get the SPI and fetch the repository infos
+ ICmisSpi spi = session.GetSpi();
+ result = spi.GetRepositoryService().GetRepositoryInfos(extension);
+
+ // put it into the cache
+ if (!hasExtension && (result != null))
+ {
+ RepositoryInfoCache cache = session.GetRepositoryInfoCache();
+ foreach (RepositoryInfo rid in result)
+ {
+ cache.Put(rid);
+ }
+ }
+
+ return result;
+ }
+
+ public IRepositoryInfo GetRepositoryInfo(string repositoryId, IExtensionsData extension)
+ {
+ IRepositoryInfo result = null;
+ bool hasExtension = (extension != null) && (extension.Extensions != null) && (extension.Extensions.Count > 0);
+
+ RepositoryInfoCache cache = session.GetRepositoryInfoCache();
+
+ // 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
+ ICmisSpi spi = session.GetSpi();
+ result = spi.GetRepositoryService().GetRepositoryInfo(repositoryId, extension);
+
+ // put it into the cache
+ if (!hasExtension)
+ {
+ cache.Put(result);
+ }
+
+ return result;
+ }
+
+ public ITypeDefinitionList GetTypeChildren(string repositoryId, string typeId, bool? includePropertyDefinitions,
+ long? maxItems, long? skipCount, IExtensionsData extension)
+ {
+ ITypeDefinitionList result = null;
+ bool hasExtension = (extension != null) && (extension.Extensions != null) && (extension.Extensions.Count > 0);
+
+ // get the SPI and fetch the type definitions
+ ICmisSpi spi = session.GetSpi();
+ result = spi.GetRepositoryService().GetTypeChildren(repositoryId, typeId, includePropertyDefinitions, maxItems,
+ skipCount, extension);
+
+ // put it into the cache
+ if (!hasExtension && (includePropertyDefinitions ?? false) && (result != null))
+ {
+ TypeDefinitionCache cache = session.GetTypeDefinitionCache();
+ foreach (ITypeDefinition tdd in result.List)
+ {
+ cache.Put(repositoryId, tdd);
+ }
+ }
+
+ return result;
+ }
+
+ public IList<ITypeDefinitionContainer> GetTypeDescendants(string repositoryId, string typeId, long? depth,
+ bool? includePropertyDefinitions, IExtensionsData extension)
+ {
+ IList<ITypeDefinitionContainer> result = null;
+ bool hasExtension = (extension != null) && (extension.Extensions != null) && (extension.Extensions.Count > 0);
+
+ // get the SPI and fetch the type definitions
+ ICmisSpi spi = session.GetSpi();
+ result = spi.GetRepositoryService().GetTypeDescendants(repositoryId, typeId, depth, includePropertyDefinitions,
+ extension);
+
+ // put it into the cache
+ if (!hasExtension && (includePropertyDefinitions ?? false) && (result != null))
+ {
+ TypeDefinitionCache cache = session.GetTypeDefinitionCache();
+ AddToTypeCache(cache, repositoryId, result);
+ }
+
+ return result;
+ }
+
+ private void AddToTypeCache(TypeDefinitionCache cache, string repositoryId, IList<ITypeDefinitionContainer> containers)
+ {
+ if (containers == null)
+ {
+ return;
+ }
+
+ foreach (ITypeDefinitionContainer container in containers)
+ {
+ cache.Put(repositoryId, container.TypeDefinition);
+ AddToTypeCache(cache, repositoryId, container.Children);
+ }
+ }
+
+ public ITypeDefinition GetTypeDefinition(string repositoryId, string typeId, IExtensionsData extension)
+ {
+ ITypeDefinition result = null;
+ bool hasExtension = (extension != null) && (extension.Extensions != null) && (extension.Extensions.Count > 0);
+
+ TypeDefinitionCache cache = session.GetTypeDefinitionCache();
+
+ // 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
+ ICmisSpi spi = session.GetSpi();
+ result = spi.GetRepositoryService().GetTypeDefinition(repositoryId, typeId, extension);
+
+ // put it into the cache
+ if (!hasExtension && (result != null))
+ {
+ cache.Put(repositoryId, result);
+ }
+
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// Object factory implementation.
+ /// </summary>
+ internal class BindingsObjectFactory : IBindingsObjectFactory
+ {
+ }
+
+ /// <summary>
+ /// SPI interface.
+ /// </summary>
+ internal interface ICmisSpi
+ {
+ void initialize(BindingSession session);
+
+ IRepositoryService GetRepositoryService();
+
+ INavigationService GetNavigationService();
+
+ IObjectService GetObjectService();
+
+ IVersioningService GetVersioningService();
+
+ IRelationshipService GetRelationshipService();
+
+ IDiscoveryService GetDiscoveryService();
+
+ IMultiFilingService GetMultiFilingService();
+
+ IAclService GetAclService();
+
+ IPolicyService GetPolicyService();
+
+ void ClearAllCaches();
+
+ void ClearRepositoryCache(string repositoryId);
+
+ void Close();
+ }
+}
Added: incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-intf.cs
URL: http://svn.apache.org/viewvc/incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-intf.cs?rev=1061233&view=auto
==============================================================================
--- incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-intf.cs (added)
+++ incubator/chemistry/dotcmis/trunk/DotCMIS/binding/binding-intf.cs Thu Jan 20 11:38:48 2011
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using DotCMIS.Binding.Services;
+using DotCMIS.Binding.Impl;
+using DotCMIS.CMISWebServicesReference;
+using System.Net;
+
+namespace DotCMIS.Binding
+{
+ public interface ICmisBinding
+ {
+ IRepositoryService GetRepositoryService();
+
+ INavigationService GetNavigationService();
+
+ IObjectService GetObjectService();
+
+ IVersioningService GetVersioningService();
+
+ IRelationshipService GetRelationshipService();
+
+ IDiscoveryService GetDiscoveryService();
+
+ IMultiFilingService GetMultiFilingService();
+
+ IAclService GetAclService();
+
+ IPolicyService GetPolicyService();
+
+ IBindingsObjectFactory GetObjectFactory();
+
+ void ClearAllCaches();
+
+ void ClearRepositoryCache(string repositoryId);
+
+ void Close();
+ }
+
+ public interface IBindingSession
+ {
+ object GetValue(string key);
+
+ object GetValue(string key, object defValue);
+
+ int GetValue(string key, int defValue);
+ }
+
+ public abstract class AbstractAuthenticationProvider
+ {
+ public IBindingSession Session { get; set; }
+
+ public abstract void Authenticate(object connection);
+
+ public string GetUser()
+ {
+ return Session.GetValue(SessionParameter.User) as string;
+ }
+
+ public string GetPassword()
+ {
+ return Session.GetValue(SessionParameter.Password) as string;
+ }
+ }
+
+ public class StandardAuthenticationProvider : AbstractAuthenticationProvider
+ {
+ public override void Authenticate(object connection)
+ {
+ string user = GetUser();
+ string password = GetPassword();
+ if (user == null || password == null)
+ {
+ return;
+ }
+
+ if (connection is RepositoryServicePortClient)
+ {
+ ((RepositoryServicePortClient)connection).ClientCredentials.UserName.UserName = user;
+ ((RepositoryServicePortClient)connection).ClientCredentials.UserName.Password = password;
+ }
+ else if (connection is NavigationServicePortClient)
+ {
+ ((NavigationServicePortClient)connection).ClientCredentials.UserName.UserName = user;
+ ((NavigationServicePortClient)connection).ClientCredentials.UserName.Password = password;
+ }
+ else if (connection is ObjectServicePortClient)
+ {
+ ((ObjectServicePortClient)connection).ClientCredentials.UserName.UserName = user;
+ ((ObjectServicePortClient)connection).ClientCredentials.UserName.Password = password;
+ }
+ else if (connection is VersioningServicePortClient)
+ {
+ ((VersioningServicePortClient)connection).ClientCredentials.UserName.UserName = user;
+ ((VersioningServicePortClient)connection).ClientCredentials.UserName.Password = password;
+ }
+ else if (connection is DiscoveryServicePortClient)
+ {
+ ((DiscoveryServicePortClient)connection).ClientCredentials.UserName.UserName = user;
+ ((DiscoveryServicePortClient)connection).ClientCredentials.UserName.Password = password;
+ }
+ else if (connection is RelationshipServicePortClient)
+ {
+ ((RelationshipServicePortClient)connection).ClientCredentials.UserName.UserName = user;
+ ((RelationshipServicePortClient)connection).ClientCredentials.UserName.Password = password;
+ }
+ else if (connection is MultiFilingServicePortClient)
+ {
+ ((MultiFilingServicePortClient)connection).ClientCredentials.UserName.UserName = user;
+ ((MultiFilingServicePortClient)connection).ClientCredentials.UserName.Password = password;
+ }
+ else if (connection is PolicyServicePortClient)
+ {
+ ((PolicyServicePortClient)connection).ClientCredentials.UserName.UserName = user;
+ ((PolicyServicePortClient)connection).ClientCredentials.UserName.Password = password;
+ }
+ else if (connection is ACLServicePortClient)
+ {
+ ((ACLServicePortClient)connection).ClientCredentials.UserName.UserName = user;
+ ((ACLServicePortClient)connection).ClientCredentials.UserName.Password = password;
+ }
+ else if (connection is WebRequest)
+ {
+ ((WebRequest)connection).Credentials = new NetworkCredential(user, password);
+ }
+ }
+ }
+
+
+ public interface IBindingsObjectFactory
+ {
+ }
+
+ public class CmisBindingFactory
+ {
+ // Default CMIS AtomPub binding SPI implementation
+ public const string BindingSpiAtomPub = "DotCMIS.Binding.AtomPub.CmisAtomPubSpi";
+ // Default CMIS Web Services binding SPI implementation
+ public const string BindingSpiWebServices = "DotCMIS.Binding.WebServices.CmisWebServicesSpi";
+
+ public const string StandardAuthenticationProviderClass = "DotCMIS.Binding.StandardAuthenticationProvider";
+
+ private IDictionary<string, string> defaults;
+
+ private CmisBindingFactory()
+ {
+ defaults = CreateNewDefaultParameters();
+ }
+
+ public static CmisBindingFactory NewInstance()
+ {
+ return new CmisBindingFactory();
+ }
+
+ public IDictionary<string, string> GetDefaultSessionParameters()
+ {
+ return defaults;
+ }
+
+ public void SetDefaultSessionParameters(IDictionary<string, string> sessionParameters)
+ {
+ if (sessionParameters == null)
+ {
+ defaults = CreateNewDefaultParameters();
+ }
+ else
+ {
+ defaults = sessionParameters;
+ }
+ }
+
+ public ICmisBinding CreateCmisBinding(IDictionary<string, string> sessionParameters)
+ {
+ CheckSessionParameters(sessionParameters, true);
+ AddDefaultParameters(sessionParameters);
+
+ return new CmisBinding(sessionParameters);
+ }
+
+ public ICmisBinding CreateCmisAtomPubBinding(IDictionary<string, string> sessionParameters)
+ {
+ CheckSessionParameters(sessionParameters, false);
+ sessionParameters[SessionParameter.BindingSpiClass] = BindingSpiAtomPub;
+ if (!sessionParameters.ContainsKey(SessionParameter.AuthenticationProviderClass))
+ {
+ sessionParameters[SessionParameter.AuthenticationProviderClass] = StandardAuthenticationProviderClass;
+ }
+
+ AddDefaultParameters(sessionParameters);
+
+ Check(sessionParameters, SessionParameter.AtomPubUrl);
+
+ return new CmisBinding(sessionParameters);
+ }
+
+ public ICmisBinding CreateCmisWebServicesBinding(IDictionary<string, string> sessionParameters)
+ {
+ CheckSessionParameters(sessionParameters, false);
+ sessionParameters[SessionParameter.BindingSpiClass] = BindingSpiWebServices;
+ if (!sessionParameters.ContainsKey(SessionParameter.AuthenticationProviderClass))
+ {
+ sessionParameters[SessionParameter.AuthenticationProviderClass] = StandardAuthenticationProviderClass;
+ }
+
+ AddDefaultParameters(sessionParameters);
+
+ Check(sessionParameters, SessionParameter.WebServicesAclService);
+ Check(sessionParameters, SessionParameter.WebServicesDiscoveryService);
+ Check(sessionParameters, SessionParameter.WebServicesMultifilingService);
+ Check(sessionParameters, SessionParameter.WebServicesNavigationService);
+ Check(sessionParameters, SessionParameter.WebServicesObjectService);
+ Check(sessionParameters, SessionParameter.WebServicesPolicyService);
+ Check(sessionParameters, SessionParameter.WebServicesRelationshipService);
+ Check(sessionParameters, SessionParameter.WebServicesRepositoryService);
+ Check(sessionParameters, SessionParameter.WebServicesVersioningService);
+
+ return new CmisBinding(sessionParameters);
+ }
+
+ // ---- internals ----
+
+ private void CheckSessionParameters(IDictionary<string, string> sessionParameters, bool mustContainSpi)
+ {
+ // don't accept null
+ if (sessionParameters == null)
+ {
+ throw new ArgumentNullException("sessionParameters");
+ }
+
+ // check binding entry
+ if (mustContainSpi)
+ {
+ string spiClass;
+
+ if (sessionParameters.TryGetValue(SessionParameter.BindingSpiClass, out spiClass))
+ {
+ throw new ArgumentException("SPI class entry (" + SessionParameter.BindingSpiClass + ") is missing!");
+ }
+
+ if ((spiClass == null) || (spiClass.Trim().Length == 0))
+ {
+ throw new ArgumentException("SPI class entry (" + SessionParameter.BindingSpiClass + ") is invalid!");
+ }
+ }
+ }
+
+ private void Check(IDictionary<string, string> sessionParameters, String parameter)
+ {
+ if (!sessionParameters.ContainsKey(parameter))
+ {
+ throw new ArgumentException("Parameter '" + parameter + "' is missing!");
+ }
+ }
+
+ private void AddDefaultParameters(IDictionary<string, string> sessionParameters)
+ {
+ foreach (string key in defaults.Keys)
+ {
+ if (!sessionParameters.ContainsKey(key))
+ {
+ sessionParameters[key] = defaults[key];
+ }
+ }
+ }
+
+ private IDictionary<string, string> CreateNewDefaultParameters()
+ {
+ IDictionary<string, string> result = new Dictionary<string, string>();
+
+ result[SessionParameter.CacheSizeRepositories] = "10";
+ result[SessionParameter.CacheSizeTypes] = "100";
+ result[SessionParameter.CacheSizeLinks] = "400";
+
+ return result;
+ }
+ }
+}