diff --git a/scm-webapp/src/main/java/sonia/scm/ClassOverride.java b/scm-webapp/src/main/java/sonia/scm/ClassOverride.java new file mode 100644 index 0000000000..4d64a07d3b --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/ClassOverride.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm; + +//~--- JDK imports ------------------------------------------------------------ + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; + +/** + * + * @author Sebastian Sdorra + */ +@XmlAccessorType(XmlAccessType.FIELD) +public class ClassOverride +{ + + /** + * Method description + * + * + * @return + */ + public Class getBind() + { + return bind; + } + + /** + * Method description + * + * + * @return + */ + public Class getTo() + { + return to; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param bind + */ + public void setBind(Class bind) + { + this.bind = bind; + } + + /** + * Method description + * + * + * @param to + */ + public void setTo(Class to) + { + this.to = to; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Class bind; + + /** Field description */ + private Class to; +} diff --git a/scm-webapp/src/main/java/sonia/scm/ClassOverrides.java b/scm-webapp/src/main/java/sonia/scm/ClassOverrides.java new file mode 100644 index 0000000000..b9088ab817 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/ClassOverrides.java @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.net.URL; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + */ +@XmlRootElement(name = "overrides") +@XmlAccessorType(XmlAccessType.FIELD) +public class ClassOverrides implements Iterable +{ + + /** Field description */ + public static final String OVERRIDE_PATH = "META-INF/scm/override.xml"; + + /** + * the logger for ClassOverrides + */ + private static final Logger logger = + LoggerFactory.getLogger(ClassOverrides.class); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + * + */ + public static ClassOverrides findOverrides() + { + ClassOverrides overrides = new ClassOverrides(); + + try + { + Enumeration overridesEnm = + getClassLoader().getResources(OVERRIDE_PATH); + JAXBContext context = JAXBContext.newInstance(ClassOverrides.class); + + while (overridesEnm.hasMoreElements()) + { + URL overrideUrl = overridesEnm.nextElement(); + + try + { + ClassOverrides co = + (ClassOverrides) context.createUnmarshaller().unmarshal( + overrideUrl); + } + catch (Exception ex) + { + logger.error("could not load ".concat(overrideUrl.toExternalForm()), + ex); + } + } + } + catch (IOException ex) + { + logger.error("could not load overrides", ex); + } + catch (JAXBException ex) + { + logger.error("could not create jaxb context for ClassOverrides", ex); + } + + return overrides; + } + + public Class getOverride(Class clazz){ + Class implementation = null; + for ( ClassOverride co : getOverrides() ){ + if ( co.getBind().equals(clazz) ){ + implementation = (Class) co.getTo(); + } + } + return implementation; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + private static ClassLoader getClassLoader() + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + if (classLoader == null) + { + classLoader = ClassOverrides.class.getClassLoader(); + } + + return classLoader; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param overrides + */ + public void append(ClassOverrides overrides) + { + getOverrides().addAll(overrides.getOverrides()); + } + + /** + * Method description + * + * + * @return + */ + @Override + public Iterator iterator() + { + return getOverrides().iterator(); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public List getOverrides() + { + if (overrides == null) + { + overrides = new ArrayList(); + } + + return overrides; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param overrides + */ + public void setOverrides(List overrides) + { + this.overrides = overrides; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + @XmlElement(name = "override") + private List overrides; +} diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index 739c88e0ff..5add9b90bc 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -193,6 +193,7 @@ public class ScmServletModule extends ServletModule { this.pluginLoader = pluginLoader; this.bindExtProcessor = bindExtProcessor; + this.overrides = ClassOverrides.findOverrides(); } //~--- methods -------------------------------------------------------------- @@ -219,13 +220,13 @@ public class ScmServletModule extends ServletModule DefaultRepositoryProvider.class).in(RequestScoped.class); // bind core - bind(StoreFactory.class).to(JAXBStoreFactory.class); + bind(StoreFactory.class, JAXBStoreFactory.class); bind(ScmConfiguration.class).toInstance(config); bind(PluginLoader.class).toInstance(pluginLoader); - bind(PluginManager.class).to(DefaultPluginManager.class); + bind(PluginManager.class, DefaultPluginManager.class); bind(KeyGenerator.class).toInstance(cu.getKeyGenerator()); bind(CipherHandler.class).toInstance(cu.getCipherHandler()); - bind(EncryptionHandler.class).to(MessageDigestEncryptionHandler.class); + bind(EncryptionHandler.class, MessageDigestEncryptionHandler.class); bindExtProcessor.bindExtensions(binder()); Class fileSystem = @@ -239,37 +240,37 @@ public class ScmServletModule extends ServletModule bind(FileSystem.class).to(fileSystem); // bind security stuff - bind(AuthenticationManager.class).to(ChainAuthenticatonManager.class); + bind(AuthenticationManager.class, ChainAuthenticatonManager.class); bind(LocalSecurityContextHolder.class); bind(WebSecurityContext.class).annotatedWith(Names.named("userSession")).to( BasicSecurityContext.class); bind(SecurityContext.class).toProvider(SecurityContextProvider.class); bind(WebSecurityContext.class).toProvider(SecurityContextProvider.class); - bind(AdministrationContext.class).to(DefaultAdministrationContext.class); + bind(AdministrationContext.class, DefaultAdministrationContext.class); // bind security cache - bind(CacheManager.class).to(EhCacheManager.class); + bind(CacheManager.class, EhCacheManager.class); // bind(RepositoryManager.class).annotatedWith(Undecorated.class).to( // BasicRepositoryManager.class); - bind(RepositoryManager.class).to(XmlRepositoryManager.class); - bind(UserManager.class).to(XmlUserManager.class); - bind(GroupManager.class).to(XmlGroupManager.class); - bind(CGIExecutorFactory.class).to(DefaultCGIExecutorFactory.class); + bind(RepositoryManager.class, XmlRepositoryManager.class); + bind(UserManager.class, XmlUserManager.class); + bind(GroupManager.class, XmlGroupManager.class); + bind(CGIExecutorFactory.class, DefaultCGIExecutorFactory.class); bind(ChangesetViewerUtil.class); bind(RepositoryBrowserUtil.class); // bind httpclient - bind(HttpClient.class).to(URLHttpClient.class); + bind(HttpClient.class, URLHttpClient.class); // bind resourcemanager if (context.getStage() == Stage.DEVELOPMENT) { - bind(ResourceManager.class).to(DevelopmentResourceManager.class); + bind(ResourceManager.class, DevelopmentResourceManager.class); } else { - bind(ResourceManager.class).to(DefaultResourceManager.class); + bind(ResourceManager.class, DefaultResourceManager.class); } // bind url provider staff @@ -378,6 +379,37 @@ public class ScmServletModule extends ServletModule } } + /** + * Method description + * + * + * @param clazz + * @param defaultImplementation + * @param + */ + private void bind(Class clazz, + Class defaultImplementation) + { + Class implementation = overrides.getOverride(clazz); + + if (implementation != null) + { + logger.info("bind {} to override {}", clazz, implementation); + } + else + { + implementation = defaultImplementation; + + if (logger.isDebugEnabled()) + { + logger.debug("bind {} to defaul implementation {}", clazz, + implementation); + } + } + + bind(clazz).to(implementation); + } + //~--- get methods ---------------------------------------------------------- /** @@ -440,6 +472,9 @@ public class ScmServletModule extends ServletModule /** Field description */ private BindingExtensionProcessor bindExtProcessor; + /** Field description */ + private ClassOverrides overrides; + /** Field description */ private PluginLoader pluginLoader; }