diff options
author | Decebal Suiu <decebal.suiu@gmail.com> | 2014-01-11 06:16:49 +0200 |
---|---|---|
committer | Decebal Suiu <decebal.suiu@gmail.com> | 2014-01-11 06:16:49 +0200 |
commit | 4662ecf8f869bcaee5c5ce6418cad56e29cf38c4 (patch) | |
tree | eb20281d30cfdc30ff6fd2a4c62b20665239e6fa | |
parent | c6a1bbda46fcd99ae48fbb8589e0138a67bf3e1d (diff) | |
parent | b57f307e53623dab815f3dfb0817be5b5dd5f503 (diff) | |
download | pf4j-4662ecf8f869bcaee5c5ce6418cad56e29cf38c4.tar.gz pf4j-4662ecf8f869bcaee5c5ce6418cad56e29cf38c4.zip |
Merge branch 'master' of https://github.com/decebals/pf4j
-rw-r--r-- | README.md | 12 | ||||
-rw-r--r-- | demo/api/pom.xml | 4 | ||||
-rw-r--r-- | demo/app/pom.xml | 4 | ||||
-rw-r--r-- | demo/plugins/plugin1/pom.xml | 246 | ||||
-rw-r--r-- | demo/plugins/plugin2/pom.xml | 230 | ||||
-rw-r--r-- | demo/plugins/plugin2/src/main/java/ro/fortsoft/pf4j/demo/hello/HelloPlugin.java | 2 | ||||
-rw-r--r-- | demo/plugins/pom.xml | 212 | ||||
-rw-r--r-- | demo/pom.xml | 4 | ||||
-rw-r--r-- | pf4j/pom.xml | 24 | ||||
-rw-r--r-- | pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java | 126 | ||||
-rw-r--r-- | pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java | 2 | ||||
-rw-r--r-- | pf4j/src/main/java/ro/fortsoft/pf4j/Extension.java | 3 | ||||
-rw-r--r-- | pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionsIndexer.java | 135 | ||||
-rw-r--r-- | pf4j/src/main/java/ro/fortsoft/pf4j/SezpozExtensionFinder.java | 80 | ||||
-rw-r--r-- | pf4j/src/main/resources/META-INF/services/javax.annotation.processing.Processor | 1 | ||||
-rw-r--r-- | pom.xml | 2 |
16 files changed, 632 insertions, 455 deletions
@@ -8,7 +8,7 @@ Current build status: [ 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. @@ -101,8 +101,8 @@ You can define an extension point in your application using **ExtensionPoint** i } -Another important internal component is **ExtensionFinder** that describes how plugin manager discovers extensions for extensions points. -**DefaultExtensionFinder** is a "link" to **SezpozExtensionFinder** that looks up extensions using **Extension** annotation. +Another important internal component is **ExtensionFinder** that describes how the plugin manager discovers extensions for the extensions points. +**DefaultExtensionFinder** looks up extensions using **Extension** annotation. You can control extension instance creation overriding `createExtensionFactory` method from DefaultExtensionFinder. public class WelcomePlugin extends Plugin { @@ -135,7 +135,7 @@ The output is: >>> Welcome >>> Hello -You can inject your custom component (for example PluginDescriptorFinder, ExtensionFinder, PluginClasspath, ...) in DefaultPluginManager just override createXXX methods (factory method pattern). +You can inject your custom component (for example PluginDescriptorFinder, ExtensionFinder, PluginClasspath, ...) in DefaultPluginManager just override `create...` methods (factory method pattern). Example: @@ -154,7 +154,7 @@ and in plugin respository you must have a plugin.properties file with the below For more information please see the demo sources. -Development runtime mode +Development mode -------------------------- PF4J can run in two modes: **DEVELOPMENT** and **DEPLOYMENT**. The DEPLOYMENT(default) mode is the standard workflow for plugins creation: create a new maven module for each plugin, codding the plugin (declares new extension points and/or @@ -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. diff --git a/demo/api/pom.xml b/demo/api/pom.xml index 1818ec5..6d76d93 100644 --- a/demo/api/pom.xml +++ b/demo/api/pom.xml @@ -4,12 +4,12 @@ <parent> <groupId>ro.fortsoft.pf4j.demo</groupId> <artifactId>pf4j-demo-parent</artifactId> - <version>0.6-SNAPSHOT</version> + <version>0.7-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>pf4j-demo-api</artifactId> - <version>0.6-SNAPSHOT</version> + <version>0.7-SNAPSHOT</version> <packaging>jar</packaging> <name>Demo Api</name> diff --git a/demo/app/pom.xml b/demo/app/pom.xml index bf07815..13c442d 100644 --- a/demo/app/pom.xml +++ b/demo/app/pom.xml @@ -4,12 +4,12 @@ <parent> <groupId>ro.fortsoft.pf4j.demo</groupId> <artifactId>pf4j-demo-parent</artifactId> - <version>0.6-SNAPSHOT</version> + <version>0.7-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>pf4j-demo-app</artifactId> - <version>0.6-SNAPSHOT</version> + <version>0.7-SNAPSHOT</version> <packaging>jar</packaging> <name>Demo App</name> diff --git a/demo/plugins/plugin1/pom.xml b/demo/plugins/plugin1/pom.xml index bf8abe5..9c6db84 100644 --- a/demo/plugins/plugin1/pom.xml +++ b/demo/plugins/plugin1/pom.xml @@ -1,123 +1,123 @@ -<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <parent>
- <groupId>ro.fortsoft.pf4j.demo</groupId>
- <artifactId>pf4j-demo-plugins</artifactId>
- <version>0.6-SNAPSHOT</version>
- </parent>
-
- <modelVersion>4.0.0</modelVersion>
- <artifactId>pf4j-demo-plugin1</artifactId>
- <version>0.6-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>Demo Plugin #1</name>
-
- <properties>
- <plugin.id>welcome-plugin</plugin.id>
- <plugin.class>ro.fortsoft.pf4j.demo.welcome.WelcomePlugin</plugin.class>
- <plugin.version>0.0.1</plugin.version>
- <plugin.provider>Decebal Suiu</plugin.provider>
- <plugin.dependencies />
- </properties>
-
- <build>
- <plugins>
- <!-- DOESN'T WORK WITH MAVEN 3 (I defined the plugin metadata in properties section)
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>properties-maven-plugin</artifactId>
- <version>1.0-alpha-2</version>
- <executions>
- <execution>
- <phase>initialize</phase>
- <goals>
- <goal>read-project-properties</goal>
- </goals>
- <configuration>
- <files>
- <file>plugin.properties</file>
- </files>
- </configuration>
- </execution>
- </executions>
- </plugin>
- -->
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-antrun-plugin</artifactId>
- <version>1.6</version>
- <executions>
- <execution>
- <id>unzip jar file</id>
- <phase>package</phase>
- <configuration>
- <target>
- <unzip src="target/${artifactId}-${version}.${packaging}" dest="target/plugin-classes" />
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
- <version>2.3</version>
- <configuration>
- <descriptors>
- <descriptor>
- src/main/assembly/assembly.xml
- </descriptor>
- </descriptors>
- <appendAssemblyId>false</appendAssemblyId>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
- <phase>package</phase>
- <goals>
- <goal>attached</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <version>2.4</version>
- <configuration>
- <archive>
- <manifestEntries>
- <Plugin-Id>${plugin.id}</Plugin-Id>
- <Plugin-Class>${plugin.class}</Plugin-Class>
- <Plugin-Version>${plugin.version}</Plugin-Version>
- <Plugin-Provider>${plugin.provider}</Plugin-Provider>
- <Plugin-Dependencies>${plugin.dependencies}</Plugin-Dependencies>
- </manifestEntries>
- </archive>
- </configuration>
- </plugin>
-
- <plugin>
- <artifactId>maven-deploy-plugin</artifactId>
- <configuration>
- <skip>true</skip>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
- <dependencies>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.6</version>
- </dependency>
- </dependencies>
-
-</project>
+<?xml version="1.0"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <parent> + <groupId>ro.fortsoft.pf4j.demo</groupId> + <artifactId>pf4j-demo-plugins</artifactId> + <version>0.7-SNAPSHOT</version> + </parent> + + <modelVersion>4.0.0</modelVersion> + <artifactId>pf4j-demo-plugin1</artifactId> + <version>0.7-SNAPSHOT</version> + <packaging>jar</packaging> + <name>Demo Plugin #1</name> + + <properties> + <plugin.id>welcome-plugin</plugin.id> + <plugin.class>ro.fortsoft.pf4j.demo.welcome.WelcomePlugin</plugin.class> + <plugin.version>0.0.1</plugin.version> + <plugin.provider>Decebal Suiu</plugin.provider> + <plugin.dependencies /> + </properties> + + <build> + <plugins> + <!-- DOESN'T WORK WITH MAVEN 3 (I defined the plugin metadata in properties section) + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>properties-maven-plugin</artifactId> + <version>1.0-alpha-2</version> + <executions> + <execution> + <phase>initialize</phase> + <goals> + <goal>read-project-properties</goal> + </goals> + <configuration> + <files> + <file>plugin.properties</file> + </files> + </configuration> + </execution> + </executions> + </plugin> + --> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.6</version> + <executions> + <execution> + <id>unzip jar file</id> + <phase>package</phase> + <configuration> + <target> + <unzip src="target/${artifactId}-${version}.${packaging}" dest="target/plugin-classes" /> + </target> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <version>2.3</version> + <configuration> + <descriptors> + <descriptor> + src/main/assembly/assembly.xml + </descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>attached</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.4</version> + <configuration> + <archive> + <manifestEntries> + <Plugin-Id>${plugin.id}</Plugin-Id> + <Plugin-Class>${plugin.class}</Plugin-Class> + <Plugin-Version>${plugin.version}</Plugin-Version> + <Plugin-Provider>${plugin.provider}</Plugin-Provider> + <Plugin-Dependencies>${plugin.dependencies}</Plugin-Dependencies> + </manifestEntries> + </archive> + </configuration> + </plugin> + + <plugin> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.6</version> + </dependency> + </dependencies> + +</project> diff --git a/demo/plugins/plugin2/pom.xml b/demo/plugins/plugin2/pom.xml index 4b84e9f..23acb7a 100644 --- a/demo/plugins/plugin2/pom.xml +++ b/demo/plugins/plugin2/pom.xml @@ -1,115 +1,115 @@ -<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <parent>
- <groupId>ro.fortsoft.pf4j.demo</groupId>
- <artifactId>pf4j-demo-plugins</artifactId>
- <version>0.6-SNAPSHOT</version>
- </parent>
-
- <modelVersion>4.0.0</modelVersion>
- <artifactId>pf4j-demo-plugin2</artifactId>
- <version>0.6-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>Demo Plugin #2</name>
-
- <properties>
- <plugin.id>hello-plugin</plugin.id>
- <plugin.class>ro.fortsoft.pf4j.demo.hello.HelloPlugin</plugin.class>
- <plugin.version>0.0.1</plugin.version>
- <plugin.provider>Decebal Suiu</plugin.provider>
- <plugin.dependencies />
- </properties>
-
- <build>
- <plugins>
- <!-- DOESN'T WORK WITH MAVEN 3 (I defined the plugin metadata in properties section)
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>properties-maven-plugin</artifactId>
- <version>1.0-alpha-2</version>
- <executions>
- <execution>
- <phase>initialize</phase>
- <goals>
- <goal>read-project-properties</goal>
- </goals>
- <configuration>
- <files>
- <file>plugin.properties</file>
- </files>
- </configuration>
- </execution>
- </executions>
- </plugin>
- -->
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-antrun-plugin</artifactId>
- <version>1.6</version>
- <executions>
- <execution>
- <id>unzip jar file</id>
- <phase>package</phase>
- <configuration>
- <target>
- <unzip src="target/${artifactId}-${version}.${packaging}" dest="target/plugin-classes" />
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
- <version>2.3</version>
- <configuration>
- <descriptors>
- <descriptor>
- src/main/assembly/assembly.xml
- </descriptor>
- </descriptors>
- <appendAssemblyId>false</appendAssemblyId>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
- <phase>package</phase>
- <goals>
- <goal>attached</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <version>2.4</version>
- <configuration>
- <archive>
- <manifestEntries>
- <Plugin-Id>${plugin.id}</Plugin-Id>
- <Plugin-Class>${plugin.class}</Plugin-Class>
- <Plugin-Version>${plugin.version}</Plugin-Version>
- <Plugin-Provider>${plugin.provider}</Plugin-Provider>
- <Plugin-Dependencies>${plugin.dependencies}</Plugin-Dependencies>
- </manifestEntries>
- </archive>
- </configuration>
- </plugin>
-
- <plugin>
- <artifactId>maven-deploy-plugin</artifactId>
- <configuration>
- <skip>true</skip>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-</project>
+<?xml version="1.0"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <parent> + <groupId>ro.fortsoft.pf4j.demo</groupId> + <artifactId>pf4j-demo-plugins</artifactId> + <version>0.7-SNAPSHOT</version> + </parent> + + <modelVersion>4.0.0</modelVersion> + <artifactId>pf4j-demo-plugin2</artifactId> + <version>0.7-SNAPSHOT</version> + <packaging>jar</packaging> + <name>Demo Plugin #2</name> + + <properties> + <plugin.id>hello-plugin</plugin.id> + <plugin.class>ro.fortsoft.pf4j.demo.hello.HelloPlugin</plugin.class> + <plugin.version>0.0.1</plugin.version> + <plugin.provider>Decebal Suiu</plugin.provider> + <plugin.dependencies /> + </properties> + + <build> + <plugins> + <!-- DOESN'T WORK WITH MAVEN 3 (I defined the plugin metadata in properties section) + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>properties-maven-plugin</artifactId> + <version>1.0-alpha-2</version> + <executions> + <execution> + <phase>initialize</phase> + <goals> + <goal>read-project-properties</goal> + </goals> + <configuration> + <files> + <file>plugin.properties</file> + </files> + </configuration> + </execution> + </executions> + </plugin> + --> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.6</version> + <executions> + <execution> + <id>unzip jar file</id> + <phase>package</phase> + <configuration> + <target> + <unzip src="target/${artifactId}-${version}.${packaging}" dest="target/plugin-classes" /> + </target> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <version>2.3</version> + <configuration> + <descriptors> + <descriptor> + src/main/assembly/assembly.xml + </descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>attached</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.4</version> + <configuration> + <archive> + <manifestEntries> + <Plugin-Id>${plugin.id}</Plugin-Id> + <Plugin-Class>${plugin.class}</Plugin-Class> + <Plugin-Version>${plugin.version}</Plugin-Version> + <Plugin-Provider>${plugin.provider}</Plugin-Provider> + <Plugin-Dependencies>${plugin.dependencies}</Plugin-Dependencies> + </manifestEntries> + </archive> + </configuration> + </plugin> + + <plugin> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/demo/plugins/plugin2/src/main/java/ro/fortsoft/pf4j/demo/hello/HelloPlugin.java b/demo/plugins/plugin2/src/main/java/ro/fortsoft/pf4j/demo/hello/HelloPlugin.java index d8963fc..7072e3d 100644 --- a/demo/plugins/plugin2/src/main/java/ro/fortsoft/pf4j/demo/hello/HelloPlugin.java +++ b/demo/plugins/plugin2/src/main/java/ro/fortsoft/pf4j/demo/hello/HelloPlugin.java @@ -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 diff --git a/demo/plugins/pom.xml b/demo/plugins/pom.xml index 05f6c27..30c2848 100644 --- a/demo/plugins/pom.xml +++ b/demo/plugins/pom.xml @@ -1,106 +1,106 @@ -<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <parent>
- <groupId>ro.fortsoft.pf4j.demo</groupId>
- <artifactId>pf4j-demo-parent</artifactId>
- <version>0.6-SNAPSHOT</version>
- </parent>
-
- <modelVersion>4.0.0</modelVersion>
- <groupId>ro.fortsoft.pf4j.demo</groupId>
- <artifactId>pf4j-demo-plugins</artifactId>
- <version>0.6-SNAPSHOT</version>
- <packaging>pom</packaging>
- <name>Demo Plugins Parent</name>
-
- <build>
- <resources>
- <resource>
- <filtering>false</filtering>
- <directory>src/main/java</directory>
- <excludes>
- <exclude>**/*.java</exclude>
- </excludes>
- </resource>
- <resource>
- <directory>src/main/resources</directory>
- </resource>
- </resources>
-
- <plugins>
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <phase>process-sources</phase>
- <goals>
- <goal>copy-dependencies</goal>
- </goals>
- <configuration>
- <outputDirectory>${project.build.directory}/lib</outputDirectory>
- <excludeScope>provided</excludeScope>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
-
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.eclipse.m2e</groupId>
- <artifactId>lifecycle-mapping</artifactId>
- <version>1.0.0</version>
- <configuration>
- <lifecycleMappingMetadata>
- <pluginExecutions>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <versionRange>[2.0,)</versionRange>
- <goals>
- <goal>copy-dependencies</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <!--
- <execute/>
- -->
- <execute>
- <runOnIncremental>true</runOnIncremental>
- <runOnConfiguration>true</runOnConfiguration>
- </execute>
- </action>
- </pluginExecution>
- </pluginExecutions>
- </lifecycleMappingMetadata>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-
- <modules>
- <module>plugin1</module>
- <module>plugin2</module>
- </modules>
-
- <dependencies>
- <dependency>
- <groupId>ro.fortsoft.pf4j</groupId>
- <artifactId>pf4j</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
-
- <dependency>
- <groupId>ro.fortsoft.pf4j.demo</groupId>
- <artifactId>pf4j-demo-api</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- </dependencies>
-
-</project>
+<?xml version="1.0"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <parent> + <groupId>ro.fortsoft.pf4j.demo</groupId> + <artifactId>pf4j-demo-parent</artifactId> + <version>0.7-SNAPSHOT</version> + </parent> + + <modelVersion>4.0.0</modelVersion> + <groupId>ro.fortsoft.pf4j.demo</groupId> + <artifactId>pf4j-demo-plugins</artifactId> + <version>0.7-SNAPSHOT</version> + <packaging>pom</packaging> + <name>Demo Plugins Parent</name> + + <build> + <resources> + <resource> + <filtering>false</filtering> + <directory>src/main/java</directory> + <excludes> + <exclude>**/*.java</exclude> + </excludes> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + + <plugins> + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <phase>process-sources</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <outputDirectory>${project.build.directory}/lib</outputDirectory> + <excludeScope>provided</excludeScope> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + + <pluginManagement> + <plugins> + <plugin> + <groupId>org.eclipse.m2e</groupId> + <artifactId>lifecycle-mapping</artifactId> + <version>1.0.0</version> + <configuration> + <lifecycleMappingMetadata> + <pluginExecutions> + <pluginExecution> + <pluginExecutionFilter> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <versionRange>[2.0,)</versionRange> + <goals> + <goal>copy-dependencies</goal> + </goals> + </pluginExecutionFilter> + <action> + <!-- + <execute /> + --> + <execute> + <runOnIncremental>true</runOnIncremental> + <runOnConfiguration>true</runOnConfiguration> + </execute> + </action> + </pluginExecution> + </pluginExecutions> + </lifecycleMappingMetadata> + </configuration> + </plugin> + </plugins> + </pluginManagement> + </build> + + <modules> + <module>plugin1</module> + <module>plugin2</module> + </modules> + + <dependencies> + <dependency> + <groupId>ro.fortsoft.pf4j</groupId> + <artifactId>pf4j</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>ro.fortsoft.pf4j.demo</groupId> + <artifactId>pf4j-demo-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + </dependencies> + +</project> diff --git a/demo/pom.xml b/demo/pom.xml index 7d00cd7..9ce0579 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -4,13 +4,13 @@ <parent> <groupId>ro.fortsoft.pf4j</groupId> <artifactId>pf4j-parent</artifactId> - <version>0.6-SNAPSHOT</version> + <version>0.7-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>ro.fortsoft.pf4j.demo</groupId> <artifactId>pf4j-demo-parent</artifactId> - <version>0.6-SNAPSHOT</version> + <version>0.7-SNAPSHOT</version> <packaging>pom</packaging> <name>Demo Parent</name> diff --git a/pf4j/pom.xml b/pf4j/pom.xml index 0859a55..f06491e 100644 --- a/pf4j/pom.xml +++ b/pf4j/pom.xml @@ -4,23 +4,29 @@ <parent> <groupId>ro.fortsoft.pf4j</groupId> <artifactId>pf4j-parent</artifactId> - <version>0.6-SNAPSHOT</version> + <version>0.7-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>pf4j</artifactId> - <version>0.6-SNAPSHOT</version> + <version>0.7-SNAPSHOT</version> <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> diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java index 66c1936..f61195b 100644 --- a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java +++ b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java @@ -12,16 +12,134 @@ */ 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 ExtensionFactory extensionFactory; + private volatile Set<String> entries; + public DefaultExtensionFinder(ClassLoader classLoader) { - super(classLoader); + this.classLoader = classLoader; + this.extensionFactory = createExtensionFactory(); } + @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 = extensionFactory.create(extensionType); + if (instance != null) { + Extension extension = extensionType.getAnnotation(Extension.class); + log.debug("Added extension {} with ordinal {}", extensionType.getName(), extension.ordinal()); + result.add(new ExtensionWrapper<T>(type.cast(instance), extension.ordinal())); + } + } else { + log.warn("{} is not an extension for extension point {}", extensionType.getName(), type.getName()); + } + } catch (ClassNotFoundException 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; + } + + /** + * Add the possibility to override the ExtensionFactory. + * The default implementation uses Class.newInstance() method. + */ + protected ExtensionFactory createExtensionFactory() { + return new ExtensionFactory() { + + @Override + public Object create(Class<?> extensionType) { + log.debug("Create instance for extension {}", extensionType.getName()); + + try { + return extensionType.newInstance(); + } catch (InstantiationException e) { + log.error(e.getMessage(), e); + } catch (IllegalAccessException e) { + log.error(e.getMessage(), e); + } + + return null; + } + + }; + } + + 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; + } + + /** + * Creates an extension instance. + */ + public static interface ExtensionFactory { + + public Object create(Class<?> extensionType); + + } + } diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java index 30658cd..fcb839b 100644 --- a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java @@ -210,7 +210,7 @@ public class DefaultPluginManager implements PluginManager { filterList.add(new NotFileFilter(createHiddenPluginFilter()));
FileFilter pluginsFilter = new AndFileFilter(filterList);
File[] directories = pluginsDirectory.listFiles(pluginsFilter);
- log.debug("Possible plugins: {}", Arrays.asList(directories));
+ log.debug("Found possible {} plugins: {}", directories.length, Arrays.asList(directories));
if (directories.length == 0) {
log.info("No plugins");
return;
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/Extension.java b/pf4j/src/main/java/ro/fortsoft/pf4j/Extension.java index f1b7cac..f2c01bd 100644 --- a/pf4j/src/main/java/ro/fortsoft/pf4j/Extension.java +++ b/pf4j/src/main/java/ro/fortsoft/pf4j/Extension.java @@ -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 index 0000000..c4a8f40 --- /dev/null +++ b/pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionsIndexer.java @@ -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 index 3f5014c..0000000 --- a/pf4j/src/main/java/ro/fortsoft/pf4j/SezpozExtensionFinder.java +++ /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 index 0000000..a944d7c --- /dev/null +++ b/pf4j/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +ro.fortsoft.pf4j.ExtensionsIndexer @@ -10,7 +10,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>ro.fortsoft.pf4j</groupId> <artifactId>pf4j-parent</artifactId> - <version>0.6-SNAPSHOT</version> + <version>0.7-SNAPSHOT</version> <packaging>pom</packaging> <name>PF4J Parent</name> <description>Plugin Framework for Java</description> |