merge with branch issue-108

This commit is contained in:
Sebastian Sdorra
2012-04-04 09:47:55 +02:00
6 changed files with 439 additions and 19 deletions

View File

@@ -89,9 +89,19 @@ public class BasicContextProvider implements SCMContextProvider
*/
public BasicContextProvider()
{
baseDirectory = findBaseDirectory();
version = loadVersion();
stage = loadProjectStage();
try
{
baseDirectory = findBaseDirectory();
version = loadVersion();
stage = loadProjectStage();
}
catch (Throwable ex)
{
this.startupError = ex;
// print exception to system err
ex.printStackTrace(System.err);
}
}
//~--- methods --------------------------------------------------------------
@@ -137,6 +147,18 @@ public class BasicContextProvider implements SCMContextProvider
return stage;
}
/**
* {@inheritDoc}
*
*
* @return
*/
@Override
public Throwable getStartupError()
{
return startupError;
}
/**
* Returns the version of the SCM-Manager. If the version is not set, the
* {@link #DEFAULT_VERSION} is returned.
@@ -182,7 +204,16 @@ public class BasicContextProvider implements SCMContextProvider
if (!directory.exists() &&!directory.mkdirs())
{
throw new IllegalStateException("could not create directory");
String msg = "could not create home directory at ".concat(
directory.getAbsolutePath());
// do not use logger
// http://www.slf4j.org/codes.html#substituteLogger
System.err.println("===================================================");
System.err.append("Error: ").println(msg);
System.err.println("===================================================");
throw new IllegalStateException(msg);
}
return directory;
@@ -319,6 +350,9 @@ public class BasicContextProvider implements SCMContextProvider
/** stage of the current SCM-Manager instance */
private Stage stage;
/** startup exception */
private Throwable startupError;
/** the version of the SCM-Manager */
private String version;
}

View File

@@ -74,6 +74,16 @@ public interface SCMContextProvider extends Closeable
*/
public Stage getStage();
/**
* Returns a exception which is occurred on context startup.
* The method returns null if the start was successful.
*
*
* @return startup exception of null
* @since 1.14
*/
public Throwable getStartupError();
/**
* Returns the version of the SCM-Manager.
*

View File

@@ -76,30 +76,32 @@ public class ScmContextListener extends GuiceServletContextListener
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)
{
if (injector != null)
if ((globalInjector != null) && ! startupError)
{
// close RepositoryManager
IOUtil.close(injector.getInstance(RepositoryManager.class));
IOUtil.close(globalInjector.getInstance(RepositoryManager.class));
// close Authenticator
IOUtil.close(injector.getInstance(AuthenticationManager.class));
IOUtil.close(globalInjector.getInstance(AuthenticationManager.class));
// close GroupManager
IOUtil.close(injector.getInstance(GroupManager.class));
IOUtil.close(globalInjector.getInstance(GroupManager.class));
// close UserManager
IOUtil.close(injector.getInstance(UserManager.class));
IOUtil.close(globalInjector.getInstance(UserManager.class));
// close StoreFactory
IOUtil.close(injector.getInstance(StoreFactory.class));
IOUtil.close(globalInjector.getInstance(StoreFactory.class));
// close CacheManager
IOUtil.close(injector.getInstance(CacheManager.class));
IOUtil.close(globalInjector.getInstance(CacheManager.class));
// remove thread local store
injector.getInstance(LocalSecurityContextHolder.class).destroy();
injector.getInstance(ServletContextListenerHolder.class).contextDestroyed(
globalInjector.getInstance(LocalSecurityContextHolder.class).destroy();
// call destroy event
globalInjector.getInstance(ServletContextListenerHolder.class).contextDestroyed(
servletContextEvent);
}
@@ -115,12 +117,25 @@ public class ScmContextListener extends GuiceServletContextListener
@Override
public void contextInitialized(ServletContextEvent servletContextEvent)
{
ScmUpgradeHandler upgradeHandler = new ScmUpgradeHandler();
if (SCMContext.getContext().getStartupError() == null)
{
ScmUpgradeHandler upgradeHandler = new ScmUpgradeHandler();
upgradeHandler.doUpgrade();
}
else
{
startupError = true;
}
upgradeHandler.doUpgrade();
super.contextInitialized(servletContextEvent);
injector.getInstance(ServletContextListenerHolder.class).contextInitialized(
// call destroy event
if ((globalInjector != null) && ! startupError)
{
globalInjector.getInstance(ServletContextListenerHolder.class).contextInitialized(
servletContextEvent);
}
}
//~--- get methods ----------------------------------------------------------
@@ -133,6 +148,26 @@ public class ScmContextListener extends GuiceServletContextListener
*/
@Override
protected Injector getInjector()
{
if (startupError)
{
globalInjector = getErrorInjector();
}
else
{
globalInjector = getDefaultInjector();
}
return globalInjector;
}
/**
* Method description
*
*
* @return
*/
private Injector getDefaultInjector()
{
PluginLoader pluginLoader = new DefaultPluginLoader();
BindingExtensionProcessor bindExtProcessor =
@@ -148,8 +183,8 @@ public class ScmContextListener extends GuiceServletContextListener
moduleList.addAll(bindExtProcessor.getModuleSet());
moduleList.addAll(overrides.getModules());
moduleList.add(0, main);
injector = Guice.createInjector(moduleList);
Injector injector = Guice.createInjector(moduleList);
SCMContextProvider context = SCMContext.getContext();
// init StoreFactory
@@ -178,12 +213,25 @@ public class ScmContextListener extends GuiceServletContextListener
authenticationManager.init(context);
// fetch listeners
return injector;
}
/**
* Method description
*
*
* @return
*/
private Injector getErrorInjector()
{
return Guice.createInjector(new ScmErrorModule());
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private Injector injector;
private Injector globalInjector;
/** Field description */
private boolean startupError = false;
}

