From 5f5fe1cf58b6f33f1a4c870b536eec6c3aa13814 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 2 Jun 2012 14:42:46 +0200 Subject: [PATCH] implement hook url detection --- .../sonia/scm/repository/HgHookManager.java | 213 ++++++++++++++++-- .../sonia/scm/web/HgHookCallbackServlet.java | 29 +++ 2 files changed, 228 insertions(+), 14 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java index 2dab5c6409..73089131f7 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java @@ -38,11 +38,21 @@ package sonia.scm.repository; import com.google.inject.Inject; import com.google.inject.Singleton; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.ConfigChangedListener; import sonia.scm.config.ScmConfiguration; import sonia.scm.util.HttpUtil; +import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ +import java.io.IOException; + +import java.net.HttpURLConnection; +import java.net.URL; + import java.util.UUID; import javax.servlet.http.HttpServletRequest; @@ -52,9 +62,20 @@ import javax.servlet.http.HttpServletRequest; * @author Sebastian Sdorra */ @Singleton -public class HgHookManager +public class HgHookManager implements ConfigChangedListener { + /** Field description */ + public static final String URL_HOOKPATH = "/hook/hg/"; + + /** + * the logger for HgHookManager + */ + private static final Logger logger = + LoggerFactory.getLogger(HgHookManager.class); + + //~--- constructors --------------------------------------------------------- + /** * Constructs ... * @@ -65,10 +86,23 @@ public class HgHookManager public HgHookManager(ScmConfiguration configuration) { this.configuration = configuration; + this.configuration.addListener(this); } //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param config + */ + @Override + public void configChanged(ScmConfiguration config) + { + hookUrl = null; + } + /** * Method description * @@ -79,23 +113,23 @@ public class HgHookManager */ public String createUrl(HttpServletRequest request) { - String url = null; - - if (configuration.isForceBaseUrl()) + if (hookUrl == null) { - url = HttpUtil.getUriWithoutEndSeperator( - configuration.getBaseUrl()).concat("/hook/hg/"); - } - else - { - StringBuilder sb = new StringBuilder(request.getScheme()); + synchronized (this) + { + if (hookUrl == null) + { + buildHookUrl(request); - sb.append("://localhost:").append(request.getLocalPort()); - sb.append(request.getContextPath()).append("/hook/hg/"); - url = sb.toString(); + if (logger.isInfoEnabled() && Util.isNotEmpty(hookUrl)) + { + logger.info("use {} for mercurial hooks", hookUrl); + } + } + } } - return url; + return hookUrl; } //~--- get methods ---------------------------------------------------------- @@ -124,6 +158,154 @@ public class HgHookManager return this.challenge.equals(challenge); } + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param request + */ + private void buildHookUrl(HttpServletRequest request) + { + if (configuration.isForceBaseUrl()) + { + if (logger.isDebugEnabled()) + { + logger.debug( + "create hook url from configured base url because force base url is enabled"); + } + + hookUrl = createConfiguredUrl(); + + if (!isUrlWorking(hookUrl)) + { + disableHooks(); + } + } + else + { + if (logger.isDebugEnabled()) + { + logger.debug("create hook url from request"); + } + + hookUrl = HttpUtil.getCompleteUrl(request, URL_HOOKPATH); + + if (!isUrlWorking(hookUrl)) + { + if (logger.isWarnEnabled()) + { + logger.warn( + "hook url {} from request does not work, try now localhost"); + } + + hookUrl = createLocalUrl(request); + + if (!isUrlWorking(hookUrl)) + { + if (logger.isWarnEnabled()) + { + logger.warn( + "localhost hook url {} does not work, try now from configured base url"); + } + + hookUrl = createConfiguredUrl(); + + if (!isUrlWorking(hookUrl)) + { + disableHooks(); + } + } + } + } + } + + /** + * Method description + * + * + * @return + */ + private String createConfiguredUrl() + { + return HttpUtil.getUriWithoutEndSeperator( + configuration.getBaseUrl()).concat("/hook/hg/"); + } + + /** + * Method description + * + * + * @param request + * + * @return + */ + private String createLocalUrl(HttpServletRequest request) + { + StringBuilder sb = new StringBuilder(request.getScheme()); + + sb.append("://localhost:").append(request.getLocalPort()); + sb.append(request.getContextPath()).append(URL_HOOKPATH); + + return sb.toString(); + } + + /** + * Method description + * + */ + private void disableHooks() + { + if (logger.isErrorEnabled()) + { + logger.error( + "disabling mercurial hooks, because hook url {} seems not to work", + hookUrl); + } + + hookUrl = Util.EMPTY_STRING; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param url + * + * @return + */ + private boolean isUrlWorking(String url) + { + boolean result = false; + + try + { + url = url.concat("?ping=true"); + + if (logger.isTraceEnabled()) + { + logger.trace("check hook url {}", url); + } + + HttpURLConnection connection = + (HttpURLConnection) new URL(url).openConnection(); + + result = connection.getResponseCode() == 204; + } + catch (IOException ex) + { + if (logger.isTraceEnabled()) + { + logger.trace("url test failed for url ".concat(url), ex); + } + } + + return result; + } + //~--- fields --------------------------------------------------------------- /** Field description */ @@ -131,4 +313,7 @@ public class HgHookManager /** Field description */ private ScmConfiguration configuration; + + /** Field description */ + private volatile String hookUrl; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java index dba36cda24..119ea7fcff 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java @@ -93,6 +93,9 @@ public class HgHookCallbackServlet extends HttpServlet /** Field description */ private static final String PARAM_NODE = "node"; + /** Field description */ + private static final String PARAM_PING = "ping"; + /** Field description */ private static final Pattern REGEX_URL = Pattern.compile("^/hook/hg/([^/]+)$"); @@ -131,6 +134,32 @@ public class HgHookCallbackServlet extends HttpServlet //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param request + * @param response + * + * @throws IOException + * @throws ServletException + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + String ping = request.getParameter(PARAM_PING); + + if (Util.isNotEmpty(ping) && Boolean.parseBoolean(ping)) + { + response.setStatus(HttpServletResponse.SC_NO_CONTENT); + } + else + { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + } + } + /** * Method description *