You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@clerezza.apache.org by re...@apache.org on 2010/09/10 22:36:59 UTC

svn commit: r995973 - in /incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access: TcManager.java TcProviderMultiplexer.java WeightedProviderComparator.java

Author: reto
Date: Fri Sep 10 20:36:58 2010
New Revision: 995973

URL: http://svn.apache.org/viewvc?rev=995973&view=rev
Log:
CLEREZZA-286: extracted WeightedTcProvider aggregation from TcManager

Added:
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcProviderMultiplexer.java
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/WeightedProviderComparator.java
Modified:
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcManager.java

Modified: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcManager.java
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcManager.java?rev=995973&r1=995972&r2=995973&view=diff
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcManager.java (original)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcManager.java Fri Sep 10 20:36:58 2010
@@ -21,10 +21,9 @@ package org.apache.clerezza.rdf.core.acc
 import org.apache.clerezza.rdf.core.impl.WriteBlockedMGraph;
 import org.apache.clerezza.rdf.core.impl.WriteBlockedTripleCollection;
 
-import java.lang.ref.WeakReference;
 import java.security.AccessControlException;
+import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -33,8 +32,6 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.ServiceLoader;
 import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
 
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentContext;
@@ -85,22 +82,14 @@ import org.apache.felix.scr.annotations.
 @Reference(name="weightedTcProvider", policy=ReferencePolicy.DYNAMIC,
 		referenceInterface=WeightedTcProvider.class,
 		cardinality=ReferenceCardinality.MANDATORY_MULTIPLE)
