KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > launch > Locator


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

18 package org.apache.tools.ant.launch;
19
20 import java.net.MalformedURLException JavaDoc;
21
22 import java.net.URL JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.FilenameFilter JavaDoc;
25 import java.io.ByteArrayOutputStream JavaDoc;
26 import java.io.UnsupportedEncodingException JavaDoc;
27 import java.text.CharacterIterator JavaDoc;
28 import java.text.StringCharacterIterator JavaDoc;
29 import java.util.Locale JavaDoc;
30
31 /**
32  * The Locator is a utility class which is used to find certain items
33  * in the environment.
34  *
35  * @since Ant 1.6
36  */

37 public final class Locator {
38     /**
39      * encoding used to represent URIs
40      */

41     public static final String JavaDoc URI_ENCODING = "UTF-8";
42     // stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir()
43
// of the Xerces-J team
44
// which ASCII characters need to be escaped
45
private static boolean[] gNeedEscaping = new boolean[128];
46     // the first hex character if a character needs to be escaped
47
private static char[] gAfterEscaping1 = new char[128];
48     // the second hex character if a character needs to be escaped
49
private static char[] gAfterEscaping2 = new char[128];
50     private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7',
51                                      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
52     // initialize the above 3 arrays
53
static {
54         for (int i = 0; i <= 0x1f; i++) {
55             gNeedEscaping[i] = true;
56             gAfterEscaping1[i] = gHexChs[i >> 4];
57             gAfterEscaping2[i] = gHexChs[i & 0xf];
58         }
59         gNeedEscaping[0x7f] = true;
60         gAfterEscaping1[0x7f] = '7';
61         gAfterEscaping2[0x7f] = 'F';
62         char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}',
63                          '|', '\\', '^', '~', '[', ']', '`'};
64         int len = escChs.length;
65         char ch;
66         for (int i = 0; i < len; i++) {
67             ch = escChs[i];
68             gNeedEscaping[ch] = true;
69             gAfterEscaping1[ch] = gHexChs[ch >> 4];
70             gAfterEscaping2[ch] = gHexChs[ch & 0xf];
71         }
72     }
73     /**
74      * Not instantiable
75      */

76     private Locator() {
77     }
78
79     /**
80      * Find the directory or jar file the class has been loaded from.
81      *
82      * @param c the class whose location is required.
83      * @return the file or jar with the class or null if we cannot
84      * determine the location.
85      *
86      * @since Ant 1.6
87      */

88     public static File JavaDoc getClassSource(Class JavaDoc c) {
89         String JavaDoc classResource = c.getName().replace('.', '/') + ".class";
90         return getResourceSource(c.getClassLoader(), classResource);
91     }
92
93     /**
94      * Find the directory or jar a given resource has been loaded from.
95      *
96      * @param c the classloader to be consulted for the source.
97      * @param resource the resource whose location is required.
98      *
99      * @return the file with the resource source or null if
100      * we cannot determine the location.
101      *
102      * @since Ant 1.6
103      */

104     public static File JavaDoc getResourceSource(ClassLoader JavaDoc c, String JavaDoc resource) {
105         if (c == null) {
106             c = Locator.class.getClassLoader();
107         }
108         URL JavaDoc url = null;
109         if (c == null) {
110             url = ClassLoader.getSystemResource(resource);
111         } else {
112             url = c.getResource(resource);
113         }
114         if (url != null) {
115             String JavaDoc u = url.toString();
116             if (u.startsWith("jar:file:")) {
117                 int pling = u.indexOf("!");
118                 String JavaDoc jarName = u.substring(4, pling);
119                 return new File JavaDoc(fromURI(jarName));
120             } else if (u.startsWith("file:")) {
121                 int tail = u.indexOf(resource);
122                 String JavaDoc dirName = u.substring(0, tail);
123                 return new File JavaDoc(fromURI(dirName));
124             }
125         }
126         return null;
127     }
128
129     /**
130      * Constructs a file path from a <code>file:</code> URI.
131      *
132      * <p>Will be an absolute path if the given URI is absolute.</p>
133      *
134      * <p>Prior to Java 1.4,
135      * swallows '%' that are not followed by two characters.</p>
136      *
137      * See <a HREF="http://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a>
138      * which makes some mention of how
139      * characters not supported by URI Reference syntax should be escaped.
140      *
141      * @param uri the URI designating a file in the local filesystem.
142      * @return the local file system path for the file.
143      * @throws IllegalArgumentException if the URI is malformed or not a legal file: URL
144      * @since Ant 1.6
145      */

