/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.core.designer;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.teiid.core.designer.util.EquivalenceUtil;
import org.teiid.core.designer.util.ExternalizeUtil;
/**
* @since 8.0
*/
public class ModelerCoreException extends CoreException implements Externalizable {
private static final String NO_MESSAGE = "No Error Message"; //$NON-NLS-1$
CoreException nestedCoreException;
/**
* No-arg constructor required by Externalizable semantics
*/
public ModelerCoreException() {
// Set the status to some non-null value for now.
super(new StatusHolder(new Status(IStatus.ERROR, CoreModelerPlugin.PLUGIN_ID, 0, getNonNullMessage(NO_MESSAGE), null)));
}
/**
* Construct an instance of ModelerCoreException.
*
* @param e
* @param code
*/
public ModelerCoreException( Throwable e,
int code ) {
super(new Status(IStatus.ERROR, CoreModelerPlugin.PLUGIN_ID, code, "", e)); //$NON-NLS-1$
}
/**
* Construct an instance of ModelerCoreException.
*
* @param exception
*/
public ModelerCoreException( CoreException exception ) {
super(exception == null ? new Status(IStatus.ERROR, CoreModelerPlugin.PLUGIN_ID, 0, "", null) : exception.getStatus()); //$NON-NLS-1$
if (exception != null) {
this.nestedCoreException = exception;
}
}
/**
* Construct an instance of ModelerCoreException.
*
* @param status
*/
public ModelerCoreException( IStatus status ) {
super(status == null ? new Status(IStatus.ERROR, CoreModelerPlugin.PLUGIN_ID, 0, "", null) : status); //$NON-NLS-1$
}
/**
* Construct an instance of ModelerCoreException.
*
* @param message
*/
public ModelerCoreException( String message ) {
super(new Status(IStatus.ERROR, CoreModelerPlugin.PLUGIN_ID, 0, getNonNullMessage(message), null));
}
/**
* Construct an instance of ModelerCoreException.
*
* @param e
*/
public ModelerCoreException( Throwable e ) {
super(new Status(IStatus.ERROR, CoreModelerPlugin.PLUGIN_ID, 0, getNonNullMessageFromThrowable(e), e));
}
/**
* Construct an instance of ModelerCoreException.
*
* @param e
* @param message
*/
public ModelerCoreException( Throwable e,
String message ) {
super(new Status(IStatus.ERROR, CoreModelerPlugin.PLUGIN_ID, 0, getNonNullMessage(message), e));
}
/**
* Subclasses may override this method, which is used by {@link #toString()} to obtain the "type" for the exception class.
*
* @return the type; defaults to "Modeler Core Exception"
*/
protected String getToStringType() {
return "Modeler Core Exception"; //$NON-NLS-1$
}
/**
* Get non-null version of message.
*
* @param message Message
* @return Original message if non-null, otherwise ""
*/
static String getNonNullMessage( String message ) {
if (message == null) {
return ""; //$NON-NLS-1$
}
return message;
}
/**
* Get non-null version of message.
*
* @param message Message
* @return Original message if non-null, otherwise ""
*/
static String getNonNullMessageFromThrowable( Throwable t ) {
if (t == null) {
return ""; //$NON-NLS-1$
}
return getNonNullMessage(t.getMessage());
}
/**
* Returns a printable representation of this exception suitable for debugging purposes only.
*/
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getToStringType());
buffer.append(":"); //$NON-NLS-1$
if (getException() != null) {
if (getException() instanceof CoreException) {
CoreException c = (CoreException)getException();
buffer.append(" Core Exception [code "); //$NON-NLS-1$
buffer.append(c.getStatus().getCode());
buffer.append("] "); //$NON-NLS-1$
buffer.append(c.getStatus().getMessage());
} else {
buffer.append(" "); //$NON-NLS-1$
buffer.append(getException().toString());
}
} else {
buffer.append(" "); //$NON-NLS-1$
buffer.append(getStatus().toString());
}
return buffer.toString();
}
/**
* Overrides the default implementation to return the message contained within the status. This is useful because when this
* object is deserialized, the deserialized message may be different from the default message (i.e. the message created by the
* no-arg constructor).
*
* @see java.lang.Throwable#getMessage()
*/
@Override
public String getMessage() {
return getStatus().getMessage();
}
public Throwable getException() {
if (this.nestedCoreException == null) {
return getStatus().getException();
}
return this.nestedCoreException;
}
/**
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
@Override
public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException {
final IStatus status = readIStatus(in);
final IStatus currentStatus = getStatus();
if (currentStatus instanceof StatusHolder && status != null) {
// Assuming the no-arg constructor of this class was called by the
// deserialization, we need to set the holder's actual IStatus
// to the object we just deserialized.
((StatusHolder)currentStatus).setStatus(status);
}
StackTraceElement[] stackTrace = (StackTraceElement[])in.readObject();
setStackTrace(stackTrace);
nestedCoreException = (CoreException)internalReadThrowable(in);
}
/**
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
@Override
public void writeExternal( ObjectOutput out ) throws IOException {
writeIStatus(out, this.getStatus());
out.writeObject(this.getStackTrace());
internalWriteThrowable(out, nestedCoreException);
}
/**
* Holder that forwards all calls to the contained IStatus instance.
*/
private static class StatusHolder implements IStatus, Serializable {
private static final long serialVersionUID = 1L;
private IStatus status = null;
StatusHolder( IStatus status ) {
setStatus(status);
}
void setStatus( IStatus status ) {
this.status = status;
}
@Override
public IStatus[] getChildren() {
return status.getChildren();
}
@Override
public int getCode() {
return status.getCode();
}
@Override
public Throwable getException() {
return status.getException();
}
@Override
public String getMessage() {
return status.getMessage();
}
@Override
public String getPlugin() {
return status.getPlugin();
}
@Override
public int getSeverity() {
return status.getSeverity();
}
@Override
public boolean isMultiStatus() {
return status.isMultiStatus();
}
@Override
public boolean isOK() {
return status.isOK();
}
@Override
public boolean matches( int severityMask ) {
return status.matches(severityMask);
}
}
/*
* Serializing CoreException and subclasses.
*/
public static void writeThrowable( ObjectOutput out,
Throwable t ) throws IOException {
if (t == null || !(t instanceof CoreException) || (t instanceof TeiidDesignerException)) {
out.writeBoolean(false);
out.writeObject(t);
} else {
out.writeBoolean(true);
writeCoreException(out, (CoreException)t);
}
}
public static void writeCoreException( ObjectOutput out,
CoreException e ) throws IOException {
writeIStatus(out, e.getStatus());
out.writeObject(e.getStackTrace());
}
public static void writeIStatus( ObjectOutput out,
IStatus status ) throws IOException {
StatusImpl serializableStatus = new StatusImpl(status);
out.writeObject(serializableStatus);
}
public static Throwable readThrowable( ObjectInput in ) throws IOException, ClassNotFoundException {
final boolean isCoreException = in.readBoolean();
if (isCoreException) {
return readCoreException(in);
}
return (Throwable)in.readObject();
}
public static CoreException readCoreException( ObjectInput in ) throws IOException, ClassNotFoundException {
IStatus status = readIStatus(in);
CoreException exception = new CoreException(status);
StackTraceElement[] stackTrace = (StackTraceElement[])in.readObject();
exception.setStackTrace(stackTrace);
return exception;
}
public static IStatus readIStatus( ObjectInput in ) throws IOException, ClassNotFoundException {
IStatus status = (IStatus)in.readObject();
return status;
}
/**
* Serializable implementation of IStatus used to serialize instances of CoreException and TeiidDesignerException
*/
public static class StatusImpl implements IStatus, Externalizable {
public static final long serialVersionUID = 0;
private StatusImpl[] children = null;
private int code = 0;
private Throwable exception = null;
private String message = null;
private String plugin = null;
private int severity = 0;
private boolean multiStatus = false;
private boolean ok = false;
/**
* Constructor required by Externalizable construct
*/
public StatusImpl() {
}
/**
* Copy constructor that converts all instances of IStatus in the original tree to an instance of StatusImpl to guarantee
* serialization.
*
* @param original
* @throws NullPointerException if the original IStatus is null
*/
public StatusImpl( IStatus original ) {
if (original.getChildren() != null) {
final int length = original.getChildren().length;
this.children = new StatusImpl[length];
for (int i = 0; i < length; i++) {
if (original.getChildren()[i] != null) {
this.children[i] = new StatusImpl(original.getChildren()[i]);
}
}
}
this.code = original.getCode();
this.exception = original.getException();
this.message = original.getMessage();
this.plugin = original.getPlugin();
this.severity = original.getSeverity();
this.multiStatus = original.isMultiStatus();
this.ok = original.isOK();
}
@Override
public IStatus[] getChildren() {
return children;
}
@Override
public int getCode() {
return code;
}
@Override
public Throwable getException() {
return exception;
}
@Override
public String getMessage() {
return message;
}
@Override
public String getPlugin() {
return plugin;
}
@Override
public int getSeverity() {
return severity;
}
@Override
public boolean isMultiStatus() {
return multiStatus;
}
@Override
public boolean isOK() {
return ok;
}
@Override
public boolean matches( int severityMask ) {
return (severity & severityMask) != 0;
}
@Override
public boolean equals( Object obj ) {
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof IStatus)) return false;
IStatus other = (IStatus)obj;
return EquivalenceUtil.areEquivalent(this.children, other.getChildren()) && this.code == other.getCode()
&& EquivalenceUtil.areEqual(this.message, other.getMessage())
&& EquivalenceUtil.areEqual(this.plugin, other.getPlugin()) && this.severity == other.getSeverity()
&& this.multiStatus == other.isMultiStatus() && this.ok == other.isOK();
// both have a throwable, or neither has a throwable
// (this.exception == null ^ other.getException() != null)
}
@Override
public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException {
final int length = in.readInt();
children = new StatusImpl[length];
for (int i = 0; i < length; i++) {
children[i] = (StatusImpl)in.readObject();
}
code = in.readInt();
exception = readThrowable(in);
message = (String)in.readObject();
plugin = (String)in.readObject();
severity = in.readInt();
multiStatus = in.readBoolean();
ok = in.readBoolean();
}
@Override
public void writeExternal( ObjectOutput out ) throws IOException {
ExternalizeUtil.writeArray(out, children);
out.writeInt(code);
writeThrowable(out, exception);
out.writeObject(message);
out.writeObject(plugin);
out.writeInt(severity);
out.writeBoolean(multiStatus);
out.writeBoolean(ok);
}
}
/*
* Serializing CoreException and subclasses.
*/
private void internalWriteThrowable(ObjectOutput out, Throwable t) throws IOException {
out.writeObject(t);
}
private Throwable internalReadThrowable(ObjectInput in) throws IOException, ClassNotFoundException {
return (Throwable)in.readObject();
}
}