1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id: XPathException.java 468655 2006-10-28 07:12:06Z minchau $ 20 */ 21 package org.apache.xpath; 22 23 import javax.xml.transform.TransformerException; 24 25 import org.w3c.dom.Node; 26 27 /** 28 * This class implements an exception object that all 29 * XPath classes will throw in case of an error. This class 30 * extends TransformerException, and may hold other exceptions. In the 31 * case of nested exceptions, printStackTrace will dump 32 * all the traces of the nested exceptions, not just the trace 33 * of this object. 34 * @xsl.usage general 35 */ 36 public class XPathException extends TransformerException 37 { 38 static final long serialVersionUID = 4263549717619045963L; 39 40 /** The home of the expression that caused the error. 41 * @serial */ 42 Object m_styleNode = null; 43 44 /** 45 * Get the stylesheet node from where this error originated. 46 * @return The stylesheet node from where this error originated, or null. 47 */ getStylesheetNode()48 public Object getStylesheetNode() 49 { 50 return m_styleNode; 51 } 52 53 /** 54 * Set the stylesheet node from where this error originated. 55 * @param styleNode The stylesheet node from where this error originated, or null. 56 */ setStylesheetNode(Object styleNode)57 public void setStylesheetNode(Object styleNode) 58 { 59 m_styleNode = styleNode; 60 } 61 62 63 /** A nested exception. 64 * @serial */ 65 protected Exception m_exception; 66 67 /** 68 * Create an XPathException object that holds 69 * an error message. 70 * @param message The error message. 71 */ XPathException(String message, ExpressionNode ex)72 public XPathException(String message, ExpressionNode ex) 73 { 74 super(message); 75 this.setLocator(ex); 76 setStylesheetNode(getStylesheetNode(ex)); 77 } 78 79 /** 80 * Create an XPathException object that holds 81 * an error message. 82 * @param message The error message. 83 */ XPathException(String message)84 public XPathException(String message) 85 { 86 super(message); 87 } 88 89 90 /** 91 * Get the XSLT ElemVariable that this sub-expression references. In order for 92 * this to work, the SourceLocator must be the owning ElemTemplateElement. 93 * @return The dereference to the ElemVariable, or null if not found. 94 */ getStylesheetNode(ExpressionNode ex)95 public org.w3c.dom.Node getStylesheetNode(ExpressionNode ex) 96 { 97 98 ExpressionNode owner = getExpressionOwner(ex); 99 100 if (null != owner && owner instanceof org.w3c.dom.Node) 101 { 102 return ((org.w3c.dom.Node)owner); 103 } 104 return null; 105 106 } 107 108 /** 109 * Get the first non-Expression parent of this node. 110 * @return null or first ancestor that is not an Expression. 111 */ getExpressionOwner(ExpressionNode ex)112 protected ExpressionNode getExpressionOwner(ExpressionNode ex) 113 { 114 ExpressionNode parent = ex.exprGetParent(); 115 while((null != parent) && (parent instanceof Expression)) 116 parent = parent.exprGetParent(); 117 return parent; 118 } 119 120 121 122 /** 123 * Create an XPathException object that holds 124 * an error message and the stylesheet node that 125 * the error originated from. 126 * @param message The error message. 127 * @param styleNode The stylesheet node that the error originated from. 128 */ XPathException(String message, Object styleNode)129 public XPathException(String message, Object styleNode) 130 { 131 132 super(message); 133 134 m_styleNode = styleNode; 135 } 136 137 /** 138 * Create an XPathException object that holds 139 * an error message, the stylesheet node that 140 * the error originated from, and another exception 141 * that caused this exception. 142 * @param message The error message. 143 * @param styleNode The stylesheet node that the error originated from. 144 * @param e The exception that caused this exception. 145 */ XPathException(String message, Node styleNode, Exception e)146 public XPathException(String message, Node styleNode, Exception e) 147 { 148 149 super(message); 150 151 m_styleNode = styleNode; 152 this.m_exception = e; 153 } 154 155 /** 156 * Create an XPathException object that holds 157 * an error message, and another exception 158 * that caused this exception. 159 * @param message The error message. 160 * @param e The exception that caused this exception. 161 */ XPathException(String message, Exception e)162 public XPathException(String message, Exception e) 163 { 164 165 super(message); 166 167 this.m_exception = e; 168 } 169 170 /** 171 * Print the the trace of methods from where the error 172 * originated. This will trace all nested exception 173 * objects, as well as this object. 174 * @param s The stream where the dump will be sent to. 175 */ printStackTrace(java.io.PrintStream s)176 public void printStackTrace(java.io.PrintStream s) 177 { 178 179 if (s == null) 180 s = System.err; 181 182 try 183 { 184 super.printStackTrace(s); 185 } 186 catch (Exception e){} 187 188 Throwable exception = m_exception; 189 190 for (int i = 0; (i < 10) && (null != exception); i++) 191 { 192 s.println("---------"); 193 exception.printStackTrace(s); 194 195 if (exception instanceof TransformerException) 196 { 197 TransformerException se = (TransformerException) exception; 198 Throwable prev = exception; 199 200 exception = se.getException(); 201 202 if (prev == exception) 203 break; 204 } 205 else 206 { 207 exception = null; 208 } 209 } 210 } 211 212 /** 213 * Find the most contained message. 214 * 215 * @return The error message of the originating exception. 216 */ getMessage()217 public String getMessage() 218 { 219 220 String lastMessage = super.getMessage(); 221 Throwable exception = m_exception; 222 223 while (null != exception) 224 { 225 String nextMessage = exception.getMessage(); 226 227 if (null != nextMessage) 228 lastMessage = nextMessage; 229 230 if (exception instanceof TransformerException) 231 { 232 TransformerException se = (TransformerException) exception; 233 Throwable prev = exception; 234 235 exception = se.getException(); 236 237 if (prev == exception) 238 break; 239 } 240 else 241 { 242 exception = null; 243 } 244 } 245 246 return (null != lastMessage) ? lastMessage : ""; 247 } 248 249 /** 250 * Print the the trace of methods from where the error 251 * originated. This will trace all nested exception 252 * objects, as well as this object. 253 * @param s The writer where the dump will be sent to. 254 */ printStackTrace(java.io.PrintWriter s)255 public void printStackTrace(java.io.PrintWriter s) 256 { 257 258 if (s == null) 259 s = new java.io.PrintWriter(System.err); 260 261 try 262 { 263 super.printStackTrace(s); 264 } 265 catch (Exception e){} 266 267 268 boolean isJdk14OrHigher = false; 269 try { 270 Throwable.class.getMethod("getCause", (Class<?>) null); 271 isJdk14OrHigher = true; 272 } catch (NoSuchMethodException nsme) { 273 // do nothing 274 } 275 276 // The printStackTrace method of the Throwable class in jdk 1.4 277 // and higher will include the cause when printing the backtrace. 278 // The following code is only required when using jdk 1.3 or lower 279 if (!isJdk14OrHigher) { 280 281 Throwable exception = m_exception; 282 283 for (int i = 0; (i < 10) && (null != exception); i++) 284 { 285 s.println("---------"); 286 287 try 288 { 289 exception.printStackTrace(s); 290 } 291 catch (Exception e) 292 { 293 s.println("Could not print stack trace..."); 294 } 295 296 if (exception instanceof TransformerException) 297 { 298 TransformerException se = (TransformerException) exception; 299 Throwable prev = exception; 300 301 exception = se.getException(); 302 303 if (prev == exception) 304 { 305 exception = null; 306 307 break; 308 } 309 } 310 else 311 { 312 exception = null; 313 } 314 } 315 } 316 } 317 318 /** 319 * Return the embedded exception, if any. 320 * Overrides javax.xml.transform.TransformerException.getException(). 321 * 322 * @return The embedded exception, or null if there is none. 323 */ getException()324 public Throwable getException() 325 { 326 return m_exception; 327 } 328 } 329