146     public static String JavaDoc fromURI(String JavaDoc uri) {
147         // #8031: first try Java 1.4.
148
Class JavaDoc uriClazz = null;
149         try {
150             uriClazz = Class.forName("java.net.URI");
151         } catch (ClassNotFoundException JavaDoc cnfe) {
152             // Fine, Java 1.3 or earlier, do it by hand.
153
}
154         // Also check for properly formed URIs. Ant formerly recommended using
155
// nonsense URIs such as "file:./foo.xml" in XML includes. You shouldn't
156
// do that (just "foo.xml" is correct) but for compatibility we special-case
157
// things when the path is not absolute, and fall back to the old parsing behavior.
158
if (uriClazz != null && uri.startsWith("file:/")) {
159             try {
160                 java.lang.reflect.Method JavaDoc createMethod
161                     = uriClazz.getMethod("create", new Class JavaDoc[] {String JavaDoc.class});
162                 Object JavaDoc uriObj = createMethod.invoke(null, new Object JavaDoc[] {uri});
163                 java.lang.reflect.Constructor JavaDoc fileConst
164                     = File JavaDoc.class.getConstructor(new Class JavaDoc[] {uriClazz});
165                 File JavaDoc f = (File JavaDoc) fileConst.newInstance(new Object JavaDoc[] {uriObj});
166                 return f.getAbsolutePath();
167             } catch (java.lang.reflect.InvocationTargetException JavaDoc e) {
168                 Throwable JavaDoc e2 = e.getTargetException();
169                 if (e2 instanceof IllegalArgumentException JavaDoc) {
170                     // Bad URI, pass this on.
171
throw (IllegalArgumentException JavaDoc) e2;
172                 } else {
173                     // Unexpected target exception? Should not happen.
174
e2.printStackTrace();
175                 }
176             } catch (Exception JavaDoc e) {
177                 // Reflection problems? Should not happen, debug.
178
e.printStackTrace();
179             }
180         }
181
182         // Fallback method for Java 1.3 or earlier.
183

184         URL JavaDoc url = null;
185         try {
186             url = new URL JavaDoc(uri);
187         } catch (MalformedURLException JavaDoc emYouEarlEx) {
188             // Ignore malformed exception
189
}
190         if (url == null || !("file".equals(url.getProtocol()))) {
191             throw new IllegalArgumentException JavaDoc("Can only handle valid file: URIs");
192         }
193         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(url.getHost());
194         if (buf.length() > 0) {
195             buf.insert(0, File.separatorChar).insert(0, File.separatorChar);
196         }
197         String JavaDoc file = url.getFile();
198         int queryPos = file.indexOf('?');
199         buf.append((queryPos < 0) ? file : file.substring(0, queryPos));
200
201         uri = buf.toString().replace('/', File.separatorChar);
202
203         if (File.pathSeparatorChar == ';' && uri.startsWith("\\") && uri.length() > 2
204             && Character.isLetter(uri.charAt(1)) && uri.lastIndexOf(':') > -1) {
205             uri = uri.substring(1);
206         }
207         String JavaDoc path = null;
208         try {
209             path = decodeUri(uri);
210             String JavaDoc cwd = System.getProperty("user.dir");
211             int posi = cwd.indexOf(":");
212             if ((posi > 0) && path.startsWith(File.separator)) {
213                path = cwd.substring(0, posi + 1) + path;
214             }
215         } catch (UnsupportedEncodingException JavaDoc exc) {
216             // not sure whether this is clean, but this method is
217
// declared not to throw exceptions.
218
throw new IllegalStateException JavaDoc("Could not convert URI to path: "
219                                             + exc.getMessage());
220         }
221         return path;
222     }
223
224     /**
225      * Decodes an Uri with % characters.
226      * The URI is escaped
227      * @param uri String with the uri possibly containing % characters.
228      * @return The decoded Uri
229      * @throws UnsupportedEncodingException if UTF-8 is not available
230      * @since Ant 1.7
231      */

