summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/tags/2.0.1-RC1/modules/extensibility/src/main/java/org/apache/tuscany/sca/core/DefaultUtilityExtensionPoint.java
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-2.x/tags/2.0.1-RC1/modules/extensibility/src/main/java/org/apache/tuscany/sca/core/DefaultUtilityExtensionPoint.java')
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/extensibility/src/main/java/org/apache/tuscany/sca/core/DefaultUtilityExtensionPoint.java219
1 files changed, 219 insertions, 0 deletions
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/extensibility/src/main/java/org/apache/tuscany/sca/core/DefaultUtilityExtensionPoint.java b/sca-java-2.x/tags/2.0.1-RC1/modules/extensibility/src/main/java/org/apache/tuscany/sca/core/DefaultUtilityExtensionPoint.java
new file mode 100644
index 0000000000..40e4635d77
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/extensibility/src/main/java/org/apache/tuscany/sca/core/DefaultUtilityExtensionPoint.java
@@ -0,0 +1,219 @@
+/*
+ * 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.tuscany.sca.core;
+
+import static org.apache.tuscany.sca.extensibility.ServiceHelper.newInstance;
+
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+
+/**
+ * Default implementation of an extension point to hold Tuscany utility utilities.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultUtilityExtensionPoint implements UtilityExtensionPoint {
+ private Map<Object, Object> utilities = new ConcurrentHashMap<Object, Object>();
+
+ private ExtensionPointRegistry registry;
+ /**
+ * Constructs a new extension point.
+ */
+ public DefaultUtilityExtensionPoint(ExtensionPointRegistry extensionPoints) {
+ this.registry = extensionPoints;
+ }
+
+ /**
+ * Add a utility to the extension point. This default implementation
+ * stores utilities against the interfaces that they implement.
+ *
+ * @param utility The instance of the utility
+ *
+ * @throws IllegalArgumentException if utility is null
+ */
+ public void addUtility(Object utility) {
+ addUtility(null, utility);
+ }
+
+ public void addUtility(Object key, Object utility) {
+ if (utility == null) {
+ throw new IllegalArgumentException("Cannot register null as a Service");
+ }
+
+ if (utility instanceof LifeCycleListener) {
+ ((LifeCycleListener)utility).start();
+ }
+
+ if (key == null) {
+ Class<?> cls = utility.getClass();
+ Set<Class<?>> interfaces = getAllInterfaces(cls);
+ for (Class<?> i : interfaces) {
+ utilities.put(i, utility);
+ }
+ if (interfaces.isEmpty() || isConcreteClass(cls)) {
+ utilities.put(cls, utility);
+ }
+ } else {
+ utilities.put(key, utility);
+ }
+ }
+
+ /**
+ * Get the utility by the interface that it implements
+ *
+ * @param utilityType The lookup key (utility interface)
+ * @return The instance of the utility
+ *
+ * @throws IllegalArgumentException if utilityType is null
+ */
+ public <T> T getUtility(Class<T> utilityType) {
+ return getUtility(utilityType, null);
+ }
+
+ /**
+ * Remove a utility based on the interface that it implements
+ *
+ * @param utility The utility to remove
+ *
+ * @throws IllegalArgumentException if utility is null
+ */
+ public void removeUtility(Object utility) {
+ if (utility == null) {
+ throw new IllegalArgumentException("Cannot remove null as a Service");
+ }
+
+ if(utility instanceof LifeCycleListener) {
+ ((LifeCycleListener) utility).stop();
+ }
+
+ for (Iterator<Map.Entry<Object, Object>> i = utilities.entrySet().iterator(); i.hasNext();) {
+ Map.Entry<Object, Object> entry = i.next();
+ if (entry.getValue() == utility) {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * Returns the set of interfaces implemented by the given class and its
+ * ancestors or a blank set if none
+ */
+ private static Set<Class<?>> getAllInterfaces(Class<?> clazz) {
+ Set<Class<?>> implemented = new HashSet<Class<?>>();
+ getAllInterfaces(clazz, implemented);
+ implemented.remove(LifeCycleListener.class);
+ return implemented;
+ }
+
+ private static void getAllInterfaces(Class<?> clazz, Set<Class<?>> implemented) {
+ Class<?>[] interfaces = clazz.getInterfaces();
+ for (Class<?> interfaze : interfaces) {
+ if (Modifier.isPublic(interfaze.getModifiers())) {
+ implemented.add(interfaze);
+ }
+ }
+ Class<?> superClass = clazz.getSuperclass();
+ // Object has no superclass so check for null
+ if (superClass != null && !superClass.equals(Object.class)) {
+ getAllInterfaces(superClass, implemented);
+ }
+ }
+
+ public <T> T getUtility(Class<T> utilityType, Object key) {
+ if (utilityType == null) {
+ throw new IllegalArgumentException("Cannot lookup Service of type null");
+ }
+
+ if (key == null) {
+ key = utilityType;
+ }
+
+ Object utility = utilities.get(key);
+
+ if (utility == null) {
+
+ // Dynamically load a utility class declared under META-INF/services/"utilityType"
+ try {
+ ServiceDeclaration utilityDeclaration =
+ registry.getServiceDiscovery().getServiceDeclaration(utilityType.getName());
+ Class<?> utilityClass = null;
+ if (utilityDeclaration != null) {
+ utilityClass = utilityDeclaration.loadClass();
+ } else if (isConcreteClass(utilityType)) {
+ utilityClass = utilityType;
+ key = utilityType;
+ }
+ if (utilityClass != null) {
+ // Construct the utility
+ if (utilityDeclaration != null) {
+ utility = newInstance(registry, utilityDeclaration);
+ } else {
+ try {
+ utility = newInstance(utilityClass, ExtensionPointRegistry.class, registry);
+ } catch (NoSuchMethodException e) {
+ utility = newInstance(utilityClass);
+ }
+ }
+ // Cache the loaded utility
+ if (key == utilityType) {
+ addUtility(utility);
+ } else {
+ addUtility(key, utility);
+ }
+ }
+ } catch (Throwable e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ return utilityType.cast(utility);
+ }
+
+ private boolean isConcreteClass(Class<?> utilityType) {
+ int modifiers = utilityType.getModifiers();
+ return !utilityType.isInterface() && Modifier.isPublic(modifiers) && !Modifier.isAbstract(modifiers);
+ }
+
+ public void start() {
+ // NOOP
+ }
+
+ public synchronized void stop() {
+ // Get a unique map as an extension point may exist in the map by different keys
+ Map<LifeCycleListener, LifeCycleListener> map = new IdentityHashMap<LifeCycleListener, LifeCycleListener>();
+ for (Object util : utilities.values()) {
+ if (util instanceof LifeCycleListener) {
+ LifeCycleListener listener = (LifeCycleListener)util;
+ map.put(listener, listener);
+ }
+ }
+ for (LifeCycleListener listener : map.values()) {
+ listener.stop();
+ }
+ utilities.clear();
+ }
+
+}