001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: XPathException.java,v 1.13 2004/08/17 16:18:27 mcnamara Exp $
018: */
019: package org.apache.xpath;
020:
021: import javax.xml.transform.TransformerException;
022:
023: import org.w3c.dom.Node;
024:
025: /**
026: * This class implements an exception object that all
027: * XPath classes will throw in case of an error. This class
028: * extends TransformerException, and may hold other exceptions. In the
029: * case of nested exceptions, printStackTrace will dump
030: * all the traces of the nested exceptions, not just the trace
031: * of this object.
032: * @xsl.usage general
033: */
034: public class XPathException extends TransformerException {
035: static final long serialVersionUID = 4263549717619045963L;
036:
037: /** The home of the expression that caused the error.
038: * @serial */
039: Object m_styleNode = null;
040:
041: /**
042: * Get the stylesheet node from where this error originated.
043: * @return The stylesheet node from where this error originated, or null.
044: */
045: public Object getStylesheetNode() {
046: return m_styleNode;
047: }
048:
049: /**
050: * Set the stylesheet node from where this error originated.
051: * @param styleNode The stylesheet node from where this error originated, or null.
052: */
053: public void setStylesheetNode(Object styleNode) {
054: m_styleNode = styleNode;
055: }
056:
057: /** A nested exception.
058: * @serial */
059: protected Exception m_exception;
060:
061: /**
062: * Create an XPathException object that holds
063: * an error message.
064: * @param message The error message.
065: */
066: public XPathException(String message, ExpressionNode ex) {
067: super (message);
068: this .setLocator(ex);
069: setStylesheetNode(getStylesheetNode(ex));
070: }
071:
072: /**
073: * Create an XPathException object that holds
074: * an error message.
075: * @param message The error message.
076: */
077: public XPathException(String message) {
078: super (message);
079: }
080:
081: /**
082: * Get the XSLT ElemVariable that this sub-expression references. In order for
083: * this to work, the SourceLocator must be the owning ElemTemplateElement.
084: * @return The dereference to the ElemVariable, or null if not found.
085: */
086: public org.w3c.dom.Node getStylesheetNode(ExpressionNode ex) {
087:
088: ExpressionNode owner = getExpressionOwner(ex);
089:
090: if (null != owner && owner instanceof org.w3c.dom.Node) {
091: return ((org.w3c.dom.Node) owner);
092: }
093: return null;
094:
095: }
096:
097: /**
098: * Get the first non-Expression parent of this node.
099: * @return null or first ancestor that is not an Expression.
100: */
101: protected ExpressionNode getExpressionOwner(ExpressionNode ex) {
102: ExpressionNode parent = ex.exprGetParent();
103: while ((null != parent) && (parent instanceof Expression))
104: parent = parent.exprGetParent();
105: return parent;
106: }
107:
108: /**
109: * Create an XPathException object that holds
110: * an error message and the stylesheet node that
111: * the error originated from.
112: * @param message The error message.
113: * @param styleNode The stylesheet node that the error originated from.
114: */
115: public XPathException(String message, Object styleNode) {
116:
117: super (message);
118:
119: m_styleNode = styleNode;
120: }
121:
122: /**
123: * Create an XPathException object that holds
124: * an error message, the stylesheet node that
125: * the error originated from, and another exception
126: * that caused this exception.
127: * @param message The error message.
128: * @param styleNode The stylesheet node that the error originated from.
129: * @param e The exception that caused this exception.
130: */
131: public XPathException(String message, Node styleNode, Exception e) {
132:
133: super (message);
134:
135: m_styleNode = styleNode;
136: this .m_exception = e;
137: }
138:
139: /**
140: * Create an XPathException object that holds
141: * an error message, and another exception
142: * that caused this exception.
143: * @param message The error message.
144: * @param e The exception that caused this exception.
145: */
146: public XPathException(String message, Exception e) {
147:
148: super (message);
149:
150: this .m_exception = e;
151: }
152:
153: /**
154: * Print the the trace of methods from where the error
155: * originated. This will trace all nested exception
156: * objects, as well as this object.
157: * @param s The stream where the dump will be sent to.
158: */
159: public void printStackTrace(java.io.PrintStream s) {
160:
161: if (s == null)
162: s = System.err;
163:
164: try {
165: super .printStackTrace(s);
166: } catch (Exception e) {
167: }
168:
169: Throwable exception = m_exception;
170:
171: for (int i = 0; (i < 10) && (null != exception); i++) {
172: s.println("---------");
173: exception.printStackTrace(s);
174:
175: if (exception instanceof TransformerException) {
176: TransformerException se = (TransformerException) exception;
177: Throwable prev = exception;
178:
179: exception = se.getException();
180:
181: if (prev == exception)
182: break;
183: } else {
184: exception = null;
185: }
186: }
187: }
188:
189: /**
190: * Find the most contained message.
191: *
192: * @return The error message of the originating exception.
193: */
194: public String getMessage() {
195:
196: String lastMessage = super .getMessage();
197: Throwable exception = m_exception;
198:
199: while (null != exception) {
200: String nextMessage = exception.getMessage();
201:
202: if (null != nextMessage)
203: lastMessage = nextMessage;
204:
205: if (exception instanceof TransformerException) {
206: TransformerException se = (TransformerException) exception;
207: Throwable prev = exception;
208:
209: exception = se.getException();
210:
211: if (prev == exception)
212: break;
213: } else {
214: exception = null;
215: }
216: }
217:
218: return (null != lastMessage) ? lastMessage : "";
219: }
220:
221: /**
222: * Print the the trace of methods from where the error
223: * originated. This will trace all nested exception
224: * objects, as well as this object.
225: * @param s The writer where the dump will be sent to.
226: */
227: public void printStackTrace(java.io.PrintWriter s) {
228:
229: if (s == null)
230: s = new java.io.PrintWriter(System.err);
231:
232: try {
233: super .printStackTrace(s);
234: } catch (Exception e) {
235: }
236:
237: boolean isJdk14OrHigher = false;
238: try {
239: Throwable.class.getMethod("getCause", null);
240: isJdk14OrHigher = true;
241: } catch (NoSuchMethodException nsme) {
242: // do nothing
243: }
244:
245: // The printStackTrace method of the Throwable class in jdk 1.4
246: // and higher will include the cause when printing the backtrace.
247: // The following code is only required when using jdk 1.3 or lower
248: if (!isJdk14OrHigher) {
249:
250: Throwable exception = m_exception;
251:
252: for (int i = 0; (i < 10) && (null != exception); i++) {
253: s.println("---------");
254:
255: try {
256: exception.printStackTrace(s);
257: } catch (Exception e) {
258: s.println("Could not print stack trace...");
259: }
260:
261: if (exception instanceof TransformerException) {
262: TransformerException se = (TransformerException) exception;
263: Throwable prev = exception;
264:
265: exception = se.getException();
266:
267: if (prev == exception) {
268: exception = null;
269:
270: break;
271: }
272: } else {
273: exception = null;
274: }
275: }
276: }
277: }
278:
279: /**
280: * Return the embedded exception, if any.
281: * Overrides javax.xml.transform.TransformerException.getException().
282: *
283: * @return The embedded exception, or null if there is none.
284: */
285: public Throwable getException() {
286: return m_exception;
287: }
288: }
|