improve plugin structure

This commit is contained in:
Sebastian Sdorra
2010-10-12 09:16:40 +02:00
parent ed34cde5f4
commit 030b2e8db0
21 changed files with 374 additions and 256 deletions

View File

@@ -12,8 +12,8 @@ package sonia.scm.api.rest.resources;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.GitConfig;
import sonia.scm.repository.GitRepositoryHandler;
//~--- JDK imports ------------------------------------------------------------
@@ -26,8 +26,6 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import sonia.scm.repository.GitConfig;
import sonia.scm.repository.GitRepositoryHandler;
/**
*
@@ -43,13 +41,13 @@ public class GitConfigResource
* Constructs ...
*
*
* @param repositoryManager
*
* @param repositoryHandler
*/
@Inject
public GitConfigResource(RepositoryManager repositoryManager)
public GitConfigResource(GitRepositoryHandler repositoryHandler)
{
repositoryHandler = (GitRepositoryHandler) repositoryManager.getHandler(
GitRepositoryHandler.TYPE_NAME);
this.repositoryHandler = repositoryHandler;
}
//~--- get methods ----------------------------------------------------------

View File

@@ -9,6 +9,8 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Singleton;
import sonia.scm.io.CommandResult;
import sonia.scm.io.ExtendedCommand;
@@ -21,6 +23,7 @@ import java.io.IOException;
*
* @author Sebastian Sdorra
*/
@Singleton
public class GitRepositoryHandler
extends AbstractSimpleRepositoryHandler<GitConfig>
{

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Document : plugin.xml
Created on : October 12, 2010, 8:29 AM
Author : sdorra
Description:
Purpose of the document follows.
-->
<plugin-config>
<repository-handlers>
<handler>sonia.scm.repository.GitRepositoryHandler</handler>
</repository-handlers>
</plugin-config>

View File

@@ -1 +0,0 @@
sonia.scm.repository.GitRepositoryHandler

View File

@@ -47,13 +47,13 @@ public class HgConfigResource
* Constructs ...
*
*
* @param repositoryManager
*
* @param handler
*/
@Inject
public HgConfigResource(RepositoryManager repositoryManager)
public HgConfigResource(HgRepositoryHandler handler)
{
handler = (HgRepositoryHandler) repositoryManager.getHandler(
HgRepositoryHandler.TYPE_NAME);
this.handler = handler;
}
//~--- get methods ----------------------------------------------------------

View File

@@ -9,6 +9,8 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Singleton;
import sonia.scm.ConfigurationException;
import sonia.scm.io.CommandResult;
import sonia.scm.io.ExtendedCommand;
@@ -37,6 +39,7 @@ import java.util.logging.Logger;
*
* @author Sebastian Sdorra
*/
@Singleton
public class HgRepositoryHandler extends AbstractRepositoryHandler<HgConfig>
{

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Document : plugin.xml
Created on : October 12, 2010, 8:29 AM
Author : sdorra
Description:
Purpose of the document follows.
-->
<plugin-config>
<repository-handlers>
<handler>sonia.scm.repository.HgRepositoryHandler</handler>
</repository-handlers>
</plugin-config>

View File

@@ -1 +0,0 @@
sonia.scm.repository.HgRepositoryHandler

View File

@@ -13,7 +13,7 @@ import sonia.scm.ConfigurationException;
import sonia.scm.SCMContextProvider;
import sonia.scm.io.CommandResult;
import sonia.scm.io.ExtendedCommand;
import sonia.scm.util.Util;
import sonia.scm.util.IOUtil;
//~--- JDK imports ------------------------------------------------------------
@@ -28,7 +28,6 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXB;
import sonia.scm.util.IOUtil;
/**
*

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Document : plugin.xml
Created on : October 12, 2010, 8:29 AM
Author : sdorra
Description:
Purpose of the document follows.
-->
<plugin-config>
<repository-handlers>
<handler>sonia.scm.repository.SvnRepositoryHandler</handler>
</repository-handlers>
</plugin-config>

View File

@@ -1 +0,0 @@
sonia.scm.repository.SvnRepositoryHandler

View File

@@ -15,4 +15,20 @@
<version>1.0-SNAPSHOT</version>
<name>scm-core</name>
<dependencies>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>${guice.version}</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
<version>${guice.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -9,12 +9,6 @@ package sonia.scm;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.group.GroupManager;
import sonia.scm.repository.BasicRepositoryManager;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.security.EncryptionHandler;
import sonia.scm.security.MessageDigestEncryptionHandler;
import sonia.scm.util.ServiceUtil;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
@@ -22,11 +16,6 @@ import sonia.scm.util.Util;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
*
* @author Sebastian Sdorra
@@ -63,33 +52,14 @@ public class BasicContextProvider implements SCMContextProvider
* @throws IOException
*/
@Override
public void close() throws IOException
{
for (SCMPlugin plugin : plugins)
{
plugin.contextDestroyed(this);
}
for (GroupManager manager : groupManagerMap.values())
{
manager.close();
}
repositoryManager.close();
}
public void close() throws IOException {}
/**
* Method description
*
*/
@Override
public void init()
{
loadGroupManagers();
loadRepositoryManager();
loadEncryptionHandler();
loadPlugins();
}
public void init() {}
//~--- get methods ----------------------------------------------------------
@@ -105,45 +75,6 @@ public class BasicContextProvider implements SCMContextProvider
return baseDirectory;
}
/**
* Method description
*
*
* @return
*/
@Override
public EncryptionHandler getEncryptionHandler()
{
return encryptionHandler;
}
/**
* Method description
*
*
* @param type
*
* @return
*/
@Override
public GroupManager getGroupManager(String type)
{
return groupManagerMap.get(type);
}
/**
* Method description
*
*
*
* @return
*/
@Override
public RepositoryManager getRepositoryManager()
{
return repositoryManager;
}
//~--- methods --------------------------------------------------------------
/**
@@ -177,82 +108,8 @@ public class BasicContextProvider implements SCMContextProvider
return directory;
}
/**
* Method description
*
*/
private void loadEncryptionHandler()
{
encryptionHandler = ServiceUtil.getService(EncryptionHandler.class);
if (encryptionHandler == null)
{
encryptionHandler = new MessageDigestEncryptionHandler();
}
}
/**
* Method description
*
*/
private void loadGroupManagers()
{
groupManagerMap = new HashMap<String, GroupManager>();
List<GroupManager> groupManagers =
ServiceUtil.getServices(GroupManager.class);
for (GroupManager manager : groupManagers)
{
manager.init(this);
groupManagerMap.put(manager.getType(), manager);
}
}
/**
* Method description
*
*/
private void loadPlugins()
{
plugins = ServiceUtil.getServices(SCMPlugin.class);
for (SCMPlugin plugin : plugins)
{
plugin.contextInitialized(this);
}
}
/**
* Method description
*
*/
private void loadRepositoryManager()
{
repositoryManager = ServiceUtil.getService(RepositoryManager.class);
if (repositoryManager == null)
{
repositoryManager = new BasicRepositoryManager();
}
repositoryManager.init(this);
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private File baseDirectory;
/** Field description */
private EncryptionHandler encryptionHandler;
/** Field description */
private Map<String, GroupManager> groupManagerMap;
/** Field description */
private List<SCMPlugin> plugins;
/** Field description */
private RepositoryManager repositoryManager;
}

View File

@@ -7,12 +7,6 @@
package sonia.scm;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.group.GroupManager;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.security.EncryptionHandler;
//~--- JDK imports ------------------------------------------------------------
import java.io.Closeable;
@@ -40,31 +34,4 @@ public interface SCMContextProvider extends Closeable
* @return
*/
public File getBaseDirectory();
/**
* Method description
*
*
* @return
*/
public EncryptionHandler getEncryptionHandler();
/**
* Method description
*
*
*
* @param type
* @return
*/
public GroupManager getGroupManager(String type);
/**
* Method description
*
*
*
* @return
*/
public RepositoryManager getRepositoryManager();
}