232     public static String JavaDoc decodeUri(String JavaDoc uri) throws UnsupportedEncodingException JavaDoc {
233         if (uri.indexOf('%') == -1) {
234             return uri;
235         }
236         ByteArrayOutputStream JavaDoc sb = new ByteArrayOutputStream JavaDoc(uri.length());
237         CharacterIterator JavaDoc iter = new StringCharacterIterator JavaDoc(uri);
238         for (char c = iter.first(); c != CharacterIterator.DONE;
239              c = iter.next()) {
240             if (c == '%') {
241                 char c1 = iter.next();
242                 if (c1 != CharacterIterator.DONE) {
243                     int i1 = Character.digit(c1, 16);
244                     char c2 = iter.next();
245                     if (c2 != CharacterIterator.DONE) {
246                         int i2 = Character.digit(c2, 16);
247                         sb.write((char) ((i1 << 4) + i2));
248                     }
249                 }
250             } else {
251                 sb.write(c);
252             }
253         }
254         return sb.toString(URI_ENCODING);
255     }
256     /**
257      * Encodes an Uri with % characters.
258      * The URI is escaped
259      * @param path String to encode.
260      * @return The encoded string, according to URI norms
261      * @throws UnsupportedEncodingException if UTF-8 is not available
262      * @since Ant 1.7
263      */

264     public static String JavaDoc encodeURI(String JavaDoc path) throws UnsupportedEncodingException JavaDoc {
265         int i = 0;
266         int len = path.length();
267         int ch = 0;
268         StringBuffer JavaDoc sb = null;
269         for (; i < len; i++) {
270             ch = path.charAt(i);
271             // if it's not an ASCII character, break here, and use UTF-8 encoding
272
if (ch >= 128) {
273                 break;
274             }
275             if (gNeedEscaping[ch]) {
276                 if (sb == null) {
277                     sb = new StringBuffer JavaDoc(path.substring(0, i));
278                 }
279                 sb.append('%');
280                 sb.append(gAfterEscaping1[ch]);
281                 sb.append(gAfterEscaping2[ch]);
282                 // record the fact that it's escaped
283
} else if (sb != null) {
284                 sb.append((char) ch);
285             }
286         }
287
288         // we saw some non-ascii character
289
if (i < len) {
290             if (sb == null) {
291                 sb = new StringBuffer JavaDoc(path.substring(0, i));
292             }
293             // get UTF-8 bytes for the remaining sub-string
294
byte[] bytes = null;
295             byte b;
296             bytes = path.substring(i).getBytes(URI_ENCODING);
297             len = bytes.length;
298
299             // for each byte
300
for (i = 0; i < len; i++) {
301                 b = bytes[i];
302                 // for non-ascii character: make it positive, then escape
303
if (b < 0) {
304                     ch = b + 256;
305                     sb.append('%');
306                     sb.append(gHexChs[ch >> 4]);
307                     sb.append(gHexChs[ch & 0xf]);
308                 } else if (gNeedEscaping[b]) {
309                     sb.append('%');
310                     sb.append(gAfterEscaping1[b]);
311                     sb.append(gAfterEscaping2[b]);
312                 } else {
313                     sb.append((char) b);
314                 }
315             }
316         }
317         return sb == null ? path : sb.toString();
318     }
319
320     /**
321      * Convert a File to a URL.
322      * File.toURL() does not encode characters like #.
323      * File.toURI() has been introduced in java 1.4, so
324      * ANT cannot use it (except by reflection)
325      * FileUtils.toURI() cannot be used by Locator.java
326      * Implemented this way.
327      * File.toURL() adds file: and changes '\' to '/' for dos OSes
328      * encodeURI converts characters like ' ' and '#' to %DD
329      * @param file the file to convert
330      * @return URL the converted File
331      * @throws MalformedURLException on error
332      */

333     public static URL JavaDoc fileToURL(File JavaDoc file)
334         throws MalformedURLException JavaDoc {
335         try {
336             return new URL JavaDoc(encodeURI(file.toURL().toString()));
337         } catch (UnsupportedEncodingException JavaDoc ex) {
338             throw new MalformedURLException JavaDoc(ex.toString());
339         }
340     }
341
342     /**
343      * Get the File necessary to load the Sun compiler tools. If the classes
344      * are available to this class, then no additional URL is required and
345      * null is returned. This may be because the classes are explicitly in the
346      * class path or provided by the JVM directly.
347      *
348      * @return the tools jar as a File if required, null otherwise.
349      */

