KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > util > location > LocatedException


1 /*
2  * Copyright 2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.util.location;
17
18 import java.lang.reflect.Method JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collections JavaDoc;
21 import java.util.List JavaDoc;
22
23 import org.apache.commons.lang.exception.ExceptionUtils;
24 import org.apache.commons.lang.exception.NestableException;
25
26 /**
27  * A cascading and located <code>Exception</code>. It is also {@link MultiLocatable} to easily build
28  * stack traces.
29  *
30  * @since 2.1.8
31  * @version $Id: LocatedException.java 291774 2005-09-26 22:47:38Z vgritsenko $
32  */

33 public class LocatedException extends NestableException
34                               implements LocatableException, MultiLocatable {
35
36     private List JavaDoc locations;
37
38     public LocatedException(String JavaDoc message) {
39         this(message, null, null);
40     }
41
42     public LocatedException(String JavaDoc message, Throwable JavaDoc cause) {
43         this(message, cause, null);
44     }
45
46     public LocatedException(String JavaDoc message, Location location) {
47         this(message, null, location);
48     }
49
50     public LocatedException(String JavaDoc message, Throwable JavaDoc cause, Location location) {
51         super(message, cause);
52         ensureCauseChainIsSet(cause);
53         addCauseLocations(this, cause);
54         addLocation(location);
55     }
56
57     private static Method JavaDoc INIT_CAUSE_METHOD = null;
58     static {
59         try {
60             INIT_CAUSE_METHOD = Throwable JavaDoc.class.getMethod("initCause", new Class JavaDoc[] { Throwable JavaDoc.class} );
61         } catch(Exception JavaDoc e) {
62             // JDK < 1.4: ignore
63
}
64     }
65
66     /**
67      * Crawl the cause chain and ensure causes are properly set using "initCause" on JDK >= 1.4.
68      * This is needed because some exceptions (e.g. SAXException) don't have a getCause() that is
69      * used to print stacktraces.
70      */

71     public static void ensureCauseChainIsSet(Throwable JavaDoc thr) {
72         if (INIT_CAUSE_METHOD == null)
73             return;
74
75         // Loop either until null or encountering exceptions that use this method.
76
while (thr != null && !(thr instanceof LocatedRuntimeException) && !(thr instanceof LocatedException)) {
77             Throwable JavaDoc parent = ExceptionUtils.getCause(thr);
78             if (parent != null) {
79                 try {
80                     INIT_CAUSE_METHOD.invoke(thr, new Object JavaDoc[]{ parent });
81                 } catch (Exception JavaDoc e) {
82                     // can happen if parent already set on exception
83
}
84             }
85             thr = parent;
86         }
87     }
88
89     /**
90      * Add to the location stack all locations of an exception chain. This allows to have all possible
91      * location information in the stacktrace, as some exceptions like SAXParseException don't output
92      * their location in printStackTrace().
93      * <p>
94      * Traversal of the call chain stops at the first <code>Locatable</code> exception which is supposed
95      * to handle the loction of its causes by itself.
96      * <p>
97      * This method is static as a convenience for {@link LocatedRuntimeException other implementations}
98      * of locatable exceptions.
99      *
100      * @param self the current locatable exception
101      * @param cause a cause of <code>self</code>
102      */

103     public static void addCauseLocations(MultiLocatable self, Throwable JavaDoc cause) {
104         if (cause == null || cause instanceof Locatable) {
105             // Locatable handles its location itself
106
return;
107         }
108         // Add parent location first
109
addCauseLocations(self, ExceptionUtils.getCause(cause));
110         // then ourselve's
111
Location loc = LocationUtils.getLocation(cause);
112         if (LocationUtils.isKnown(loc)) {
113             // Get the exception's short name
114
String JavaDoc name = cause.getClass().getName();
115             int pos = name.lastIndexOf('.');
116             if (pos != -1) {
117                 name = name.substring(pos+1);
118             }
119             loc = new LocationImpl("[" + name + "]", loc.getURI(), loc.getLineNumber(), loc.getColumnNumber());
120             self.addLocation(loc);
121         }
122     }
123
124     public Location getLocation() {
125         return locations == null ? null : (Location)locations.get(0);
126     }
127
128     public List JavaDoc getLocations() {
129         return locations == null ? Collections.EMPTY_LIST : locations;
130     }
131
132     public String JavaDoc getRawMessage() {
133         return super.getMessage();
134     }
135
136     /**
137      * Standard way of building the message of a {@link LocatableException}, as a Java-like
138      * stack trace of locations.
139      *
140      * @param message the exception's message, given by <code>super.getMessage()</code> (can be null)
141      * @param locations the location list (can be null)
142      *
143      * @return the message, or <code>null</code> no message and locations were given.
144      */

145     public static String JavaDoc getMessage(String JavaDoc message, List JavaDoc locations) {
146         if (locations == null || locations.isEmpty()) {
147             return message;
148         }
149
150         // Produce a Java-like stacktrace with locations
151
StringBuffer JavaDoc buf = message == null ? new StringBuffer JavaDoc() : new StringBuffer JavaDoc(message);
152         for (int i = 0; i < locations.size(); i++) {
153             buf.append("\n\tat ").append(LocationUtils.toString((Location)locations.get(i)));
154         }
155         return buf.toString();
156     }
157
158     public String JavaDoc getMessage() {
159         return getMessage(super.getMessage(), locations);
160     }
161
162     public void addLocation(Location loc) {
163         if (LocationUtils.isUnknown(loc))
164             return;
165
166         if (locations == null) {
167             this.locations = new ArrayList JavaDoc(1); // Start small
168
}
169         locations.add(LocationImpl.get(loc));
170     }
171 }
172
Popular Tags