de.knurt.fam.plugin.DefaultPluginResolver.java Source code

Java tutorial

Introduction

Here is the source code for de.knurt.fam.plugin.DefaultPluginResolver.java

Source

/*
 * Copyright 2009-2012 by KNURT Systeme (http://www.knurt.de)
 *
 * Licensed under the Creative Commons License Attribution-NonCommercial-ShareAlike 3.0 Unported;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://creativecommons.org/licenses/by-nc-sa/3.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 de.knurt.fam.plugin;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.apache.commons.digester.plugins.PluginConfigurationException;

import de.knurt.fam.connector.FamConnector;
import de.knurt.fam.core.aspects.logging.FamLog;

/**
 * resolve loading plugins and support interfaces to set specific behaviour.
 * 
 * @author Daniel Oltmanns <info@knurt.de>
 * @since 1.3.0 (10/09/2010)
 */
public class DefaultPluginResolver implements PluginResolver {

    private RegisterSubmission registerSubmission = null;
    private List<Plugin> plugins = new ArrayList<Plugin>();

    public List<Plugin> getPlugins() {
        return plugins;
    }

    /** {@inheritDoc} */
    @Override
    public RegisterSubmission getRegisterSubmission() {
        return this.registerSubmission;
    }

    private boolean implementz(Class<?> clazz, Class<?> interfaze) {
        return this.implementz(clazz, interfaze.getName());
    }

    private boolean implementz(Class<?> clazz, String interfaceName) {
        boolean result = false;
        Class<?>[] interfaces = clazz.getInterfaces();
        for (Class<?> interfaze : interfaces) {
            if (interfaze.getName().equals(interfaceName)) {
                result = true;
                break;
            }
        }
        return result;
    }

    private boolean isPlugin(Class<?> cl) {
        return this.implementz(cl, Plugin.class);
    }

    /** {@inheritDoc} */
    @Override
    protected void finalize() throws Throwable {
        for (Plugin plugin : this.plugins) {
            plugin.stop();
        }
    }

    /** one and only instance of DefaultPluginResolver */
    private volatile static DefaultPluginResolver me;

    /** construct DefaultPluginResolver */
    private DefaultPluginResolver() {
        this.initPlugins();
    }

    private void initPlugins() {
        File pluginDirectory = new File(FamConnector.me().getPluginDirectory());
        if (pluginDirectory.exists() && pluginDirectory.isDirectory() && pluginDirectory.canRead()) {
            File[] files = pluginDirectory.listFiles();
            ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader();
            for (File file : files) {
                if (file.isFile() && file.getName().toLowerCase().endsWith("jar")) {
                    JarFile jar = null;
                    try {
                        jar = new JarFile(file.getAbsoluteFile().toString());
                        Enumeration<JarEntry> jarEntries = jar.entries();
                        while (jarEntries.hasMoreElements()) {
                            JarEntry entry = jarEntries.nextElement();
                            if (entry.getName().toLowerCase().endsWith("class")) {
                                String className = entry.getName().replaceAll("/", ".").replaceAll("\\.class$", "");
                                // @SuppressWarnings("resource") // classLoader must not be closed, getting an "IllegalStateException: zip file closed" otherwise
                                URLClassLoader classLoader = new URLClassLoader(new URL[] { file.toURI().toURL() },
                                        currentThreadClassLoader);
                                Class<?> cl = classLoader.loadClass(className);
                                if (this.isPlugin(cl)) {
                                    Plugin plugin = (Plugin) cl.newInstance();
                                    this.plugins.add(plugin);
                                }
                            }
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                        FamLog.logException(this.getClass(), e, "failed to load plugin", 201010091426l);
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                        FamLog.logException(this.getClass(), e, "failed to load plugin", 201010091424l);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                        FamLog.logException(this.getClass(), e, "failed to load plugin", 201010091425l);
                    } catch (IOException e) {
                        e.printStackTrace();
                        FamLog.logException(this.getClass(), e, "failed to load plugin", 201010091351l);
                    } finally {
                        try {
                            jar.close();
                        } catch (Exception e) {
                        }
                    }
                }
            }
            for (Plugin plugin : this.plugins) {
                boolean found = false;
                if (this.implementz(plugin.getClass(), RegisterSubmission.class)) {
                    if (found == true) {
                        throw new PluginConfigurationException("Found more than one RegisterSubmission classes");
                        // TODO #19 supply a solution Ticket
                    }
                    this.registerSubmission = (RegisterSubmission) plugin;
                    found = true;
                }
            }
            for (Plugin plugin : this.plugins) {
                plugin.start();
            }
        }
        // search plugin
        if (this.registerSubmission == null) {
            this.registerSubmission = new DefaultRegisterSubmission();
        }
    }

    /**
     * return the one and only instance of DefaultPluginResolver
     * 
     * @return the one and only instance of DefaultPluginResolver
     */
    public static DefaultPluginResolver getInstance() {
        if (me == null) {
            //  no instance so far
            synchronized (DefaultPluginResolver.class) {
                if (me == null) {
                    //  still no instance so far
                    //  the one and only me
                    me = new DefaultPluginResolver();
                }
            }
        }
        return me;
    }

    /**
     * short for {@link #getInstance()}
     * 
     * @return the one and only instance of DefaultPluginResolver
     */
    public static DefaultPluginResolver me() {
        return getInstance();
    }

    /**
     * init plugins as far as it is not initialized by now
     */
    public static void init() {
        getInstance();
    }
}