KickJava   Java API By Example, From Geeks To Geeks.

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


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.ref.WeakReference JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.List JavaDoc;
21
22 import javax.xml.transform.SourceLocator JavaDoc;
23 import javax.xml.transform.TransformerException JavaDoc;
24
25 import org.xml.sax.Locator JavaDoc;
26 import org.xml.sax.SAXParseException JavaDoc;
27
28 /**
29  * Location-related utility methods.
30  *
31  * @version $Id: LocationUtils.java 280939 2005-09-14 20:54:16Z sylvain $
32  * @since 2.1.8
33  */

34 public class LocationUtils {
35     
36     /**
37      * The string representation of an unknown location: "<code>[unknown location]</code>".
38      */

39     public static final String JavaDoc UNKNOWN_STRING = "[unknown location]";
40     
41     private static List JavaDoc finders = new ArrayList JavaDoc();
42     
43     /**
44      * An finder or object locations
45      *
46      * @since 2.1.8
47      */

48     public interface LocationFinder {
49         /**
50          * Get the location of an object
51          * @param obj the object for which to find a location
52          * @param description and optional description to be added to the object's location
53          * @return the object's location or <code>null</code> if object's class isn't handled
54          * by this finder.
55          */

56         Location getLocation(Object JavaDoc obj, String JavaDoc description);
57     }
58
59     private LocationUtils() {
60         // Forbid instanciation
61
}
62     
63     
64     /**
65      * Builds a string representation of a location, in the
66      * "<code><em>descripton</em> - <em>uri</em>:<em>line</em>:<em>column</em></code>"
67      * format (e.g. "<code>foo - file://path/to/file.xml:3:40</code>"). For {@link Location#UNKNOWN an unknown location}, returns
68      * {@link #UNKNOWN_STRING}.
69      *
70      * @return the string representation
71      */

72     public static String JavaDoc toString(Location location) {
73         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
74
75         String JavaDoc description = location.getDescription();
76         if (description != null) {
77             result.append(description).append(" - ");
78         }
79
80         String JavaDoc uri = location.getURI();
81         if (uri != null) {
82             result.append(uri).append(':').append(location.getLineNumber()).append(':').append(location.getColumnNumber());
83         } else {
84             result.append(UNKNOWN_STRING);
85         }
86         
87         return result.toString();
88     }
89
90     /**
91      * Parse a location string of the form "<code><em>uri</em>:<em>line</em>:<em>column</em></code>" (e.g.
92      * "<code>path/to/file.xml:3:40</code>") to a Location object. Additionally, a description may
93      * also optionally be present, separated with an hyphen (e.g. "<code>foo - path/to/file.xml:3.40</code>").
94      *
95      * @param text the text to parse
96      * @return the location (possibly <code>null</code> if text was null or in an incorrect format)
97      */

98     public static LocationImpl parse(String JavaDoc text) throws IllegalArgumentException JavaDoc {
99         if (text == null || text.length() == 0) {
100             return null;
101         }
102
103         // Do we have a description?
104
String JavaDoc description;
105         int uriStart = text.lastIndexOf(" - "); // lastIndexOf to allow the separator to be in the description
106
if (uriStart > -1) {
107             description = text.substring(0, uriStart);
108             uriStart += 3; // strip " - "
109
} else {
110             description = null;
111             uriStart = 0;
112         }
113         
114         try {
115             int colSep = text.lastIndexOf(':');
116             if (colSep > -1) {
117                 int column = Integer.parseInt(text.substring(colSep + 1));
118                 
119                 int lineSep = text.lastIndexOf(':', colSep - 1);
120                 if (lineSep > -1) {
121                     int line = Integer.parseInt(text.substring(lineSep + 1, colSep));
122                     return new LocationImpl(description, text.substring(uriStart, lineSep), line, column);
123                 }
124             } else {
125                 // unkonwn?
126
if (text.endsWith(UNKNOWN_STRING)) {
127                     return LocationImpl.UNKNOWN;
128                 }
129             }
130         } catch(Exception JavaDoc e) {
131             // Ignore: handled below
132
}
133         
134         return LocationImpl.UNKNOWN;
135     }
136
137     /**
138      * Checks if a location is known, i.e. it is not null nor equal to {@link Location#UNKNOWN}.
139      *
140      * @param location the location to check
141      * @return <code>true</code> if the location is known
142      */

143     public static boolean isKnown(Location location) {
144         return location != null && !Location.UNKNOWN.equals(location);
145     }
146
147     /**
148      * Checks if a location is unknown, i.e. it is either null or equal to {@link Location#UNKNOWN}.
149      *
150      * @param location the location to check
151      * @return <code>true</code> if the location is unknown
152      */

153     public static boolean isUnknown(Location location) {
154         return location == null || Location.UNKNOWN.equals(location);
155     }
156
157     /**
158      * Add a {@link LocationFinder} to the list of finders that will be queried for an object's
159      * location by {@link #getLocation(Object, String)}.
160      * <p>
161      * <b>Important:</b> LocationUtils internally stores a weak reference to the finder. This
162      * avoids creating strong links between the classloader holding this class and the finder's
163      * classloader, which can cause some weird memory leaks if the finder's classloader is to
164      * be reloaded. Therefore, you <em>have</em> to keep a strong reference to the finder in the
165      * calling code, e.g.:
166      * <pre>
167      * private static LocationUtils.LocationFinder myFinder =
168      * new LocationUtils.LocationFinder() {
169      * public Location getLocation(Object obj, String desc) {
170      * ...
171      * }
172      * };
173      *
174      * static {
175      * LocationUtils.addFinder(myFinder);
176      * }
177      * </pre>
178      *
179      * @param finder the location finder to add
180      */

181     public static void addFinder(LocationFinder finder) {
182         if (finder == null) {
183             return;
184         }
185
186         synchronized(LocationFinder.class) {
187             // Update a clone of the current finder list to avoid breaking
188
// any iteration occuring in another thread.
189
List JavaDoc newFinders = new ArrayList JavaDoc(finders);
190             newFinders.add(new WeakReference JavaDoc(finder));
191             finders = newFinders;
192         }
193     }
194     
195     /**
196      * Get the location of an object. Some well-known located classes built in the JDK are handled
197      * by this method. Handling of other located classes can be handled by adding new location finders.
198      *
199      * @param obj the object of which to get the location
200      * @return the object's location, or {@link Location#UNKNOWN} if no location could be found
201      */

202     public static Location getLocation(Object JavaDoc obj) {
203         return getLocation(obj, null);
204     }
205     
206     /**
207      * Get the location of an object. Some well-known located classes built in the JDK are handled
208      * by this method. Handling of other located classes can be handled by adding new location finders.
209      *
210      * @param obj the object of which to get the location
211      * @param description an optional description of the object's location, used if a Location object
212      * has to be created.
213      * @return the object's location, or {@link Location#UNKNOWN} if no location could be found
214      */

215     public static Location getLocation(Object JavaDoc obj, String JavaDoc description) {
216         if (obj instanceof Locatable) {
217             return ((Locatable)obj).getLocation();
218         }
219         
220         // Check some well-known locatable exceptions
221
if (obj instanceof SAXParseException JavaDoc) {
222             SAXParseException JavaDoc spe = (SAXParseException JavaDoc)obj;
223             if (spe.getSystemId() != null) {
224                 return new LocationImpl(description, spe.getSystemId(), spe.getLineNumber(), spe.getColumnNumber());
225             } else {
226                 return Location.UNKNOWN;
227             }
228         }
229         
230         if (obj instanceof TransformerException JavaDoc) {
231             TransformerException JavaDoc ex = (TransformerException JavaDoc)obj;
232             SourceLocator JavaDoc locator = ex.getLocator();
233             if (locator != null && locator.getSystemId() != null) {
234                 return new LocationImpl(description, locator.getSystemId(), locator.getLineNumber(), locator.getColumnNumber());
235             } else {
236                 return Location.UNKNOWN;
237             }
238         }
239         
240         if (obj instanceof Locator JavaDoc) {
241             Locator JavaDoc locator = (Locator JavaDoc)obj;
242             if (locator.getSystemId() != null) {
243                 return new LocationImpl(description, locator.getSystemId(), locator.getLineNumber(), locator.getColumnNumber());
244             } else {
245                 return Location.UNKNOWN;
246             }
247         }
248
249         List JavaDoc currentFinders = finders; // Keep the current list
250
int size = currentFinders.size();
251         for (int i = 0; i < size; i++) {
252             WeakReference JavaDoc ref = (WeakReference JavaDoc)currentFinders.get(i);
253             LocationFinder finder = (LocationFinder)ref.get();
254             if (finder == null) {
255                 // This finder was garbage collected: update finders
256
synchronized(LocationFinder.class) {
257                     // Update a clone of the current list to avoid breaking current iterations
258
List JavaDoc newFinders = new ArrayList JavaDoc(finders);
259                     newFinders.remove(ref);
260                     finders = newFinders;
261                 }
262             }
263             
264             Location result = finder.getLocation(obj, description);
265             if (result != null) {
266                 return result;
267             }
268         }
269
270         return Location.UNKNOWN;
271     }
272 }
273
Popular Tags