-public class TcManager implements TcProvider {
+public class TcManager extends TcProviderMultiplexer {
 
-	private SortedSet<WeightedTcProvider> providerList = new TreeSet<WeightedTcProvider>(
-			new WeightedProviderComparator());
 	private static volatile TcManager instance;
 
 	private TcAccessController tcAccessController = new TcAccessController(this);
 
-	/**
-	 * Mapping to LockableMGraph's and ServiceRegistration using their URI's as key.
-	 * Makes sure that per URI only one instance of the LockableMGraph is used,
-	 * otherwise the locks in the <code>LockableMGraph</code>s would have no effect
-	 * between different instances and concurrency issues could occur.
-	 */
-	private Map<UriRef, GraphHolder> synchronizedLockableMGraphCache = Collections
-			.synchronizedMap(new HashMap<UriRef, GraphHolder>());
+	private Map<UriRef, ServiceRegistration> serviceRegistrations = Collections
+			.synchronizedMap(new HashMap<UriRef, ServiceRegistration>());
 
 
 	@Reference(policy=ReferencePolicy.DYNAMIC,
@@ -108,13 +97,9 @@ public class TcManager implements TcProv
 	protected QueryEngine queryEngine;
 
 	private ComponentContext componentContext;
+	private Collection<UriRef> mGraphsToRegisterOnActivation = new HashSet<UriRef>();
+	private Collection<UriRef> graphsToRegisterOnActivation = new HashSet<UriRef>();
 
-	/*
-	 * A store that keeps <code>WeightedTcProvider</code>S in case the
-	 * componentContext is null. Used in activate().
-	 */
-	private final Set<WeightedTcProvider> providerStore =
-			Collections.synchronizedSet(new HashSet<WeightedTcProvider>());
 
 	/**
 	 * the constructor sets the singleton instance to allow instantiation by
@@ -162,189 +147,26 @@ public class TcManager implements TcProv
 
 	protected void activate(final ComponentContext componentContext) {
 		this.componentContext = componentContext;
-		synchronized(providerStore) {
-			Iterator<WeightedTcProvider> it = providerStore.iterator();
-			while (it.hasNext()) {
-				WeightedTcProvider provider = it.next();
-				updateLockableMGraphCache(provider, true);
-			}
-		}
-		providerStore.clear();
-	}
-
-	protected void deactivate(final ComponentContext componentContext) {
-		this.componentContext = null;
-	}
-
-	/**
-	 * Registers a provider
-	 * 
-	 * @param provider
-	 *            the provider to be registered
-	 */
-	protected void bindWeightedTcProvider(WeightedTcProvider provider) {
-		providerList.add(provider);
-		if (componentContext != null) {
-			updateLockableMGraphCache(provider, true);
-		}  else {
-			providerStore.add(provider);
-		}
-	}
-
-	/**
-	 * Unregister a provider
-	 * 
-	 * @param provider
-	 *            the provider to be deregistered
-	 */
-	protected void unbindWeightedTcProvider(
-			WeightedTcProvider provider) {
-		providerList.remove(provider);
-		providerStore.remove(provider);
-		updateLockableMGraphCache(provider, false);
-	}
-
-	/**
-	 * Updates the lockableMGraphCache AFTER a new <code>provider</code> was
-	 * bound or unbound.
-	 * This method also takes care of registering and unregistering
-	 * provided triple collections as services based on the weight of
-	 * all affected providers.
-	 * 
-	 * @param provider
-	 *            the provider that was added or removed
-	 * @param providerAdded
-	 *            <code>boolean</code> that should be set as <code>true</code>
-	 *            if <code>provider</code> was added to
-	 *            <code>org.apache.clerezza.rdf.core.TcManager.providerList</code>
-	 *            otherwise <code>false</code>
-	 */
-	private void updateLockableMGraphCache(WeightedTcProvider provider,
-			boolean providerAdded) {
-		Set<UriRef> uriSet = provider.listTripleCollections();
-		if (!(uriSet == null || uriSet.isEmpty())) {
-			if (providerAdded) {
-				weightedProviderAdded(provider, uriSet);
-			} else {
-				weightedProviderRemoved(provider, uriSet);
-			}
-		}
-	}
-
-	private void weightedProviderAdded(WeightedTcProvider newProvider,
-			Set<UriRef> newProvidedUris) {
-		Set<WeightedTcProvider> lowerWeightedProviderList = getLowerWeightedProvider(newProvider);
-		for (UriRef name : newProvidedUris) {
-			final GraphHolder holder = synchronizedLockableMGraphCache
-					.get(name);
-			if ((holder != null) && (holder.getWeightedTcProvider() != null)) {
-				if (lowerWeightedProviderList.contains(holder
-							.getWeightedTcProvider())) {
-					unregisterService(name);
-					synchronizedLockableMGraphCache.remove(name);
-				} else {
-					continue;
-				}
-			}
-			ServiceRegistration serviceReg = registerAsService(name,
-					newProvider.getTriples(name));
-			if (serviceReg != null) {
-				synchronizedLockableMGraphCache.put(name,
-						new GraphHolder(newProvider, null, serviceReg));
-			}
-		}
-	}
-
-	private void unregisterService(UriRef name) {
-		GraphHolder entry = synchronizedLockableMGraphCache.get(name);
-		if (entry != null) {
-			ServiceRegistration reg = entry.getServiceRegistration();
-			if (reg != null) {
-				reg.unregister();
-			}
-		}
-	}
-
-	private ServiceRegistration registerAsService(UriRef name,
-			TripleCollection triples) {
-		if (componentContext == null) {
-			return null;
+		for (UriRef name : mGraphsToRegisterOnActivation) {
+			registerMGraphAsService(name);
 		}
-		Dictionary props = new Properties();
-		props.put("name", name.getUnicodeString());
-		String[] interfaceNames;
-		Object service;
-		if (triples instanceof MGraph) {
-			interfaceNames = new String[]{
-				MGraph.class.getName(),
-				LockableMGraph.class.getName()
-			};
-			service = new MGraphServiceFactory(this, name, tcAccessController);
-		} else if (triples instanceof Graph) {
-			interfaceNames = new String[]{Graph.class.getName()};
-			service = new GraphServiceFactory(this, name, tcAccessController);
-		} else {
-			return null;
+		for (UriRef name : graphsToRegisterOnActivation) {
+			registerGraphAsService(name);
 		}
-		return componentContext.getBundleContext().registerService(
-				interfaceNames, service, props);
 	}
 
-
-	private Set<WeightedTcProvider> getLowerWeightedProvider(
-			WeightedTcProvider newProvider) {
-		boolean referenceProviderPassed = false;
-		Set<WeightedTcProvider> lowerWeightedProviderList = new HashSet<WeightedTcProvider>();
-		for (WeightedTcProvider weightedProvider : providerList) {
-			if (referenceProviderPassed) {
-				lowerWeightedProviderList.add(weightedProvider);
-			} else if (newProvider.equals(weightedProvider)) {
-				referenceProviderPassed = true;
-			}
-		}
-		return lowerWeightedProviderList;
-	}
-
-	private void weightedProviderRemoved(WeightedTcProvider oldProvider,
-			Set<UriRef> oldProvidedUris) {
-		for (UriRef name : oldProvidedUris) {
-			final GraphHolder holder = synchronizedLockableMGraphCache
-					.get(name);
-			if ((holder != null) && (holder.getWeightedTcProvider() != null)
-					&& holder.getWeightedTcProvider().equals(oldProvider)) {
-				unregisterService(name);
-				synchronizedLockableMGraphCache.remove(name);
-				
-				// check if another WeightedTcProvider has the TripleCollection.
-				// And if so register as service.
-				for (WeightedTcProvider provider : providerList) {
-					try {
-						TripleCollection triples = provider.getTriples(name);
-						synchronizedLockableMGraphCache.put(name, new GraphHolder(
-								provider, null, registerAsService(name, triples)));
-						break;
-					} catch (NoSuchEntityException e) {
-						// continue;
-					}
-				}
-
-			}
+	protected void deactivate(final ComponentContext componentContext) {
+		for (ServiceRegistration registration : serviceRegistrations.values()) {
+			registration.unregister();
 		}
+		serviceRegistrations.clear();
+		this.componentContext = null;
 	}
 
 	@Override
 	public Graph getGraph(UriRef name) throws NoSuchEntityException {
 		tcAccessController.checkReadPermission(name);
-		for (TcProvider provider : providerList) {
-			try {
-				return provider.getGraph(name);
-			} catch (NoSuchEntityException e) {
-				//we do nothing and try our luck with the next provider
-			} catch (IllegalArgumentException e) {
-				//we do nothing and try our luck with the next provider
-			}
-		}
-		throw new NoSuchEntityException(name);
+		return super.getGraph(name);
 	}
 
 	@Override
@@ -353,60 +175,9 @@ public class TcManager implements TcProv
 			tcAccessController.checkReadWritePermission(name);
 		} catch (AccessControlException e) {
 			tcAccessController.checkReadPermission(name);
-			return new WriteBlockedMGraph(getUnsecuredMGraph(name));
-		}
-		return getUnsecuredMGraph(name);
-	}
-
-	private LockableMGraph getUnsecuredMGraph(UriRef name)
-			throws NoSuchEntityException {
-		LockableMGraph result = getMGraphFromCache(name);
-		if (result == null) {
-			synchronized (this) {
-				result = getMGraphFromCache(name);
-				if (result == null) {
-					result = getUnsecuredMGraphAndAddToCache(name);
-				}
-			}
-		}
-		return result;
-	}
-
-	private LockableMGraph getMGraphFromCache(UriRef name) {
-		GraphHolder holder = synchronizedLockableMGraphCache.get(name);
-		if (holder == null) {
-			return null;
+			return new WriteBlockedMGraph(super.getMGraph(name));
 		}
-		return holder.getMGraph();
-	}
-
-	private LockableMGraph getUnsecuredMGraphAndAddToCache(UriRef name)
-			throws NoSuchEntityException {
-		for (WeightedTcProvider provider : providerList) {
-			try {
-				MGraph providedMGraph = provider.getMGraph(name);
-				LockableMGraph result;
-				if (providedMGraph instanceof LockableMGraph) {
-					result = (LockableMGraph) providedMGraph;
-				} else {
-					result = new LockableMGraphWrapper(providedMGraph);
-				}
-				
-				GraphHolder holder = synchronizedLockableMGraphCache.get(name);
-				ServiceRegistration serviceReg = null;
-				if (holder != null) {
-					serviceReg = holder.getServiceRegistration();
-				}
-				synchronizedLockableMGraphCache.put(name, new GraphHolder(
-						provider, result, serviceReg));
-				return result;
-			} catch (NoSuchEntityException e) {
-				//we do nothing and try our luck with the next provider
-			} catch (IllegalArgumentException e) {
-				//we do nothing and try our luck with the next provider
-			}
-		}
-		throw new NoSuchEntityException(name);
+		return super.getMGraph(name);
 	}
 
 	@Override
@@ -416,152 +187,52 @@ public class TcManager implements TcProv
 		} catch (AccessControlException e) {
 			tcAccessController.checkReadPermission(name);
 			return new WriteBlockedTripleCollection(
-					getUnsecuredTriples(name));
+					super.getTriples(name));
 		}
-		return getUnsecuredTriples(name);
+		return super.getTriples(name);
 	}
 
-	private TripleCollection getUnsecuredTriples(UriRef name)
-			throws NoSuchEntityException {
-		TripleCollection result;
-		for (WeightedTcProvider provider : providerList) {
-			try {
-				result = provider.getTriples(name);
-				if (!(result instanceof MGraph)) {
-					return result;
-				} else {
-					// This is to ensure the MGraph gets added to the cache
-					return getUnsecuredMGraph(name);
-				}
-			} catch (NoSuchEntityException e) {
-				//we do nothing and try our luck with the next provider
-			} catch (IllegalArgumentException e) {
-				//we do nothing and try our luck with the next provider
-			}
-		}
-		throw new NoSuchEntityException(name);
-	}
+	
 
 	@Override
 	public LockableMGraph createMGraph(UriRef name)
 			throws UnsupportedOperationException {
 		tcAccessController.checkReadWritePermission(name);
-		for (WeightedTcProvider provider : providerList) {
-			try {
-				MGraph providedMGraph = provider.createMGraph(name);
-				LockableMGraph result;
-				if (providedMGraph instanceof LockableMGraph) {
-					result = (LockableMGraph) providedMGraph;
-				} else {
-					result = new LockableMGraphWrapper(providedMGraph);
-				}
-
-				// unregisters a possible Graph or MGraph service under this name
-				// provided by a WeightedTcProvider with a lower weight.
-				unregisterService(name);
-			    
-				ServiceRegistration newReg = registerAsService(name, result);
-				synchronizedLockableMGraphCache.put(name, new GraphHolder(
-						provider, result, newReg));
-				return result;
-			} catch (UnsupportedOperationException e) {
-				//we do nothing and try our luck with the next provider
-			} catch (IllegalArgumentException e) {
-				//we do nothing and try our luck with the next provider
-			}
-		}
-		throw new UnsupportedOperationException(
-				"No provider could create MGraph.");
+		return super.createMGraph(name);
 	}
 
 	@Override
 	public Graph createGraph(UriRef name, TripleCollection triples) {
 		tcAccessController.checkReadWritePermission(name);
-		for (WeightedTcProvider provider : providerList) {
-			try {
-				Graph result = provider.createGraph(name, triples);
-
-				// unregisters a possible Graph or MGraph service under this name
-				// provided by a WeightedTcProvider with a lower weight.
-				unregisterService(name);
-			    
-				ServiceRegistration newReg = registerAsService(name, result);
-				synchronizedLockableMGraphCache.put(name, new GraphHolder(
-						provider, null, newReg));
-				return result;
-			} catch (UnsupportedOperationException e) {
-				//we do nothing and try our luck with the next provider
-			} catch (IllegalArgumentException e) {
-				//we do nothing and try our luck with the next provider
-			}
-		}
-		throw new UnsupportedOperationException(
-				"No provider could create Graph.");
+		return super.createGraph(name, triples);
 	}
 
 	@Override
 	public void deleteTripleCollection(UriRef name) {
 		tcAccessController.checkReadWritePermission(name);
-		for (TcProvider provider : providerList) {
-			try {
-				provider.deleteTripleCollection(name);
-				final GraphHolder holder = synchronizedLockableMGraphCache
-						.get(name);
-				if ((holder != null)
-						&& (holder.getWeightedTcProvider() != null)
-						&& holder.getWeightedTcProvider().equals(provider)) {
-					unregisterService(name);
-					synchronizedLockableMGraphCache.remove(name);
-				}
-				return;
-			} catch (UnsupportedOperationException e) {
-				// we do nothing and try our luck with the next provider
-			} catch (NoSuchEntityException e) {
-				//we do nothing and try our luck with the next provider
-			} catch (IllegalArgumentException e) {
-				//we do nothing and try our luck with the next provider
-			}
-		}
-		// this throws a NoSuchEntityException if the graph doesn't exist
-		getTriples(name);
-		// the entity exists but cannot be deleted
-		throw new UnsupportedOperationException(
-				"No provider could delete the entity.");
+		super.deleteTripleCollection(name);
 	}
 
 	@Override
 	public Set<UriRef> getNames(Graph graph) {
-		Set<UriRef> result = new HashSet<UriRef>();
-		for (TcProvider provider : providerList) {
-			result.addAll(provider.getNames(graph));
-		}
-		return result;
+		return super.getNames(graph);
 	}
 
 	@Override
 	public Set<UriRef> listGraphs() {
-		Set<UriRef> result = new HashSet<UriRef>();
-		for (TcProvider provider : providerList) {
-			result.addAll(provider.listGraphs());
-		}
+		Set<UriRef> result = super.listGraphs();
 		return excludeNonReadable(result);
 	}
 
 	@Override
 	public Set<UriRef> listMGraphs() {
-		Set<UriRef> result = new HashSet<UriRef>();
-		for (TcProvider provider : providerList) {
-			result.addAll(provider.listMGraphs());
-		}
+		Set<UriRef> result = super.listMGraphs();
 		return excludeNonReadable(result);
 	}
 
 	@Override
 	public Set<UriRef> listTripleCollections() {
-		Set<UriRef> result = new HashSet<UriRef>();
-		for (TcProvider provider : providerList) {
-			result.addAll(provider.listTripleCollections());
-		}
+		Set<UriRef> result = super.listTripleCollections();
 		return excludeNonReadable(result);
 	}
 
@@ -583,24 +254,6 @@ public class TcManager implements TcProv
 	}
 
 	/**
-	 * Compares the WeightedTcManagementProviders, descending for weight and
-	 * ascending by name
-	 */
-	static class WeightedProviderComparator implements
-			Comparator<WeightedTcProvider> {
-
-		@Override
-		public int compare(WeightedTcProvider o1, WeightedTcProvider o2) {
-			int o1Weight = o1.getWeight();
-			int o2Weight = o2.getWeight();
-			if (o1Weight != o2Weight) {
-				return o2Weight - o1Weight;
-			}
-			return o1.getClass().toString().compareTo(o2.getClass().toString());
-		}
-	}
-
-	/**
 	 * Executes any sparql query. The type of the result object will vary
 	 * depending on the type of the query.
 	 * 
@@ -709,33 +362,79 @@ public class TcManager implements TcProv
 	}
 
 	/**
-	 * Contains an unsecured LockableMGraph, a ServiceRegistration and
-	 * the WeightedTcProvider that generated the graph
+	 * Registers a provider
+	 *
+	 * @param provider
+	 *            the provider to be registered
 	 */
-	private static class GraphHolder {
-		private WeightedTcProvider tcProvider;
-		private WeakReference<LockableMGraph> mGraphReference;
-		private ServiceRegistration serviceReg;
+	protected void bindWeightedTcProvider(WeightedTcProvider provider) {
+		addWeightedTcProvider(provider);
+	}
 
-		private GraphHolder(WeightedTcProvider tcProvider, LockableMGraph mGraph,
-				ServiceRegistration serviceReg) {
-			this.tcProvider = tcProvider;
-			this.mGraphReference = new WeakReference<LockableMGraph>(mGraph);
-			this.serviceReg = serviceReg;
-		}
+	/**
+	 * Unregister a provider
+	 *
+	 * @param provider
+	 *            the provider to be deregistered
+	 */
+	protected void unbindWeightedTcProvider(
+			WeightedTcProvider provider) {
+		removeWeightedTcProvider(provider);
+	}
 
-		private LockableMGraph getMGraph() {
-			return this.mGraphReference.get();
+	@Override
+	protected void mGraphAppears(UriRef name) {
+		if (componentContext == null) {
+			mGraphsToRegisterOnActivation.add(name);
+		} else {
+			registerMGraphAsService(name);
 		}
+	}
 
-		private WeightedTcProvider getWeightedTcProvider() {
-			return this.tcProvider;
+	@Override
+	protected void graphAppears(UriRef name) {
+		if (componentContext == null) {
+			graphsToRegisterOnActivation.add(name);
+		} else {
+			registerGraphAsService(name);
 		}
+	}
 
-		private ServiceRegistration getServiceRegistration() {
-			return serviceReg;
-		}
+	private void registerMGraphAsService(UriRef name) {
+		
+		Dictionary props = new Properties();
+		props.put("name", name.getUnicodeString());
+		String[] interfaceNames;
+		final TripleCollection triples = getTriples(name);
+		interfaceNames = new String[]{
+			MGraph.class.getName(),
+			LockableMGraph.class.getName()
+		};
+		Object service = new MGraphServiceFactory(this, name, tcAccessController);
+		ServiceRegistration serviceReg = componentContext.getBundleContext().registerService(
+				interfaceNames, service, props);
+		serviceRegistrations.put(name, serviceReg);
+	}
+
+	private void registerGraphAsService(UriRef name) {
+		Dictionary props = new Properties();
+		props.put("name", name.getUnicodeString());
+		String[] interfaceNames;
+		interfaceNames = new String[]{Graph.class.getName()};
+		Object service = new GraphServiceFactory(this, name, tcAccessController);
 
+		ServiceRegistration serviceReg = componentContext.getBundleContext().registerService(
+				interfaceNames, service, props);
+		serviceRegistrations.put(name, serviceReg);
 	}
 
+	@Override
+	protected void tcDisappears(UriRef name) {
+		mGraphsToRegisterOnActivation.remove(name);
+		graphsToRegisterOnActivation.remove(name);
+		ServiceRegistration reg = serviceRegistrations.get(name);
+		if (reg != null) {
+			reg.unregister();
+		}
+	}
 }

Added: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcProviderMultiplexer.java
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcProviderMultiplexer.java?rev=995973&view=auto
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcProviderMultiplexer.java (added)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/TcProviderMultiplexer.java Fri Sep 10 20:36:58 2010
@@ -0,0 +1,444 @@
+/*
+ * 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.clerezza.rdf.core.access;
+
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.TripleCollection;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.sparql.QueryEngine;
+
+/**
+ * This makes a set of WeightedTcProvider appear as one TcProvider. It delegates
+ * requests to the WeightedTcProvider with the highest Weight
+ *
+ * @author reto
+ */
+public class TcProviderMultiplexer implements TcProvider {
+
+	private SortedSet<WeightedTcProvider> providerList = new TreeSet<WeightedTcProvider>(
+			new WeightedProviderComparator());
+	/**
+	 * Mapping to LockableMGraph's and ServiceRegistration using their URI's as key.
+	 * Makes sure that per URI only one instance of the LockableMGraph is used,
+	 * otherwise the locks in the <code>LockableMGraph</code>s would have no effect
+	 * between different instances and concurrency issues could occur.
+	 */
+	private Map<UriRef, MGraphHolder> mGraphCache = Collections.synchronizedMap(new HashMap<UriRef, MGraphHolder>());
+
+	/**
+	 * Registers a provider
+	 *
+	 * @param provider
+	 *            the provider to be registered
+	 */
+	public void addWeightedTcProvider(WeightedTcProvider provider) {
+		providerList.add(provider);
+		updateLockableMGraphCache(provider, true);
+	}
+
+	/**
+	 * Unregister a provider
+	 *
+	 * @param provider
+	 *            the provider to be deregistered
+	 */
+	public void removeWeightedTcProvider(
+			WeightedTcProvider provider) {
+		providerList.remove(provider);
+		updateLockableMGraphCache(provider, false);
+	}
+
+	/**
+	 * subclasses overwrite this method to be notified when a new
+	 * Graph is available (either because it has been created or being
+	 * provided by a newly added WeightedTcProvider). The default implementation
+	 * does nothing.
+	 *
+	 * @param name
+	 */
+	protected void graphAppears(UriRef name) {
+	}
+
+	/**
+	 * subclasses overwrite this method to be notified when a new
+	 * MGraph is available (either because it has been created or being
+	 * provided by a newly added WeightedTcProvider). The default implementation
+	 * does nothing.
+	 *
+	 * @param name
+	 */
+	protected void mGraphAppears(UriRef name) {
+	}
+
+	/**
+	 * subclasses overwrite this method to be notified whenTripleCollection is 
+	 * no longer available (either because it has been deleted or bacause its
+	 * WeightedTcProvider was removed). The default implementation does nothing.
+	 *
+	 * for implementational reasons even for name of TripleCollection not
+	 * previously registered.
+	 *
+	 * @param name
+	 */
+	protected void tcDisappears(UriRef name) {
+	}
+
+	/**
+	 * Updates the lockableMGraphCache AFTER a new <code>provider</code> was
+	 * bound or unbound.
+	 * This method also takes care of registering and unregistering
+	 * provided triple collections as services based on the weight of
+	 * all affected providers.
+	 *
+	 * @param provider
+	 *            the provider that was added or removed
+	 * @param providerAdded
+	 *            <code>boolean</code> that should be set as <code>true</code>
+	 *            if <code>provider</code> was added to
+	 *            <code>org.apache.clerezza.rdf.core.TcManager.providerList</code>
+	 *            otherwise <code>false</code>
+	 */
+	private void updateLockableMGraphCache(WeightedTcProvider provider,
+			boolean providerAdded) {
+		Set<UriRef> uriSet = provider.listTripleCollections();
+		if (!(uriSet == null || uriSet.isEmpty())) {
+			if (providerAdded) {
+				weightedProviderAdded(provider, uriSet);
+			} else {
+				weightedProviderRemoved(provider, uriSet);
+			}
+		}
+	}
+
+	private void weightedProviderAdded(WeightedTcProvider newProvider,
+			Set<UriRef> newProvidedUris) {
+		Set<WeightedTcProvider> lowerWeightedProviderList = getLowerWeightedProvider(newProvider);
+		for (UriRef name : newProvidedUris) {
+			final MGraphHolder holder = mGraphCache.get(name);
+			if ((holder != null) && (holder.getWeightedTcProvider() != null)) {
+				if (lowerWeightedProviderList.contains(holder.getWeightedTcProvider())) {
+					tcDisappears(name);
+					mGraphCache.remove(name);
+				} else {
+					continue;
+				}
+			}
+			TripleCollection triples = newProvider.getTriples(name);
+			if (triples instanceof MGraph) {
+				mGraphCache.put(name, new MGraphHolder(newProvider, ensureLockable((MGraph)triples)));
+				mGraphAppears(name);
+			} else {
+				graphAppears(name);
+			}
+
+		}
+	}
+
+	
+
+	private Set<WeightedTcProvider> getLowerWeightedProvider(
+			WeightedTcProvider newProvider) {
+		boolean referenceProviderPassed = false;
+		Set<WeightedTcProvider> lowerWeightedProviderList = new HashSet<WeightedTcProvider>();
+		for (WeightedTcProvider weightedProvider : providerList) {
+			if (referenceProviderPassed) {
+				lowerWeightedProviderList.add(weightedProvider);
+			} else if (newProvider.equals(weightedProvider)) {
+				referenceProviderPassed = true;
+			}
+		}
+		return lowerWeightedProviderList;
+	}
+
+	private void weightedProviderRemoved(WeightedTcProvider oldProvider,
+			Set<UriRef> oldProvidedUris) {
+		for (UriRef name : oldProvidedUris) {
+			final MGraphHolder holder = mGraphCache.get(name);
+			if ((holder != null) && (holder.getWeightedTcProvider() != null)
+					&& holder.getWeightedTcProvider().equals(oldProvider)) {
+				tcDisappears(name);
+				mGraphCache.remove(name);
+
+				// check if another WeightedTcProvider has the TripleCollection.
+				// And if so register as service.
+				for (WeightedTcProvider provider : providerList) {
+					try {
+						TripleCollection triples = provider.getTriples(name);
+						if (triples instanceof MGraph) {
+							mGraphCache.put(name, new MGraphHolder(provider, ensureLockable((MGraph)triples)));
+							mGraphAppears(name);
+						} else {
+							graphAppears(name);
+						}
+						break;
+					} catch (NoSuchEntityException e) {
+						// continue;
+					}
+				}
+
+			}
+		}
+	}
+
+	@Override
+	public Graph getGraph(UriRef name) throws NoSuchEntityException {
+		for (TcProvider provider : providerList) {
+			try {
+				return provider.getGraph(name);
+			} catch (NoSuchEntityException e) {
+				//we do nothing and try our luck with the next provider
+			} catch (IllegalArgumentException e) {
+				//we do nothing and try our luck with the next provider
+			}
+		}
+		throw new NoSuchEntityException(name);
+	}
+
+	@Override
+	public LockableMGraph getMGraph(UriRef name)
+			throws NoSuchEntityException {
+		LockableMGraph result = getMGraphFromCache(name);
+		if (result == null) {
+			synchronized (this) {
+				result = getMGraphFromCache(name);
+				if (result == null) {
+					result = getUnsecuredMGraphAndAddToCache(name);
+				}
+			}
+		}
+		return result;
+	}
+
+	private LockableMGraph getMGraphFromCache(UriRef name) {
+		MGraphHolder holder = mGraphCache.get(name);
+		if (holder == null) {
+			return null;
+		}
+		return holder.getMGraph();
+	}
+
+	private LockableMGraph getUnsecuredMGraphAndAddToCache(UriRef name)
+			throws NoSuchEntityException {
+		for (WeightedTcProvider provider : providerList) {
+			try {
+				MGraph providedMGraph = provider.getMGraph(name);
+				LockableMGraph result = ensureLockable(providedMGraph);
+
+				MGraphHolder holder = mGraphCache.get(name);
+				mGraphCache.put(name, new MGraphHolder(
+						provider, result));
+				return result;
+			} catch (NoSuchEntityException e) {
+				//we do nothing and try our luck with the next provider
+			} catch (IllegalArgumentException e) {
+				//we do nothing and try our luck with the next provider
+			}
+		}
+		throw new NoSuchEntityException(name);
+	}
+
+	@Override
+	public TripleCollection getTriples(UriRef name)
+			throws NoSuchEntityException {
+		TripleCollection result;
+		for (WeightedTcProvider provider : providerList) {
+			try {
+				result = provider.getTriples(name);
+				if (!(result instanceof MGraph)) {
+					return result;
+				} else {
+					// This is to ensure the MGraph gets added to the cache
+					return getMGraph(name);
+				}
+			} catch (NoSuchEntityException e) {
+				//we do nothing and try our luck with the next provider
+			} catch (IllegalArgumentException e) {
+				//we do nothing and try our luck with the next provider
+			}
+		}
+		throw new NoSuchEntityException(name);
+	}
+
+	@Override
+	public LockableMGraph createMGraph(UriRef name)
+			throws UnsupportedOperationException {
+
+		for (WeightedTcProvider provider : providerList) {
+			try {
+				MGraph providedMGraph = provider.createMGraph(name);
+				LockableMGraph result;
+				if (providedMGraph instanceof LockableMGraph) {
+					result = (LockableMGraph) providedMGraph;
+				} else {
+					result = new LockableMGraphWrapper(providedMGraph);
+				}
+
+				// unregisters a possible Graph or MGraph service under this name
+				// provided by a WeightedTcProvider with a lower weight.
+				tcDisappears(name);
+				mGraphCache.put(name, new MGraphHolder(provider, null));
+				mGraphAppears(name);
+				return result;
+			} catch (UnsupportedOperationException e) {
+				//we do nothing and try our luck with the next provider
+			} catch (IllegalArgumentException e) {
+				//we do nothing and try our luck with the next provider
+			}
+		}
+		throw new UnsupportedOperationException(
+				"No provider could create MGraph.");
+	}
+
+	@Override
+	public Graph createGraph(UriRef name, TripleCollection triples) {
+		for (WeightedTcProvider provider : providerList) {
+			try {
+				Graph result = provider.createGraph(name, triples);
+
+				// unregisters a possible Graph or MGraph service under this name
+				// provided by a WeightedTcProvider with a lower weight.
+				tcDisappears(name);
+				mGraphCache.put(name, new MGraphHolder(provider, null));
+				graphAppears(name);
+				return result;
+			} catch (UnsupportedOperationException e) {
+				//we do nothing and try our luck with the next provider
+			} catch (IllegalArgumentException e) {
+				//we do nothing and try our luck with the next provider
+			}
+		}
+		throw new UnsupportedOperationException(
+				"No provider could create Graph.");
+	}
+
+	@Override
+	public void deleteTripleCollection(UriRef name) {
+		for (TcProvider provider : providerList) {
+			try {
+				provider.deleteTripleCollection(name);
+				final MGraphHolder holder = mGraphCache.get(name);
+				if ((holder != null)
+						&& (holder.getWeightedTcProvider() != null)
+						&& holder.getWeightedTcProvider().equals(provider)) {
+					tcDisappears(name);
+					mGraphCache.remove(name);
+				}
+				return;
+			} catch (UnsupportedOperationException e) {
+				// we do nothing and try our luck with the next provider
+			} catch (NoSuchEntityException e) {
+				//we do nothing and try our luck with the next provider
+			} catch (IllegalArgumentException e) {
+				//we do nothing and try our luck with the next provider
+			}
+		}
+		// this throws a NoSuchEntityException if the graph doesn't exist
+		getTriples(name);
+		// the entity exists but cannot be deleted
+		throw new UnsupportedOperationException(
+				"No provider could delete the entity.");
+	}
+
+	@Override
+	public Set<UriRef> getNames(Graph graph) {
+		Set<UriRef> result = new HashSet<UriRef>();
+		for (TcProvider provider : providerList) {
+			result.addAll(provider.getNames(graph));
+		}
+		return result;
+	}
+
+	@Override
+	public Set<UriRef> listGraphs() {
+		Set<UriRef> result = new HashSet<UriRef>();
+		for (TcProvider provider : providerList) {
+			result.addAll(provider.listGraphs());
+		}
+		return result;
+	}
+
+	@Override
+	public Set<UriRef> listMGraphs() {
+		Set<UriRef> result = new HashSet<UriRef>();
+		for (TcProvider provider : providerList) {
+			result.addAll(provider.listMGraphs());
+		}
+		return result;
+	}
+
+	@Override
+	public Set<UriRef> listTripleCollections() {
+		Set<UriRef> result = new HashSet<UriRef>();
+		for (TcProvider provider : providerList) {
+			result.addAll(provider.listTripleCollections());
+		}
+		return result;
+	}
+
+	private LockableMGraph ensureLockable(MGraph providedMGraph) {
+		LockableMGraph result;
+		if (providedMGraph instanceof LockableMGraph) {
+			result = (LockableMGraph) providedMGraph;
+		} else {
+			result = new LockableMGraphWrapper(providedMGraph);
+		}
+		return result;
+	}
+
+	/**
+	 * Contains an unsecured LockableMGraph, a ServiceRegistration and
+	 * the WeightedTcProvider that generated the graph
+	 */
+	private static class MGraphHolder {
+
+		private WeightedTcProvider tcProvider;
+		private WeakReference<LockableMGraph> mGraphReference;
+
+		MGraphHolder(WeightedTcProvider tcProvider, LockableMGraph mGraph) {
+			this.tcProvider = tcProvider;
+			this.mGraphReference = new WeakReference<LockableMGraph>(mGraph);
+		}
+
+		LockableMGraph getMGraph() {
+			return this.mGraphReference.get();
+		}
+
+		WeightedTcProvider getWeightedTcProvider() {
+			return this.tcProvider;
+		}
+	}
+
+	//methods for debuging / monitoring
+	public SortedSet<WeightedTcProvider> getProviderList() {
+		return providerList;
+	}
+}

Added: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/WeightedProviderComparator.java
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/WeightedProviderComparator.java?rev=995973&view=auto
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/WeightedProviderComparator.java (added)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/access/WeightedProviderComparator.java Fri Sep 10 20:36:58 2010
@@ -0,0 +1,20 @@
+package org.apache.clerezza.rdf.core.access;
+
+import java.util.Comparator;
+
+/**
+ * Compares the WeightedTcManagementProviders, descending for weight and
+ * ascending by name
+ */
+public class WeightedProviderComparator implements Comparator<WeightedTcProvider> {
+
+	@Override
+	public int compare(WeightedTcProvider o1, WeightedTcProvider o2) {
+		int o1Weight = o1.getWeight();
+		int o2Weight = o2.getWeight();
+		if (o1Weight != o2Weight) {
+			return o2Weight - o1Weight;
+		}
+		return o1.getClass().toString().compareTo(o2.getClass().toString());
+	}
+}