de.zib.gndms.infra.system.PluggableTaskFlowProvider.java Source code

Java tutorial

Introduction

Here is the source code for de.zib.gndms.infra.system.PluggableTaskFlowProvider.java

Source

/*
 * Copyright 2008-${YEAR} Zuse Institute Berlin (ZIB)
 *
 *  Licensed 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 de.zib.gndms.infra.system;

import de.zib.gndms.logic.model.gorfx.taskflow.TaskFlowFactory;
import de.zib.gndms.logic.model.gorfx.taskflow.TaskFlowProviderImpl;
import de.zib.gndms.neomodel.common.Session;
import de.zib.gndms.stuff.GNDMSInjector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author try ma ik jo rr a zib
 * @date 27.06.11  18:38
 * @brief
 */
public class PluggableTaskFlowProvider extends TaskFlowProviderImpl {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    private String pluginDir;
    private boolean hasFactories = false;
    private GNDMSystem system;
    private ClassLoader cl;

    public void loadPlugins(boolean checkDeps) {

        Map<String, TaskFlowFactory> plugins = new HashMap<String, TaskFlowFactory>(10);

        ServiceLoader<TaskFlowFactory> sl;
        if (getCl() != null)
            sl = ServiceLoader.load(TaskFlowFactory.class, getCl());
        else
            sl = ServiceLoader.load(TaskFlowFactory.class);

        for (TaskFlowFactory bp : sl) {
            try {
                register(bp, plugins);
            } catch (IllegalStateException e) {
                logger.warn(e.getMessage());
            }
        }

        setFactories(plugins);

        if (checkDeps)
            checkDeps();

        // call all PostConstruct methods
        for (TaskFlowFactory bp : sl) {
            for (Method method : bp.getClass().getDeclaredMethods()) {
                if (method.getAnnotation(PostConstruct.class) != null) {
                    ReflectionUtils.makeAccessible(method);
                    try {
                        method.invoke(bp, (Object[]) null);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(
                                "THIS IS NOT HAPPENING!!! Method had been made accessible but is not accessible anyway",
                                e);
                    } catch (InvocationTargetException e) {
                        throw new RuntimeException(
                                "Could not call PostConstruct method (" + method.toGenericString() + ")", e);
                    }
                }
            }
        }

        // todo this is just for development change this for releases:
        //        if ( getFactories().size() == 0 )
        //            throw new IllegalStateException( "no plugs found" );
    }

    @PostConstruct
    public void loadPlugins() {

        PluginLoader pl = new PluginLoader(pluginDir);
        try {
            ClassLoader cl = pl.loadPlugins();
            setCl(cl);
            loadPlugins(true);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @PreDestroy
    public void destroyPlugins() {

        final Map<String, TaskFlowFactory> factories = getFactories();

        for (TaskFlowFactory factory : factories.values()) {
            for (Method method : factory.getClass().getDeclaredMethods()) {
                if (method.getAnnotation(PreDestroy.class) != null) {
                    ReflectionUtils.makeAccessible(method);
                    try {
                        method.invoke(factory, (Object[]) null);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(
                                "THIS IS NOT HAPPENING!!! Method had been made accessible but is not accessible anyway",
                                e);
                    } catch (InvocationTargetException e) {
                        throw new RuntimeException(
                                "Could not call PreDestroy method (" + method.toGenericString() + ")", e);
                    }
                }
            }
        }
    }

    public int pluginCount() {
        return getFactories().size();
    }

    public void listPlugins() {
        Map<String, TaskFlowFactory> plugins = getFactories();
        for (String k : plugins.keySet()) {
            logger.debug(k + ": " + plugins.get(k).getVersion() + " class: " + plugins.get(k).getClass().getName());
        }
    }

    public void register(TaskFlowFactory tff, Map<String, TaskFlowFactory> plugins) {

        if (plugins.containsKey(tff.getTaskFlowKey()))
            throw new IllegalStateException("plugin " + tff.getTaskFlowKey() + " already exists");

        logger.debug("registering factory: " + tff.getTaskFlowKey());
        plugins.put(tff.getTaskFlowKey(), tff);

        final GNDMSInjector injector = system.getInstanceDir().getSystemAccessInjector();
        injector.injectMembers(tff);
        tff.setInjector(injector);
        Session session = system.getDao().beginSession();
        try {
            tff.registerType(session);
            session.success();
        } finally {
            session.finish();
        }
    }

    public void checkDeps() {

        Map<String, TaskFlowFactory> plugins = getFactories();
        List<String> missing = new ArrayList<String>();

        for (String k : plugins.keySet()) {
            TaskFlowFactory<?, ?> tff = plugins.get(k);
            for (String dep : tff.depends()) {
                if (!plugins.containsKey(dep))
                    missing.add(dep);
            }
        }

        if (missing.size() != 0) {
            StringBuilder mes = new StringBuilder();
            mes.append("Missing plugin dependencies detected:");
            for (String k : missing) {
                mes.append('\n');
                mes.append(k);
            }
            logger.warn(mes.toString());
        }
    }

    @Override
    public void setFactories(Map<String, TaskFlowFactory> factories) {

        if (hasFactories)
            throw new IllegalStateException("factories are already set");

        hasFactories = true;
        super.setFactories(factories); // overriden method implementation
    }

    public GNDMSystem getSystem() {

        return system;
    }

    public void setSystem(final GNDMSystem system) {

        this.system = system;
    }

    public ClassLoader getCl() {

        return cl;
    }

    public void setCl(final ClassLoader cl) {

        this.cl = cl;
    }

    public String getPluginDir() {

        return pluginDir;
    }

    public void setPluginDir(final String pluginDir) {

        this.pluginDir = pluginDir;
    }
}