KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > io > IOUtils


1 /* ========================================================================
2  * JCommon : a free general purpose class library for the Java(tm) platform
3  * ========================================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jcommon/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ------------
28  * IOUtils.java
29  * ------------
30  * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
31  *
32  * Original Author: Thomas Morgner;
33  * Contributor(s): David Gilbert (for Object Refinery Limited);
34  *
35  * $Id: IOUtils.java,v 1.6 2005/11/03 09:55:27 mungady Exp $
36  *
37  * Changes
38  * -------
39  * 26-Jan-2003 : Initial version
40  * 23-Feb-2003 : Documentation
41  * 25-Feb-2003 : Fixed Checkstyle issues (DG);
42  * 29-Apr-2003 : Moved to jcommon
43  * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL;
44  * added support for query strings within these urls (TM);
45  */

46
47 package org.jfree.io;
48
49 import java.io.File JavaDoc;
50 import java.io.IOException JavaDoc;
51 import java.io.InputStream JavaDoc;
52 import java.io.OutputStream JavaDoc;
53 import java.io.Reader JavaDoc;
54 import java.io.Writer JavaDoc;
55 import java.net.URL JavaDoc;
56 import java.util.ArrayList JavaDoc;
57 import java.util.Iterator JavaDoc;
58 import java.util.List JavaDoc;
59 import java.util.StringTokenizer JavaDoc;
60
61 /**
62  * The IOUtils provide some IO related helper methods.
63  *
64  * @author Thomas Morgner.
65  */

