/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.web.error;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.enonic.cms.framework.util.HtmlEncoder;
import com.enonic.cms.core.product.ProductVersion;
/**
* This class implements site error details.
*/
public final class ErrorDetails
{
private final Request request;
private final Throwable error;
private final int statusCode;
private final List<Throwable> allErrors;
private final String NO_MESSAGE = "No message";
/**
* Constructs the error details.
*/
public ErrorDetails( HttpServletRequest request, Throwable throwable, int statusCode )
{
this.request = new Request( request );
this.error = throwable;
this.statusCode = statusCode;
this.allErrors = findAllExceptions( this.error );
}
/**
* Return the error title.
*/
public String getTitle()
{
return "An Error Occured (" + this.statusCode + ")";
}
/**
* Return the message.
*/
public String getMessage()
{
if ( this.error == null )
{
return null;
}
String message = this.error.getMessage();
if ( message == null )
{
return NO_MESSAGE;
}
return message;
}
/**
* Return the request.
*/
public Request getRequest()
{
return this.request;
}
/**
* Return the response error.
*/
public int getStatusCode()
{
return this.statusCode;
}
/**
* Return the exception.
*/
public Throwable getException()
{
return this.error;
}
/**
* Return number of stack traces.
*/
public int getNumExceptions()
{
return this.allErrors.size();
}
/**
* Return the error title of error number.
*/
public String getExceptionMessage( int num )
{
if ( ( num >= 0 ) && ( num < this.allErrors.size() ) )
{
String message = this.allErrors.get( num ).getMessage();
if ( message != null )
{
return message;
}
else
{
return NO_MESSAGE;
}
}
else
{
return "";
}
}
/**
* Return the exception stack trace.
*/
public String getExceptionStackTrace( int num )
{
return getExceptionStackTrace( num, -1 );
}
/**
* Return the exception stack trace.
*/
public String getExceptionStackTrace( int num, int numLines )
{
if ( ( num >= 0 ) && ( num < this.allErrors.size() ) )
{
return getExceptionStackTrace( this.allErrors.get( num ), numLines );
}
else
{
return "";
}
}
/**
* Return the exception stack trace.
*/
private static String getExceptionStackTrace( Throwable error, int numLines )
{
StringBuffer buffer = new StringBuffer();
buffer.append( error.getClass().getName() );
if ( error.getMessage() != null )
{
buffer.append( ": " ).append( error.getMessage() );
}
buffer.append( "\n" );
StackTraceElement[] elements = error.getStackTrace();
int numLinesToPrint = numLines >= 0 ? Math.min( elements.length, numLines ) : elements.length;
for ( int i = 0; i < numLinesToPrint; i++ )
{
buffer.append( " at " ).append( elements[i].toString() ).append( "\n" );
}
int numMore = elements.length - numLinesToPrint;
if ( numMore > 0 )
{
buffer.append( " ... (" ).append( numMore ).append( " more) ..." );
}
return buffer.toString();
}
/**
* Find all exceptions.
*/
private static List<Throwable> findAllExceptions( Throwable error )
{
ArrayList<Throwable> list = new ArrayList<Throwable>();
if ( error != null )
{
findAllExceptions( list, error );
}
return list;
}
/**
* Find all exceptions.
*/
private static void findAllExceptions( List<Throwable> list, Throwable error )
{
if ( ( error != null ) && !list.contains( error ) )
{
list.add( error );
findAllExceptions( list, error.getCause() );
}
}
/**
* Return generated on string.
*/
public String getGeneratedOnString()
{
return "Generated by " + ProductVersion.getFullTitleAndVersion() + " on " + ( new Date() ).toString();
}
/**
* A wrapper of the HttpServletRequest that translates null-returns to empty strings.
*/
public class Request
{
private final HttpServletRequest request;
public Request( HttpServletRequest request )
{
this.request = request;
}
public String getServletPath()
{
return getAsSafe( request.getServletPath() );
}
public String getRemoteAddr()
{
return getAsSafe( request.getRemoteAddr() );
}
public String getRequestURI()
{
return getAsSafe( request.getRequestURI() );
}
public String getPathInfo()
{
return getAsSafe( request.getPathInfo() );
}
public String getContextPath()
{
return getAsSafe( request.getContextPath() );
}
public String getMethod()
{
return getAsSafe( request.getMethod() );
}
public String getProtocol()
{
return getAsSafe( request.getProtocol() );
}
public String getScheme()
{
return getAsSafe( request.getScheme() );
}
public String getServerName()
{
return getAsSafe( request.getServerName() );
}
public Enumeration getParameterNames()
{
return request.getParameterNames();
}
public String getParameterValuesAsCommaSeparatedString( String name )
{
StringBuffer s = new StringBuffer( "" );
String[] values = request.getParameterValues( name );
for ( int i = 0; i < values.length; i++ )
{
String v = values[i];
v = HtmlEncoder.encode( v );
s.append( v );
if ( i < values.length - 1 )
{
s.append( "," );
}
}
return s.toString();
}
private String getAsSafe( String value )
{
if ( value == null )
{
return "";
}
return value;
}
}
}