diff --git a/plugins/scm-hg-plugin/pom.xml b/plugins/scm-hg-plugin/pom.xml
index 6526d7391c..e1b081c9a0 100644
--- a/plugins/scm-hg-plugin/pom.xml
+++ b/plugins/scm-hg-plugin/pom.xml
@@ -14,5 +14,15 @@
scm-hg-plugin
1.0-SNAPSHOT
scm-hg-plugin
-
+
+
+
+
+ sonia.scm
+ scm-web-api
+ 1.0-SNAPSHOT
+
+
+
+
diff --git a/plugins/scm-hg-plugin/src/main/java/sonia/scm/HgPlugin.java b/plugins/scm-hg-plugin/src/main/java/sonia/scm/HgPlugin.java
new file mode 100644
index 0000000000..555b38161b
--- /dev/null
+++ b/plugins/scm-hg-plugin/src/main/java/sonia/scm/HgPlugin.java
@@ -0,0 +1,37 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.InputStream;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgPlugin extends ScmWebPluginAdapter
+{
+
+ /** Field description */
+ public static final String SCRIPT = "/sonia/scm/hg.config.js";
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public InputStream getScript()
+ {
+ return HgPlugin.class.getResourceAsStream(SCRIPT);
+ }
+}
diff --git a/plugins/scm-hg-plugin/src/main/java/sonia/scm/api/rest/resources/HgConfigResource.java b/plugins/scm-hg-plugin/src/main/java/sonia/scm/api/rest/resources/HgConfigResource.java
new file mode 100644
index 0000000000..a928fa2d62
--- /dev/null
+++ b/plugins/scm-hg-plugin/src/main/java/sonia/scm/api/rest/resources/HgConfigResource.java
@@ -0,0 +1,93 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm.api.rest.resources;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import sonia.scm.repository.HgConfig;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.RepositoryManager;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@Singleton
+@Path("config/repositories/hg")
+@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+public class HgConfigResource
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param repositoryManager
+ */
+ @Inject
+ public HgConfigResource(RepositoryManager repositoryManager)
+ {
+ handler = (HgRepositoryHandler) repositoryManager.getHandler(
+ HgRepositoryHandler.TYPE_NAME);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @GET
+ public HgConfig getConfig()
+ {
+ return handler.getConfig();
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param uriInfo
+ * @param config
+ *
+ * @return
+ */
+ @POST
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response setConfig(@Context UriInfo uriInfo, HgConfig config)
+ {
+ handler.setConfig(config);
+ handler.storeConfig();
+
+ return Response.created(uriInfo.getRequestUri()).build();
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private HgRepositoryHandler handler;
+}
diff --git a/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java b/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java
index cd308b085b..82e537acbd 100644
--- a/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java
+++ b/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java
@@ -153,19 +153,19 @@ public class HgRepositoryHandler implements RepositoryHandler
File baseDirectory = context.getBaseDirectory();
AssertUtil.assertIsNotNull(baseDirectory);
+ configFile = new File(baseDirectory, CONFIG_FILE);
+ loadConfig();
+ }
- File configFile = new File(baseDirectory, CONFIG_FILE);
-
+ /**
+ * Method description
+ *
+ */
+ public void loadConfig()
+ {
if (configFile.exists())
{
config = JAXB.unmarshal(configFile, HgConfig.class);
-
- if (config.getConfigDirectory() == null)
- {
- File configDirectory = new File(baseDirectory, DEFAULT_CONFIGPATH);
-
- config.setConfigDirectory(configDirectory);
- }
}
}
@@ -213,6 +213,15 @@ public class HgRepositoryHandler implements RepositoryHandler
}
}
+ /**
+ * Method description
+ *
+ */
+ public void storeConfig()
+ {
+ JAXB.marshal(config, configFile);
+ }
+
//~--- get methods ----------------------------------------------------------
/**
@@ -285,6 +294,17 @@ public class HgRepositoryHandler implements RepositoryHandler
return repositories;
}
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public HgConfig getConfig()
+ {
+ return config;
+ }
+
/**
* Method description
*
@@ -309,6 +329,19 @@ public class HgRepositoryHandler implements RepositoryHandler
return config != null;
}
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param config
+ */
+ public void setConfig(HgConfig config)
+ {
+ this.config = config;
+ }
+
//~--- methods --------------------------------------------------------------
/**
@@ -501,4 +534,7 @@ public class HgRepositoryHandler implements RepositoryHandler
/** Field description */
private HgConfig config;
+
+ /** Field description */
+ private File configFile;
}
diff --git a/plugins/scm-hg-plugin/src/main/resources/META-INF/services/sonia.scm.ScmWebPlugin b/plugins/scm-hg-plugin/src/main/resources/META-INF/services/sonia.scm.ScmWebPlugin
new file mode 100644
index 0000000000..3797a95535
--- /dev/null
+++ b/plugins/scm-hg-plugin/src/main/resources/META-INF/services/sonia.scm.ScmWebPlugin
@@ -0,0 +1 @@
+sonia.scm.HgPlugin
\ No newline at end of file
diff --git a/plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg.config.js b/plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg.config.js
new file mode 100644
index 0000000000..3089378655
--- /dev/null
+++ b/plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg.config.js
@@ -0,0 +1,6 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml
index ab593f2b9a..a8e5c37171 100644
--- a/scm-webapp/pom.xml
+++ b/scm-webapp/pom.xml
@@ -31,17 +31,17 @@
1.0-SNAPSHOT
+
+ sonia.scm
+ scm-web-api
+ 1.0-SNAPSHOT
+
+
sonia.scm.plugins
scm-hg-plugin
1.0-SNAPSHOT
-
-
- com.sun.jersey
- jersey-core
- ${jersey.version}
-
com.sun.jersey
@@ -67,18 +67,6 @@
${jersey.version}
-
- com.google.inject
- guice
- ${guice.version}
-
-
-
- com.google.inject.extensions
- guice-servlet
- ${guice.version}
-
-
net.sf.ehcache
ehcache-core
@@ -95,6 +83,21 @@
org.mortbay.jetty
maven-jetty-plugin
6.1.25
+
+
+
+ org.apache.commons.logging.Log
+ org.apache.commons.logging.impl.Jdk14Logger
+
+
+
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
diff --git a/scm-webapp/src/main/java/sonia/scm/ContextListener.java b/scm-webapp/src/main/java/sonia/scm/ContextListener.java
index 7865102e60..2486b9f802 100644
--- a/scm-webapp/src/main/java/sonia/scm/ContextListener.java
+++ b/scm-webapp/src/main/java/sonia/scm/ContextListener.java
@@ -11,27 +11,20 @@ package sonia.scm;
import com.google.inject.Guice;
import com.google.inject.Injector;
+import com.google.inject.Module;
import com.google.inject.servlet.GuiceServletContextListener;
-import com.google.inject.servlet.ServletModule;
+import javax.servlet.ServletContextEvent;
-import sonia.scm.api.rest.UriExtensionsConfig;
-import sonia.scm.filter.GZipFilter;
-import sonia.scm.filter.SecurityFilter;
-import sonia.scm.filter.StaticResourceFilter;
-import sonia.scm.repository.Repository;
-import sonia.scm.repository.RepositoryManager;
-import sonia.scm.security.Authenticator;
-import sonia.scm.security.DemoAuthenticator;
+import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
-import com.sun.jersey.api.core.PackagesResourceConfig;
-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.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
*
@@ -40,32 +33,18 @@ import java.util.Map;
public class ContextListener extends GuiceServletContextListener
{
- /** Field description */
- public static final String PATTERN_PAGE = "*.html";
+ @Override
+ public void contextInitialized(ServletContextEvent servletContextEvent)
+ {
+ Logger logger = Logger.getLogger("");
+ logger.setLevel(Level.ALL);
+ ConsoleHandler handler = new ConsoleHandler();
+ handler.setLevel(Level.ALL);
+ logger.addHandler( handler );
+ super.contextInitialized(servletContextEvent);
+ }
- /** Field description */
- public static final String PATTERN_RESTAPI = "/api/rest/*";
- /** Field description */
- public static final String PATTERN_SCRIPT = "*.js";
-
- /** Field description */
- public static final String PATTERN_STYLESHEET = "*.css";
-
- /** Field description */
- public static final String REST_PACKAGE = "sonia.scm.api.rest";
-
- /** Field description */
- public static final String[] PATTERN_STATIC_RESOURCES = new String[] {
- PATTERN_SCRIPT,
- PATTERN_STYLESHEET, "*.jpg", "*.gif", "*.png" };
-
- /** Field description */
- public static final String[] PATTERN_COMPRESSABLE = new String[] {
- PATTERN_SCRIPT,
- PATTERN_STYLESHEET, "*.json", "*.xml", "*.txt" };
-
- //~--- get methods ----------------------------------------------------------
/**
* Method description
@@ -76,41 +55,25 @@ public class ContextListener extends GuiceServletContextListener
@Override
protected Injector getInjector()
{
- return Guice.createInjector(new ServletModule()
+ ScmWebPluginContext webPluginContext = new ScmWebPluginContext();
+ List plugins = webPluginContext.getPlugins();
+ List modules = new ArrayList();
+
+ modules.add(new ScmServletModule(webPluginContext));
+
+ if (Util.isNotEmpty(plugins))
{
- @Override
- protected void configureServlets()
+ for (ScmWebPlugin plugin : plugins)
{
- SCMContextProvider context = SCMContext.getContext();
+ Module[] moduleArray = plugin.getModules();
- bind(Authenticator.class).to(DemoAuthenticator.class);
- bind(SCMContextProvider.class).toInstance(context);
- bind(RepositoryManager.class).toInstance(
- context.getRepositoryManager());
-
- // filters
- filter(PATTERN_PAGE,
- PATTERN_STATIC_RESOURCES).through(StaticResourceFilter.class);
- filter(PATTERN_PAGE, PATTERN_COMPRESSABLE).through(GZipFilter.class);
- filter(PATTERN_RESTAPI).through(SecurityFilter.class);
-
- // jersey
- Map params = new HashMap();
-
- /*
- * params.put("com.sun.jersey.spi.container.ContainerRequestFilters",
- * "com.sun.jersey.api.container.filter.LoggingFilter");
- * params.put("com.sun.jersey.spi.container.ContainerResponseFilters",
- * "com.sun.jersey.api.container.filter.LoggingFilter");
- * params.put("com.sun.jersey.config.feature.Trace", "true");
- * params.put("com.sun.jersey.config.feature.TracePerRequest", "true");
- */
- params.put(ResourceConfig.FEATURE_REDIRECT, Boolean.TRUE.toString());
- params.put(ServletContainer.RESOURCE_CONFIG_CLASS,
- UriExtensionsConfig.class.getName());
- params.put(PackagesResourceConfig.PROPERTY_PACKAGES, REST_PACKAGE);
- serve(PATTERN_RESTAPI).with(GuiceContainer.class, params);
+ if (Util.isNotEmpty(moduleArray))
+ {
+ modules.addAll(Arrays.asList(moduleArray));
+ }
}
- });
+ }
+
+ return Guice.createInjector(modules);
}
}
diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
new file mode 100644
index 0000000000..c8789904b8
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
@@ -0,0 +1,128 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.servlet.ServletModule;
+
+import sonia.scm.api.rest.UriExtensionsConfig;
+import sonia.scm.filter.GZipFilter;
+import sonia.scm.filter.SecurityFilter;
+import sonia.scm.filter.StaticResourceFilter;
+import sonia.scm.plugin.ScriptResourceServlet;
+import sonia.scm.repository.RepositoryManager;
+import sonia.scm.security.Authenticator;
+import sonia.scm.security.DemoAuthenticator;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import com.sun.jersey.api.core.PackagesResourceConfig;
+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.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class ScmServletModule extends ServletModule
+{
+
+ /** Field description */
+ public static final String PATTERN_PAGE = "*.html";
+
+ /** Field description */
+ public static final String PATTERN_PLUGIN_SCRIPT = "/plugins/sonia.plugin.js";
+
+ /** Field description */
+ public static final String PATTERN_RESTAPI = "/api/rest/*";
+
+ /** Field description */
+ public static final String PATTERN_SCRIPT = "*.js";
+
+ /** Field description */
+ public static final String PATTERN_STYLESHEET = "*.css";
+
+ /** Field description */
+ public static final String REST_PACKAGE = "sonia.scm.api.rest";
+
+ /** Field description */
+ public static final String[] PATTERN_STATIC_RESOURCES = new String[] {
+ PATTERN_SCRIPT,
+ PATTERN_STYLESHEET, "*.jpg", "*.gif", "*.png" };
+
+ /** Field description */
+ public static final String[] PATTERN_COMPRESSABLE = new String[] {
+ PATTERN_SCRIPT,
+ PATTERN_STYLESHEET, "*.json", "*.xml", "*.txt" };
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param webPluginContext
+ */
+ ScmServletModule(ScmWebPluginContext webPluginContext)
+ {
+ this.webPluginContext = webPluginContext;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ */
+ @Override
+ protected void configureServlets()
+ {
+ SCMContextProvider context = SCMContext.getContext();
+
+ bind(Authenticator.class).to(DemoAuthenticator.class);
+ bind(SCMContextProvider.class).toInstance(context);
+ bind(RepositoryManager.class).toInstance(context.getRepositoryManager());
+ bind(ScmWebPluginContext.class).toInstance(webPluginContext);
+
+ // filters
+ filter(PATTERN_PAGE,
+ PATTERN_STATIC_RESOURCES).through(StaticResourceFilter.class);
+ filter(PATTERN_PAGE, PATTERN_COMPRESSABLE).through(GZipFilter.class);
+ filter(PATTERN_RESTAPI).through(SecurityFilter.class);
+
+ // plugin resources
+ serve(PATTERN_PLUGIN_SCRIPT).with(ScriptResourceServlet.class);
+
+ // jersey
+ Map params = new HashMap();
+
+ /*
+ * params.put("com.sun.jersey.spi.container.ContainerRequestFilters",
+ * "com.sun.jersey.api.container.filter.LoggingFilter");
+ * params.put("com.sun.jersey.spi.container.ContainerResponseFilters",
+ * "com.sun.jersey.api.container.filter.LoggingFilter");
+ * params.put("com.sun.jersey.config.feature.Trace", "true");
+ * params.put("com.sun.jersey.config.feature.TracePerRequest", "true");
+ */
+ params.put(ResourceConfig.FEATURE_REDIRECT, Boolean.TRUE.toString());
+ params.put(ServletContainer.RESOURCE_CONFIG_CLASS,
+ UriExtensionsConfig.class.getName());
+ params.put(PackagesResourceConfig.PROPERTY_PACKAGES, REST_PACKAGE);
+ serve(PATTERN_RESTAPI).with(GuiceContainer.class, params);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private ScmWebPluginContext webPluginContext;
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/filter/StaticResourceFilter.java b/scm-webapp/src/main/java/sonia/scm/filter/StaticResourceFilter.java
index d196a2e9fc..5463360f24 100644
--- a/scm-webapp/src/main/java/sonia/scm/filter/StaticResourceFilter.java
+++ b/scm-webapp/src/main/java/sonia/scm/filter/StaticResourceFilter.java
@@ -75,7 +75,7 @@ public class StaticResourceFilter extends HttpFilter
String uri = request.getRequestURI();
File resource = getResourceFile(request, uri);
- if (resource.exists())
+ if (!resource.exists())
{
WebUtil.addETagHeader(response, resource);
WebUtil.addStaticCacheControls(response, WebUtil.TIME_YEAR);
@@ -100,7 +100,7 @@ public class StaticResourceFilter extends HttpFilter
}
else
{
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
+ chain.doFilter(request, response);
}
}
diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/AbstractResourceServlet.java b/scm-webapp/src/main/java/sonia/scm/plugin/AbstractResourceServlet.java
new file mode 100644
index 0000000000..177aa68c27
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/plugin/AbstractResourceServlet.java
@@ -0,0 +1,186 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm.plugin;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public abstract class AbstractResourceServlet extends HttpServlet
+{
+
+ /** Field description */
+ public static final String DEFAULT_CHARSET = "UTF-8";
+
+ /** Field description */
+ private static final long serialVersionUID = -7703282364120349053L;
+
+ public AbstractResourceServlet()
+ {
+ System.out.println("CONSTRUCT !!!");
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+
+
+ /**
+ * Method description
+ *
+ *
+ * @param stream
+ *
+ * @throws IOException
+ * @throws ServletException
+ */
+ protected abstract void appendResources(OutputStream stream)
+ throws ServletException, IOException;
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ protected abstract String getContentType();
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @throws ServletException
+ */
+ @Override
+ public void init() throws ServletException
+ {
+ System.out.println("INIT !!!");
+
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+
+ try
+ {
+ appendResources(output);
+ }
+ catch (IOException ex)
+ {
+ throw new ServletException(ex);
+ }
+ finally
+ {
+ Util.close(output);
+ }
+
+ this.content = output.toByteArray();
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param response
+ *
+ * @throws IOException
+ * @throws ServletException
+ */
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ processRequest(request, response);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param response
+ *
+ * @throws IOException
+ * @throws ServletException
+ */
+ @Override
+ protected void doPost(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ processRequest(request, response);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ protected String getCharacterEncoding()
+ {
+ return DEFAULT_CHARSET;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param response
+ *
+ * @throws IOException
+ * @throws ServletException
+ */
+ private void processRequest(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ System.out.println( "JA !!!" );
+
+ response.setCharacterEncoding(getCharacterEncoding());
+ response.setContentType(getContentType());
+ response.setContentLength(content.length);
+
+ OutputStream output = response.getOutputStream();
+
+ try
+ {
+ output.write(content);
+ }
+ finally
+ {
+ Util.close(output);
+ }
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private byte[] content;
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/ScriptResourceServlet.java b/scm-webapp/src/main/java/sonia/scm/plugin/ScriptResourceServlet.java
new file mode 100644
index 0000000000..b344048026
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/plugin/ScriptResourceServlet.java
@@ -0,0 +1,123 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm.plugin;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import sonia.scm.ScmWebPlugin;
+import sonia.scm.ScmWebPluginContext;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import java.util.List;
+
+import javax.servlet.ServletException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@Singleton
+public class ScriptResourceServlet extends AbstractResourceServlet
+{
+
+ /** Field description */
+ public static final String CONTENT_TYPE = "text/javascript";
+
+ /** Field description */
+ private static final long serialVersionUID = -5769146163848821050L;
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param stream
+ *
+ * @throws IOException
+ * @throws ServletException
+ */
+ @Override
+ protected void appendResources(OutputStream stream)
+ throws ServletException, IOException
+ {
+ stream.write(
+ "function sayPluginHello(){ alert('Plugin Hello !'); }".concat(
+ System.getProperty("line.separator")).getBytes());
+
+ List plugins = webPluginContext.getPlugins();
+
+ if (Util.isNotEmpty(plugins))
+ {
+ for (ScmWebPlugin plugin : plugins)
+ {
+ appendResource(stream, plugin);
+ }
+ }
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ protected String getContentType()
+ {
+ return CONTENT_TYPE;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param stream
+ * @param plugin
+ *
+ * @throws IOException
+ * @throws ServletException
+ */
+ private void appendResource(OutputStream stream, ScmWebPlugin plugin)
+ throws ServletException, IOException
+ {
+ InputStream input = plugin.getScript();
+
+ if (input != null)
+ {
+ try
+ {
+ Util.copy(input, stream);
+ }
+ finally
+ {
+ Util.close(input);
+ }
+ }
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ @Inject
+ private ScmWebPluginContext webPluginContext;
+}
diff --git a/scm-webapp/src/main/webapp/index.html b/scm-webapp/src/main/webapp/index.html
index d58c0e7560..f9b7282209 100644
--- a/scm-webapp/src/main/webapp/index.html
+++ b/scm-webapp/src/main/webapp/index.html
@@ -19,6 +19,7 @@
+
SCM-WebAPP