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

org.apache.commons.discovery.tools.SPInterface Maven / Gradle / Ivy

Go to download

Its an port to fix bugs in OSGi support. ... The Apache Commons Discovery 0.5 component is about discovering, or finding, implementations for pluggable interfaces.

There is a newer version: 7.4.0
Show 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.commons.discovery.tools;

import java.lang.reflect.InvocationTargetException;

import org.apache.commons.discovery.DiscoveryException;

/**
 * Represents a Service Programming Interface (spi).
 * - SPI's name
 * - SPI's (provider) class
 * - SPI's (alternate) override property name
 *
 * In addition, while there are many cases where this is NOT
 * usefull, for those in which it is:
 *
 * - expected constructor argument types and parameters values.
 *
 * @param  The SPI type
 */
public class SPInterface {

    /**
     * Construct object representing Class {@code provider}.
     *
     * @param  The SPI type
     * @param provider The SPI class
     * @return A new object representing Class {@code provider}
     * @since 0.5
     */
    public static  SPInterface newSPInterface(Class provider) {
        return newSPInterface(provider, provider.getName());
    }

    /**
     * Construct object representing Class {@code provider}.
     *
     * @param  The SPI type
     * @param provider The SPI class
     * @param propertyName when looking for the name of a class implementing
     *        the provider class, a discovery strategy may involve looking for
     *        (system or other) properties having either the name of the class
     *        (provider) or the propertyName.
     * @return A new object representing Class {@code provider}
     * @since 0.5
     */
    public static  SPInterface newSPInterface(Class provider, String propertyName) {
        return new SPInterface(provider, propertyName);
    }

    /**
     * Construct object representing Class {@code provider}.
     *
     * @param  The SPI type
     * @param provider The SPI class
     * @param constructorParamClasses classes representing the
     *        constructor argument types
     * @param constructorParams objects representing the
     *        constructor arguments
     * @return A new object representing Class {@code provider}
     * @since 0.5
     */
    public static  SPInterface newSPInterface(Class provider,
            Class constructorParamClasses[],
            Object constructorParams[]) {
        return newSPInterface(provider, provider.getName(), constructorParamClasses, constructorParams);
    }

    /**
     * Construct object representing Class {@code provider}.
     *
     * @param  The SPI type
     * @param provider The SPI class
     * @param propertyName when looking for the name of a class implementing
     *        the provider class, a discovery strategy may involve looking for
     *        (system or other) properties having either the name of the class
     *        (provider) or the propertyName.
     * @param constructorParamClasses classes representing the
     *        constructor argument types
     * @param constructorParams objects representing the
     *        constructor arguments
     * @return A new object representing Class {@code provider}
     * @since 0.5
     */
    public static  SPInterface newSPInterface(Class provider,
            String propertyName,
            Class constructorParamClasses[],
            Object constructorParams[]) {
        return new SPInterface(provider, propertyName, constructorParamClasses, constructorParams);
    }

    /**
     * The service programming interface: intended to be
     * an interface or abstract class, but not limited
     * to those two.
     */
    private final Class spi;

    /**
     * The property name to be used for finding the name of
     * the SPI implementation class.
     */
    private final String propertyName;

    private final Class  paramClasses[];

    private final Object params[];

    /**
     * Construct object representing Class provider.
     *
     * @param provider The SPI class
     */
    public SPInterface(Class provider) {
        this(provider, provider.getName());
    }

    /**
     * Construct object representing Class provider.
     *
     * @param spi The SPI class
     *
     * @param propertyName when looking for the name of a class implementing
     *        the provider class, a discovery strategy may involve looking for
     *        (system or other) properties having either the name of the class
     *        (provider) or the propertyName.
     */
    public SPInterface(Class spi, String propertyName) {
        this.spi = spi;
        this.propertyName = propertyName;
        this.paramClasses = null;
        this.params = null;
    }

    /**
     * Construct object representing Class provider.
     *
     * @param provider The SPI class
     *
     * @param constructorParamClasses classes representing the
     *        constructor argument types.
     *
     * @param constructorParams objects representing the
     *        constructor arguments.
     */
    public SPInterface(Class provider,
                       Class constructorParamClasses[],
                       Object constructorParams[]) {
        this(provider,
             provider.getName(),
             constructorParamClasses,
             constructorParams);
    }

    /**
     * Construct object representing Class provider.
     *
     * @param spi The SPI class
     *
     * @param propertyName when looking for the name of a class implementing
     *        the provider class, a discovery strategy may involve looking for
     *        (system or other) properties having either the name of the class
     *        (provider) or the propertyName.
     *
     * @param constructorParamClasses classes representing the
     *        constructor argument types.
     *
     * @param constructorParams objects representing the
     *        constructor arguments.
     */
    public SPInterface(Class spi,
                       String propertyName,
                       Class constructorParamClasses[],
                       Object constructorParams[]) {
        this.spi = spi;
        this.propertyName = propertyName;
        this.paramClasses = constructorParamClasses;
        this.params = constructorParams;
    }

    /**
     * Returns the SPI class name.
     *
     * @return The SPI class name
     */
    public String getSPName() {
        return spi.getName();
    }

    /**
     * Returns the SPI class.
     *
     * @return The SPI class
     */
    public Class getSPClass() {
        return spi;
    }

    /**
     * Returns the property name to be used for finding
     * the name of the SPI implementation class.
     *
     * @return The property name to be used for finding
     *         the name of the SPI implementation class
     */
    public String getPropertyName() {
        return propertyName;
    }

    /**
     * Creates a new instance of the given SPI class.
     *
     * @param  Any type extends T
     * @param impl The SPI class has to be instantiated
     * @return A new instance of the given SPI class
     * @throws DiscoveryException if the class implementing
     *            the SPI cannot be found, cannot be loaded and
     *            instantiated, or if the resulting class does not implement
     *            (or extend) the SPI
     * @throws InstantiationException see {@link Class#newInstance()}
     * @throws IllegalAccessException see {@link Class#newInstance()}
     * @throws NoSuchMethodException see {@link Class#newInstance()}
     * @throws InvocationTargetException see {@link Class#newInstance()}
     */
    public  S newInstance(Class impl)
        throws DiscoveryException,
               InstantiationException,
               IllegalAccessException,
               NoSuchMethodException,
               InvocationTargetException {
        verifyAncestory(impl);

        return ClassUtils.newInstance(impl, paramClasses, params);
    }

    /**
     * Verifies the given SPI implementation is a SPI specialization.
     *
     * @param  Any type extends T
     * @param impl The SPI instantance
     */
    public  void verifyAncestory(Class impl) {
        ClassUtils.verifyAncestory(spi, impl);
    }

}