View File

@@ -0,0 +1,62 @@
/**
* 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;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.servlet.ServletModule;
import sonia.scm.template.ErrorServlet;
import sonia.scm.template.FreemarkerTemplateHandler;
import sonia.scm.template.TemplateHandler;
/**
*
* @author Sebastian Sdorra
*/
public class ScmErrorModule extends ServletModule
{
/**
* Method description
*
*/
@Override
protected void configureServlets()
{
SCMContextProvider context = SCMContext.getContext();
bind(SCMContextProvider.class).toInstance(context);
bind(TemplateHandler.class).to(FreemarkerTemplateHandler.class);
serve(ScmServletModule.PATTERN_ALL).with(ErrorServlet.class);
}
}

View File

@@ -0,0 +1,165 @@
/**
* 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.template;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Throwables;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import sonia.scm.SCMContextProvider;
import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author Sebastian Sdorra
*/
@Singleton
public class ErrorServlet extends HttpServlet
{
/** Field description */
private static final long serialVersionUID = -3289076078469757874L;
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param context
* @param handler
*/
@Inject
public ErrorServlet(SCMContextProvider context, TemplateHandler handler)
{
this.context = context;
this.handler = handler;
}
//~--- methods --------------------------------------------------------------
/**
* 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);
}
/**
* Method description
*
*
* @param request
* @param response
*
* @throws IOException
* @throws ServletException
*/
private void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
PrintWriter writer = null;
try
{
writer = response.getWriter();
Map<String, Object> env = new HashMap<String, Object>();
String error = Util.EMPTY_STRING;
if (context.getStartupError() != null)
{
error = Throwables.getStackTraceAsString(context.getStartupError());
}
env.put("error", error);
handler.render("/error.html", writer, env);
}
finally
{
IOUtil.close(context);
}
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private SCMContextProvider context;
/** Field description */
private TemplateHandler handler;
}

View File

@@ -0,0 +1,101 @@
<!--*
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
-->
<!DOCTYPE html>
<html>
<head>
<title>SCM-Manager Error</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
body {
background-color: #ffffff;
margin: 10px;
color: #202020;
font-family: Verdana,Helvetica,Arial,sans-serif;
font-size: 75%;
}
h1, h2, h3, h4, h5 {
font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
font-weight: bold;
margin: 0px;
padding: 0px;
color: #D20005;
}
h1 {
font-size: 18px;
border-bottom: 1px solid #AFAFAF;
}
h2 {
font-size: 14px;
border-bottom: 1px solid #AFAFAF;
}
a:link, a:visited {
color: #045491;
font-weight: bold;
text-decoration: none;
}
a:link:hover, a:visited:hover {
color: #045491;
font-weight: bold;
text-decoration: underline;
}
table {
border: 0 none;
border-collapse: collapse;
font-size: 100%;
margin: 20px 0;
padding: 20px;
width: 100%;
}
td, th {
padding: 3px;
vertical-align: top;
border: 1px solid #CCCCCC;
text-align: left;
}
.small {
width: 20%;
}
</style>
</head>
<body>
<h1>SCM-Manager Error</h1>
<p>
There is an error occurred during SCM-Manager startup.
</p>
<pre>
${error}
</pre>
</body>
</html>