]> source.dussan.org Git - pf4j.git/commitdiff
remove sezpoz dependency
authorDecebal Suiu <decebal.suiu@gmail.com>
Thu, 10 Oct 2013 12:11:23 +0000 (15:11 +0300)
committerDecebal Suiu <decebal.suiu@gmail.com>
Thu, 10 Oct 2013 12:11:23 +0000 (15:11 +0300)
README.md
demo/plugins/plugin2/src/main/java/ro/fortsoft/pf4j/demo/hello/HelloPlugin.java
pf4j/pom.xml
pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java
pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
pf4j/src/main/java/ro/fortsoft/pf4j/Extension.java
pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionsIndexer.java [new file with mode: 0644]
pf4j/src/main/java/ro/fortsoft/pf4j/SezpozExtensionFinder.java [deleted file]
pf4j/src/main/resources/META-INF/services/javax.annotation.processing.Processor [new file with mode: 0644]

index e11b75076b61b1431a5fb599f87ce8d9cc8fab4c..15b7947b385e46f67b04868e0958f9b1c8bccfa3 100644 (file)
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Current build status:  [![Build Status](https://buildhive.cloudbees.com/job/dece
 Features/Benefits
 -------------------
 With PF4J you can easily transform a monolithic java application in a modular application. 
-PF4J is an open source (Apache license) lightweight (around 35KB) plugin framework for java, with minimal dependencies and very extensible (see PluginDescriptorFinder and ExtensionFinder).
+PF4J is an open source (Apache license) lightweight (around 50KB) plugin framework for java, with minimal dependencies (only slf4j-api) and very extensible (see PluginDescriptorFinder and ExtensionFinder).
 
 No XML, only Java.
 
@@ -102,7 +102,7 @@ You can define an extension point in your application using **ExtensionPoint** i
     }
 
 Another important internal component is **ExtensionFinder** that describes how the plugin manager discovers extensions for the extensions points.   
-**DefaultExtensionFinder** is a "link" to **SezpozExtensionFinder** that looks up extensions using **Extension** annotation.
+**DefaultExtensionFinder** looks up extensions using **Extension** annotation.
 
     public class WelcomePlugin extends Plugin {
 
@@ -169,7 +169,7 @@ You can retrieve the current runtime mode using `PluginManager.getRuntimeMode()`
 The DefaultPluginManager determines automatically the correct runtime mode and for DEVELOPMENT mode overrides some components(pluginsDirectory is __"../plugins"__, __PropertiesPluginDescriptorFinder__ as PluginDescriptorFinder, __DevelopmentPluginClasspath__ as PluginClassPath).  
 Another advantage of DEVELOPMENT runtime mode is that you can execute some code lines only in this mode (for example more debug messages). 
 
-If you use maven as build manger, after each dependency modification in you plugin (maven module) you must run Maven>Update Project...   
+If you use maven as build manger, after each dependency modification in your plugin (maven module) you must run Maven>Update Project...   
 
 
 For more details see the demo application. 
index d8963fcde46c318b2934a94c2665eedac9ed34ba..7072e3dc27cd7954be543ab6e66b7d4ffb8ce6ba 100644 (file)
@@ -38,7 +38,7 @@ public class HelloPlugin extends Plugin {
         System.out.println("HelloPlugin.stop()");
     }
 
-    @Extension
+    @Extension(ordinal=1)
     public static class HelloGreeting implements Greeting {
 
        @Override
index 0859a554790817f3314869b537c27a33c1195428..52e120b17b60be30428bc335c21f4d25c90eb57b 100644 (file)
     <packaging>jar</packaging>
     <name>PF4J</name>
     <description>Plugin Framework for Java</description>
-        
-    <dependencies>
-        <dependency>
-            <groupId>net.java.sezpoz</groupId>
-            <artifactId>sezpoz</artifactId>
-            <version>1.9</version>
-        </dependency>
 
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-compiler-plugin</artifactId>
+                               <configuration>
+                                       <compilerArgument>-proc:none</compilerArgument>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+       
+    <dependencies>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
index 66c1936869dab23a89925102ea985305a3c6041c..5ab989b6a7ed5de73f63691005085070f2127c2d 100644 (file)
  */
 package ro.fortsoft.pf4j;
 
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
- * The default implementation for ExtensionFinder. 
- * Now, this class it's a "link" to {@link ro.fortsoft.pf4j.SezpozExtensionFinder}.
+ * The default implementation for ExtensionFinder.
+ * All extensions declared in a plugin are indexed in a file "META-INF/extensions.idx".
+ * This class lookup extensions in all extensions index files "META-INF/extensions.idx". 
  * 
  * @author Decebal Suiu
  */
-public class DefaultExtensionFinder extends SezpozExtensionFinder {
+public class DefaultExtensionFinder implements ExtensionFinder {
 
+       private static final Logger log = LoggerFactory.getLogger(DefaultExtensionFinder.class);
+       
+       private ClassLoader classLoader;
+       private volatile Set<String> entries;
+       
        public DefaultExtensionFinder(ClassLoader classLoader) {
-               super(classLoader);
+               this.classLoader = classLoader;
+       }
+       
+       @Override
+       public <T> List<ExtensionWrapper<T>> find(Class<T> type) {
+               log.debug("Find extensions for extension point {}", type.getName());
+        List<ExtensionWrapper<T>> result = new ArrayList<ExtensionWrapper<T>>();
+        if (entries == null) {
+               entries = readIndexFiles();
+        }
+                
+        for (String entry : entries) {
+               try {
+                       Class<?> extensionType = classLoader.loadClass(entry);
+                       log.debug("Checking extension type {}", extensionType.getName());
+               if (type.isAssignableFrom(extensionType)) {
+                    Object instance = extensionType.newInstance();
+                    if (instance != null) {
+                               Extension extension = extensionType.getAnnotation(Extension.class);
+                               log.debug("Added extension {} with ordinal {}", extensionType, extension.ordinal());
+                               result.add(new ExtensionWrapper<T>(type.cast(instance), extension.ordinal()));
+                    }
+               } else {
+                       log.warn("{} is not an extension for extension point {}", extensionType, type.getName());
+               }
+               } catch (ClassNotFoundException e) {
+                       log.error(e.getMessage(), e);
+               } catch (InstantiationException e) {
+                       log.error(e.getMessage(), e);
+                       } catch (IllegalAccessException e) {
+                               log.error(e.getMessage(), e);
+                       }
+        }
+        
+        if (entries.isEmpty()) {
+               log.debug("No extensions found for extension point {}", type.getName());
+        } else {
+               log.debug("Found {} extensions for extension point {}", entries.size(), type.getName());
+        }
+
+        // sort by "ordinal" property
+        Collections.sort(result);
+               
+               return result;
        }
        
+       private Set<String> readIndexFiles() {
+               log.debug("Reading extensions index files");
+               Set<String> entries = new HashSet<String>();
+               
+               try {
+                       Enumeration<URL> indexFiles = classLoader.getResources(ExtensionsIndexer.EXTENSIONS_RESOURCE);
+                       while (indexFiles.hasMoreElements()) {
+                               Reader reader = new InputStreamReader(indexFiles.nextElement().openStream(), "UTF-8");
+                               ExtensionsIndexer.readIndex(reader, entries);
+                       }
+               } catch (IOException e) {
+                       log.error(e.getMessage(), e);
+               }                       
+
+        if (entries.isEmpty()) {
+               log.debug("No extensions found");
+        } else {
+               log.debug("Found possible {} extensions", entries.size());
+        }
+
+               return entries;
+       }       
+       
 }
index 30658cdd2df8b8fb56da50dccd45db71c783f15a..fcb839b6ca8b3f3dfa404d1bd58ca24e0b9e6787 100644 (file)
@@ -210,7 +210,7 @@ public class DefaultPluginManager implements PluginManager {
         filterList.add(new NotFileFilter(createHiddenPluginFilter()));\r
         FileFilter pluginsFilter = new AndFileFilter(filterList);\r
         File[] directories = pluginsDirectory.listFiles(pluginsFilter);\r
-        log.debug("Possible plugins: {}", Arrays.asList(directories));\r
+        log.debug("Found possible {} plugins: {}", directories.length, Arrays.asList(directories));\r
         if (directories.length == 0) {\r
                log.info("No plugins");\r
                return;\r
index f1b7cace5d67e801516b8f34277ef69f65787183..f2c01bd81c779fc2667d2e6d539986a1a8df10e5 100644 (file)
@@ -19,12 +19,9 @@ import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
-import net.java.sezpoz.Indexable;
-
 /**
  * @author Decebal Suiu
  */
-@Indexable
 @Retention(RUNTIME)
 @Target(TYPE)
 @Documented
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionsIndexer.java b/pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionsIndexer.java
new file mode 100644 (file)
index 0000000..c4a8f40
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2013 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;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+
+/**
+ * @author Decebal Suiu
+ */
+public class ExtensionsIndexer extends AbstractProcessor {
+
+       public static final String EXTENSIONS_RESOURCE = "META-INF/extensions.idx";
+       
+       private List<TypeElement> extensions = new ArrayList<TypeElement>();
+       
+       @Override
+       public SourceVersion getSupportedSourceVersion() {
+               return SourceVersion.latest();
+       }
+
+       @Override
+       public Set<String> getSupportedAnnotationTypes() {
+               Set<String> annotationTypes = new HashSet<String>();
+        annotationTypes.add(Extension.class.getName());
+        
+        return annotationTypes;
+       }
+       
+       @Override
+       public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+               if (roundEnv.processingOver()) {
+            return false;
+        }
+               
+               for (Element element : roundEnv.getElementsAnnotatedWith(Extension.class)) {
+                       if (!(element instanceof TypeElement)) {
+                               continue;
+                       }
+
+                       TypeElement typeElement = (TypeElement) element;
+                       String message = "Extension found in " + processingEnv.getElementUtils().getBinaryName(typeElement).toString();
+                       processingEnv.getMessager().printMessage(Kind.NOTE, message);
+                       extensions.add(typeElement);
+        }
+               
+               /*
+               if (!roundEnv.processingOver()) {
+                       return false;
+               }
+               */
+
+               write();
+               
+               return false;
+//             return true; // no further processing of this annotation type
+       }
+       
+       private void write() {
+               Set<String> entries = new HashSet<String>();
+               for (TypeElement typeElement : extensions) {
+                       entries.add(processingEnv.getElementUtils().getBinaryName(typeElement).toString());
+               }
+               
+               read(entries); // read old entries
+               write(entries); // write entries
+       }
+
+       private void write(Set<String> entries) {
+               try {
+                       FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", EXTENSIONS_RESOURCE);
+                       Writer writer = file.openWriter();
+                       for (String entry : entries) {
+                               writer.write(entry);
+                               writer.write("\n");
+                       }
+                       writer.close();
+               } catch (FileNotFoundException e) {
+                       // it's the first time, create the file
+               } catch (IOException e) {
+                       processingEnv.getMessager().printMessage(Kind.ERROR, e.toString());
+               }
+       }
+       
+       private void read(Set<String> entries) {
+               try {
+                       FileObject file = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", EXTENSIONS_RESOURCE);
+                       readIndex(file.openReader(true), entries);
+               } catch (FileNotFoundException e) {
+               } catch (IOException e) {
+                       // thrown by Eclipse JDT when not found
+               } catch (UnsupportedOperationException e) {
+                       // java6 does not support reading old index files
+               }
+       }
+       
+       public static void readIndex(Reader reader, Set<String> entries) throws IOException {
+               BufferedReader bufferedReader = new BufferedReader(reader);
+               
+               String line;
+               while ((line = bufferedReader.readLine()) != null) {
+                       entries.add(line);
+               }
+               
+               reader.close();
+       }
+       
+}
\ No newline at end of file
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/SezpozExtensionFinder.java b/pf4j/src/main/java/ro/fortsoft/pf4j/SezpozExtensionFinder.java
deleted file mode 100644 (file)
index 3f5014c..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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;
-
-import java.lang.reflect.AnnotatedElement;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import net.java.sezpoz.Index;
-import net.java.sezpoz.IndexItem;
-
-/**
- * Using Sezpoz(http://sezpoz.java.net/) for extensions discovery.
- * 
- * @author Decebal Suiu
- */
-public class SezpozExtensionFinder implements ExtensionFinder {
-
-       private static final Logger log = LoggerFactory.getLogger(SezpozExtensionFinder.class);
-       
-       private volatile List<IndexItem<Extension, Object>> indices;
-       private ClassLoader classLoader;
-       
-       public SezpozExtensionFinder(ClassLoader classLoader) {
-               this.classLoader = classLoader;
-       }
-       
-       @Override
-       public <T> List<ExtensionWrapper<T>> find(Class<T> type) {
-               log.debug("Find extensions for {}", type);
-        List<ExtensionWrapper<T>> result = new ArrayList<ExtensionWrapper<T>>();
-               getIndices();
-//             System.out.println("indices =  "+ indices);
-               for (IndexItem<Extension, Object> item : indices) {
-            try {
-               AnnotatedElement element = item.element();
-               Class<?> extensionType = (Class<?>) element;
-               log.debug("Checking extension type {}", extensionType);
-               if (type.isAssignableFrom(extensionType)) {
-                    Object instance = item.instance();
-                    if (instance != null) {
-                               log.debug("Added extension {}", extensionType);
-                                               result.add(new ExtensionWrapper<T>(type.cast(instance), item.annotation().ordinal()));
-                    }
-                }
-            } catch (InstantiationException e) {
-               log.error(e.getMessage(), e);
-                       }
-               }
-               
-               return result;
-       }
-
-        private List<IndexItem<Extension, Object>> getIndices() {
-         if (indices == null) {
-             indices = new ArrayList<IndexItem<Extension, Object>>(); 
-             Iterator<IndexItem<Extension, Object>> it = Index.load(Extension.class, Object.class, classLoader).iterator();
-             while (it.hasNext()) {
-                indices.add(it.next());
-             }
-         }
-         
-         return indices;
-     }
-        
-}
diff --git a/pf4j/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/pf4j/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644 (file)
index 0000000..a944d7c
--- /dev/null
@@ -0,0 +1 @@
+ro.fortsoft.pf4j.ExtensionsIndexer