Commits

Sebastian Sdorra committed efafe76

improve handling of mercurial errors

  • Participants
  • Parent commits e384a49
  • Branches issue-138

Comments (0)

Files changed (2)

File scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIExceptionHandler.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.web;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.util.IOUtil;
+import sonia.scm.util.Util;
+import sonia.scm.web.cgi.CGIExceptionHandler;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import java.text.MessageFormat;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgCGIExceptionHandler implements CGIExceptionHandler
+{
+
+  /** Field description */
+  public static final String CONTENT_TYPE_ERROR = "application/hg-error";
+
+  /** TODO create a bundle for error messages */
+  public static final String ERROR_NOT_CONFIGURED =
+    "The mercurial installation on the scm-manager server seems to be not configured correctly. Please check the settings.";
+
+  /** Field description */
+  public static final String ERROR_UNKNOWN =
+    "There is an unknown error occurred: '{0}'";
+
+  /**
+   * the logger for HgCGIExceptionHandler
+   */
+  private static final Logger logger =
+    LoggerFactory.getLogger(HgCGIExceptionHandler.class);
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param request
+   * @param response
+   * @param ex
+   */
+  @Override
+  public void handleException(HttpServletRequest request,
+                              HttpServletResponse response, Throwable ex)
+  {
+    if (logger.isErrorEnabled())
+    {
+      logger.error("not able to handle mercurial request", ex);
+    }
+
+    try
+    {
+      sendError(response, createErrorMessage(ex));
+    }
+    catch (IOException ioEx)
+    {
+      logger.error("could not write error message to client", ioEx);
+    }
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param response
+   * @param message
+   *
+   * @throws IOException
+   */
+  public void sendError(HttpServletResponse response, String message)
+          throws IOException
+  {
+    response.setContentType(CONTENT_TYPE_ERROR);
+
+    PrintWriter writer = null;
+
+    try
+    {
+      writer = response.getWriter();
+      writer.println(message);
+    }
+    finally
+    {
+      IOUtil.close(writer);
+    }
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param ex
+   *
+   * @return
+   */
+  private String createErrorMessage(Throwable ex)
+  {
+    return MessageFormat.format(ERROR_UNKNOWN, Util.nonNull(ex.getMessage()));
+  }
+}

File scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java

     this.handler = handler;
     this.hookManager = hookManager;
     this.requestListenerUtil = requestListenerUtil;
+    this.exceptionHandler = new HgCGIExceptionHandler();
   }
 
   //~--- methods --------------------------------------------------------------
 
     if (repository == null)
     {
-      throw new ServletException("repository not found");
+      if (logger.isDebugEnabled())
+      {
+        logger.debug("no hg repository found at {}", request.getRequestURI());
+      }
+
+      response.setStatus(HttpServletResponse.SC_NOT_FOUND);
     }
+    else if (!handler.isConfigured())
+    {
+      exceptionHandler.sendError(response,
+                                 HgCGIExceptionHandler.ERROR_NOT_CONFIGURED);
+    }
+    else
+    {
+      try
+      {
+        handleRequest(request, response, repository);
+      }
+      catch (Exception ex)
+      {
+        exceptionHandler.handleException(request, response, ex);
+      }
+    }
+  }
 
+  /**
+   * Method description
+   *
+   *
+   * @param request
+   * @param response
+   * @param repository
+   *
+   * @throws IOException
+   * @throws ServletException
+   */
+  private void handleRequest(HttpServletRequest request,
+                             HttpServletResponse response,
+                             Repository repository)
+          throws ServletException, IOException
+  {
     if (requestListenerUtil.callListeners(request, response, repository))
     {
       process(request, response, repository);
     String name = repository.getName();
     File directory = handler.getDirectory(repository);
     String pythonPath = HgUtil.getPythonPath(handler.getConfig());
-    
     CGIExecutor executor = cgiExecutorFactory.createExecutor(configuration,
                              getServletContext(), request, response);
 
   private ScmConfiguration configuration;
 
   /** Field description */
+  private HgCGIExceptionHandler exceptionHandler;
+
+  /** Field description */
   private HgRepositoryHandler handler;
 
   /** Field description */