001: /*--
002:
003: Copyright (C) 2002-2005 Adrian Price.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The names "OBE" and "Open Business Engine" must not be used to
019: endorse or promote products derived from this software without prior
020: written permission. For written permission, please contact
021: adrianprice@sourceforge.net.
022:
023: 4. Products derived from this software may not be called "OBE" or
024: "Open Business Engine", nor may "OBE" or "Open Business Engine"
025: appear in their name, without prior written permission from
026: Adrian Price (adrianprice@users.sourceforge.net).
027:
028: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
029: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
030: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
032: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
034: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
035: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
036: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
037: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
038: POSSIBILITY OF SUCH DAMAGE.
039:
040: For more information on OBE, please see
041: <http://obe.sourceforge.net/>.
042:
043: */
044:
045: package org.obe.server.j2ee.ejb;
046:
047: import org.wfmc.wapi.WMWorkflowException;
048:
049: import java.io.PrintStream;
050: import java.io.PrintWriter;
051:
052: /**
053: * This exception class represents a runtime exception.
054: *
055: * @author Adrian Price
056: */
057: public class WMRuntimeException extends RuntimeException {
058:
059: // In order to maintain backwards and forwards compatiblity of serialized
060: // objects across versions, observe the following restrictions when modifying
061: // this class:
062: // * Deleting fields - If a field is deleted in a class, the stream written
063: // will not contain its value. When the stream is read by an earlier class,
064: // the value of the field will be set to the default value because no value
065: // is available in the stream. However, this default value may adversely
066: // impair the ability of the earlier version to fulfill its contract.
067: // * Moving classes up or down the hierarchy - This cannot be allowed since
068: // the data in the stream appears in the wrong sequence.
069: // * Changing a nonstatic field to static or a nontransient field to transient
070: // - When relying on default serialization, this change is equivalent to
071: // deleting a field from the class. This version of the class will not write
072: // that data to the stream, so it will not be available to be read by
073: // earlier versions of the class. As when deleting a field, the field of the
074: // earlier version will be initialized to the default value, which can cause
075: // the class to fail in unexpected ways.
076: // * Changing the declared type of a primitive field - Each version of the
077: // class writes the data with its declared type. Earlier versions of the
078: // class attempting to read the field will fail because the type of the data
079: // in the stream does not match the type of the field.
080: // * Changing the writeObject or readObject method so that it no longer writes
081: // or reads the default field data or changing it so that it attempts to
082: // write it or read it when the previous version did not. The default field
083: // data must consistently either appear or not appear in the stream.
084: // * Changing a class from Serializable to Externalizable or visa-versa is an
085: // incompatible change since the stream will contain data that is
086: // incompatible with the implementation in the available class.
087: // * Removing either Serializable or Externalizable is an incompatible change
088: // since when written it will no longer supply the fields needed by older
089: // versions of the class.
090: // * Adding the writeReplace or readResolve method to a class is incompatible
091: // if the behavior would produce an object that is incompatible with any
092: // older version of the class.
093: private static final long serialVersionUID = 8040333929441041718L;
094:
095: // JDK1.4 introduced chained throwables, and printStackTrace() now traverses
096: // the chain to the root cause, printing all stack traces.
097: private static final boolean JDK1_4;
098: private Throwable _cause;
099: private int _msgCode; // Message code from ZapletException interface.
100: private Object[] _args; // Substitution parameter values (optional).
101:
102: static {
103: boolean jdk1_4;
104: try {
105: Throwable.class.getMethod("getCause", new Class[] {});
106: jdk1_4 = true;
107: } catch (NoSuchMethodException e) {
108: jdk1_4 = false;
109: }
110: JDK1_4 = jdk1_4;
111: }
112:
113: /**
114: * Construct a new WMRuntimeException with a nested exception.
115: *
116: * @param cause Nested exception.
117: */
118: public WMRuntimeException(Exception cause) {
119: this (0, null, cause);
120: }
121:
122: /**
123: * Construct a new WMRuntimeException with the specified error code
124: * and/or nested exception.
125: *
126: * @param msgCode Message code, a key into the message catalog.
127: * @param args Optional arguments for substitution into localized message
128: * string.
129: * @param cause Nested exception (can be <code>null</code>).
130: */
131: public WMRuntimeException(int msgCode, Object[] args,
132: Exception cause) {
133: super (cause.getMessage());
134: _cause = cause;
135: _msgCode = msgCode;
136: _args = args;
137: }
138:
139: public Throwable getCause() {
140: return _cause;
141: }
142:
143: public Object[] getMessageArgs() {
144: return _args;
145: }
146:
147: public final int getMessageCode() {
148: return _msgCode;
149: }
150:
151: public final void printStackTrace() {
152: printStackTrace(System.err);
153: }
154:
155: public final void printStackTrace(PrintStream stream) {
156: super .printStackTrace(stream);
157: // Only print causal stack traces if pre-JDK 1.4.
158: if (!JDK1_4) {
159: Throwable t = getCause();
160: while (t != null) {
161: stream.println("Caused by: " + t);
162: t.printStackTrace(stream);
163: if (t instanceof WMRuntimeException)
164: t = ((WMRuntimeException) t).getCause();
165: else if (t instanceof WMWorkflowException)
166: t = ((WMWorkflowException) t).getCause();
167: else
168: break;
169: }
170: }
171: }
172:
173: public final void printStackTrace(PrintWriter writer) {
174: super .printStackTrace(writer);
175: // Only print causal stack traces if pre-JDK 1.4.
176: if (!JDK1_4) {
177: Throwable t = getCause();
178: while (t != null) {
179: writer.println("Caused by: " + t);
180: t.printStackTrace(writer);
181: if (t instanceof WMRuntimeException)
182: t = ((WMRuntimeException) t).getCause();
183: else if (t instanceof WMWorkflowException)
184: t = ((WMWorkflowException) t).getCause();
185: else
186: break;
187: }
188: }
189: }
190: }
|