diff options
author | David Ostrovsky <david@ostrovsky.org> | 2014-03-10 01:50:49 +0100 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2014-04-10 18:58:09 -0400 |
commit | 84f406bfd20ec2076cf7616e7f396ad480513bc4 (patch) | |
tree | 661045f193871d676c1c06b996b831469cfc067c | |
parent | 261ddf0fcf9a55fbb5b4e7c6c2cdb4c2f8c860fe (diff) | |
download | gitblit-84f406bfd20ec2076cf7616e7f396ad480513bc4.tar.gz gitblit-84f406bfd20ec2076cf7616e7f396ad480513bc4.zip |
Add plugins/extension infrastructure
Plugins are stored in `${baseFolder}/plugins` and are loaded
during startup by the PluginManager.
A plugin defines it's metadata in META-INF/MANIFEST.MF:
Plugin-Class: com.gitblit.plugins.cookbook.CookbookPlugin
Plugin-Dependencies: foo, bar
Plugin-Id: gitblit-plugin
Plugin-Provider: John Doe
Plugin-Version: 1.0
Plugins can define extension points that can be implemented
by other plugins and they can depend on other plugins:
Plugin-Dependencies: foo, bar
During the load phase, a directed acyclic graph is built and the loading
order of the dependency chain is reversed using a topological sort;
parent followed by children. The parent plugin classloader is the
combined classloader of all parent plugins.
Change-Id: I738821fa2bff02a5dbe339a944cc7e3c4dd8e299
-rw-r--r-- | .classpath | 1 | ||||
-rw-r--r-- | build.moxie | 1 | ||||
-rw-r--r-- | gitblit.iml | 11 | ||||
-rw-r--r-- | src/main/distrib/data/gitblit.properties | 8 | ||||
-rw-r--r-- | src/main/java/WEB-INF/web.xml | 3 | ||||
-rw-r--r-- | src/main/java/com/gitblit/DaggerModule.java | 13 | ||||
-rw-r--r-- | src/main/java/com/gitblit/FederationClient.java | 2 | ||||
-rw-r--r-- | src/main/java/com/gitblit/GitBlit.java | 7 | ||||
-rw-r--r-- | src/main/java/com/gitblit/dagger/DaggerFilter.java | 2 | ||||
-rw-r--r-- | src/main/java/com/gitblit/manager/GitblitManager.java | 18 | ||||
-rw-r--r-- | src/main/java/com/gitblit/manager/IGitblit.java | 3 | ||||
-rw-r--r-- | src/main/java/com/gitblit/manager/IPluginManager.java | 39 | ||||
-rw-r--r-- | src/main/java/com/gitblit/manager/PluginManager.java | 56 | ||||
-rw-r--r-- | src/main/java/com/gitblit/servlet/GitblitContext.java | 2 | ||||
-rw-r--r-- | src/main/java/com/gitblit/servlet/SyndicationFilter.java | 1 |
15 files changed, 157 insertions, 10 deletions
@@ -76,6 +76,7 @@ <classpathentry kind="lib" path="ext/args4j-2.0.26.jar" sourcepath="ext/src/args4j-2.0.26.jar" /> <classpathentry kind="lib" path="ext/jedis-2.3.1.jar" sourcepath="ext/src/jedis-2.3.1.jar" /> <classpathentry kind="lib" path="ext/commons-pool2-2.0.jar" sourcepath="ext/src/commons-pool2-2.0.jar" /> + <classpathentry kind="lib" path="ext/pf4j-0.6.jar" sourcepath="ext/src/pf4j-0.6.jar" /> <classpathentry kind="lib" path="ext/junit-4.11.jar" sourcepath="ext/src/junit-4.11.jar" /> <classpathentry kind="lib" path="ext/hamcrest-core-1.3.jar" sourcepath="ext/src/hamcrest-core-1.3.jar" /> <classpathentry kind="lib" path="ext/selenium-java-2.28.0.jar" sourcepath="ext/src/selenium-java-2.28.0.jar" /> diff --git a/build.moxie b/build.moxie index 6015becc..eb2878a8 100644 --- a/build.moxie +++ b/build.moxie @@ -174,6 +174,7 @@ dependencies: - compile 'args4j:args4j:2.0.26' :war :fedclient :authority - compile 'commons-codec:commons-codec:1.7' :war - compile 'redis.clients:jedis:2.3.1' :war +- compile 'ro.fortsoft.pf4j:pf4j:0.6' :war - test 'junit' # Dependencies for Selenium web page testing - test 'org.seleniumhq.selenium:selenium-java:${selenium.version}' @jar diff --git a/gitblit.iml b/gitblit.iml index a48f12ad..ed067f28 100644 --- a/gitblit.iml +++ b/gitblit.iml @@ -790,6 +790,17 @@ </SOURCES> </library> </orderEntry> + <orderEntry type="module-library"> + <library name="pf4j-0.6.jar"> + <CLASSES> + <root url="jar://$MODULE_DIR$/ext/pf4j-0.6.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES> + <root url="jar://$MODULE_DIR$/ext/src/pf4j-0.6.jar!/" /> + </SOURCES> + </library> + </orderEntry> <orderEntry type="module-library" scope="TEST"> <library name="junit-4.11.jar"> <CLASSES> diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index 64a52f5c..762344b4 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -1844,3 +1844,11 @@ server.requireClientCertificates = false # SINCE 0.5.0
# RESTART REQUIRED
server.shutdownPort = 8081
+
+# Base folder for plugins.
+# This folder may contain Gitblit plugins
+#
+# SINCE 1.6.0
+# RESTART REQUIRED
+# BASEFOLDER
+plugins.folder = ${baseFolder}/plugins
diff --git a/src/main/java/WEB-INF/web.xml b/src/main/java/WEB-INF/web.xml index 1451ec63..77456d47 100644 --- a/src/main/java/WEB-INF/web.xml +++ b/src/main/java/WEB-INF/web.xml @@ -199,7 +199,6 @@ <url-pattern>/robots.txt</url-pattern>
</servlet-mapping>
-
<!-- Git Access Restriction Filter
<url-pattern> MUST match:
* GitServlet
@@ -322,4 +321,4 @@ <url-pattern>/*</url-pattern>
</filter-mapping>
-</web-app>
\ No newline at end of file +</web-app>
diff --git a/src/main/java/com/gitblit/DaggerModule.java b/src/main/java/com/gitblit/DaggerModule.java index b109f1db..1805c4ec 100644 --- a/src/main/java/com/gitblit/DaggerModule.java +++ b/src/main/java/com/gitblit/DaggerModule.java @@ -19,9 +19,11 @@ import javax.inject.Singleton; import com.gitblit.manager.AuthenticationManager; import com.gitblit.manager.FederationManager; +import com.gitblit.manager.PluginManager; import com.gitblit.manager.IAuthenticationManager; import com.gitblit.manager.IFederationManager; import com.gitblit.manager.IGitblit; +import com.gitblit.manager.IPluginManager; import com.gitblit.manager.INotificationManager; import com.gitblit.manager.IProjectManager; import com.gitblit.manager.IRepositoryManager; @@ -62,6 +64,7 @@ import dagger.Provides; IRepositoryManager.class, IProjectManager.class, IFederationManager.class, + IPluginManager.class, // the monolithic manager IGitblit.class, @@ -88,6 +91,10 @@ public class DaggerModule { return new UserManager(runtimeManager); } + @Provides @Singleton IPluginManager providePluginManager(IRuntimeManager runtimeManager) { + return new PluginManager(runtimeManager); + } + @Provides @Singleton IAuthenticationManager provideAuthenticationManager( IRuntimeManager runtimeManager, IUserManager userManager) { @@ -161,7 +168,8 @@ public class DaggerModule { IPublicKeyManager publicKeyManager, IRepositoryManager repositoryManager, IProjectManager projectManager, - IFederationManager federationManager) { + IFederationManager federationManager, + IPluginManager pluginManager) { return new GitBlit( runtimeManager, @@ -171,7 +179,8 @@ public class DaggerModule { publicKeyManager, repositoryManager, projectManager, - federationManager); + federationManager, + pluginManager); } @Provides @Singleton GitBlitWebApp provideWebApplication( diff --git a/src/main/java/com/gitblit/FederationClient.java b/src/main/java/com/gitblit/FederationClient.java index d20025f0..67a68654 100644 --- a/src/main/java/com/gitblit/FederationClient.java +++ b/src/main/java/com/gitblit/FederationClient.java @@ -97,7 +97,7 @@ public class FederationClient { UserManager users = new UserManager(runtime).start();
RepositoryManager repositories = new RepositoryManager(runtime, users).start();
FederationManager federation = new FederationManager(runtime, notifications, repositories).start();
- IGitblit gitblit = new GitblitManager(runtime, notifications, users, null, null, repositories, null, federation);
+ IGitblit gitblit = new GitblitManager(runtime, notifications, users, null, null, repositories, null, federation, null);
FederationPullService puller = new FederationPullService(gitblit, federation.getFederationRegistrations()) {
@Override
diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java index b223d03c..147b2e16 100644 --- a/src/main/java/com/gitblit/GitBlit.java +++ b/src/main/java/com/gitblit/GitBlit.java @@ -28,6 +28,7 @@ import com.gitblit.manager.IAuthenticationManager; import com.gitblit.manager.IFederationManager; import com.gitblit.manager.IGitblit; import com.gitblit.manager.INotificationManager; +import com.gitblit.manager.IPluginManager; import com.gitblit.manager.IProjectManager; import com.gitblit.manager.IRepositoryManager; import com.gitblit.manager.IRuntimeManager; @@ -71,7 +72,8 @@ public class GitBlit extends GitblitManager { IPublicKeyManager publicKeyManager, IRepositoryManager repositoryManager, IProjectManager projectManager, - IFederationManager federationManager) { + IFederationManager federationManager, + IPluginManager pluginManager) { super(runtimeManager, notificationManager, @@ -80,7 +82,8 @@ public class GitBlit extends GitblitManager { publicKeyManager, repositoryManager, projectManager, - federationManager); + federationManager, + pluginManager); this.injector = ObjectGraph.create(getModules()); diff --git a/src/main/java/com/gitblit/dagger/DaggerFilter.java b/src/main/java/com/gitblit/dagger/DaggerFilter.java index 1c73d4b7..68fe6058 100644 --- a/src/main/java/com/gitblit/dagger/DaggerFilter.java +++ b/src/main/java/com/gitblit/dagger/DaggerFilter.java @@ -39,7 +39,7 @@ public abstract class DaggerFilter implements Filter { inject(objectGraph);
}
- protected abstract void inject(ObjectGraph dagger);
+ protected abstract void inject(ObjectGraph dagger) throws ServletException;
@Override
public void destroy() {
diff --git a/src/main/java/com/gitblit/manager/GitblitManager.java b/src/main/java/com/gitblit/manager/GitblitManager.java index 8856715a..34c101e2 100644 --- a/src/main/java/com/gitblit/manager/GitblitManager.java +++ b/src/main/java/com/gitblit/manager/GitblitManager.java @@ -43,6 +43,8 @@ import org.eclipse.jgit.transport.RefSpec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ro.fortsoft.pf4j.PluginWrapper; + import com.gitblit.Constants; import com.gitblit.Constants.AccessPermission; import com.gitblit.Constants.AccessRestrictionType; @@ -116,6 +118,8 @@ public class GitblitManager implements IGitblit { protected final IFederationManager federationManager; + protected final IPluginManager pluginManager; + public GitblitManager( IRuntimeManager runtimeManager, INotificationManager notificationManager, @@ -124,7 +128,8 @@ public class GitblitManager implements IGitblit { IPublicKeyManager publicKeyManager, IRepositoryManager repositoryManager, IProjectManager projectManager, - IFederationManager federationManager) { + IFederationManager federationManager, + IPluginManager pluginManager) { this.settings = runtimeManager.getSettings(); this.runtimeManager = runtimeManager; @@ -135,6 +140,7 @@ public class GitblitManager implements IGitblit { this.repositoryManager = repositoryManager; this.projectManager = projectManager; this.federationManager = federationManager; + this.pluginManager = pluginManager; } @Override @@ -1171,4 +1177,14 @@ public class GitblitManager implements IGitblit { public boolean isIdle(Repository repository) { return repositoryManager.isIdle(repository); } + + @Override + public <T> List<T> getExtensions(Class<T> clazz) { + return pluginManager.getExtensions(clazz); + } + + @Override + public PluginWrapper whichPlugin(Class<?> clazz) { + return pluginManager.whichPlugin(clazz); + } } diff --git a/src/main/java/com/gitblit/manager/IGitblit.java b/src/main/java/com/gitblit/manager/IGitblit.java index f4221cf9..7961a06b 100644 --- a/src/main/java/com/gitblit/manager/IGitblit.java +++ b/src/main/java/com/gitblit/manager/IGitblit.java @@ -36,7 +36,8 @@ public interface IGitblit extends IManager, IAuthenticationManager, IRepositoryManager, IProjectManager, - IFederationManager { + IFederationManager, + IPluginManager { /** * Returns a list of repository URLs and the user access permission. diff --git a/src/main/java/com/gitblit/manager/IPluginManager.java b/src/main/java/com/gitblit/manager/IPluginManager.java new file mode 100644 index 00000000..670e9769 --- /dev/null +++ b/src/main/java/com/gitblit/manager/IPluginManager.java @@ -0,0 +1,39 @@ +/* + * Copyright 2014 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.manager; + +import java.util.List; + +import ro.fortsoft.pf4j.PluginWrapper; + +public interface IPluginManager extends IManager { + + /** + * Retrieves the extension for given class 'clazz'. + * + * @param clazz extension point class to retrieve extension for + * @return list of extensions + */ + public <T> List<T> getExtensions(Class<T> clazz); + + /** + * Retrieves the {@link PluginWrapper} that loaded the given class 'clazz'. + * + * @param clazz extension point class to retrieve extension for + * @return PluginWrapper that loaded the given class + */ + public PluginWrapper whichPlugin(Class<?> clazz); +} diff --git a/src/main/java/com/gitblit/manager/PluginManager.java b/src/main/java/com/gitblit/manager/PluginManager.java new file mode 100644 index 00000000..5eb00e92 --- /dev/null +++ b/src/main/java/com/gitblit/manager/PluginManager.java @@ -0,0 +1,56 @@ +/* + * Copyright 2014 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.manager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ro.fortsoft.pf4j.DefaultPluginManager; + +import com.gitblit.Keys; + +/** + * The plugin manager maintains the lifecycle of plugins. It is exposed as + * Dagger bean. The extension consumers supposed to retrieve plugin manager + * from the Dagger DI and retrieve extensions provided by active plugins. + * + * @author David Ostrovsky + * + */ +public class PluginManager extends DefaultPluginManager implements + IPluginManager { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + public PluginManager(IRuntimeManager runtimeManager) { + super(runtimeManager.getFileOrFolder(Keys.plugins.folder, + "${baseFolder}/plugins")); + } + + @Override + public PluginManager start() { + logger.info("Plugin manager started"); + loadPlugins(); + startPlugins(); + return this; + } + + @Override + public PluginManager stop() { + stopPlugins(); + return null; + } +} diff --git a/src/main/java/com/gitblit/servlet/GitblitContext.java b/src/main/java/com/gitblit/servlet/GitblitContext.java index cf8bba01..a98fe192 100644 --- a/src/main/java/com/gitblit/servlet/GitblitContext.java +++ b/src/main/java/com/gitblit/servlet/GitblitContext.java @@ -41,6 +41,7 @@ import com.gitblit.dagger.DaggerContext; import com.gitblit.manager.IAuthenticationManager; import com.gitblit.manager.IFederationManager; import com.gitblit.manager.IGitblit; +import com.gitblit.manager.IPluginManager; import com.gitblit.manager.IManager; import com.gitblit.manager.INotificationManager; import com.gitblit.manager.IProjectManager; @@ -184,6 +185,7 @@ public class GitblitContext extends DaggerContext { startManager(injector, IProjectManager.class); startManager(injector, IFederationManager.class); startManager(injector, IGitblit.class); + startManager(injector, IPluginManager.class); logger.info(""); logger.info("All managers started."); diff --git a/src/main/java/com/gitblit/servlet/SyndicationFilter.java b/src/main/java/com/gitblit/servlet/SyndicationFilter.java index 67a845ea..b399588b 100644 --- a/src/main/java/com/gitblit/servlet/SyndicationFilter.java +++ b/src/main/java/com/gitblit/servlet/SyndicationFilter.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.text.MessageFormat;
import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
|