diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java
index 4a458a6e6a..79236ab679 100644
--- a/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java
+++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java
@@ -132,7 +132,7 @@ public class RepositoryPermission implements PermissionObject, Serializable
{
// Normally we do not have a log of repository permissions having the same size of verbs, but different content.
// Therefore we do not use the verbs themselves for the hash code but only the number of verbs.
- return Objects.hashCode(name, verbs.size(), groupPermission);
+ return Objects.hashCode(name, verbs == null? -1: verbs.size(), groupPermission);
}
diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml
index e6a784ddfe..f3c96af5fc 100644
--- a/scm-webapp/pom.xml
+++ b/scm-webapp/pom.xml
@@ -184,6 +184,12 @@
${guice.version}
+
+ com.google.inject.extensions
+ guice-assistedinject
+ ${guice.version}
+
+
diff --git a/scm-webapp/src/main/java/sonia/scm/BootstrapModule.java b/scm-webapp/src/main/java/sonia/scm/BootstrapModule.java
new file mode 100644
index 0000000000..dcb1fe90cf
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/BootstrapModule.java
@@ -0,0 +1,102 @@
+package sonia.scm;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.throwingproviders.ThrowingProviderBinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import sonia.scm.config.ScmConfiguration;
+import sonia.scm.io.DefaultFileSystem;
+import sonia.scm.io.FileSystem;
+import sonia.scm.plugin.DefaultPluginLoader;
+import sonia.scm.repository.RepositoryDAO;
+import sonia.scm.repository.xml.XmlRepositoryDAO;
+import sonia.scm.security.CipherUtil;
+import sonia.scm.security.DefaultKeyGenerator;
+import sonia.scm.security.KeyGenerator;
+import sonia.scm.store.BlobStoreFactory;
+import sonia.scm.store.ConfigurationEntryStoreFactory;
+import sonia.scm.store.ConfigurationStoreFactory;
+import sonia.scm.store.DataStoreFactory;
+import sonia.scm.store.FileBlobStoreFactory;
+import sonia.scm.store.JAXBConfigurationEntryStoreFactory;
+import sonia.scm.store.JAXBConfigurationStoreFactory;
+import sonia.scm.store.JAXBDataStoreFactory;
+import sonia.scm.util.ScmConfigurationUtil;
+
+public class BootstrapModule extends AbstractModule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BootstrapModule.class);
+
+ private final ClassOverrides overrides;
+ private final DefaultPluginLoader pluginLoader;
+
+ public BootstrapModule(ClassOverrides overrides, DefaultPluginLoader pluginLoader) {
+ this.overrides = overrides;
+ this.pluginLoader = pluginLoader;
+ }
+
+ @Override
+ protected void configure() {
+ install(ThrowingProviderBinder.forModule(this));
+
+ ScmConfiguration config = getScmConfiguration();
+
+ CipherUtil cu = CipherUtil.getInstance();
+
+ SCMContextProvider context = SCMContext.getContext();
+
+ bind(SCMContextProvider.class).toInstance(context);
+
+ bind(KeyGenerator.class).to(DefaultKeyGenerator.class);
+
+ bind(RepositoryDAO.class, XmlRepositoryDAO.class);
+
+ bind(FileSystem.class, DefaultFileSystem.class);
+
+
+ // bind core
+ bind(ConfigurationStoreFactory.class, JAXBConfigurationStoreFactory.class);
+ bind(ConfigurationEntryStoreFactory.class, JAXBConfigurationEntryStoreFactory.class);
+ bind(DataStoreFactory.class, JAXBDataStoreFactory.class);
+ bind(BlobStoreFactory.class, FileBlobStoreFactory.class);
+
+ // bind(ScmConfiguration.class).toInstance(config);
+// bind(PluginLoader.class).toInstance(pluginLoader);
+// bind(PluginManager.class, DefaultPluginManager.class);
+
+ // note CipherUtil uses an other generator
+// bind(KeyGenerator.class).to(DefaultKeyGenerator.class);
+// bind(CipherHandler.class).toInstance(cu.getCipherHandler());
+// bind(FileSystem.class, DefaultFileSystem.class);
+ }
+
+ private void bind(Class clazz, Class extends T> defaultImplementation) {
+ Class extends T> implementation = find(clazz, defaultImplementation);
+ LOG.debug("bind {} to {}", clazz, implementation);
+ bind(clazz).to(implementation);
+ }
+
+ private Class extends T> find(Class clazz, Class extends T> defaultImplementation) {
+ Class extends T> implementation = overrides.getOverride(clazz);
+
+ if (implementation != null) {
+ LOG.info("found override {} for {}", implementation, clazz);
+ } else {
+ implementation = defaultImplementation;
+
+ LOG.trace(
+ "no override available for {}, using default implementation {}",
+ clazz, implementation);
+ }
+
+ return implementation;
+ }
+
+ private ScmConfiguration getScmConfiguration() {
+ ScmConfiguration configuration = new ScmConfiguration();
+
+ ScmConfigurationUtil.getInstance().load(configuration);
+
+ return configuration;
+ }
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java
index 8ae005e826..6dbc33af03 100644
--- a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java
+++ b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java
@@ -37,6 +37,7 @@ import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.inject.Injector;
import com.google.inject.Module;
+import com.google.inject.assistedinject.Assisted;
import org.apache.shiro.guice.web.ShiroWebModule;
import org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener;
import org.slf4j.Logger;
@@ -55,6 +56,7 @@ import sonia.scm.upgrade.UpgradeManager;
import sonia.scm.user.UserManager;
import sonia.scm.util.IOUtil;
+import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import java.util.Collections;
@@ -77,9 +79,12 @@ public class ScmContextListener extends GuiceResteasyBootstrapServletContextList
private final Set plugins;
private Injector injector;
- //~--- constructors ---------------------------------------------------------
-
- public ScmContextListener(ClassLoader parent, Set plugins)
+ public interface Factory {
+ ScmContextListener create(ClassLoader parent, Set plugins);
+ }
+
+ @Inject
+ public ScmContextListener(@Assisted ClassLoader parent, @Assisted Set plugins)
{
this.parent = parent;
this.plugins = plugins;
diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
index a3661a25f0..fb65b15236 100644
--- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
+++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
@@ -208,9 +208,9 @@ public class ScmServletModule extends ServletModule
{
install(ThrowingProviderBinder.forModule(this));
- SCMContextProvider context = SCMContext.getContext();
-
- bind(SCMContextProvider.class).toInstance(context);
+// SCMContextProvider context = SCMContext.getContext();
+//
+// bind(SCMContextProvider.class).toInstance(context);
ScmConfiguration config = getScmConfiguration();
CipherUtil cu = CipherUtil.getInstance();
@@ -230,10 +230,10 @@ public class ScmServletModule extends ServletModule
bind(ScmEventBus.class).toInstance(ScmEventBus.getInstance());
// bind core
- bind(ConfigurationStoreFactory.class, JAXBConfigurationStoreFactory.class);
- bind(ConfigurationEntryStoreFactory.class, JAXBConfigurationEntryStoreFactory.class);
- bind(DataStoreFactory.class, JAXBDataStoreFactory.class);
- bind(BlobStoreFactory.class, FileBlobStoreFactory.class);
+// bind(ConfigurationStoreFactory.class, JAXBConfigurationStoreFactory.class);
+// bind(ConfigurationEntryStoreFactory.class, JAXBConfigurationEntryStoreFactory.class);
+// bind(DataStoreFactory.class, JAXBDataStoreFactory.class);
+// bind(BlobStoreFactory.class, FileBlobStoreFactory.class);
bind(ScmConfiguration.class).toInstance(config);
bind(PluginLoader.class).toInstance(pluginLoader);
bind(PluginManager.class, DefaultPluginManager.class);
@@ -242,9 +242,9 @@ public class ScmServletModule extends ServletModule
bind(Scheduler.class).to(QuartzScheduler.class);
// note CipherUtil uses an other generator
- bind(KeyGenerator.class).to(DefaultKeyGenerator.class);
+// bind(KeyGenerator.class).to(DefaultKeyGenerator.class);
bind(CipherHandler.class).toInstance(cu.getCipherHandler());
- bind(FileSystem.class, DefaultFileSystem.class);
+// bind(FileSystem.class, DefaultFileSystem.class);
// bind health check stuff
bind(HealthCheckContextListener.class);
@@ -266,7 +266,7 @@ public class ScmServletModule extends ServletModule
// bind dao
bind(GroupDAO.class, XmlGroupDAO.class);
bind(UserDAO.class, XmlUserDAO.class);
- bind(RepositoryDAO.class, XmlRepositoryDAO.class);
+// bind(RepositoryDAO.class, XmlRepositoryDAO.class);
bindDecorated(RepositoryManager.class, DefaultRepositoryManager.class,
RepositoryManagerProvider.class);
diff --git a/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextListener.java b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextListener.java
index be5a1e7ac2..766024158a 100644
--- a/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextListener.java
+++ b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextListener.java
@@ -28,22 +28,25 @@
*/
-
package sonia.scm.boot;
-//~--- non-JDK imports --------------------------------------------------------
-
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
-
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
+import sonia.scm.BootstrapModule;
+import sonia.scm.ClassOverrides;
import sonia.scm.SCMContext;
import sonia.scm.ScmContextListener;
import sonia.scm.Stage;
import sonia.scm.event.ScmEventBus;
+import sonia.scm.plugin.DefaultPluginLoader;
import sonia.scm.plugin.Plugin;
import sonia.scm.plugin.PluginException;
import sonia.scm.plugin.PluginLoadException;
@@ -53,29 +56,23 @@ import sonia.scm.plugin.SmpArchive;
import sonia.scm.util.ClassLoaders;
import sonia.scm.util.IOUtil;
-//~--- JDK imports ------------------------------------------------------------
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.IOException;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
-
import javax.xml.bind.DataBindingException;
import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
/**
*
@@ -161,7 +158,38 @@ public class BootstrapContextListener implements ServletContextListener
Set plugins = PluginsInternal.collectPlugins(cl,
pluginDirectory.toPath());
- contextListener = new ScmContextListener(cl, plugins);
+
+ Module scmContextListenerModule = new AbstractModule() {
+ @Override
+ protected void configure() {
+
+ install(new FactoryModuleBuilder().build(ScmContextListener.Factory.class));
+ }
+ };
+
+
+
+ DefaultPluginLoader pluginLoader = new DefaultPluginLoader(context, cl, plugins);
+
+ Injector bootstrapInjector = Guice.createInjector(new BootstrapModule(
+ ClassOverrides.findOverrides(pluginLoader.getUberClassLoader()),
+ pluginLoader
+ ),
+ scmContextListenerModule
+ );
+
+
+
+
+ contextListener = bootstrapInjector.getInstance(ScmContextListener.Factory.class).create(cl, plugins);
+
+
+// Set steps = bootstrapInjector.getInstance(....);
+ // migrate
+
+
+
+// contextListener = new ScmContextListener(cl, plugins);
}
catch (IOException ex)
{
@@ -169,7 +197,7 @@ public class BootstrapContextListener implements ServletContextListener
}
contextListener.contextInitialized(sce);
-
+
// register for restart events
if (!registered
&& (SCMContext.getContext().getStage() == Stage.DEVELOPMENT))