All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.tuscany.sca.core.DefaultUtilityExtensionPoint Maven / Gradle / Ivy

The newest version!
/*
 * 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: 898590 $ $Date: 2010-01-12 17:00:58 -0800 (Tue, 12 Jan 2010) $
 */
public class DefaultUtilityExtensionPoint implements UtilityExtensionPoint {
    private Map utilities = new ConcurrentHashMap();

    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> 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 getUtility(Class 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> i = utilities.entrySet().iterator(); i.hasNext();) {
            Map.Entry 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> getAllInterfaces(Class clazz) {
        Set> implemented = new HashSet>();
        getAllInterfaces(clazz, implemented);
        implemented.remove(LifeCycleListener.class);
        return implemented;
    }

    private static void getAllInterfaces(Class clazz, Set> 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 getUtility(Class 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 map = new IdentityHashMap();
        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();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy