Home | History | Annotate | Download | only in xpath
      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    */
     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 }
    329