KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > template > TemplateException


1 /*
2  * Copyright (c) 2003 The Visigoth Software Society. All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowledgement:
19  * "This product includes software developed by the
20  * Visigoth Software Society (http://www.visigoths.org/)."
21  * Alternately, this acknowledgement may appear in the software itself,
22  * if and wherever such third-party acknowledgements normally appear.
23  *
24  * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
25  * project contributors may be used to endorse or promote products derived
26  * from this software without prior written permission. For written
27  * permission, please contact visigoths@visigoths.org.
28  *
29  * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
30  * nor may "FreeMarker" or "Visigoth" appear in their names
31  * without prior written permission of the Visigoth Software Society.
32  *
33  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
37  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  * ====================================================================
46  *
47  * This software consists of voluntary contributions made by many
48  * individuals on behalf of the Visigoth Software Society. For more
49  * information on the Visigoth Software Society, please see
50  * http://www.visigoths.org/
51  */

52
53 package freemarker.template;
54
55 import java.io.OutputStreamWriter JavaDoc;
56 import java.io.PrintWriter JavaDoc;
57 import java.io.StringWriter JavaDoc;
58 import java.lang.reflect.Method JavaDoc;
59
60 import freemarker.core.Environment;
61
62 /**
63  * The FreeMarker classes usually use this exception and its descendants to
64  * signal FreeMarker specific exceptions.
65  *
66  * @version $Id: TemplateException.java,v 1.26 2005/01/04 23:11:39 ddekany Exp $
67  */

68 public class TemplateException extends Exception JavaDoc {
69
70     private static final boolean BEFORE_1_4 = before14();
71     private static boolean before14() {
72         Class JavaDoc ec = Exception JavaDoc.class;
73         try {
74             ec.getMethod("getCause", new Class JavaDoc[]{});
75         } catch (Throwable JavaDoc e) {
76             return true;
77         }
78         return false;
79     }
80
81     private static final Class JavaDoc[] EMPTY_CLASS_ARRAY = new Class JavaDoc[]{};
82
83     private static final Object JavaDoc[] EMPTY_OBJECT_ARRAY = new Object JavaDoc[]{};
84     
85     /** The underlying cause of this exception, if any */
86     private final Exception JavaDoc causeException;
87     private final Environment env;
88     private final String JavaDoc ftlInstructionStack;
89
90
91     /**
92      * Constructs a TemplateException with no specified detail message
93      * or underlying cause.
94      */

95     public TemplateException(Environment env) {
96         this(null, null, env);
97     }
98
99     /**
100      * Constructs a TemplateException with the given detail message,
101      * but no underlying cause exception.
102      *
103      * @param description the description of the error that occurred
104      */

105     public TemplateException(String JavaDoc description, Environment env) {
106         this(description, null, env);
107     }
108
109     /**
110      * Constructs a TemplateException with the given underlying Exception,
111      * but no detail message.
112      *
113      * @param cause the underlying <code>Exception</code> that caused this
114      * exception to be raised
115      */

116     public TemplateException(Exception JavaDoc cause, Environment env) {
117         this(null, cause, env);
118     }
119
120     /**
121      * Constructs a TemplateException with both a description of the error
122      * that occurred and the underlying Exception that caused this exception
123      * to be raised.
124      *
125      * @param description the description of the error that occurred
126      * @param cause the underlying <code>Exception</code> that caused this
127      * exception to be raised
128      */

129     public TemplateException(String JavaDoc description, Exception JavaDoc cause, Environment env) {
130         super(getDescription(description, cause));
131         causeException = cause;
132         this.env = env;
133         if(env != null)
134         {
135             StringWriter JavaDoc sw = new StringWriter JavaDoc();
136             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
137             env.outputInstructionStack(pw);
138             pw.flush();
139             ftlInstructionStack = sw.toString();
140         }
141         else
142         {
143             ftlInstructionStack = "";
144         }
145     }
146
147     private static String JavaDoc getDescription(String JavaDoc description, Exception JavaDoc cause) {
148         if(description != null) {
149             return description;
150         }
151         if(cause != null) {
152             return cause.getClass().getName() + ": " + cause.getMessage();
153         }
154         return "No error message";
155     }
156     
157     /**
158      * <p>Returns the underlying exception that caused this exception to be
159      * generated.</p>
160      * <p><b>Note:</b><br />
161      * avoided calling it <code>getCause</code> to avoid name clash with
162      * JDK 1.4 method. This would be problematic because the JDK 1.4 method
163      * returns a <code>Throwable</code> rather than an <code>Exception</code>.</p>
164      *
165      * @return the underlying <code>Exception</code>, if any, that caused this
166      * exception to be raised
167      */

168     public Exception JavaDoc getCauseException() {
169         return causeException;
170     }
171
172     /**
173      * Returns the same exception as <code>getCauseException</code>. Provided
174      * to enable full JDK-generated stack traces when running under JDK 1.4.
175      *
176      * @see Throwable#getCause()
177      * @return the underlying <code>Exception</code>, if any, that caused this
178      * exception to be raised
179      */

180     public Throwable JavaDoc getCause() {
181         return causeException;
182     }
183     
184     /**
185      * Returns the quote of the problematic FTL instruction and the FTL stack strace.
186      */

187     public String JavaDoc getFTLInstructionStack() {
188         return ftlInstructionStack;
189     }
190
191     /**
192      * @return the execution environment in which the exception occurred
193      */

194     public Environment getEnvironment() {
195         return env;
196     }
197
198     public void printStackTrace(java.io.PrintStream JavaDoc ps) {
199         PrintWriter JavaDoc pw = new PrintWriter JavaDoc(new OutputStreamWriter JavaDoc(ps), true);
200         printStackTrace(pw);
201         pw.flush();
202     }
203
204     public void printStackTrace(PrintWriter JavaDoc pw) {
205         pw.println();
206         pw.println(getMessage());
207         if (ftlInstructionStack != null && ftlInstructionStack.length() != 0) {
208             pw.println("The problematic instruction:");
209             pw.println(ftlInstructionStack);
210         }
211         pw.println("Java backtrace for programmers:");
212         pw.println("----------");
213         super.printStackTrace(pw);
214         if (BEFORE_1_4 && causeException != null) {
215             pw.println("Underlying cause: ");
216             causeException.printStackTrace(pw);
217         }
218         
219         // Dirty hack to fight with stupid ServletException class whose
220
// getCause() method doesn't work properly. Also an aid for pre-J2xE 1.4
221
// users.
222
try {
223             // Reflection is used to prevent dependency on Servlet classes.
224
Method JavaDoc m = causeException.getClass().getMethod("getRootCause", EMPTY_CLASS_ARRAY);
225             Throwable JavaDoc rootCause = (Throwable JavaDoc) m.invoke(causeException, EMPTY_OBJECT_ARRAY);
226             if (rootCause != null) {
227                 Throwable JavaDoc j14Cause = null;
228                 if (!BEFORE_1_4) {
229                     m = causeException.getClass().getMethod("getCause", EMPTY_CLASS_ARRAY);
230                     j14Cause = (Throwable JavaDoc) m.invoke(causeException, EMPTY_OBJECT_ARRAY);
231                 }
232                 if (j14Cause == null) {
233                     pw.println("ServletException root cause: ");
234                     rootCause.printStackTrace(pw);
235                 }
236             }
237         } catch (Throwable JavaDoc exc) {
238             ; // ignore
239
}
240     }
241     
242 }
243
Popular Tags