350     public static File JavaDoc getToolsJar() {
351         // firstly check if the tools jar is already in the classpath
352
boolean toolsJarAvailable = false;
353         try {
354             // just check whether this throws an exception
355
Class.forName("com.sun.tools.javac.Main");
356             toolsJarAvailable = true;
357         } catch (Exception JavaDoc e) {
358             try {
359                 Class.forName("sun.tools.javac.Main");
360                 toolsJarAvailable = true;
361             } catch (Exception JavaDoc e2) {
362                 // ignore
363
}
364         }
365         if (toolsJarAvailable) {
366             return null;
367         }
368         // couldn't find compiler - try to find tools.jar
369
// based on java.home setting
370
String JavaDoc javaHome = System.getProperty("java.home");
371         File JavaDoc toolsJar = new File JavaDoc(javaHome + "/lib/tools.jar");
372         if (toolsJar.exists()) {
373             // Found in java.home as given
374
return toolsJar;
375         }
376         if (javaHome.toLowerCase(Locale.US).endsWith(File.separator + "jre")) {
377             javaHome = javaHome.substring(0, javaHome.length() - 4);
378             toolsJar = new File JavaDoc(javaHome + "/lib/tools.jar");
379         }
380         if (!toolsJar.exists()) {
381             System.out.println("Unable to locate tools.jar. "
382                  + "Expected to find it in " + toolsJar.getPath());
383             return null;
384         }
385         return toolsJar;
386     }
387
388     /**
389      * Get an array of URLs representing all of the jar files in the
390      * given location. If the location is a file, it is returned as the only
391      * element of the array. If the location is a directory, it is scanned for
392      * jar files.
393      *
394      * @param location the location to scan for Jars.
395      *
396      * @return an array of URLs for all jars in the given location.
397      *
398      * @exception MalformedURLException if the URLs for the jars cannot be
399      * formed.
400      */

401     public static URL JavaDoc[] getLocationURLs(File JavaDoc location)
402          throws MalformedURLException JavaDoc {
403         return getLocationURLs(location, new String JavaDoc[]{".jar"});
404     }
405
406     /**
407      * Get an array of URLs representing all of the files of a given set of
408      * extensions in the given location. If the location is a file, it is
409      * returned as the only element of the array. If the location is a
410      * directory, it is scanned for matching files.
411      *
412      * @param location the location to scan for files.
413      * @param extensions an array of extension that are to match in the
414      * directory search.
415      *
416      * @return an array of URLs of matching files.
417      * @exception MalformedURLException if the URLs for the files cannot be
418      * formed.
419      */

420     public static URL JavaDoc[] getLocationURLs(File JavaDoc location,
421                                         final String JavaDoc[] extensions)
422          throws MalformedURLException JavaDoc {
423         URL JavaDoc[] urls = new URL JavaDoc[0];
424
425         if (!location.exists()) {
426             return urls;
427         }
428         if (!location.isDirectory()) {
429             urls = new URL JavaDoc[1];
430             String JavaDoc path = location.getPath();
431             for (int i = 0; i < extensions.length; ++i) {
432                 if (path.toLowerCase().endsWith(extensions[i])) {
433                     urls[0] = fileToURL(location);
434                     break;
435                 }
436             }
437             return urls;
438         }
439         File JavaDoc[] matches = location.listFiles(
440             new FilenameFilter JavaDoc() {
441                 public boolean accept(File JavaDoc dir, String JavaDoc name) {
442                     for (int i = 0; i < extensions.length; ++i) {
443                         if (name.toLowerCase().endsWith(extensions[i])) {
444                             return true;
445                         }
446                     }
447                     return false;
448                 }
449             });
450         urls = new URL JavaDoc[matches.length];
451         for (int i = 0; i < matches.length; ++i) {
452             urls[i] = fileToURL(matches[i]);
453         }
454         return urls;
455     }
456 }
457
Popular Tags