]> source.dussan.org Git - pf4j.git/commitdiff
work on plugin dependecy
authorDecebal Suiu <decebal.suiu@gmail.com>
Wed, 7 Nov 2012 11:40:33 +0000 (13:40 +0200)
committerDecebal Suiu <decebal.suiu@gmail.com>
Wed, 7 Nov 2012 11:40:33 +0000 (13:40 +0200)
12 files changed:
README.md
demo/app/src/main/java/ro/fortsoft/pf4j/demo/Boot.java
pf4j/src/main/java/ro/fortsoft/pf4j/CyclicDependencyException.java [new file with mode: 0644]
pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
pf4j/src/main/java/ro/fortsoft/pf4j/DependencyResolver.java
pf4j/src/main/java/ro/fortsoft/pf4j/PluginClassLoader.java
pf4j/src/main/java/ro/fortsoft/pf4j/PluginDependency.java [new file with mode: 0644]
pf4j/src/main/java/ro/fortsoft/pf4j/PluginDescriptor.java
pf4j/src/main/java/ro/fortsoft/pf4j/PluginLoader.java
pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java
pf4j/src/main/java/ro/fortsoft/pf4j/PluginNotFoundException.java [new file with mode: 0644]
pf4j/src/main/java/ro/fortsoft/pf4j/PluginWrapper.java

index 55430c48b47f526265a1119f3fe72abafa0016ab..dc4e01e6e49c894dc3e0396e729101208a6d8c55 100644 (file)
--- a/README.md
+++ b/README.md
@@ -20,12 +20,6 @@ Artifacts
 Using Maven
 -------------------
 
