org.ow2.mind.plugin.BasicPluginManager.java Source code

Java tutorial

Introduction

Here is the source code for org.ow2.mind.plugin.BasicPluginManager.java

Source

/**
 * Copyright (C) 2010 STMicroelectronics
 *
 * This file is part of "Mind Compiler" is free software: you can redistribute 
 * it and/or modify it under the terms of the GNU Lesser General Public License 
 * as published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contact: mind@ow2.org
 *
 * Authors: Matthieu Leclercq
 * Contributors: Ali Erdem Ozcan
 */

package org.ow2.mind.plugin;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.objectweb.fractal.adl.CompilerError;
import org.objectweb.fractal.adl.error.GenericErrors;
import org.objectweb.fractal.adl.util.FractalADLLogManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.name.Named;

/**
 * Basic implementation of the {@link PluginManager} interface.
 */
@Singleton
public class BasicPluginManager implements PluginManager {

    public final static String PLUGIN_CLASS_LOADER = "plugin-class-loader";

    private static final String EXTENSION_POINT_ELEMENT_NAME = "extension-point";
    private static final String EXTENSION_ELEMENT_NAME = "extension";
    private static final String PLUGIN_NAME_ATTR_NAME = "name";
    private static final String PLUGIN_ID_ATTR_NAME = "id";

    public static final String PLUGIN_XML = "mind-plugin.xml";

    protected PluginRegistry pluginRegistry;

    protected DocumentBuilder builder = null;

    @Inject
    @Named(PLUGIN_CLASS_LOADER)
    protected ClassLoader classLoader;

    @Inject
    protected Injector injector;

    protected static Logger pluginLogger = FractalADLLogManager.getLogger("plugin");

    // ---------------------------------------------------------------------------
    // Constructor
    // ---------------------------------------------------------------------------

    public BasicPluginManager() {
        final DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        try {
            builder = builderFactory.newDocumentBuilder();
        } catch (final ParserConfigurationException e) {
            throw new CompilerError(GenericErrors.INTERNAL_ERROR, e, "Can't initialize document builder");
        }
    }

    // ---------------------------------------------------------------------------
    // Implementation of the PluginManager interface
    // ---------------------------------------------------------------------------

    public ExtensionPoint getExtensionPoint(final String extensionPoint) {
        return getRegistry().extensionPoints.get(extensionPoint);
    }

    public Iterable<Extension> getExtensions(final String extensionPoint) {
        final ExtensionPoint point = getExtensionPoint(extensionPoint);
        if (point == null)
            return null;
        return point.getExtensions();
    }

    public Iterable<ConfigurationElement> getConfigurationElements(final String extensionPoint) {
        final ExtensionPoint point = getExtensionPoint(extensionPoint);
        if (point == null)
            return null;
        return point.getConfigurationElements();
    }

    public Iterable<ConfigurationElement> getConfigurationElements(final String extensionPoint, final String name) {
        final ExtensionPoint point = getExtensionPoint(extensionPoint);
        if (point == null)
            return null;
        return point.getConfigurationElements(name);
    }

    public Iterable<String> getExtensionPointNames() {
        return Iterables.unmodifiableIterable(getRegistry().extensionPoints.keySet());
    }

    public <T> T getInstance(final Class<T> clazz) {
        return injector.getInstance(clazz);
    }

    // ---------------------------------------------------------------------------
    // Utility classes and methods
    // ---------------------------------------------------------------------------

    protected PluginRegistry initRegistry() {
        final PluginRegistry registry = new PluginRegistry();

        final ClassLoader classLoader = (this.classLoader != null) ? this.classLoader
                : this.getClass().getClassLoader();
        Enumeration<URL> plugins = null;
        try {
            plugins = classLoader.getResources(PLUGIN_XML);
        } catch (final IOException e) {
            throw new CompilerError(GenericErrors.INTERNAL_ERROR, e, "Can't find plugin descriptors");
        }

        while (plugins.hasMoreElements()) {
            final URL url = plugins.nextElement();
            initPlugin(classLoader, url, registry);
        }

        // bind extensions to extension points :
        for (final Plugin plugin : registry.plugins.values()) {
            if (pluginLogger.isLoggable(Level.FINE)) {
                pluginLogger.fine("Initializing the plugin " + plugin.getId());
            }
            for (final Extension extension : plugin.getExtensions()) {
                final ExtensionPointImpl point = registry.extensionPoints.get(extension.getExtensionPointID());
                if (point == null) {
                    throw new CompilerError(GenericErrors.INTERNAL_ERROR,
                            "Unknown Extenstion point ID \"" + extension.getExtensionPointID()
                                    + "\" referenced by plugin \"" + plugin.getId() + "\".");
                }
                point.bindExtension(extension);
            }
        }

        return registry;
    }

    protected void initPlugin(final ClassLoader classLoader, final URL pluginDesc, final PluginRegistry registry) {

        final Document document;
        try {
            document = builder.parse(pluginDesc.openStream());
        } catch (final FileNotFoundException e) {
            throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
                    "Unable to find the plugin descriptor '" + pluginDesc + "'.");
        } catch (final IOException e) {
            throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
                    "Unable to access the plugin descriptor '" + pluginDesc + "'.");
        } catch (final SAXException e) {
            throw new CompilerError(GenericErrors.INTERNAL_ERROR, e,
                    "Unable to parse the XML plugin descriptor '" + pluginDesc + "'.");
        }
        final Element root = document.getDocumentElement();
        final String id = root.getAttribute(PLUGIN_ID_ATTR_NAME);
        final String name = root.getAttribute(PLUGIN_NAME_ATTR_NAME);

        // create plugin object and add it in the registry
        final PluginImpl plugin = new PluginImpl(this, pluginDesc, id, name, classLoader);
        final Plugin prevPlugin = registry.plugins.put(plugin.getId(), plugin);
        if (prevPlugin != null) {
            throw new CompilerError(GenericErrors.INTERNAL_ERROR,
                    "Invalid plugin ID \"" + plugin.getId() + "\" A plugin with the same name is already defined.");
        }

        // add extension and extension points to plugin and registry
        final NodeList nodes = root.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            final Node node = nodes.item(i);
            if (!(node instanceof Element))
                continue;
            final Element element = (Element) node;
            if (element.getNodeName().equals(EXTENSION_ELEMENT_NAME)) {
                plugin.addExtension(new ExtensionImpl(plugin, element));
            } else if (element.getNodeName().equals(EXTENSION_POINT_ELEMENT_NAME)) {
                final ExtensionPointImpl point = new ExtensionPointImpl(plugin, element);
                final ExtensionPoint prevPoint = registry.extensionPoints.put(point.getQualifiedId(), point);
                if (prevPoint != null) {
                    throw new CompilerError(GenericErrors.INTERNAL_ERROR, "Invalid Extenstion point ID \"" + id
                            + "\" An extension point with the same name is already defined.");
                }
                plugin.addExtensionPoint(point);
            }
        }

    }

    protected synchronized PluginRegistry getRegistry() {
        if (pluginRegistry == null) {
            pluginRegistry = initRegistry();
        }
        return pluginRegistry;
    }

    protected static final class PluginRegistry {
        final Map<String, PluginImpl> plugins = new HashMap<String, PluginImpl>();
        final Map<String, ExtensionPointImpl> extensionPoints = new HashMap<String, ExtensionPointImpl>();
    }
}