66 public class IOUtils {
67
68     /** the singleton instance of the utility package. */
69     private static IOUtils instance;
70
71     /**
72      * DefaultConstructor.
73      */

74     private IOUtils() {
75     }
76
77     /**
78      * Gets the singleton instance of the utility package.
79      *
80      * @return the singleton instance.
81      */

82     public static IOUtils getInstance() {
83         if (instance == null) {
84             instance = new IOUtils();
85         }
86         return instance;
87     }
88
89     /**
90      * Checks, whether the URL uses a file based protocol.
91      *
92      * @param url the url.
93      * @return true, if the url is file based.
94      */

95     private boolean isFileStyleProtocol(final URL JavaDoc url) {
96         if (url.getProtocol().equals("http")) {
97             return true;
98         }
99         if (url.getProtocol().equals("https")) {
100             return true;
101         }
102         if (url.getProtocol().equals("ftp")) {
103             return true;
104         }
105         if (url.getProtocol().equals("file")) {
106             return true;
107         }
108         if (url.getProtocol().equals("jar")) {
109             return true;
110         }
111         return false;
112     }
113
114     /**
115      * Parses the given name and returns the name elements as List of Strings.
116      *
117      * @param name the name, that should be parsed.
118      * @return the parsed name.
119      */

120     private List JavaDoc parseName(final String JavaDoc name) {
121         final ArrayList JavaDoc list = new ArrayList JavaDoc();
122         final StringTokenizer JavaDoc strTok = new StringTokenizer JavaDoc(name, "/");
123         while (strTok.hasMoreElements()) {
124             final String JavaDoc s = (String JavaDoc) strTok.nextElement();
125             if (s.length() != 0) {
126                 list.add(s);
127             }
128         }
129         return list;
130     }
131
132     /**
133      * Transforms the name list back into a single string, separated with "/".
134      *
135      * @param name the name list.
136      * @param query the (optional) query for the URL.
137      * @return the constructed name.
138      */

139     private String JavaDoc formatName(final List JavaDoc name, final String JavaDoc query) {
140         final StringBuffer JavaDoc b = new StringBuffer JavaDoc();
141         final Iterator JavaDoc it = name.iterator();
142         while (it.hasNext()) {
143             b.append(it.next());
144             if (it.hasNext()) {
145                 b.append("/");
146             }
147         }
148         if (query != null) {
149             b.append('?');
150             b.append(query);
151         }
152         return b.toString();
153     }
154
155     /**
156      * Compares both name lists, and returns the last common index shared
157      * between the two lists.
158      *
159      * @param baseName the name created using the base url.
160      * @param urlName the target url name.
161      * @return the number of shared elements.
162      */

163     private int startsWithUntil(final List JavaDoc baseName, final List JavaDoc urlName) {
164         final int minIdx = Math.min(urlName.size(), baseName.size());
165         for (int i = 0; i < minIdx; i++) {
166             final String JavaDoc baseToken = (String JavaDoc) baseName.get(i);
167             final String JavaDoc urlToken = (String JavaDoc) urlName.get(i);
168             if (!baseToken.equals(urlToken)) {
169                 return i;
170             }
171         }
172         return minIdx;
173     }
174
175     /**
176      * Checks, whether the URL points to the same service. A service is equal
177      * if the protocol, host and port are equal.
178      *
179      * @param url a url
180      * @param baseUrl an other url, that should be compared.
181      * @return true, if the urls point to the same host and port and use the
182      * same protocol, false otherwise.
183      */

184     private boolean isSameService(final URL JavaDoc url, final URL JavaDoc baseUrl) {
185         if (!url.getProtocol().equals(baseUrl.getProtocol())) {
186             return false;
187         }
188         if (!url.getHost().equals(baseUrl.getHost())) {
189             return false;
190         }
191         if (url.getPort() != baseUrl.getPort()) {
192             return false;
193         }
194         return true;
195     }
196
197     /**
198      * Creates a relative url by stripping the common parts of the the url.
199      *
200      * @param url the to be stripped url
201      * @param baseURL the base url, to which the <code>url</code> is relative
202      * to.
203      * @return the relative url, or the url unchanged, if there is no relation
204      * beween both URLs.
205      */

206     public String JavaDoc createRelativeURL(final URL JavaDoc url, final URL JavaDoc baseURL) {
207         if (url == null) {
208             throw new NullPointerException JavaDoc("content url must not be null.");
209         }
210         if (baseURL == null) {
211             throw new NullPointerException JavaDoc("baseURL must not be null.");
212         }
213         if (isFileStyleProtocol(url) && isSameService(url, baseURL)) {
214
215             // If the URL contains a query, ignore that URL; do not
216
// attemp to modify it...
217
final List JavaDoc urlName = parseName(getPath(url));
218             final List JavaDoc baseName = parseName(getPath(baseURL));
219             final String JavaDoc query = getQuery(url);
220
221             if (!isPath(baseURL)) {
222                 baseName.remove(baseName.size() - 1);
223             }
224
225             // if both urls are identical, then return the plain file name...
226
if (url.equals(baseURL)) {
227                 return (String JavaDoc) urlName.get(urlName.size() - 1);
228             }
229
230             int commonIndex = startsWithUntil(urlName, baseName);
231             if (commonIndex == 0) {
232                 return url.toExternalForm();
233             }
234
235             if (commonIndex == urlName.size()) {
236                 // correct the base index if there is some weird mapping
237
// detected,
238
// fi. the file url is fully included in the base url:
239
//
240
// base: /file/test/funnybase
241
// file: /file/test
242
//
243
// this could be a valid configuration whereever virtual
244
// mappings are allowed.
245
commonIndex -= 1;
246             }
247
248             final ArrayList JavaDoc retval = new ArrayList JavaDoc();
249             if (baseName.size() >= urlName.size()) {
250                 final int levels = baseName.size() - commonIndex;
251                 for (int i = 0; i < levels; i++) {
252                     retval.add("..");
253                 }
254             }
255
256             retval.addAll(urlName.subList(commonIndex, urlName.size()));
257             return formatName(retval, query);
258         }
259         return url.toExternalForm();
260     }
261
262     /**
263      * Returns <code>true</code> if the URL represents a path, and
264      * <code>false</code> otherwise.
265      *
266      * @param baseURL the URL.
267      *
268      * @return A boolean.
269      */

270     private boolean isPath(final URL JavaDoc baseURL) {
271         if (getPath(baseURL).endsWith("/")) {
272             return true;
273         }
274         else if (baseURL.getProtocol().equals("file")) {
275             final File JavaDoc f = new File JavaDoc(getPath(baseURL));
276             try {
277                 if (f.isDirectory()) {
278                     return true;
279                 }
280             }
281             catch (SecurityException JavaDoc se) {
282                 // ignored ...
283
}
284         }
285         return false;
286     }
287
288     /**
289      * Implements the JDK 1.3 method URL.getPath(). The path is defined
290      * as URL.getFile() minus the (optional) query.
291      *
292      * @param url the URL
293      * @return the path
294      */

295     private String JavaDoc getQuery (final URL JavaDoc url) {
296         final String JavaDoc file = url.getFile();
297         final int queryIndex = file.indexOf('?');
298         if (queryIndex == -1) {
299             return null;
300         }
301         return file.substring(queryIndex + 1);
302     }
303
304     /**
305      * Implements the JDK 1.3 method URL.getPath(). The path is defined
306      * as URL.getFile() minus the (optional) query.
307      *
308      * @param url the URL
309      * @return the path
310      */

311     private String JavaDoc getPath (final URL JavaDoc url) {
312         final String JavaDoc file = url.getFile();
313         final int queryIndex = file.indexOf('?');
314         if (queryIndex == -1) {
315             return file;
316         }
317         return file.substring(0, queryIndex);
318     }
319
320     /**
321      * Copies the InputStream into the OutputStream, until the end of the stream
322      * has been reached. This method uses a buffer of 4096 kbyte.
323      *
324      * @param in the inputstream from which to read.
325      * @param out the outputstream where the data is written to.
326      * @throws IOException if a IOError occurs.
327      */

328     public void copyStreams(final InputStream JavaDoc in, final OutputStream JavaDoc out)
329         throws IOException JavaDoc {
330         copyStreams(in, out, 4096);
331     }
332
333     /**
334      * Copies the InputStream into the OutputStream, until the end of the stream
335      * has been reached.
336      *
337      * @param in the inputstream from which to read.
338      * @param out the outputstream where the data is written to.
339      * @param buffersize the buffer size.
340      * @throws IOException if a IOError occurs.
341      */

342     public void copyStreams(final InputStream JavaDoc in, final OutputStream JavaDoc out,
343             final int buffersize) throws IOException JavaDoc {
344         // create a 4kbyte buffer to read the file
345
final byte[] bytes = new byte[buffersize];
346
347         // the input stream does not supply accurate available() data
348
// the zip entry does not know the size of the data
349
int bytesRead = in.read(bytes);
350         while (bytesRead > -1) {
351             out.write(bytes, 0, bytesRead);
352             bytesRead = in.read(bytes);
353         }
354     }
355
356     /**
357      * Copies the contents of the Reader into the Writer, until the end of the
358      * stream has been reached. This method uses a buffer of 4096 kbyte.
359      *
360      * @param in the reader from which to read.
361      * @param out the writer where the data is written to.
362      * @throws IOException if a IOError occurs.
363      */

364     public void copyWriter(final Reader JavaDoc in, final Writer JavaDoc out)
365         throws IOException JavaDoc {
366         copyWriter(in, out, 4096);
367     }
368
369     /**
370      * Copies the contents of the Reader into the Writer, until the end of the
371      * stream has been reached.
372      *
373      * @param in the reader from which to read.
374      * @param out the writer where the data is written to.
375      * @param buffersize the buffer size.
376      *
377      * @throws IOException if a IOError occurs.
378      */

379     public void copyWriter(final Reader JavaDoc in, final Writer JavaDoc out,
380             final int buffersize)
381         throws IOException JavaDoc {
382         // create a 4kbyte buffer to read the file
383
final char[] bytes = new char[buffersize];
384
385         // the input stream does not supply accurate available() data
386
// the zip entry does not know the size of the data
387
int bytesRead = in.read(bytes);
388         while (bytesRead > -1) {
389             out.write(bytes, 0, bytesRead);
390             bytesRead = in.read(bytes);
391         }
392     }
393
394     /**
395      * Extracts the file name from the URL.
396      *
397      * @param url the url.
398      * @return the extracted filename.
399      */

400     public String JavaDoc getFileName(final URL JavaDoc url) {
401         final String JavaDoc file = url.getFile();
402         final int last = file.lastIndexOf("/");
403         if (last < 0) {
404             return file;
405         }
406         return file.substring(last);
407     }
408
409     /**
410      * Removes the file extension from the given file name.
411      *
412      * @param file the file name.
413      * @return the file name without the file extension.
414      */

415     public String JavaDoc stripFileExtension(final String JavaDoc file) {
416         final int idx = file.lastIndexOf(".");
417         // handles unix hidden files and files without an extension.
418
if (idx < 1) {
419             return file;
420         }
421         return file.substring(0, idx);
422     }
423
424     /**
425      * Returns the file extension of the given file name.
426      * The returned value will contain the dot.
427      *
428      * @param file the file name.
429      * @return the file extension.
430      */

431     public String JavaDoc getFileExtension(final String JavaDoc file) {
432         final int idx = file.lastIndexOf(".");
433         // handles unix hidden files and files without an extension.
434
if (idx < 1) {
435             return "";
436         }
437         return file.substring(idx);
438     }
439
440     /**
441      * Checks, whether the child directory is a subdirectory of the base
442      * directory.
443      *
444      * @param base the base directory.
445      * @param child the suspected child directory.
446      * @return true, if the child is a subdirectory of the base directory.
447      * @throws IOException if an IOError occured during the test.
448      */

449     public boolean isSubDirectory(File JavaDoc base, File JavaDoc child)
450         throws IOException JavaDoc {
451         base = base.getCanonicalFile();
452         child = child.getCanonicalFile();
453
454         File JavaDoc parentFile = child;
455         while (parentFile != null) {
456             if (base.equals(parentFile)) {
457                 return true;
458             }
459             parentFile = parentFile.getParentFile();
460         }
461         return false;
462     }
463 }
464
Popular Tags