-First you must install the pf4j artifacts in your local maven repository with:
-
-    mvn clean install
-
-I will upload these artifacts in maven central repository as soon as possible.
-
 In your pom.xml you must define the dependencies to PF4J artifacts with:
 
 ```xml
@@ -43,8 +37,8 @@ How to use
 It's very simple to add pf4j in your application:
 
     public static void main(String[] args) {
-       ...
-       
+        ...
+        
         PluginManager pluginManager = new DefaultPluginManager();
         pluginManager.loadPlugins();
         pluginManager.startPlugins();
@@ -118,11 +112,15 @@ In above code I supply an extension for the `Greeting` extension point.
 
 You can retrieve all extensions for an extension point with:
 
-    List<ExtensionWrapper<Greeting>> greetings = pluginManager.getExtensions(Greeting.class);
-    for (ExtensionWrapper<Greeting> greeting : greetings) {
-       System.out.println(">>> " + greeting.getInstance().getGreeting());
+    List<Greeting> greetings = pluginManager.getExtensions(Greeting.class);
+    for (Greeting greeting : greetings) {
+        System.out.println(">>> " + greeting.getGreeting());
     }
 
+The output is:
+
+    >>> Welcome
+    >>> Hello
 
 For more information please see the demo sources.
 
index 9a361fa24f39dda9221f0e702a9d1cb018eef1da..9f218cf78aee16e789499309664d73ee1b7b8a05 100644 (file)
@@ -17,7 +17,6 @@ import java.util.List;
 import org.apache.commons.lang.StringUtils;
 
 import ro.fortsoft.pf4j.DefaultPluginManager;
-import ro.fortsoft.pf4j.ExtensionWrapper;
 import ro.fortsoft.pf4j.PluginManager;
 import ro.fortsoft.pf4j.demo.api.Greeting;
 
@@ -37,9 +36,9 @@ public class Boot {
         pluginManager.loadPlugins();
         pluginManager.startPlugins();
         
-        List<ExtensionWrapper<Greeting>> greetings = pluginManager.getExtensions(Greeting.class);
-        for (ExtensionWrapper<Greeting> greeting : greetings) {
-               System.out.println(">>> " + greeting.getInstance().getGreeting());
+        List<Greeting> greetings = pluginManager.getExtensions(Greeting.class);
+        for (Greeting greeting : greetings) {
+               System.out.println(">>> " + greeting.getGreeting());
         }
         
         pluginManager.stopPlugins();
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/CyclicDependencyException.java b/pf4j/src/main/java/ro/fortsoft/pf4j/CyclicDependencyException.java
new file mode 100644 (file)
index 0000000..483665c
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 Decebal Suiu
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
+ * the License. You may obtain a copy of the License in the LICENSE file, or 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 ro.fortsoft.pf4j;
+
+/**
+ * CyclicDependencyException will be thrown if a cyclic dependency is detected.
+ * 
+ * @author Decebal Suiu
+ */
+class CyclicDependencyException extends PluginException {
+
+       private static final long serialVersionUID = 1L;
+
+       public CyclicDependencyException(String message) {
+               super(message);
+       }
+
+}
index ea56e6736aacbc7e4ac16ae74f46fb33ca919768..2b36357cfe6ef81dca8cd32deffaa9d924ec86ca 100644 (file)
@@ -15,8 +15,6 @@ package ro.fortsoft.pf4j;
 import java.io.File;
 import java.io.FilenameFilter;
 import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -30,7 +28,6 @@ import ro.fortsoft.pf4j.util.UberClassLoader;
 import ro.fortsoft.pf4j.util.Unzip;
 import ro.fortsoft.pf4j.util.ZipFilter;
 
-
 /**
  * Default implementation of the PluginManager interface.
  *
@@ -52,7 +49,7 @@ public class DefaultPluginManager implements PluginManager {
     /**
      * A map of plugins this manager is responsible for (the key is the 'pluginId').
      */
-    private Map<String, Plugin> plugins;
+    private Map<String, PluginWrapper> plugins;
 
     /**
      * A map of plugin class loaders (he key is the 'pluginId').
@@ -67,17 +64,17 @@ public class DefaultPluginManager implements PluginManager {
     /**
      * A list with unresolved plugins (unresolved dependency).
      */
-    private List<Plugin> unresolvedPlugins;
+    private List<PluginWrapper> unresolvedPlugins;
 
     /**
      * A list with resolved plugins (resolved dependency).
      */
-    private List<Plugin> resolvedPlugins;
+    private List<PluginWrapper> resolvedPlugins;
 
     /**
      * A list with disabled plugins.
      */
-    private List<Plugin> disabledPlugins;
+    private List<PluginWrapper> disabledPlugins;
     
     private UberClassLoader uberClassLoader;
 
@@ -96,12 +93,12 @@ public class DefaultPluginManager implements PluginManager {
      */
     public DefaultPluginManager(File pluginsDirectory) {
         this.pluginsDirectory = pluginsDirectory;
-        plugins = new HashMap<String, Plugin>();
+        plugins = new HashMap<String, PluginWrapper>();
         pluginClassLoaders = new HashMap<String, PluginClassLoader>();
         pathToIdMap = new HashMap<String, String>();
-        unresolvedPlugins = new ArrayList<Plugin>();
-        resolvedPlugins = new ArrayList<Plugin>();
-        disabledPlugins = new ArrayList<Plugin>();
+        unresolvedPlugins = new ArrayList<PluginWrapper>();
+        resolvedPlugins = new ArrayList<PluginWrapper>();
+        disabledPlugins = new ArrayList<PluginWrapper>();
         pluginDescriptorFinder = new DefaultPluginDescriptorFinder();
         uberClassLoader = new UberClassLoader();
         extensionFinder = new DefaultExtensionFinder(uberClassLoader);
@@ -110,23 +107,23 @@ public class DefaultPluginManager implements PluginManager {
     /**
      * Retrieves all active plugins.
      */
-    public List<Plugin> getPlugins() {
-        return new ArrayList<Plugin>(plugins.values());
+    public List<PluginWrapper> getPlugins() {
+        return new ArrayList<PluginWrapper>(plugins.values());
     }
 
-       public List<Plugin> getResolvedPlugins() {
+       public List<PluginWrapper> getResolvedPlugins() {
                return resolvedPlugins;
        }
 
-       public Plugin getPlugin(String pluginId) {
+       public PluginWrapper getPlugin(String pluginId) {
                return plugins.get(pluginId);
        }
 
-    public List<Plugin> getUnresolvedPlugins() {
+    public List<PluginWrapper> getUnresolvedPlugins() {
                return unresolvedPlugins;
        }
 
-       public List<Plugin> getDisabledPlugins() {
+       public List<PluginWrapper> getDisabledPlugins() {
                return disabledPlugins;
        }
 
@@ -134,13 +131,13 @@ public class DefaultPluginManager implements PluginManager {
      * Start all active plugins.
      */
     public void startPlugins() {
-       List<Plugin> resolvedPlugins = getResolvedPlugins();
-        for (Plugin plugin : resolvedPlugins) {
+       List<PluginWrapper> resolvedPlugins = getResolvedPlugins();
+        for (PluginWrapper pluginWrapper : resolvedPlugins) {
             try {
-                               plugin.start();
+               LOG.info("Start plugin '" + pluginWrapper.getDescriptor().getPluginId() + "'");
+                               pluginWrapper.getPlugin().start();
                        } catch (PluginException e) {
-                               // TODO Auto-generated catch block
-                               e.printStackTrace();
+                               LOG.error(e.getMessage(), e);
                        }
         }
     }
@@ -149,13 +146,13 @@ public class DefaultPluginManager implements PluginManager {
      * Stop all active plugins.
      */
     public void stopPlugins() {
-       List<Plugin> resolvedPlugins = getResolvedPlugins();
-        for (Plugin plugin : resolvedPlugins) {
+       List<PluginWrapper> resolvedPlugins = getResolvedPlugins();
+        for (PluginWrapper pluginWrapper : resolvedPlugins) {
             try {
-                               plugin.stop();
+               LOG.info("Stop plugin '" + pluginWrapper.getDescriptor().getPluginId() + "'");
+               pluginWrapper.getPlugin().stop();
                        } catch (PluginException e) {
-                               // TODO Auto-generated catch block
-                               e.printStackTrace();
+                               LOG.error(e.getMessage(), e);
                        }
         }
     }
@@ -178,7 +175,6 @@ public class DefaultPluginManager implements PluginManager {
                                expandPluginArchive(zipFile);
                        } catch (IOException e) {
                                LOG.error(e.getMessage(), e);
-                               e.printStackTrace();
                        }
         }
 
@@ -188,9 +184,8 @@ public class DefaultPluginManager implements PluginManager {
         for (String directory : directories) {
             try {
                 loadPlugin(directory);
-            } catch (Exception e) {
+            } catch (PluginException e) {
                                LOG.error(e.getMessage(), e);
-                e.printStackTrace();
             }
         }
 
@@ -201,7 +196,11 @@ public class DefaultPluginManager implements PluginManager {
         }
 
         // resolve 'unresolvedPlugins'
-        resolvePlugins();
+        try {
+                       resolvePlugins();
+               } catch (PluginException e) {
+                       LOG.error(e.getMessage(), e);
+               }
     }
 
     /**
@@ -211,11 +210,17 @@ public class DefaultPluginManager implements PluginManager {
        return pluginClassLoaders.get(pluginId);
     }
 
-       public <T> List<ExtensionWrapper<T>> getExtensions(Class<T> type) {
-               return extensionFinder.find(type);
+       public <T> List<T> getExtensions(Class<T> type) {
+               List<ExtensionWrapper<T>> extensionsWrapper = extensionFinder.find(type);
+               List<T> extensions = new ArrayList<T>(extensionsWrapper.size());
+               for (ExtensionWrapper<T> extensionWrapper : extensionsWrapper) {
+                       extensions.add(extensionWrapper.getInstance());
+               }
+               
+               return extensions;
        }
        
-       private void loadPlugin(String fileName) throws Exception {
+       private void loadPlugin(String fileName) throws PluginException {
         // test for plugin directory
         File pluginDirectory = new File(pluginsDirectory, fileName);
         if (!pluginDirectory.isDirectory()) {
@@ -244,25 +249,20 @@ public class DefaultPluginManager implements PluginManager {
 
         // load plugin
         LOG.debug("Loading plugin '" + pluginPath + "'");
-        PluginWrapper pluginWrapper = new PluginWrapper(pluginDescriptor);
-        PluginLoader pluginLoader = new PluginLoader(this, pluginWrapper, pluginDirectory);
+        PluginLoader pluginLoader = new PluginLoader(this, pluginDescriptor, pluginDirectory);
         pluginLoader.load();
         LOG.debug("Loaded plugin '" + pluginPath + "'");
         
-        // set some variables in plugin wrapper
-        pluginWrapper.setPluginPath(pluginPath);
-        pluginWrapper.setPluginClassLoader(pluginLoader.getPluginClassLoader());
-
-        // create the plugin instance
-        LOG.debug("Creating instance for plugin '" + pluginPath + "'");
-        Plugin plugin = getPluginInstance(pluginWrapper, pluginLoader);
-        LOG.debug("Created instance '" + plugin + "' for plugin '" + pluginPath + "'");
+        // create the plugin wrapper
+        LOG.debug("Creating wrapper for plugin '" + pluginPath + "'");
+        PluginWrapper pluginWrapper = new PluginWrapper(pluginDescriptor, pluginPath, pluginLoader.getPluginClassLoader());
+        LOG.debug("Created wrapper '" + pluginWrapper + "' for plugin '" + pluginPath + "'");
 
         String pluginId = pluginDescriptor.getPluginId();
 
         // add plugin to the list with plugins
-        plugins.put(pluginId, plugin);
-        unresolvedPlugins.add(plugin);
+        plugins.put(pluginId, pluginWrapper);
+        unresolvedPlugins.add(pluginWrapper);
 
         // add plugin class loader to the list with class loaders
         PluginClassLoader pluginClassLoader = pluginLoader.getPluginClassLoader();
@@ -289,39 +289,17 @@ public class DefaultPluginManager implements PluginManager {
         }
     }
 
-    private Plugin getPluginInstance(PluginWrapper pluginWrapper, PluginLoader pluginLoader)
-               throws Exception {
-       String pluginClassName = pluginWrapper.getDescriptor().getPluginClass();
-
-        ClassLoader pluginClassLoader = pluginLoader.getPluginClassLoader();
-        Class<?> pluginClass = pluginClassLoader.loadClass(pluginClassName);
-
-        // once we have the class, we can do some checks on it to ensure
-        // that it is a valid implementation of a plugin.
-        int modifiers = pluginClass.getModifiers();
-        if (Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers)
-                || (!Plugin.class.isAssignableFrom(pluginClass))) {
-            throw new PluginException("The plugin class '" + pluginClassName
-                    + "' is not compatible.");
-        }
-
-        // create the plugin instance
-        Constructor<?> constructor = pluginClass.getConstructor(new Class[] { PluginWrapper.class });
-        Plugin plugin = (Plugin) constructor.newInstance(new Object[] { pluginWrapper });
-
-        return plugin;
-    }
-
-       private void resolvePlugins() {
-        resolveDependencies();
+       private void resolvePlugins() throws PluginException {
+               resolveDependencies();
        }
 
-       private void resolveDependencies() {
+       private void resolveDependencies() throws PluginException {
                DependencyResolver dependencyResolver = new DependencyResolver(unresolvedPlugins);
-        resolvedPlugins = dependencyResolver.getSortedDependencies();
-        for (Plugin plugin : resolvedPlugins) {
-               unresolvedPlugins.remove(plugin);
-               uberClassLoader.addLoader(plugin.getWrapper().getPluginClassLoader());
+               resolvedPlugins = dependencyResolver.getSortedPlugins();
+        for (PluginWrapper pluginWrapper : resolvedPlugins) {
+               unresolvedPlugins.remove(pluginWrapper);
+               uberClassLoader.addLoader(pluginWrapper.getPluginClassLoader());
+               LOG.info("Plugin '" + pluginWrapper.getDescriptor().getPluginId() + "' resolved");
         }
        }
 
index 7485b22b5e98872b53c211011573fdb376af3d85..524d4cc0f04a43d82b01f77efd43d305112be91d 100644 (file)
@@ -28,24 +28,24 @@ class DependencyResolver {
 
        private static final Logger LOG = LoggerFactory.getLogger(DependencyResolver.class);
        
-    private List<Plugin> plugins;
+    private List<PluginWrapper> plugins;
 
-       public DependencyResolver(List<Plugin> plugins) {
+       public DependencyResolver(List<PluginWrapper> plugins) {
                this.plugins = plugins;
        }
 
        /**
         * Get the list of plugins in dependency sorted order.
         */
-       public List<Plugin> getSortedDependencies() {
+       public List<PluginWrapper> getSortedPlugins() throws PluginException {
                DirectedGraph<String> graph = new DirectedGraph<String>();
-               for (Plugin plugin : plugins) {
-                       PluginDescriptor descriptor = plugin.getWrapper().getDescriptor();
+               for (PluginWrapper pluginWrapper : plugins) {
+                       PluginDescriptor descriptor = pluginWrapper.getDescriptor();
                        String pluginId = descriptor.getPluginId();
-                       List<String> dependencies = descriptor.getDependencies();
+                       List<PluginDependency> dependencies = descriptor.getDependencies();
                        if (!dependencies.isEmpty()) {
-                               for (String dependency : dependencies) {
-                                       graph.addEdge(pluginId, dependency);
+                               for (PluginDependency dependency : dependencies) {
+                                       graph.addEdge(pluginId, dependency.getPluginId());
                                }
                        } else {
                                graph.addVertex(pluginId);
@@ -56,12 +56,11 @@ class DependencyResolver {
                List<String> pluginsId = graph.reverseTopologicalSort();
 
                if (pluginsId == null) {
-                       LOG.error("Cyclic dependences !!!");
-                       return null;
+                       throw new CyclicDependencyException("Cyclic dependences !!!" + graph.toString());
                }
 
                LOG.debug("Plugins order: " + pluginsId);
-               List<Plugin> sortedPlugins = new ArrayList<Plugin>();
+               List<PluginWrapper> sortedPlugins = new ArrayList<PluginWrapper>();
                for (String pluginId : pluginsId) {
                        sortedPlugins.add(getPlugin(pluginId));
                }
@@ -69,14 +68,14 @@ class DependencyResolver {
                return sortedPlugins;
        }
 
-       private Plugin getPlugin(String pluginId) {
-               for (Plugin plugin : plugins) {
-                       if (pluginId.equals(plugin.getWrapper().getDescriptor().getPluginId())) {
-                               return plugin;
+       private PluginWrapper getPlugin(String pluginId) throws PluginNotFoundException {
+               for (PluginWrapper pluginWrapper : plugins) {
+                       if (pluginId.equals(pluginWrapper.getDescriptor().getPluginId())) {
+                               return pluginWrapper;
                        }
                }
 
-               return null;
+               throw new PluginNotFoundException(pluginId);
        }
 
 }
index 1d80c928fbb696a873a02a96b6ab5b795f7c31e3..2f7ce1eac393b939d9843106d9c3d39fd86da686 100644 (file)
@@ -28,13 +28,13 @@ class PluginClassLoader extends URLClassLoader {
        private static final String PLUGIN_PACKAGE_PREFIX = "ro.fortsoft.pf4j.";
 
        private PluginManager pluginManager;
-       private PluginWrapper pluginWrapper;
-
-       public PluginClassLoader(PluginManager pluginManager, PluginWrapper pluginWrapper, ClassLoader parent) {
+       private PluginDescriptor pluginDescriptor;
+       
+       public PluginClassLoader(PluginManager pluginManager, PluginDescriptor pluginDescriptor, ClassLoader parent) {
                super(new URL[0], parent);
                
                this.pluginManager = pluginManager;
-               this.pluginWrapper = pluginWrapper;
+               this.pluginDescriptor = pluginDescriptor;
        }
 
        @Override
@@ -74,9 +74,9 @@ class PluginClassLoader extends URLClassLoader {
         }
 
         // look in dependencies
-        List<String> dependencies = pluginWrapper.getDescriptor().getDependencies();
-        for (String dependency : dependencies) {
-               PluginClassLoader classLoader = pluginManager.getPluginClassLoader(dependency);
+        List<PluginDependency> dependencies = pluginDescriptor.getDependencies();
+        for (PluginDependency dependency : dependencies) {
+               PluginClassLoader classLoader = pluginManager.getPluginClassLoader(dependency.getPluginId());
                try {
                        return classLoader.loadClass(className);
                } catch (ClassNotFoundException e) {
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginDependency.java b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginDependency.java
new file mode 100644 (file)
index 0000000..d63b66a
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 Decebal Suiu
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
+ * the License. You may obtain a copy of the License in the LICENSE file, or 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 ro.fortsoft.pf4j;
+
+/**
+ * @author Decebal Suiu
+ */
+public class PluginDependency {
+
+       private String pluginId;
+       private PluginVersion pluginVersion;
+       
+       public PluginDependency(String dependency) {
+               /*
+                int index = dependency.indexOf(':');
+                if (index == -1) {
+                        throw new IllegalArgumentException("Illegal dependency specifier "+ dependency);
+                }
+                
+                this.pluginId = dependency.substring(0, index);
+                this.pluginVersion = PluginVersion.createVersion(dependency.substring(index + 1));
+                */
+               this.pluginId = dependency;
+       }
+
+       public String getPluginId() {
+               return pluginId;
+       }
+
+       public PluginVersion getPluginVersion() {
+               return pluginVersion;
+       }
+
+       @Override
+       public String toString() {
+               return "PluginDependency [pluginId=" + pluginId + ", pluginVersion=" + pluginVersion + "]";
+       }
+       
+}
index 494877eb64c4a268687ace76c3bcecb117148bfb..aa2c4950b39c631871fe0f7a4e4f04bf869882e5 100644 (file)
@@ -33,12 +33,11 @@ class PluginDescriptor {
     private String pluginClass;
     private PluginVersion version;
     private String provider;
-    private String pluginPath;
-    private List<String> dependencies;
+    private List<PluginDependency> dependencies;
     private PluginClassLoader pluginClassLoader;
 
     public PluginDescriptor() {
-        dependencies = new ArrayList<String>();
+        dependencies = new ArrayList<PluginDependency>();
     }
 
     /**
@@ -69,18 +68,11 @@ class PluginDescriptor {
         return provider;
     }
 
-    /**
-     * Returns the path of this plugin relative to plugins directory.
-     */
-    public String getPluginPath() {
-        return pluginPath;
-    }
-
     /**
      * Returns all dependencies declared by this plugin.
      * Returns an empty array if this plugin does not declare any require.
      */
-    public List<String> getDependencies() {
+    public List<PluginDependency> getDependencies() {
         return dependencies;
     }
 
@@ -100,7 +92,6 @@ class PluginDescriptor {
             .append("pluginClass", pluginClass)
             .append("version", version)
             .append("provider", provider)
-            .append("pluginPath", pluginPath)
             .append("dependencies", dependencies)
             .toString();
     }
@@ -120,14 +111,14 @@ class PluginDescriptor {
     void setProvider(String provider) {
         this.provider = provider;
     }
-
-    void setPluginPath(String pluginPath) {
-        this.pluginPath = pluginPath;
-    }
     
     void setDependencies(String dependencies) {
        if (dependencies != null) {
-               this.dependencies = Arrays.asList(StringUtils.split(dependencies, ','));
+               this.dependencies = new ArrayList<PluginDependency>();
+               List<String> tokens = Arrays.asList(StringUtils.split(dependencies, ','));
+               for (String dependency : tokens) {
+                       this.dependencies.add(new PluginDependency(dependency));
+               }
        } else {
                this.dependencies = Collections.emptyList();
        }
index 8ae65e742533e6217daa3ec8431fd2c93496a25c..7533f57ad9798be2b7619a879ba45185bb678625 100644 (file)
@@ -23,7 +23,6 @@ import org.slf4j.LoggerFactory;
 import ro.fortsoft.pf4j.util.DirectoryFilter;
 import ro.fortsoft.pf4j.util.JarFilter;
 
-
 /**
  * Load all informations needed by a plugin.
  * This means add all jar files from 'lib' directory, 'classes'
@@ -53,12 +52,12 @@ class PluginLoader {
 
     private PluginClassLoader pluginClassLoader;
 
-    public PluginLoader(PluginManager pluginManager, PluginWrapper pluginWrapper, File pluginRepository) {
+    public PluginLoader(PluginManager pluginManager, PluginDescriptor pluginDescriptor, File pluginRepository) {
         this.pluginRepository = pluginRepository;
         classesDirectory = new File(pluginRepository, "classes");
         libDirectory = new File(pluginRepository, "lib");
         ClassLoader parent = getClass().getClassLoader(); 
-        pluginClassLoader = new PluginClassLoader(pluginManager, pluginWrapper, parent);        
+        pluginClassLoader = new PluginClassLoader(pluginManager, pluginDescriptor, parent);        
         LOG.debug("Created class loader " + pluginClassLoader);
     }
 
index e191e22df465f72f24342f9449fede98684e4d87..c8e4fe92d396dae662345d280dd4e2292b0920dc 100644 (file)
@@ -25,7 +25,7 @@ public interface PluginManager {
     /**
      * Retrieves all plugins.
      */
-    public List<Plugin> getPlugins();
+    public List<PluginWrapper> getPlugins();
 
     /**
      * Load plugins.
@@ -44,6 +44,6 @@ public interface PluginManager {
 
        public PluginClassLoader getPluginClassLoader(String pluginId);
 
-       public <T> List<ExtensionWrapper<T>> getExtensions(Class<T> type);
+       public <T> List<T> getExtensions(Class<T> type);
        
 }
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginNotFoundException.java b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginNotFoundException.java
new file mode 100644 (file)
index 0000000..67658f3
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 Decebal Suiu
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
+ * the License. You may obtain a copy of the License in the LICENSE file, or 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 ro.fortsoft.pf4j;
+
+/**
+ * @author Decebal Suiu
+ */
+class PluginNotFoundException extends PluginException {
+
+       private static final long serialVersionUID = 1L;
+       
+       private String pluginId;
+
+       public PluginNotFoundException(String pluginId) {
+               super("Plugin '" + pluginId + "' not found.");
+               
+               this.pluginId = pluginId;
+       }
+
+       public String getPluginId() {
+               return pluginId;
+       }
+
+}
index 6d935e0cb8c1e7283966973ffb4f0bbc36f5ed9b..a1a636894f39f91922ba1399eec9d135ba3222a5 100644 (file)
  */
 package ro.fortsoft.pf4j;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
 /**
  * A wrapper over plugin instance.
  *
@@ -22,9 +28,20 @@ public class PluginWrapper {
        PluginDescriptor descriptor;
        String pluginPath;
        PluginClassLoader pluginClassLoader;
+       Plugin plugin;
        
-       public PluginWrapper(PluginDescriptor descriptor) {
+       public PluginWrapper(PluginDescriptor descriptor, String pluginPath, PluginClassLoader pluginClassLoader) {
                this.descriptor = descriptor;
+               this.pluginPath = pluginPath;
+               this.pluginClassLoader = pluginClassLoader;
+               
+               // TODO
+               try {
+                       plugin = createPluginInstance();
+               } catch (Exception e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
        }
        
     /**
@@ -50,12 +67,36 @@ public class PluginWrapper {
        return pluginClassLoader;
     }
 
-       void setPluginPath(String pluginPath) {
-               this.pluginPath = pluginPath;
+    public Plugin getPlugin() {
+               return plugin;
        }
 
-       void setPluginClassLoader(PluginClassLoader pluginClassLoader) {
-               this.pluginClassLoader = pluginClassLoader;
-       }
+       private Plugin createPluginInstance() throws Exception {
+       String pluginClassName = descriptor.getPluginClass();
+        Class<?> pluginClass = pluginClassLoader.loadClass(pluginClassName);
+
+        // once we have the class, we can do some checks on it to ensure
+        // that it is a valid implementation of a plugin.
+        int modifiers = pluginClass.getModifiers();
+        if (Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers)
+                || (!Plugin.class.isAssignableFrom(pluginClass))) {
+            throw new PluginException("The plugin class '" + pluginClassName + "' is not compatible.");
+        }
+
+        // create the plugin instance
+        Constructor<?> constructor = pluginClass.getConstructor(new Class[] { PluginWrapper.class });
+        Plugin plugin = (Plugin) constructor.newInstance(new Object[] { this });
+
+        return plugin;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("descriptor", descriptor)
+            .append("pluginPath", pluginPath)
+            .append("plugin", plugin)
+            .toString();
+    }
 
 }