001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * 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 */ 018 /* 019 * $Id: XPathException.java 468655 2006-10-28 07:12:06Z minchau $ 020 */ 021 package org.apache.xpath; 022 023 import javax.xml.transform.TransformerException; 024 025 import org.w3c.dom.Node; 026 027 /** 028 * This class implements an exception object that all 029 * XPath classes will throw in case of an error. This class 030 * extends TransformerException, and may hold other exceptions. In the 031 * case of nested exceptions, printStackTrace will dump 032 * all the traces of the nested exceptions, not just the trace 033 * of this object. 034 * @xsl.usage general 035 */ 036 public class XPathException extends TransformerException 037 { 038 static final long serialVersionUID = 4263549717619045963L; 039 040 /** The home of the expression that caused the error. 041 * @serial */ 042 Object m_styleNode = null; 043 044 /** 045 * Get the stylesheet node from where this error originated. 046 * @return The stylesheet node from where this error originated, or null. 047 */ 048 public Object getStylesheetNode() 049 { 050 return m_styleNode; 051 } 052 053 /** 054 * Set the stylesheet node from where this error originated. 055 * @param styleNode The stylesheet node from where this error originated, or null. 056 */ 057 public void setStylesheetNode(Object styleNode) 058 { 059 m_styleNode = styleNode; 060 } 061 062 063 /** A nested exception. 064 * @serial */ 065 protected Exception m_exception; 066 067 /** 068 * Create an XPathException object that holds 069 * an error message. 070 * @param message The error message. 071 */ 072 public XPathException(String message, ExpressionNode ex) 073 { 074 super(message); 075 this.setLocator(ex); 076 setStylesheetNode(getStylesheetNode(ex)); 077 } 078 079 /** 080 * Create an XPathException object that holds 081 * an error message. 082 * @param message The error message. 083 */ 084 public XPathException(String message) 085 { 086 super(message); 087 } 088 089 090 /** 091 * Get the XSLT ElemVariable that this sub-expression references. In order for 092 * this to work, the SourceLocator must be the owning ElemTemplateElement. 093 * @return The dereference to the ElemVariable, or null if not found. 094 */ 095 public org.w3c.dom.Node getStylesheetNode(ExpressionNode ex) 096 { 097 098 ExpressionNode owner = getExpressionOwner(ex); 099 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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",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 */ 324 public Throwable getException() 325 { 326 return m_exception; 327 } 328 }