KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > text > URI_utils


1 package gnu.text;
2 /* #ifdef use:java.net.URI */
3 import java.net.URI JavaDoc;
4 /* #endif */
5 import java.net.URL JavaDoc;
6 import java.net.URLConnection JavaDoc;
7 import java.io.*;
8 import gnu.lists.FString;
9 import gnu.mapping.CallContext;
10 import gnu.mapping.InPort;
11 import gnu.mapping.Table2D;
12
13 public class URI_utils
14 {
15   public static boolean isAbsolute (Object JavaDoc uri)
16   {
17     if (uri instanceof URL JavaDoc)
18       return true;
19     if (uri instanceof File)
20       return ((File) uri).isAbsolute();
21     /* #ifdef use:java.net.URI */
22     if (uri instanceof URI JavaDoc)
23       return ((URI JavaDoc) uri).isAbsolute();
24     /* #endif */
25     return InPort.uriSchemeSpecified(uri.toString());
26   }
27
28   /** Handle name that starts with "class-resource:/". */
29   static URL JavaDoc resourceURL (Object JavaDoc uri, String JavaDoc str)
30     throws java.io.IOException JavaDoc
31   {
32     // Either: class-resource:/PACKAGE/CLASS
33
// or: class-resource:/CLASS
34
// or: class-resource:/PACKAGE/RESOURCE
35
// or: class-resource:/RESOURCE
36
ClassLoader JavaDoc loader = getClassLoaderForURI(uri);
37     if (loader == null)
38       throw new IOException("unknown class-loader for URI '"+str+'\'');
39     URL JavaDoc url
40       = loader.getResource(str.substring(CLASS_RESOURCE_URI_PREFIX_LENGTH));
41     if (url == null)
42       throw new FileNotFoundException(str);
43     return url;
44   }
45
46   public static URL JavaDoc FiletoURL (File file)
47   {
48     try
49       {
50         /* #ifdef JAVA2 */
51         /* #ifdef use:java.net.URI */
52         return file.toURI().toURL();
53         /* #else */
54         // return file.toURL();
55
/* #endif */
56         /* #else */
57         // char fileSep = File.separatorChar;
58
// return new URL("file:" + file.getAbsolutePath().replace(fileSep, '/'));
59
/* #endif */
60       }
61     catch (Throwable JavaDoc ex)
62       {
63         throw gnu.mapping.WrappedException.wrapIfNeeded(ex);
64       }
65   }
66
67   public static URL JavaDoc toURL (Object JavaDoc uri)
68     throws java.io.IOException JavaDoc
69   {
70     uri = toFileOrURL(uri);
71     if (uri instanceof File)
72       return FiletoURL((File) uri);
73     return (URL JavaDoc) uri;
74   }
75
76   public static long lastModified (Object JavaDoc uri)
77   {
78     try
79       {
80         uri = toFileOrURL(uri);
81         if (uri instanceof File)
82           return ((File) uri).lastModified();
83         return ((URL JavaDoc) uri).openConnection().getLastModified();
84       }
85     catch (Throwable JavaDoc ex)
86       {
87         return 0;
88       }
89   }
90
91   public static Object JavaDoc toFileOrURL (Object JavaDoc uri)
92     throws java.io.IOException JavaDoc
93   {
94     if (uri instanceof URL JavaDoc || uri instanceof File)
95       return uri;
96     String JavaDoc str = uri.toString();
97     if (str.startsWith(CLASS_RESOURCE_URI_PREFIX))
98       return resourceURL(uri, str);
99     if (! InPort.uriSchemeSpecified(str))
100       {
101         CallContext ctx = CallContext.getInstance();
102         String JavaDoc base = ctx.getBaseUriRaw();
103         if (base == null || ! InPort.uriSchemeSpecified(base))
104           {
105             char fileSep = File.separatorChar;
106             str = str.replace('/', fileSep);
107             File file = new File(str);
108             if (base == null || file.isAbsolute())
109               return file;
110             File dir = new File(base.replace('/', fileSep));
111             if (! dir.isDirectory())
112               {
113                 /* #ifdef JAVA2 */
114                 dir = dir.getParentFile();
115                 /* #else */
116                 // dir = new File(dir.getParent());
117
/* #endif */
118               }
119             return new File(dir, str);
120           }
121         try
122           {
123             str = resolve(str, base).toString();
124           }
125         catch (java.net.URISyntaxException JavaDoc ex)
126           {
127             throw new IOException("invalid URI syntax: '"+str+'\'');
128           }
129       }
130     // Note JDK (upto 1.5.0, at least) throws an UnknownServiceException
131
// "protocol doesn't support output" if you do getOutputStream on
132
// a "file:" URL. That seems lame, but let's avoid that!
133
if (str.startsWith("file:"))
134       {
135         /* #ifdef use:java.net.URI */
136         try { return new File(new URI JavaDoc(str)); }
137         catch (Throwable JavaDoc ex) { }
138         /* #else */
139         // if (File.separatorChar == '/') // Otherwise it's more complicated.
140
// return new File(str.substring(5));
141
/* #endif */
142       }
143
144     return new URL JavaDoc(str);
145   }
146
147   public static InputStream getInputStream (Object JavaDoc uri)
148     throws java.io.IOException JavaDoc
149   {
150     uri = toFileOrURL(uri);
151     if (uri instanceof File)
152       return new FileInputStream((File) uri);
153     return ((URL JavaDoc) uri).openConnection().getInputStream();
154   }
155
156   public static OutputStream getOutputStream (Object JavaDoc uri)
157     throws java.io.IOException JavaDoc
158   {
159     uri = toFileOrURL(uri);
160     if (uri instanceof File)
161       return new FileOutputStream((File) uri);
162     URLConnection JavaDoc conn = ((URL JavaDoc) uri).openConnection();
163     conn.setDoInput(false);
164     conn.setDoOutput(true);
165     return conn.getOutputStream();
166   }
167
168   /* #ifdef use:java.net.URI */
169   public static URI JavaDoc toURI (Object JavaDoc uri)
170     throws java.net.URISyntaxException JavaDoc
171   {
172     if (uri instanceof String JavaDoc || uri instanceof FString)
173       return nametoURI(uri.toString());
174     if (uri instanceof File)
175       return FiletoURI((File) uri);
176     if (uri instanceof URL JavaDoc)
177       uri = URLtoURI((URL JavaDoc) uri);
178     return (URI JavaDoc) uri;
179   }
180   /* #else */
181   // public static String toURI (Object uri)
182
// {
183
// if (uri instanceof String || uri instanceof FString)
184
// return nametoURIString(uri.toString());
185
// if (uri instanceof File)
186
// return FiletoURI((File) uri).toString();
187
// return URLtoURI((URL) uri);
188
// }
189
/* #endif */
190
191   /* #ifdef use:java.net.URI */
192   static URI JavaDoc URLtoURI (URL JavaDoc url)
193     throws java.net.URISyntaxException JavaDoc
194   {
195     /* #ifdef JAVA5 */
196     // return url.toURI();
197
/* #else */
198     return new URI JavaDoc(url.toString());
199     /* #endif */
200   }
201   /* #else */
202   // static String URLtoURI (URL url)
203
// {
204
// return url.toString();
205
// }
206
/* #endif */
207
208   public static String JavaDoc toURIString (Object JavaDoc uri)
209   /* #ifdef use:java.net.URI */
210     throws java.net.URISyntaxException JavaDoc
211   /* #endif */
212   {
213     if (uri instanceof String JavaDoc || uri instanceof FString)
214       return nametoURIString(uri.toString());
215     if (uri instanceof File)
216       return FiletoURI((File) uri).toString();
217     /* #ifdef use:java.net.URI */
218     if (uri instanceof URL JavaDoc)
219       uri = URLtoURI((URL JavaDoc) uri);
220     return ((URI JavaDoc) uri).toString();
221     /* #else */
222     // return ((URL) uri).toString();
223
/* #endif */
224   }
225
226   public static String JavaDoc nametoURIString (String JavaDoc str)
227   /* #ifdef use:java.net.URI */
228     throws java.net.URISyntaxException JavaDoc
229   /* #endif */
230   {
231     if (InPort.uriSchemeSpecified(str))
232       return str;
233     char fileSep = File.separatorChar;
234     if (fileSep != '/')
235       str = str.replace('/', fileSep);
236     return FiletoURI(new File(str)).toString();
237   }
238
239   /* #ifdef use:java.net.URI */
240   public static URI JavaDoc nametoURI (String JavaDoc str)
241     throws java.net.URISyntaxException JavaDoc
242   {
243     try
244       {
245         return new URI JavaDoc(str);
246       }
247     catch (java.net.URISyntaxException JavaDoc ex)
248       {
249         if (InPort.uriSchemeSpecified(str))
250           throw ex;
251         char fileSep = File.separatorChar;
252         if (fileSep != '/')
253           str = str.replace('/', fileSep);
254         return FiletoURI(new File(str));
255       }
256   }
257
258   public static URI JavaDoc FiletoURI (File file)
259     throws java.net.URISyntaxException JavaDoc
260   {
261     if (file.isAbsolute())
262       return file.toURI();
263     /* We don't want to just use File.toURI(),
264        because that turns a relative File into an absolute URI. */

265     String JavaDoc fname = file.toString();
266     char fileSep = File.separatorChar;
267     if (fileSep != '/')
268       fname = fname.replace(fileSep, '/');
269     return new URI JavaDoc(null, null, fname, null);
270   }
271   /* #else */
272   // public static String FiletoURI (File file)
273
// {
274
// if (file.isAbsolute())
275
// return FiletoURL(file).toString();
276
// else
277
// return file.toString().replace(File.separatorChar, '/');
278
// }
279
/* #endif */
280
281   private static gnu.mapping.Symbol keyClassLoader =
282     new gnu.mapping.Symbol(null, "(class-loader)");
283
284   static ClassLoader JavaDoc getClassLoaderForURI (Object JavaDoc uri)
285   {
286     // We use Table.2D as a weak map from URI objects to a ClassLoader,
287
// for "class-resource:" URIs. Earlier we used java.util.WeakHashMap,
288
// but that didn't work, possibly because what we really need is the
289
// non-standard WeakIdentityHashMap. So instead, I wrote a new Table2D
290
// class, which should be useful in its own right, and may also have
291
// less overhead. --PB.
292
Table2D table = Table2D.getInstance();
293     synchronized (table)
294       {
295         return (ClassLoader JavaDoc) table.get(uri, keyClassLoader, null);
296       }
297   }
298
299   static private void setClassLoaderForURI (Object JavaDoc uri, ClassLoader JavaDoc loader)
300   {
301     Table2D table = Table2D.getInstance();
302     synchronized (table)
303       {
304         table.put(uri, keyClassLoader, loader);
305       }
306   }
307
308   /** A special URI-scheme for accessing resources relative to a ClassLoader.
309    * The resource is found using ClassLoader's getResource method.
310    * The actual ClassLoader is found using getClassLoaderForURI. */

311   public static final String JavaDoc CLASS_RESOURCE_URI_PREFIX = "class-resource:/";
312
313   /** The length of CLASS_RESOURCE_URI_PREFIX, including ":/". */
314   public static final int CLASS_RESOURCE_URI_PREFIX_LENGTH = 16;
315
316   public static
317   /* #ifdef use:java.net.URI */
318   URI JavaDoc
319   /* #else */
320   // String
321
/* #endif */
322   makeClassResourceURI (Class JavaDoc clas)
323   {
324     String JavaDoc cname = clas.getName();
325     int dot = cname.lastIndexOf('.');
326     /* #ifdef JAVA5 */
327     // StringBuilder sbuf = new StringBuilder();
328
/* #else */
329     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
330     /* #endif */
331     sbuf.append(CLASS_RESOURCE_URI_PREFIX);
332     if (dot >= 0)
333       {
334         sbuf.append(cname.substring(0, dot));
335         sbuf.append('/');
336         cname = cname.substring(dot+1);
337       }
338     sbuf.append(cname);
339     String JavaDoc str = sbuf.toString();
340     /* #ifdef use:java.net.URI */
341     URI JavaDoc uri;
342     try
343       {
344         uri = new URI JavaDoc(str);
345       }
346     catch (Throwable JavaDoc ex)
347       {
348         throw gnu.mapping.WrappedException.wrapIfNeeded(ex);
349       }
350     /* #else */
351     // String uri = str;
352
/* #endif */
353     ClassLoader JavaDoc loader = clas.getClassLoader();
354     setClassLoaderForURI(uri, loader);
355     return uri;
356   }
357
358   public static
359   /* #ifdef use:java.net.URI */
360   URI JavaDoc
361   /* #else */
362   // String
363
/* #endif */
364   resolve (Object JavaDoc relative, Object JavaDoc base)
365     throws java.net.URISyntaxException JavaDoc
366   {
367     String JavaDoc rstr;
368     if (relative instanceof URL JavaDoc)
369       { // URLs are always absolute.
370
return URLtoURI((URL JavaDoc) relative);
371       }
372     /* #ifdef use:java.net.URI */
373     else if (relative instanceof URI JavaDoc)
374       {
375         URI JavaDoc rel = (URI JavaDoc) relative;
376         if (rel.isAbsolute())
377           return rel;
378         rstr = rel.toString();
379       }
380     /* #endif */
381     else if (relative instanceof String JavaDoc || relative instanceof FString)
382       {
383         rstr = relative.toString();
384         if (InPort.uriSchemeSpecified(rstr))
385           return toURI(rstr);
386       }
387     else if (relative instanceof File)
388       {
389         File file = (File) relative;
390         if (file.isAbsolute())
391           {
392             /* #ifdef use:java.net.URI */
393             return file.toURI();
394             /* #endif */
395           }
396         rstr = file.toString();
397       }
398     else
399       throw new gnu.mapping.WrongType("resolve-uri", 1, "uri/file/string");
400     char fileSep = File.separatorChar;
401     if (fileSep != '/')
402       {
403         // Check for Windows absolute filename.
404
if (rstr.length() >= 2
405             && ((rstr.charAt(1) == ':' && Character.isLetter(rstr.charAt(0)))
406                 || (rstr.charAt(0) == fileSep && rstr.charAt(1) == fileSep)))
407           {
408             return toURI(new File(rstr));
409           }
410         rstr = rstr.replace(fileSep, '/');
411       }
412     /* #ifdef use:java.net.URI */
413     URI JavaDoc resolved = toURI(base).resolve(new URI JavaDoc(null, rstr, null));
414     /* #else */
415     // /* The following is an appximation of URI's rsolve method. */
416
// /* For example, it doesn't simplify "../" to "". */
417
// String sbase = toURI(base);
418
// int lastSl = sbase.lastIndexOf('/');
419
// StringBuffer sbuf = new StringBuffer(sbase);
420
// if (lastSl >= 0)
421
// sbuf.setLength(lastSl+1);
422
// else
423
// sbuf.append('/');
424
// if (rstr.length() > 0 && rstr.charAt(0) == '/')
425
// {
426
// /* Rstr is an absolute file name, but doesn't have a uri scheme. */
427
// int baseLen = sbase.length();
428
// int pathStart = InPort.uriSchemeLength(sbase);
429
// if (pathStart <= 1)
430
// return rstr;
431
// pathStart++;
432
// /* Add the "authority" - usually a host-name. */
433
// if (pathStart + 1 < baseLen
434
// && sbase.charAt(pathStart) == '/'
435
// && sbase.charAt(pathStart+1) == '/')
436
// {
437
// int p2 = sbase.indexOf('/', pathStart+2);
438
// if (p2 < 0)
439
// p2 = baseLen; // ? append '/'? FIXME
440
// pathStart = p2;
441
// }
442
// sbuf.setLength(pathStart);
443
// }
444
// sbuf.append(rstr);
445
// String resolved = sbuf.toString();
446
/* #endif */
447      if (resolved.toString().startsWith(CLASS_RESOURCE_URI_PREFIX))
448        {
449          ClassLoader JavaDoc loader = getClassLoaderForURI(base);
450          setClassLoaderForURI(resolved, loader);
451        }
452     return resolved;
453   }
454
455   /** Convert an absolute URI to one relatve to a given base.
456    * This goes beyond java.net.URI.relativize in that if the arguments
457    * have a common prefix, it can create a relative URI using "../" steps.
458    */

459   public static Object JavaDoc relativize (Object JavaDoc in, Object JavaDoc base)
460     throws java.net.URISyntaxException JavaDoc, java.io.IOException JavaDoc
461   {
462     String JavaDoc baseStr = URI_utils.toURI(base).normalize().toString();
463     String JavaDoc inStr = URI_utils.toURI(URI_utils.toURL(in)).normalize().toString();
464     int baseLen = baseStr.length();
465     int inLen = inStr.length();
466     int i = 0;
467     int sl = 0;
468     int colon = 0;
469     for (; i < baseLen && i < inLen; i++)
470       {
471         char cb = baseStr.charAt(i);
472         char ci = inStr.charAt(i);
473         if (cb != ci)
474           break;
475         if (cb == '/')
476           sl = i;
477         if (cb == ':')
478           colon = i;
479       }
480     if (colon > 0
481         && (sl > colon + 2 || baseLen <= colon+2 || baseStr.charAt(colon+2) != '/')
482         && (colon + 2 != CLASS_RESOURCE_URI_PREFIX_LENGTH
483             || ! inStr.substring(0, colon + 2).equals(CLASS_RESOURCE_URI_PREFIX)
484             || getClassLoaderForURI(base) == getClassLoaderForURI(in)))
485       {
486         baseStr = baseStr.substring(sl+1);
487         inStr = inStr.substring(sl+1);
488       }
489     else
490       return in;
491     /* #ifdef JAVA5 */
492     // StringBuilder sbuf = new StringBuilder();
493
/* #else */
494     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
495     /* #endif */
496     sl = 0;
497     for (i = baseLen = baseStr.length(); --i >= 0; )
498       if (baseStr.charAt(i) == '/') // sep?
499
sbuf.append("../");
500     sbuf.append(inStr);
501     return sbuf.toString();
502   }
503 }
504
Popular Tags