View File

@@ -1,32 +0,0 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm;
/**
*
* @author Sebastian Sdorra
*/
public interface SCMPlugin
{
/**
* Method description
*
*
* @param context
*/
public void contextDestroyed(SCMContextProvider context);
/**
* Method description
*
*
* @param context
*/
public void contextInitialized(SCMContextProvider context);
}

View File

@@ -0,0 +1,91 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm.plugin;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.repository.RepositoryHandler;
//~--- JDK imports ------------------------------------------------------------
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author Sebastian Sdorra
*/
@XmlRootElement(name = "plugin-config")
@XmlAccessorType(XmlAccessType.FIELD)
public class SCMPlugin
{
/**
* Constructs ...
*
*/
public SCMPlugin()
{
handlers = new HashSet<Class<? extends RepositoryHandler>>();
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param handlerClass
*
* @return
*/
public boolean addHandler(Class<? extends RepositoryHandler> handlerClass)
{
return handlers.add(handlerClass);
}
/**
* Method description
*
*
* @param handlerClass
*
* @return
*/
public boolean removeHandler(Class<? extends RepositoryHandler> handlerClass)
{
return handlers.remove(handlerClass);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public Collection<Class<? extends RepositoryHandler>> getHandlers()
{
return handlers;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
@XmlElementWrapper(name = "repository-handlers")
@XmlElement(name = "handler")
private Set<Class<? extends RepositoryHandler>> handlers;
}

View File

@@ -0,0 +1,142 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm.plugin;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.repository.RepositoryHandler;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXB;
/**
*
* @author Sebastian Sdorra
*/
public class SCMPluginManager
{
/** Field description */
public static final String PATH_PLUGINCONFIG = "META-INF/scm/plugin.xml";
/** Field description */
private static final Logger logger =
Logger.getLogger(SCMPluginManager.class.getName());
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*/
public SCMPluginManager()
{
repositoryHandlers = new HashSet<Class<? extends RepositoryHandler>>();
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @throws IOException
*/
public void load() throws IOException
{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null)
{
classLoader = SCMPluginManager.class.getClassLoader();
}
load(classLoader);
}
/**
* Method description
*
*
* @param classLoader
*
* @throws IOException
*/
public void load(ClassLoader classLoader) throws IOException
{
Enumeration<URL> urlEnum = classLoader.getResources(PATH_PLUGINCONFIG);
if (urlEnum != null)
{
while (urlEnum.hasMoreElements())
{
URL url = urlEnum.nextElement();
loadPlugin(url);
}
}
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public Set<Class<? extends RepositoryHandler>> getRepositoryHandlers()
{
return repositoryHandlers;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param url
*/
private void loadPlugin(URL url)
{
try
{
SCMPlugin plugin = JAXB.unmarshal(url, SCMPlugin.class);
Collection<Class<? extends RepositoryHandler>> handlers =
plugin.getHandlers();
if (Util.isNotEmpty(handlers))
{
repositoryHandlers.addAll(handlers);
}
}
catch (Exception ex)
{
logger.log(Level.SEVERE, null, ex);
}
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private Set<Class<? extends RepositoryHandler>> repositoryHandlers;
}

View File

@@ -9,12 +9,14 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
import com.google.inject.Singleton;
import sonia.scm.ConfigurationException;
import sonia.scm.SCMContext;
import sonia.scm.SCMContextProvider;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.ServiceUtil;
import sonia.scm.util.Util;
import sonia.scm.util.IOUtil;
//~--- JDK imports ------------------------------------------------------------
@@ -32,17 +34,26 @@ import java.util.Set;
*
* @author Sebastian Sdorra
*/
@Singleton
public class BasicRepositoryManager extends AbstractRepositoryManager
{
/**
* Constructs ...
*
*
* @param handlerSet
*/
public BasicRepositoryManager()
@Inject
public BasicRepositoryManager(Set<RepositoryHandler> handlerSet)
{
handlerMap = new HashMap<String, RepositoryHandler>();
types = new ArrayList<RepositoryType>();
for (RepositoryHandler handler : handlerSet)
{
addHandler(handler);
}
}
//~--- methods --------------------------------------------------------------
@@ -70,6 +81,7 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
handlerMap.put(type.getName(), handler);
handler.init(SCMContext.getContext());
types.add(type);
}
/**
@@ -81,9 +93,9 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
@Override
public void close() throws IOException
{
for (RepositoryHandler manager : handlerMap.values())
for (RepositoryHandler handler : handlerMap.values())
{
manager.close();
IOUtil.close(handler);
}
}
@@ -128,23 +140,7 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
* @param context
*/
@Override
public void init(SCMContextProvider context)
{
List<RepositoryHandler> handlerList =
ServiceUtil.getServices(RepositoryHandler.class);
if (Util.isNotEmpty(handlerList))
{
for (RepositoryHandler handler : handlerList)
{
RepositoryType type = handler.getType();
types.add(type);
handlerMap.put(type.getName(), handler);
handler.init(context);
}
}
}
public void init(SCMContextProvider context) {}
/**
* Method description

View File

@@ -36,12 +36,6 @@
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>${guice.version}</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId>

View File

@@ -79,6 +79,12 @@
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
<version>${guice.version}</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>

View File

@@ -9,10 +9,14 @@ package sonia.scm;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.multibindings.Multibinder;
import com.google.inject.servlet.ServletModule;
import sonia.scm.api.rest.UriExtensionsConfig;
import sonia.scm.plugin.SCMPluginManager;
import sonia.scm.plugin.ScriptResourceServlet;
import sonia.scm.repository.BasicRepositoryManager;
import sonia.scm.repository.RepositoryHandler;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.ScmWebPluginContext;
import sonia.scm.web.security.Authenticator;
@@ -25,8 +29,12 @@ import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
@@ -88,8 +96,30 @@ public class ScmServletModule extends ServletModule
SCMContextProvider context = SCMContext.getContext();
bind(SCMContextProvider.class).toInstance(context);
Multibinder<RepositoryHandler> repositoryHandlerBinder =
Multibinder.newSetBinder(binder(), RepositoryHandler.class);
SCMPluginManager pluginManager = new SCMPluginManager();
try
{
pluginManager.load();
}
catch (IOException ex)
{
Logger.getLogger(ScmServletModule.class.getName()).log(Level.SEVERE,
null, ex);
}
for (Class<? extends RepositoryHandler> handler :
pluginManager.getRepositoryHandlers())
{
bind(handler);
repositoryHandlerBinder.addBinding().to(handler);
}
bind(Authenticator.class).to(DemoAuthenticator.class);
bind(RepositoryManager.class).toInstance(context.getRepositoryManager());
bind(RepositoryManager.class).to(BasicRepositoryManager.class);
bind(ScmWebPluginContext.class).toInstance(webPluginContext);
/*