package org.marketcetera.util.ws.wrappers; import java.io.Serializable; import javax.xml.bind.annotation.XmlTransient; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.marketcetera.util.except.I18NThrowable; import org.marketcetera.util.misc.ClassVersion; /** * A container for the information marshalled/serialized by a {@link * RemoteException}. That information is encapsulated in a container, * instead of being marshalled/serialized as individual properties of * {@link RemoteException}, so that the exception may perform * post-processing after all component properties below are set. * * <p>The stack trace capture is a string array, containing the * individual lines of the receiver's throwable stack trace printing: * the first string is usually the exception class and message, and * the remaining strings represent individual frames in the unravelled * stack.</p> * * <p>Equality and hash code generation ignore the receiver's * throwable, its wrapper, and its class name.</p> * * @author tlerios@marketcetera.com * @since 1.0.0 * @version $Id: RemoteProperties.java 16154 2012-07-14 16:34:05Z colin $ */ /* $License$ */ @ClassVersion("$Id: RemoteProperties.java 16154 2012-07-14 16:34:05Z colin $") public class RemoteProperties implements Serializable { // CLASS DATA. private static final long serialVersionUID=1L; // INSTANCE DATA. private transient Throwable mThrowable; private SerWrapper<Throwable> mWrapper; private String[] mTraceCapture; private String mServerMessage; private String mServerString; private String mServerName; // CONSTRUCTORS. /** * Creates a new container for a {@link RemoteException} that * wraps the given throwable. * * @param throwable The throwable, which may be null. */ public RemoteProperties (Throwable throwable) { setTransientThrowable(throwable); if (getTransientThrowable()==null) { return; } setWrapper(new SerWrapper<Throwable>(getTransientThrowable())); setTraceCapture(ExceptionUtils.getStackFrames(getTransientThrowable())); if (getTransientThrowable() instanceof I18NThrowable) { setServerMessage(((I18NThrowable)getTransientThrowable()). getLocalizedDetail()); } else { setServerMessage(getTransientThrowable().getLocalizedMessage()); } setServerString(getTransientThrowable().toString()); setServerName(getTransientThrowable().getClass().getName()); } /** * Creates a new container. This empty constructor is intended for * use by JAXB and Java serialization. It must be public because a * non-public one does not work for classes that are marshalled by * JAXB as part of an exception. */ public RemoteProperties() {} // INSTANCE METHODS. /** * Sets the receiver's throwable to the given one. * * @param throwable The throwable, which may be null. */ private void setTransientThrowable (Throwable throwable) { mThrowable=throwable; } /** * Returns the receiver's throwable. * * @return The throwable, which may be null. */ @XmlTransient private Throwable getTransientThrowable() { return mThrowable; } /** * Set the receiver's throwable (wrapper) to the given one. * * @param wrapper The throwable (wrapper), which may be null. */ public void setWrapper (SerWrapper<Throwable> wrapper) { mWrapper=wrapper; } /** * Returns the receiver's throwable (wrapper). * * @return The throwable (wrapper), which may be null. */ public SerWrapper<Throwable> getWrapper() { return mWrapper; } /** * Set the receiver's stack trace capture to the given one. * * @param traceCapture The capture, which may be null. */ public void setTraceCapture (String[] traceCapture) { mTraceCapture=traceCapture; } /** * Returns the receiver's stack trace capture. * * @return The capture, which may be null. */ public String[] getTraceCapture() { return mTraceCapture; } /** * Sets the receiver's server-localized message to the given one. * * @param serverMessage The message, which may be null. */ public void setServerMessage (String serverMessage) { mServerMessage=serverMessage; } /** * Returns the receiver's server-localized message. * * @return The message, which may be null. */ public String getServerMessage() { return mServerMessage; } /** * Sets the receiver's server string representation to the given * one. * * @param serverString The string, which may be null. */ public void setServerString (String serverString) { mServerString=serverString; } /** * Returns the receiver's server string representation. * * @return The string, which may be null. */ public String getServerString() { return mServerString; } /** * Sets the receiver's server class name to the given one. * * @param serverName The name, which may be null. */ public void setServerName (String serverName) { mServerName=serverName; } /** * Returns the receiver's server class name. * * @return The name, which may be null. */ public String getServerName() { return mServerName; } /** * Returns a best-effort reconstruction of the receiver's * throwable, as described in {@link RemoteException}. * * @return The throwable, which may be null. */ public Throwable getThrowable() { if (getTransientThrowable()!=null) { return getTransientThrowable(); } if (getWrapper()==null) { return null; } if (getWrapper().getRaw()!=null) { return getWrapper().getRaw(); } return new RemoteProxyException (getServerMessage(),getTraceCapture(), getServerString(),getServerName()); } // Object. @Override public int hashCode() { return (ArrayUtils.hashCode(getTraceCapture())+ ObjectUtils.hashCode(getServerMessage())+ ObjectUtils.hashCode(getServerString())); } @Override public boolean equals (Object other) { if (this==other) { return true; } if ((other==null) || !getClass().equals(other.getClass())) { return false; } RemoteProperties o=(RemoteProperties)other; return (ArrayUtils.isEquals(getTraceCapture(),o.getTraceCapture()) && ObjectUtils.equals(getServerMessage(),o.getServerMessage()) && ObjectUtils.equals(getServerString(),o.getServerString())); } }