improve api

This commit is contained in:
Sebastian Sdorra
2010-09-16 21:50:30 +02:00
parent 16070397b0
commit 2f170494cf
13 changed files with 689 additions and 102 deletions

View File

@@ -14,5 +14,15 @@
<artifactId>scm-hg-plugin</artifactId> <artifactId>scm-hg-plugin</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<name>scm-hg-plugin</name> <name>scm-hg-plugin</name>
<dependencies>
<dependency>
<groupId>sonia.scm</groupId>
<artifactId>scm-web-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project> </project>

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -153,19 +153,19 @@ public class HgRepositoryHandler implements RepositoryHandler
File baseDirectory = context.getBaseDirectory(); File baseDirectory = context.getBaseDirectory();
AssertUtil.assertIsNotNull(baseDirectory); 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()) if (configFile.exists())
{ {
config = JAXB.unmarshal(configFile, HgConfig.class); 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 ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/** /**
@@ -285,6 +294,17 @@ public class HgRepositoryHandler implements RepositoryHandler
return repositories; return repositories;
} }
/**
* Method description
*
*
* @return
*/
public HgConfig getConfig()
{
return config;
}
/** /**
* Method description * Method description
* *
@@ -309,6 +329,19 @@ public class HgRepositoryHandler implements RepositoryHandler
return config != null; return config != null;
} }
//~--- set methods ----------------------------------------------------------
/**
* Method description
*
*
* @param config
*/
public void setConfig(HgConfig config)
{
this.config = config;
}
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
/** /**
@@ -501,4 +534,7 @@ public class HgRepositoryHandler implements RepositoryHandler
/** Field description */ /** Field description */
private HgConfig config; private HgConfig config;
/** Field description */
private File configFile;
} }

View File

@@ -0,0 +1 @@
sonia.scm.HgPlugin

View File

@@ -0,0 +1,6 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

View File

@@ -31,17 +31,17 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>sonia.scm</groupId>
<artifactId>scm-web-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>sonia.scm.plugins</groupId> <groupId>sonia.scm.plugins</groupId>
<artifactId>scm-hg-plugin</artifactId> <artifactId>scm-hg-plugin</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>com.sun.jersey</groupId>
@@ -67,18 +67,6 @@
<version>${jersey.version}</version> <version>${jersey.version}</version>
</dependency> </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>
<version>${guice.version}</version>
</dependency>
<dependency> <dependency>
<groupId>net.sf.ehcache</groupId> <groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId> <artifactId>ehcache-core</artifactId>
@@ -95,6 +83,21 @@
<groupId>org.mortbay.jetty</groupId> <groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId> <artifactId>maven-jetty-plugin</artifactId>
<version>6.1.25</version> <version>6.1.25</version>
<configuration>
<systemproperties>
<systemproperty>
<name>org.apache.commons.logging.Log</name>
<value>org.apache.commons.logging.impl.Jdk14Logger</value>
</systemproperty>
</systemproperties>
</configuration>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
</plugin> </plugin>
</plugins> </plugins>

View File

@@ -11,27 +11,20 @@ package sonia.scm;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.servlet.GuiceServletContextListener; 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.util.Util;
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;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.core.PackagesResourceConfig; import java.util.ArrayList;
import com.sun.jersey.api.core.ResourceConfig; import java.util.Arrays;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; import java.util.List;
import com.sun.jersey.spi.container.servlet.ServletContainer; import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.HashMap; import java.util.logging.Logger;
import java.util.Map;
/** /**
* *
@@ -40,32 +33,18 @@ import java.util.Map;
public class ContextListener extends GuiceServletContextListener public class ContextListener extends GuiceServletContextListener
{ {
/** Field description */ @Override
public static final String PATTERN_PAGE = "*.html"; 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 * Method description
@@ -76,41 +55,25 @@ public class ContextListener extends GuiceServletContextListener
@Override @Override
protected Injector getInjector() protected Injector getInjector()
{ {
return Guice.createInjector(new ServletModule() ScmWebPluginContext webPluginContext = new ScmWebPluginContext();
List<ScmWebPlugin> plugins = webPluginContext.getPlugins();
List<Module> modules = new ArrayList<Module>();
modules.add(new ScmServletModule(webPluginContext));
if (Util.isNotEmpty(plugins))
{ {
@Override for (ScmWebPlugin plugin : plugins)
protected void configureServlets()
{ {
SCMContextProvider context = SCMContext.getContext(); Module[] moduleArray = plugin.getModules();
bind(Authenticator.class).to(DemoAuthenticator.class); if (Util.isNotEmpty(moduleArray))
bind(SCMContextProvider.class).toInstance(context); {
bind(RepositoryManager.class).toInstance( modules.addAll(Arrays.asList(moduleArray));
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<String, String> params = new HashMap<String, String>();
/*
* 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);
} }
}); }
return Guice.createInjector(modules);
} }
} }

View File

@@ -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<String, String> params = new HashMap<String, String>();
/*
* 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;
}

View File

@@ -75,7 +75,7 @@ public class StaticResourceFilter extends HttpFilter
String uri = request.getRequestURI(); String uri = request.getRequestURI();
File resource = getResourceFile(request, uri); File resource = getResourceFile(request, uri);
if (resource.exists()) if (!resource.exists())
{ {
WebUtil.addETagHeader(response, resource); WebUtil.addETagHeader(response, resource);
WebUtil.addStaticCacheControls(response, WebUtil.TIME_YEAR); WebUtil.addStaticCacheControls(response, WebUtil.TIME_YEAR);
@@ -100,7 +100,7 @@ public class StaticResourceFilter extends HttpFilter
} }
else else
{ {
response.sendError(HttpServletResponse.SC_NOT_FOUND); chain.doFilter(request, response);
} }
} }

View File

@@ -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;
}

View File

@@ -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<ScmWebPlugin> 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;
}

View File

@@ -19,6 +19,7 @@
<script type="text/javascript" src="resources/js/sonia.group.js"></script> <script type="text/javascript" src="resources/js/sonia.group.js"></script>
<script type="text/javascript" src="resources/js/sonia.repository.js"></script> <script type="text/javascript" src="resources/js/sonia.repository.js"></script>
<script type="text/javascript" src="resources/js/layout.js"></script> <script type="text/javascript" src="resources/js/layout.js"></script>
<script type="text/javascript" src="plugins/sonia.plugin.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<title>SCM-WebAPP</title> <title>SCM-WebAPP</title>