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

org.apache.tuscany.sca.extensibility.ServiceHelper 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.extensibility;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.Map;

import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.LifeCycleListener;

/**
 * A helper for handling service lifecycle and instantiations
 * @tuscany.spi.extension.asclient
 */
public class ServiceHelper {
    private ServiceHelper() {
    }

    /**
     * Start the service instance
     * @param instance
     */
    public static boolean start(Object instance) {
        if (instance instanceof LifeCycleListener) {
            ((LifeCycleListener)instance).start();
            return true;
        }
        return false;
    }

    /**
     * Stop the service instance
     * @param instance
     */
    public static boolean stop(Object instance) {
        if (instance instanceof LifeCycleListener) {
            ((LifeCycleListener)instance).stop();
            return true;
        }
        return false;
    }

    /**
     * Stop a collection of service instances
     * @param instances
     */
    public static void stop(Collection instances) {
        if (instances == null) {
            return;
        }
        for (Object instance : instances) {
            if (instance instanceof LifeCycleListener) {
                ((LifeCycleListener)instance).stop();
            }
        }
    }

    /**
     * Create a service instance with one parameter
     * @param cls The service type
     * @param parameterType The parameter type
     * @param parameter The parameter value
     * @return The newly created service instance
     * @throws Exception
     */
    public static  T newInstance(Class cls, Class parameterType, Object parameter) throws Exception {
        Constructor constructor = cls.getConstructor(parameterType);
        return constructor.newInstance(parameter);
    }

    /**
     * Create a service instance with an array of parameters
     * @param cls The service type
     * @param parameterTypes An array of parameter types
     * @param parameters An array of parameter values
     * @return The newly created service instance 
     * @throws Exception
     */
    public static  T newInstance(Class cls, Class parameterTypes[], Object... parameters) throws Exception {
        Constructor constructor = cls.getConstructor(parameterTypes);
        return constructor.newInstance(parameters);
    }

    /**
     * Create a service instance with the default no-arg constructor
     * @param cls The service type
     * @return The newly created service instance
     * @throws Exception
     */
    public static  T newInstance(Class cls) throws Exception {
        Constructor constructor = cls.getConstructor();
        return constructor.newInstance();
    }

    private final static Class[] ARG_TYPES = new Class[] {ExtensionPointRegistry.class, Map.class};

    /**
     * Create a service instance from the service declaration
     * @param 
     * @param registry The extension point registry
     * @param sd The service declaration
     * @return The newly created service instance
     * @throws Exception
     */
    public static  T newInstance(ExtensionPointRegistry registry, ServiceDeclaration sd) throws Exception {
        Class cls = (Class)sd.loadClass();
        T instance = null;
        try {
            // Try constructor(ExtensionPointRegistry.class)
            instance = newInstance(cls, ExtensionPointRegistry.class, registry);
        } catch (NoSuchMethodException e) {
            try {
                // Try Try constructor(ExtensionPointRegistry.class, Map.class)
                instance = newInstance(cls, ARG_TYPES, registry, sd.getAttributes());
            } catch (NoSuchMethodException e1) {
                // Try constructor()
                instance = newInstance(cls);
            }
        }
        return instance;
    }

    public static  T newLazyInstance(ExtensionPointRegistry registry, ServiceDeclaration sd, Class serviceType) {
        return serviceType.cast(Proxy.newProxyInstance(serviceType.getClassLoader(),
                                                       new Class[] {serviceType, LifeCycleListener.class},
                                                       new InvocationHandlerImpl(registry, serviceType, sd)));
    }

    private static class InvocationHandlerImpl implements InvocationHandler {
        private ExtensionPointRegistry registry;
        private Class type;
        private ServiceDeclaration sd;
        private Object instance;

        private final static Method STOP_METHOD = getMethod(LifeCycleListener.class, "stop");
        private final static Method START_METHOD = getMethod(LifeCycleListener.class, "start");
        private final static Method EQUALS_METHOD = getMethod(Object.class, "equals");
        private final static Method HASHCODE_METHOD = getMethod(Object.class, "hashCode");
        private final static Method TOSTRING_METHOD = getMethod(Object.class, "toString");

        private static Method getMethod(Class type, String name) {
            Method[] methods = type.getMethods();
            for (Method method : methods) {
                if (name.equals(method.getName())) {
                    return method;
                }
            }
            return null;
        }

        public InvocationHandlerImpl(ExtensionPointRegistry registry, Class type, ServiceDeclaration sd) {
            super();
            this.registry = registry;
            this.sd = sd;
            this.type = type;
        }

        private Object getAttribute(Method method) throws Exception {
            if (method.getParameterTypes().length != 0) {
                return null;
            }
            String name = method.getName();
            if (name.equals("getModelType") && method.getReturnType() == Class.class) {
                return sd.loadClass(sd.getAttributes().get("model"));
            } else if (name.equals("getArtifactType")) {
                return ServiceDeclarationParser.getQName(sd.getAttributes().get("qname"));
            }
            return null;
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            synchronized (this) {
                // Check if the method is to get the qname/model attribute
                Object value = getAttribute(method);
                if (value != null) {
                    return value;
                }
                if (instance == null && method.getDeclaringClass() == type) {
                    // Only initialize the instance when a method on the service type is invoked
                    instance = newInstance(registry, sd);
                    start(instance);
                }
                if (method.equals(EQUALS_METHOD)) {
                    return proxy == args[0];
                } else if (method.equals(HASHCODE_METHOD)) {
                    return System.identityHashCode(proxy);
                } else if (method.equals(TOSTRING_METHOD)) {
                    return "Proxy: " + sd.toString();
                }
                if (instance == null) {
                    return null;
                }
            }
            if (method.equals(STOP_METHOD)) {
                stop(instance);
                return null;
            } else if (method.equals(START_METHOD)) {
                // Skip the start()
                return null;
            } else {
                return method.invoke(instance, args);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy