Package eas.plugins

Source Code of eas.plugins.PluginFactory$SuperFinder

/*
* File name:    PluginFactory.java
* Java version: 6.0
* Author(s):    Lukas König
* File created: 20.05.2009
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
*   author or licensor (but not in any way that suggests that they endorse
*   you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
*   distribute the resulting work only under the same or a similar license to
*   this one.
*
* + Detailed license conditions (Germany):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/

package eas.plugins;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;

import eas.miscellaneous.StaticMethods;
import eas.miscellaneous.inspectJAR_RAM.Finder;
import eas.miscellaneous.system.Reflections;
import eas.miscellaneous.system.ZipIt;
import eas.plugins.standard.other.NullPlugin;
import eas.simulation.EASRunnable;
import eas.startSetup.GlobalVariables;
import eas.startSetup.ParCollection;
import eas.startSetup.Starter;

/**
* Implements a factory for plugin objects. All plugins contained in the
* package hierarchy get scanned automatically.
*
* @author Lukas König
*/
public class PluginFactory {

    /**
     * Das Standardplugin.
     */
    public static final String STD_PLUGIN = new NullPlugin().id();
   
    /**
     * Lists all classes of the framework.
     *
     * @return  All classes of the framework.
     *          Note that classes from .jar files are ignored.
     */
    private static LinkedList<Class<?>> getAllClasses() {
        return Reflections.getAllClassesRecursively(GlobalVariables.ROOT_PACKAGE_NAME);
    }
   
    @SuppressWarnings("rawtypes")
    class SuperFinder extends Finder.DefaultSpecification {

        @Override
        public boolean isClassFinder() {
            return true;
        }

        @Override
        public java.lang.String entryPath() {
            return "eas.plugins.Plugin";
        }

        public LinkedList<Class> classes = new LinkedList<Class>();
       
        @Override
        public boolean accepts(final java.lang.Class class_) {
            if (Plugin.class.isAssignableFrom(class_)) {
                classes.add(class_);
                return true;
            } else {
                return false;
            }
        }
    }
   
    public static LinkedList<Class<Plugin<?>>> STORED_PLUGINS
        = loadPluginsFromFile(false);
   
    public static final String PLUGIN_STORAGE_FILE_NAME = "plugins.dat";

    @SuppressWarnings("unchecked")
  public static LinkedList<Class<Plugin<?>>> loadPluginsFromFile(boolean includeHidden) {
        LinkedList<Class<Plugin<?>>> plugins;
       
        try {
            plugins = deserializePlugins(PLUGIN_STORAGE_FILE_NAME);
        } catch (Exception e) {
            GlobalVariables.getPrematureParameters().logInfo("<PluginFactory> Plugins could not be loaded from file: " + e.toString());
            GlobalVariables.getPrematureParameters().logInfo("<PluginFactory> Searching plugins in local class tree...");
           
            if (new File(".").getAbsolutePath().contains(" ")) {
                GlobalVariables.getPrematureParameters().logWarning(
                        "<PluginFactory> EAS should not be located in a directory path which contains white spaces. "
                        + "Otherwise automatic plugin detection may be delayed.\n"
                        + "Path: " + new File(".").getAbsolutePath());
            }
           
            plugins = findAllNonAbstractPluginClasses(includeHidden);
            GlobalVariables.getPrematureParameters().logInfo("<PluginFactory> " + plugins.size() + " Plugins extracted from local class tree.");
            try {
                serializePlugins(plugins, PLUGIN_STORAGE_FILE_NAME);
            } catch (IOException e1) {
                GlobalVariables.getPrematureParameters().log(StaticMethods.LOG_ERROR, "<PluginFactory> Plugins not serialized.");
                throw new RuntimeException(e1.toString());
            }
        }
       
        // Try extracting plugins from JAR file.
        if (plugins == null || plugins.size() == 0) {
          GlobalVariables.getPrematureParameters().logInfo(
              "<PluginFactory> No plugins found in local class tree. Try generating JAR and extracting from there.");
         
          try {
        PluginFactory.createJAR("./TEMP-JAR---123.jar");
       
              SuperFinder f = new PluginFactory().new SuperFinder();
              Finder ff = new Finder(f);
              ff.inspectJar(new JarFile(new File("./TEMP-JAR---123.jar")));
             
              for (Class<?> c : f.classes) {
                  if (!c.isInterface() && !c.isAnonymousClass()
                          && !Modifier.toString(c.getModifiers()).contains("abstract")) {
                      PluginProperties p = c.getAnnotation(PluginProperties.class);
                     
                      boolean hidden = false;
                      if (p != null) {
                          hidden = p.pluginIsHidden();
                      }
                     
                      if (includeHidden || !hidden) {
                        plugins.add((Class<Plugin<?>>) c);
                      }
                  }
              }
             
              String succ = "Successful -- ";
             
              if (plugins == null || plugins.size() == 0) {
                succ = "Sorry, did not work (try removing white spaces!) -- ";
              }
             
            GlobalVariables.getPrematureParameters().logInfo(
                "<PluginFactory> " + succ + plugins.size() + " plugins extracted from JAR.");

            // Store plugins.
              try {
                  serializePlugins(plugins, PLUGIN_STORAGE_FILE_NAME);
              } catch (IOException e1) {
                  GlobalVariables.getPrematureParameters().log(StaticMethods.LOG_ERROR, "<PluginFactory> Plugins not serialized.");
                  throw new RuntimeException(e1.toString());
              }
      } catch (IOException e) {
        GlobalVariables.getPrematureParameters().logError(
            "<PluginFactory> Plugins could not be extracted from JAR (" + e.toString() + ")");
      } finally {
        StaticMethods.deleteDAT("TEMP-JAR---123.jar");
      }
        }
       
        if (plugins == null || plugins.size() == 0) {
          GlobalVariables.getPrematureParameters().logError("<PluginFactory> No plugins loaded -- you will not be able to start a simulation.");
          plugins = new LinkedList<Class<Plugin<?>>>();
        }

        return plugins;
    }
   
    public static void serializePlugins(LinkedList<Class<Plugin<?>>> o, String filename) throws IOException {
        FileOutputStream f_out = new FileOutputStream(filename);
        ObjectOutputStream obj_out = new ObjectOutputStream (f_out);
        obj_out.writeObject (o);
        obj_out.close();
        f_out.close();
    }
   
    @SuppressWarnings("unchecked")
    private static LinkedList<Class<Plugin<?>>> deserializePlugins(String filename)
            throws IOException, ClassNotFoundException {
        GlobalVariables.getPrematureParameters().logInfo("<PluginFactory> Try loading plugins from file: " + filename + "...");
        FileInputStream f_in = new FileInputStream(filename);
        ObjectInputStream obj_in = new ObjectInputStream (f_in);
        LinkedList<Class<Plugin<?>>> obj = (LinkedList<Class<Plugin<?>>>) obj_in.readObject();
        GlobalVariables.getPrematureParameters().logInfo("<PluginFactory> " + obj.size() + " Plugins loaded from file: " + filename + ".");
        obj_in.close();
        f_in.close();
        return obj;
    }
   
    /**
     * Search all plugins from package tree and jars.
     *
     * @return  All classes from the framework that implement the plugin
     *          interface and which do NOT contain the plugin property
     *          "pluginIsHidden = true" within the PluginProperties
     *          annotation.
     */
    @SuppressWarnings({ "unchecked" })
    public static LinkedList<Class<Plugin<?>>> findAllNonAbstractPluginClasses(boolean includeHidden) {
        LinkedList<Class<Plugin<?>>> classes = new LinkedList<Class<Plugin<?>>>();
       
        // Find plugins in local tree.
        try {
            for (Class<?> c : getAllClasses()) {
                if (Plugin.class.isAssignableFrom(c)) {
                    if (!c.isInterface() && !c.isAnonymousClass()
                            && !Modifier.toString(c.getModifiers()).contains("abstract")) {
                        PluginProperties p = c.getAnnotation(PluginProperties.class);
                       
                        boolean hidden = false;
                        if (p != null) {
                            hidden = p.pluginIsHidden();
                        }
                       
                        if (includeHidden || !hidden) {
                            classes.add((Class<Plugin<?>>) c);
                        }
                    }
                }
            }
        } catch (Exception e) {
        }

        // Find plugins in jar file.
        try {
            SuperFinder f = new PluginFactory().new SuperFinder();
            Finder ff = new Finder(f);
           
            ff.inspectJar();
           
            for (Class<?> c : f.classes) {
                if (!c.isInterface() && !c.isAnonymousClass()
                        && !Modifier.toString(c.getModifiers()).contains("abstract")) {
                    PluginProperties p = c.getAnnotation(PluginProperties.class);
                   
                    boolean hidden = false;
                    if (p != null) {
                        hidden = p.pluginIsHidden();
                    }
                   
                    if (includeHidden || !hidden) {
                        classes.add((Class<Plugin<?>>) c);
                    }
                }
            }
        } catch (Exception e) {

        }

        return classes;
    }
   
    private static boolean outputWritten = false;
   
    /**
     * Gibt ein konstantes Plugin mit dem übergebenen Namen zurück.
     *
     * @param plugName  Der Name des Plugins.
     * @param params    Die Parameter.
     *
     * @return Das Plugin, falls ein Matching mit dem Namen gefunden
     *         wurde, <code>null</code> sonst.
     */
    public static Plugin<?> getKonstPlug(
            final String plugName,
            final ParCollection params) {
        Plugin<?> plugin = null;
        LinkedList<Class<Plugin<?>>> pluginClasses = PluginFactory.STORED_PLUGINS;
        LinkedList<Plugin<?>> plugins = new LinkedList<Plugin<?>>();
        Plugin<?> testObject;
       
       
        for (Class<Plugin<?>> c : pluginClasses) {
            try {
                testObject = c.newInstance();
                plugins.add(testObject);
                if (testObject.id().equalsIgnoreCase(plugName)) {
                    if (plugin != null) {
                        StaticMethods.log(
                                StaticMethods.LOG_ERROR,
                                "<PluginFactory> Plugin id "
                                + plugName
                                + " exists more than once. "
                                + "Chosing randomly.",
                                params);
                    }
                    plugin = testObject;
                }
            } catch (Exception e) {
                StaticMethods.logError("<PluginFactory> There was a problem with plugin " + c + ":\n", params);
                e.printStackTrace();
            }
        }

        if (!outputWritten) {
            for (Plugin<?> p : plugins) {
                try {
                    StaticMethods.log(
                            StaticMethods.LOG_INFO,
                            "<PluginFactory> Plugin found \"" + p.id() + "\".",
                            params);
                } catch (Exception e) {
                   
                }
            }
            outputWritten = true;
        }
       
        /*
         * Plugins from jar-files have to be included in the code here.
         * Use the pattern given once as an example in the comment below.
         * Note that possibly existing plugins with the same id will be
         * overwritten by the plugin from the jar file (being logged as an
         * error).
         */
       
/*        if (plugName.equalsIgnoreCase(new TestPlug1().id())) {
            if (plugin != null) {
                SonstMeth.log(
                        SonstMeth.LOG_ERROR,
                        "Plugin id "
                        + plugName
                        + " exists more than once. "
                        + "Chosing randomly.",
                        params);
            }

            plugin = new TestPlug1();
          }
*/
       
        if (plugin == null) {
            StaticMethods.log(
                    StaticMethods.LOG_ERROR,
                    "<PluginFactory> Plugin not found: " + plugName,
                    params);
           
//            GeneralDialog dia = new GeneralDialog(
//                    null,
//                    "WARNING: Plugin " + plugName + " not found.",
//                    "PluginFactory: " + "\"" + plugName + "\" not found.",
//                    GeneralDialog.OK_BUTT,
//                    null);
//            dia.setVisible(true);
           
            return null;
        }
       
        StaticMethods.log(
                StaticMethods.LOG_STAGE1,
                "<PluginFactory> Plugin generated: " + plugName,
                params);
       
        return plugin;
    }
   
    /**
     * @param plugStr  Der zu überprüfende String.
     *
     * @return  Ob der String zu einem registrierten Plugin gehört.
     */
    public static boolean existsPlugin(final String plugStr) {
        return PluginFactory.getKonstPlug(plugStr, null) != null;
    }
   
    private static void createJAR(String jarFileName) throws IOException {
      File jarFile = new File(jarFileName);
     
        // JAR file name + (relative) path.
        final JarOutputStream jos = ZipIt.getJARstream(
                jarFile,
                Starter.class.getName());
        ZipIt.addToJARDirectoryRecursively(
                jos,
                Starter.class.getPackage().getName().split("[.]")[0], // "eas"
                jarFile);
        jos.close();
    }
   
    private static LinkedList<Class<AbstractDefaultPlugin<?>>> getAllADPluginClasses() {
        LinkedList<Class<AbstractDefaultPlugin<?>>> list = new LinkedList<>();
       
        for (Class<Plugin<?>> pClass : STORED_PLUGINS) {
            try {
                @SuppressWarnings("unchecked")
                Class<AbstractDefaultPlugin<?>> adpClass = (Class<AbstractDefaultPlugin<?>>)
                                    ((AbstractDefaultPlugin<?>) pClass.newInstance()).getClass();
                list.add(adpClass);
            } catch (Exception e) {}
        }
       
        return list;
    }

    /**
     * Returns all plugins that can be used in the context of a given EASRunnable.
     *
     * @param rbl  The runnable to check againts.
     *
     * @return  The list of matching plugins.
     */
    public static LinkedList<Class<AbstractDefaultPlugin<?>>> getMatchingPlugins(EASRunnable rbl) {
        LinkedList<Class<AbstractDefaultPlugin<?>>> matchingPlugins = new LinkedList<>();

        for (Class<AbstractDefaultPlugin<?>> pClass : getAllADPluginClasses()) {
            Class<?> desiredClass = StaticMethods.getTypeArguments(AbstractDefaultPlugin.class, pClass).get(0);
            if (rbl != null && desiredClass != null && desiredClass.isAssignableFrom(rbl.getClass())) {
                matchingPlugins.add(pClass);
            }
        }
       
        return matchingPlugins;
    }
}
TOP

Related Classes of eas.plugins.PluginFactory$SuperFinder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.