summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ostrovsky <david@ostrovsky.org>2014-03-10 01:50:49 +0100
committerJames Moger <james.moger@gitblit.com>2014-04-10 18:58:09 -0400
commit84f406bfd20ec2076cf7616e7f396ad480513bc4 (patch)
tree661045f193871d676c1c06b996b831469cfc067c
parent261ddf0fcf9a55fbb5b4e7c6c2cdb4c2f8c860fe (diff)
downloadgitblit-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--.classpath1
-rw-r--r--build.moxie1
-rw-r--r--gitblit.iml11
-rw-r--r--src/main/distrib/data/gitblit.properties8
-rw-r--r--src/main/java/WEB-INF/web.xml3
-rw-r--r--src/main/java/com/gitblit/DaggerModule.java13
-rw-r--r--src/main/java/com/gitblit/FederationClient.java2
-rw-r--r--src/main/java/com/gitblit/GitBlit.java7
-rw-r--r--src/main/java/com/gitblit/dagger/DaggerFilter.java2
-rw-r--r--src/main/java/com/gitblit/manager/GitblitManager.java18
-rw-r--r--src/main/java/com/gitblit/manager/IGitblit.java3
-rw-r--r--src/main/java/com/gitblit/manager/IPluginManager.java39
-rw-r--r--src/main/java/com/gitblit/manager/PluginManager.java56
-rw-r--r--src/main/java/com/gitblit/servlet/GitblitContext.java2
-rw-r--r--src/main/java/com/gitblit/servlet/SyndicationFilter.java1
15 files changed, 157 insertions, 10 deletions
diff --git a/.classpath b/.classpath
index d3aec7e8..252a7c96 100644
--- a/.classpath
+++ b/.classpath
@@ -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;