1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * @LastModified: Oct 2017
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.xpath.internal;
  23 
  24 import javax.xml.transform.TransformerException;
  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    */
  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    */
  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    */
  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    */
  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    */
  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    */
 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", (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    */
 324   public Throwable getException()
 325   {
 326     return m_exception;
 327   }
 328 }