001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.core;
018:
019: import java.io.PrintStream;
020: import java.io.PrintWriter;
021:
022: /**
023: * Subclass of java.rmi.NoSuchObjectException which adds init cause to the exception.
024: */
025: public class NoSuchObjectException extends
026: java.rmi.NoSuchObjectException {
027: private Throwable cause = this ;
028:
029: public NoSuchObjectException(String detailMessage) {
030: super (detailMessage);
031: }
032:
033: /**
034: * Constructs a new instance of this class with its walkback, message and
035: * cause filled in.
036: *
037: * @param detailMessage String The detail message for the exception.
038: * @param throwable The cause of this Throwable
039: */
040: public NoSuchObjectException(String detailMessage,
041: Throwable throwable) {
042: super (detailMessage);
043: cause = throwable;
044: }
045:
046: public NoSuchObjectException(Throwable throwable) {
047: super (throwable == null ? null : throwable.toString());
048: cause = throwable;
049: }
050:
051: /**
052: * Answers the extra information message which was provided when the
053: * throwable was created. If no message was provided at creation time, then
054: * answer null. Subclasses may override this method to answer localized text
055: * for the message.
056: *
057: * @return String The receiver's message.
058: */
059: public String getLocalizedMessage() {
060: return getMessage();
061: }
062:
063: /**
064: * Outputs a printable representation of the receiver's walkback on the
065: * System.err stream.
066: */
067: public void printStackTrace() {
068: printStackTrace(System.err);
069: }
070:
071: /**
072: * Count the number of duplicate stack frames, starting from
073: * the end of the stack.
074: *
075: * @param currentStack a stack to compare
076: * @param parentStack a stack to compare
077: * @return the number of duplicate stack frames.
078: */
079: private static int countDuplicates(
080: StackTraceElement[] currentStack,
081: StackTraceElement[] parentStack) {
082: int duplicates = 0;
083: int parentIndex = parentStack.length;
084: for (int i = currentStack.length; --i >= 0
085: && --parentIndex >= 0;) {
086: StackTraceElement parentFrame = parentStack[parentIndex];
087: if (parentFrame.equals(currentStack[i])) {
088: duplicates++;
089: } else {
090: break;
091: }
092: }
093: return duplicates;
094: }
095:
096: /**
097: * Outputs a printable representation of the receiver's walkback on the
098: * stream specified by the argument.
099: *
100: * @param err PrintStream The stream to write the walkback on.
101: */
102: public void printStackTrace(PrintStream err) {
103: err.println(toString());
104: // Don't use getStackTrace() as it calls clone()
105: // Get stackTrace, in case stackTrace is reassigned
106: StackTraceElement[] stack = getStackTrace();
107: for (int i = 0; i < stack.length; i++) {
108: err.println("\tat " + stack[i]);
109: }
110:
111: StackTraceElement[] parentStack = stack;
112: Throwable throwable = getCause();
113: while (throwable != null) {
114: err.print("Caused by: ");
115: err.println(throwable);
116: StackTraceElement[] currentStack = throwable
117: .getStackTrace();
118: int duplicates = countDuplicates(currentStack, parentStack);
119: for (int i = 0; i < currentStack.length - duplicates; i++) {
120: err.println("\tat " + currentStack[i]);
121: }
122: if (duplicates > 0) {
123: err.println("\t... " + duplicates + " more");
124: }
125: parentStack = currentStack;
126: throwable = throwable.getCause();
127: }
128: }
129:
130: /**
131: * Outputs a printable representation of the receiver's walkback on the
132: * writer specified by the argument.
133: *
134: * @param err PrintWriter The writer to write the walkback on.
135: */
136: public void printStackTrace(PrintWriter err) {
137: err.println(toString());
138: // Don't use getStackTrace() as it calls clone()
139: // Get stackTrace, in case stackTrace is reassigned
140: StackTraceElement[] stack = getStackTrace();
141: for (int i = 0; i < stack.length; i++) {
142: err.println("\tat " + stack[i]);
143: }
144:
145: StackTraceElement[] parentStack = stack;
146: Throwable throwable = getCause();
147: while (throwable != null) {
148: err.print("Caused by: ");
149: err.println(throwable);
150: StackTraceElement[] currentStack = throwable
151: .getStackTrace();
152: int duplicates = countDuplicates(currentStack, parentStack);
153: for (int i = 0; i < currentStack.length - duplicates; i++) {
154: err.println("\tat " + currentStack[i]);
155: }
156: if (duplicates > 0) {
157: err.println("\t... " + duplicates + " more");
158: }
159: parentStack = currentStack;
160: throwable = throwable.getCause();
161: }
162: }
163:
164: /**
165: * Answers a string containing a concise, human-readable description of the
166: * receiver.
167: *
168: * @return String a printable representation for the receiver.
169: */
170: public String toString() {
171: String msg = getLocalizedMessage();
172: String name = getClass().getName();
173: if (msg == null) {
174: return name;
175: }
176: return new StringBuffer(name.length() + 2 + msg.length())
177: .append(name).append(": ").append(msg).toString();
178: }
179:
180: /**
181: * Initialize the cause of the receiver. The cause cannot be reassigned.
182: *
183: * @param throwable The cause of this Throwable
184: * @return the receiver.
185: * @throws IllegalArgumentException when the cause is the receiver
186: * @throws IllegalStateException when the cause has already been initialized
187: */
188: public synchronized NoSuchObjectException initCause(
189: Throwable throwable) {
190: cause = throwable;
191: return this ;
192: }
193:
194: /**
195: * Answers the cause of this Throwable, or null if there is no cause.
196: *
197: * @return Throwable The receiver's cause.
198: */
199: public Throwable getCause() {
200: if (cause == this) {
201: return null;
202: }
203: return cause;
204: }
205: }
|