From 9396e9e86a55ef61ffdb08fb3bdd78762b903f40 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 12 Oct 2010 14:56:29 +0200 Subject: [PATCH] improve GitCGIServlet --- .../java/sonia/scm/repository/GitConfig.java | 25 +++++++ .../java/sonia/scm/web/GitCGIServlet.java | 53 ++++++++++++- .../main/resources/sonia/scm/git.config.js | 5 ++ .../sonia/scm/web/cgi/AbstractCGIServlet.java | 37 +++++++--- .../java/sonia/scm/web/cgi/CGIRunner.java | 74 ++++++------------- .../main/java/sonia/scm/web/cgi/EnvList.java | 22 ++++-- 6 files changed, 144 insertions(+), 72 deletions(-) diff --git a/plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitConfig.java b/plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitConfig.java index adb2542462..7eba7a0fae 100644 --- a/plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitConfig.java +++ b/plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitConfig.java @@ -30,6 +30,17 @@ public class GitConfig extends SimpleRepositoryConfig return gitBinary; } + /** + * Method description + * + * + * @return + */ + public String getGitHttpBackend() + { + return gitHttpBackend; + } + //~--- set methods ---------------------------------------------------------- /** @@ -43,8 +54,22 @@ public class GitConfig extends SimpleRepositoryConfig this.gitBinary = gitBinary; } + /** + * Method description + * + * + * @param gitHttpBackend + */ + public void setGitHttpBackend(String gitHttpBackend) + { + this.gitHttpBackend = gitHttpBackend; + } + //~--- fields --------------------------------------------------------------- /** Field description */ private String gitBinary = "git"; + + /** Field description */ + private String gitHttpBackend = "git-http-backend"; } diff --git a/plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitCGIServlet.java b/plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitCGIServlet.java index c2f06eddac..7da4f5114b 100644 --- a/plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitCGIServlet.java +++ b/plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitCGIServlet.java @@ -9,8 +9,11 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- +import com.google.inject.Inject; import com.google.inject.Singleton; +import sonia.scm.repository.GitConfig; +import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.web.cgi.AbstractCGIServlet; import sonia.scm.web.cgi.EnvList; @@ -46,18 +49,47 @@ public class GitCGIServlet extends AbstractCGIServlet * * * @return + * + * @throws ServletException */ @Override - protected EnvList createEnvironment() + protected EnvList createBaseEnvironment() throws ServletException { - EnvList list = super.createEnvironment(); + EnvList list = super.createBaseEnvironment(); - list.set(ENV_PROJECT_ROOT, "/tmp/git"); list.set(ENV_HTTP_EXPORT_ALL, ""); return list; } + /** + * Method description + * + * + * @param baseEnvironment + * + * @return + * + * @throws ServletException + */ + @Override + protected EnvList createRequestEnvironment(EnvList baseEnvironment) + throws ServletException + { + GitConfig config = repositoryHandler.getConfig(); + + if (config == null) + { + throw new ServletException("git is not configured"); + } + + EnvList env = new EnvList(baseEnvironment); + + env.set(ENV_PROJECT_ROOT, config.getRepositoryDirectory().getPath()); + + return env; + } + //~--- get methods ---------------------------------------------------------- /** @@ -75,6 +107,19 @@ public class GitCGIServlet extends AbstractCGIServlet protected File getCommand(HttpServletRequest req) throws ServletException, IOException { - return new File("/opt/local/libexec/git-core/git-http-backend/"); + GitConfig config = repositoryHandler.getConfig(); + + if (config == null) + { + throw new ServletException("git is not configured"); + } + + return new File(config.getGitHttpBackend()); } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + @Inject + private GitRepositoryHandler repositoryHandler; } diff --git a/plugins/scm-git-plugin/src/main/resources/sonia/scm/git.config.js b/plugins/scm-git-plugin/src/main/resources/sonia/scm/git.config.js index e5229a5508..1f3b77e51a 100644 --- a/plugins/scm-git-plugin/src/main/resources/sonia/scm/git.config.js +++ b/plugins/scm-git-plugin/src/main/resources/sonia/scm/git.config.js @@ -20,6 +20,11 @@ registerConfigPanel({ name: 'baseUrl', fieldLabel: 'Base URL', allowBlank : false + },{ + xtype : 'textfield', + fieldLabel : 'Git-Http-Backend', + name : 'gitHttpBackend', + allowBlank : false }], onSubmit: function(values){ diff --git a/scm-web-api/src/main/java/sonia/scm/web/cgi/AbstractCGIServlet.java b/scm-web-api/src/main/java/sonia/scm/web/cgi/AbstractCGIServlet.java index b4adbce035..b163dd8752 100644 --- a/scm-web-api/src/main/java/sonia/scm/web/cgi/AbstractCGIServlet.java +++ b/scm-web-api/src/main/java/sonia/scm/web/cgi/AbstractCGIServlet.java @@ -56,8 +56,9 @@ public abstract class AbstractCGIServlet extends HttpServlet @Override public void init() throws ServletException { - cgiRunner = new CGIRunner(getServletContext(), createEnvironment(), - getCmdPrefix(), isExitStateIgnored()); + cgiRunner = new CGIRunner(getServletContext(), getCmdPrefix(), + isExitStateIgnored()); + baseEnvironment = createBaseEnvironment(); } /** @@ -65,8 +66,10 @@ public abstract class AbstractCGIServlet extends HttpServlet * * * @return + * + * @throws ServletException */ - protected EnvList createEnvironment() + protected EnvList createBaseEnvironment() throws ServletException { EnvList env = new EnvList(); Enumeration e = getInitParameterNames(); @@ -94,6 +97,22 @@ public abstract class AbstractCGIServlet extends HttpServlet return env; } + /** + * Method description + * + * + * @param baseEnvironment + * + * @return + * + * @throws ServletException + */ + protected EnvList createRequestEnvironment(EnvList baseEnvironment) + throws ServletException + { + return new EnvList(baseEnvironment); + } + /** * Method description * @@ -108,7 +127,8 @@ public abstract class AbstractCGIServlet extends HttpServlet protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - cgiRunner.exec(getCommand(req), req.getPathInfo(), req, resp); + cgiRunner.exec(createRequestEnvironment(baseEnvironment), getCommand(req), + req.getPathInfo(), req, resp); } //~--- get methods ---------------------------------------------------------- @@ -124,10 +144,6 @@ public abstract class AbstractCGIServlet extends HttpServlet return null; } - ; - - //~--- get methods ---------------------------------------------------------- - /** * Method description * @@ -139,10 +155,11 @@ public abstract class AbstractCGIServlet extends HttpServlet return false; } - ; - //~--- fields --------------------------------------------------------------- + /** Field description */ + private EnvList baseEnvironment; + /** Field description */ private CGIRunner cgiRunner; } diff --git a/scm-web-api/src/main/java/sonia/scm/web/cgi/CGIRunner.java b/scm-web-api/src/main/java/sonia/scm/web/cgi/CGIRunner.java index 4cf7bb67d1..5bd982775f 100644 --- a/scm-web-api/src/main/java/sonia/scm/web/cgi/CGIRunner.java +++ b/scm-web-api/src/main/java/sonia/scm/web/cgi/CGIRunner.java @@ -55,11 +55,10 @@ public class CGIRunner * @param cmdPrefix * @param ignoreExitState */ - public CGIRunner(ServletContext context, EnvList environment, + public CGIRunner(ServletContext context, String cmdPrefix, boolean ignoreExitState) { this.context = context; - this.environment = environment; this.cmdPrefix = cmdPrefix; this.ignoreExitState = ignoreExitState; } @@ -77,7 +76,7 @@ public class CGIRunner * * @throws IOException */ - public void exec(File command, String pathInfo, HttpServletRequest req, + public void exec(EnvList environment, File command, String pathInfo, HttpServletRequest req, HttpServletResponse res) throws IOException { @@ -99,39 +98,37 @@ public class CGIRunner pathTranslated = path; } - EnvList env = new EnvList(environment); - // these ones are from "The WWW Common Gateway Interface Version 1.1" // look at : // http://Web.Golux.Com/coar/cgi/draft-coar-cgi-v11-03-clean.html#6.1.1 - env.set("AUTH_TYPE", req.getAuthType()); - env.set("CONTENT_LENGTH", Integer.toString(len)); - env.set("CONTENT_TYPE", req.getContentType()); - env.set("GATEWAY_INTERFACE", "CGI/1.1"); + environment.set("AUTH_TYPE", req.getAuthType()); + environment.set("CONTENT_LENGTH", Integer.toString(len)); + environment.set("CONTENT_TYPE", req.getContentType()); + environment.set("GATEWAY_INTERFACE", "CGI/1.1"); if ((pathInfo != null) && (pathInfo.length() > 0)) { - env.set("PATH_INFO", pathInfo); + environment.set("PATH_INFO", pathInfo); } - env.set("PATH_TRANSLATED", pathTranslated); - env.set("QUERY_STRING", req.getQueryString()); - env.set("REMOTE_ADDR", req.getRemoteAddr()); - env.set("REMOTE_HOST", req.getRemoteHost()); + environment.set("PATH_TRANSLATED", pathTranslated); + environment.set("QUERY_STRING", req.getQueryString()); + environment.set("REMOTE_ADDR", req.getRemoteAddr()); + environment.set("REMOTE_HOST", req.getRemoteHost()); // The identity information reported about the connection by a // RFC 1413 [11] request to the remote agent, if // available. Servers MAY choose not to support this feature, or // not to request the data for efficiency reasons. // "REMOTE_IDENT" => "NYI" - env.set("REMOTE_USER", req.getRemoteUser()); - env.set("REQUEST_METHOD", req.getMethod()); - env.set("SCRIPT_NAME", scriptName); - env.set("SCRIPT_FILENAME", scriptPath); - env.set("SERVER_NAME", req.getServerName()); - env.set("SERVER_PORT", Integer.toString(req.getServerPort())); - env.set("SERVER_PROTOCOL", req.getProtocol()); - env.set("SERVER_SOFTWARE", context.getServerInfo()); + environment.set("REMOTE_USER", req.getRemoteUser()); + environment.set("REQUEST_METHOD", req.getMethod()); + environment.set("SCRIPT_NAME", scriptName); + environment.set("SCRIPT_FILENAME", scriptPath); + environment.set("SERVER_NAME", req.getServerName()); + environment.set("SERVER_PORT", Integer.toString(req.getServerPort())); + environment.set("SERVER_PROTOCOL", req.getProtocol()); + environment.set("SERVER_SOFTWARE", context.getServerInfo()); Enumeration enm = req.getHeaderNames(); @@ -140,11 +137,11 @@ public class CGIRunner String name = (String) enm.nextElement(); String value = req.getHeader(name); - env.set("HTTP_" + name.toUpperCase().replace('-', '_'), value); + environment.set("HTTP_" + name.toUpperCase().replace('-', '_'), value); } // these extra ones were from printenv on www.dev.nomura.co.uk - env.set("HTTPS", (req.isSecure() + environment.set("HTTPS", (req.isSecure() ? "ON" : "OFF")); @@ -172,8 +169,8 @@ public class CGIRunner } Process p = (dir == null) - ? Runtime.getRuntime().exec(execCmd, env.getEnvArray()) - : Runtime.getRuntime().exec(execCmd, env.getEnvArray(), dir); + ? Runtime.getRuntime().exec(execCmd, environment.getEnvArray()) + : Runtime.getRuntime().exec(execCmd, environment.getEnvArray(), dir); // hook processes input to browser's output (async) final InputStream inFromReq = req.getInputStream(); @@ -327,17 +324,6 @@ public class CGIRunner return context; } - /** - * Method description - * - * - * @return - */ - public EnvList getEnvironment() - { - return environment; - } - /** * Method description * @@ -373,17 +359,6 @@ public class CGIRunner this.context = context; } - /** - * Method description - * - * - * @param environment - */ - public void setEnvironment(EnvList environment) - { - this.environment = environment; - } - /** * Method description * @@ -481,9 +456,6 @@ public class CGIRunner /** Field description */ private ServletContext context; - /** Field description */ - private EnvList environment; - /** Field description */ private boolean ignoreExitState; } diff --git a/scm-web-api/src/main/java/sonia/scm/web/cgi/EnvList.java b/scm-web-api/src/main/java/sonia/scm/web/cgi/EnvList.java index abbdccea10..e5e7189181 100644 --- a/scm-web-api/src/main/java/sonia/scm/web/cgi/EnvList.java +++ b/scm-web-api/src/main/java/sonia/scm/web/cgi/EnvList.java @@ -27,7 +27,7 @@ public class EnvList * Constructs ... * */ - EnvList() + public EnvList() { envMap = new HashMap(); } @@ -38,13 +38,26 @@ public class EnvList * * @param l */ - EnvList(EnvList l) + public EnvList(EnvList l) { envMap = new HashMap(l.envMap); } //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param key + * + * @return + */ + public boolean containsKey(String key) + { + return envMap.containsKey(key); + } + /** * Method description * @@ -57,11 +70,6 @@ public class EnvList return envMap.toString(); } - public boolean containsKey( String key ) - { - return envMap.containsKey(key); - } - //~--- get methods ---------------------------------------------------------- /**