/*******************************************************************************
* Copyright (c) 2004, 2006
* Thomas Hallgren, Kenneth Olwing, Mitch Sonies
* Pontus Rydin, Nils Unden, Peer Torngren
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the individual
* copyright holders listed above, as Initial Contributors under such license.
* The text of such license is available at www.eclipse.org.
*******************************************************************************/
package org.eclipse.equinox.p2.authoring.internal;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.p2.authoring.P2AuthoringUIPlugin;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* This class contains basic wrap and unwrap functionality for various commonly
* used exceptions. The idea is to normalize exception into a {@link CoreException}
*
* @author Thomas Hallgren
*/
public abstract class P2AuthoringException extends CoreException
{
protected P2AuthoringException(IStatus status)
{
super(status);
}
private static final long serialVersionUID = -3152601911941317801L;
// Special class that gives us access to the setMessage
//
private static class BMStatus extends Status
{
public BMStatus(int severity, String pluginId, int code, String message, Throwable exception)
{
super(severity, pluginId, code, message, exception);
}
@Override
protected void setMessage(String message)
{
super.setMessage(message);
}
}
public static IStatus createStatus(String message, Throwable cause)
{
return new BMStatus(IStatus.ERROR, P2AuthoringUIPlugin.PLUGIN_ID, IStatus.OK, message, cause);
}
public static void setMessageStatus(IStatus status, String message, Object...args)
{
((BMStatus)status).setMessage(String.format(message, args));
}
public static void deeplyPrint(IStatus status, PrintStream strm, boolean stackTrace, boolean includeWarnings)
{
deeplyPrint(status, strm, stackTrace, includeWarnings, 0);
}
public static void deeplyPrint(Throwable e, PrintStream strm, boolean stackTrace)
{
deeplyPrint(e, strm, stackTrace, 0);
}
public static CoreException fromMessage(String message, Object...args)
{
return fromMessage(null, message, args);
}
public static CoreException fromMessage(Throwable cause, String message, Object...args)
{
CoreException ce = new CoreException(createStatus(String.format(message, args), cause));
if(cause != null)
ce.initCause(cause);
return ce;
}
public static Throwable unwind(Throwable t)
{
for(;;)
{
Class<?> tc = t.getClass();
// We don't use instanceof operator since we want
// the explicit class, not subclasses.
//
if(tc != RuntimeException.class
&& tc != InvocationTargetException.class
&& tc != SAXException.class
&& tc != IOException.class)
break;
Throwable cause = t.getCause();
if(cause == null)
break;
String msg = t.getMessage();
if(msg != null && !msg.equals(cause.toString()))
break;
t = cause;
}
return t;
}
public static CoreException unwindCoreException(CoreException exception)
{
IStatus status = exception.getStatus();
while(status != null && status.getException() instanceof CoreException)
{
exception = (CoreException)status.getException();
status = exception.getStatus();
}
return exception;
}
public static CoreException wrap(IStatus status)
{
CoreException e = new CoreException(status);
Throwable t = status.getException();
if(t != null)
e.initCause(t);
return e;
}
public static CoreException wrap(Throwable t)
{
t = unwind(t);
if(t instanceof CoreException)
return unwindCoreException((CoreException)t);
if(t instanceof OperationCanceledException || t instanceof InterruptedException)
return new CoreException(Status.CANCEL_STATUS);
String msg = t.toString();
if(t instanceof SAXParseException)
{
SAXParseException se = (SAXParseException)t;
StringBuffer bld = new StringBuffer(msg);
bld.append(": ");
bld.append(se.getSystemId());
bld.append(" at line: ");
bld.append(se.getLineNumber());
bld.append(" column: ");
bld.append(se.getColumnNumber());
msg = bld.toString();
}
return fromMessage(t, msg);
}
private static void appendLevelString(PrintStream strm, int level)
{
if(level > 0)
{
strm.print("[0");
for(int idx = 1; idx < level; ++idx)
{
strm.print('.');
strm.print(level);
}
strm.print(']');
}
}
private static void deeplyPrint(CoreException ce, PrintStream strm, boolean stackTrace, boolean includeWarnings, int level)
{
appendLevelString(strm, level);
if(stackTrace)
ce.printStackTrace(strm);
deeplyPrint(ce.getStatus(), strm, stackTrace, includeWarnings, level);
}
private static void deeplyPrint(IStatus status, PrintStream strm, boolean stackTrace, boolean includeWarnings, int level)
{
switch(status.getSeverity())
{
case IStatus.ERROR:
break;
case IStatus.WARNING:
if(includeWarnings)
break;
/* Fall through */
default:
return;
}
appendLevelString(strm, level);
String msg = status.getMessage();
strm.println(msg);
Throwable cause = status.getException();
if(cause != null)
{
strm.print("Caused by: ");
if(stackTrace || !(msg.equals(cause.getMessage()) || msg.equals(cause.toString())))
deeplyPrint(cause, strm, stackTrace, level);
}
if(status.isMultiStatus())
{
IStatus[] children = status.getChildren();
for(int i = 0; i < children.length; i++)
deeplyPrint(children[i], strm, stackTrace, includeWarnings, level + 1);
}
}
private static void deeplyPrint(Throwable t, PrintStream strm, boolean stackTrace, int level)
{
if(t instanceof CoreException)
deeplyPrint((CoreException)t, strm, stackTrace, false, level);
else
{
appendLevelString(strm, level);
if(stackTrace)
t.printStackTrace(strm);
else
{
strm.println(t.toString());
Throwable cause = t.getCause();
if(cause != null)
{
strm.print("Caused by: ");
deeplyPrint(cause, strm, stackTrace, level);
}
}
}
}
}