KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > util > file > Files


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.util.file;
23
24 import java.io.BufferedInputStream JavaDoc;
25 import java.io.BufferedOutputStream JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.FileInputStream JavaDoc;
28 import java.io.FileOutputStream JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.InputStream JavaDoc;
31 import java.io.OutputStream JavaDoc;
32 import java.io.UnsupportedEncodingException JavaDoc;
33 import java.net.URL JavaDoc;
34
35 import org.jboss.logging.Logger;
36 import org.jboss.util.stream.Streams;
37
38 /**
39  * A collection of file utilities.
40  *
41  * @author <a HREF="mailto:jason@planet57.com">Jason Dillon</a>
42  * @author <a HREF="mailto:Scott.Stark@jboss.org">Scott Stark<a/>
43  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
44  * @version $Revision: 1958 $
45  */

46 public final class Files
47 {
48    /** The Logger instance */
49    private static final Logger log = Logger.getLogger(Files.class);
50    
51    /** for byte-to-hex conversions */
52    private static final char[] hexDigits = new char[]
53       { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
54    
55    /** The default size of the copy buffer. */
56    public static final int DEFAULT_BUFFER_SIZE = 8192;
57
58    /** Delete a file, or a directory and all of its contents.
59     *
60     * @param dir The directory or file to delete.
61     * @return True if all delete operations were successfull.
62     */

63    public static boolean delete(final File JavaDoc dir)
64    {
65       boolean success = true;
66
67       File JavaDoc files[] = dir.listFiles();
68       if (files != null)
69       {
70          for (int i = 0; i < files.length; i++)
71          {
72             File JavaDoc f = files[i];
73             if( f.isDirectory() == true )
74             {
75                // delete the directory and all of its contents.
76
if( delete(f) == false )
77                {
78                   success = false;
79                   log.debug("Failed to delete dir: "+f.getAbsolutePath());
80                }
81             }
82             // delete each file in the directory
83
else if( f.delete() == false )
84             {
85                success = false;
86                log.debug("Failed to delete file: "+f.getAbsolutePath());
87             }
88          }
89       }
90
91       // finally delete the directory
92
if( dir.delete() == false )
93       {
94          success = false;
95          log.debug("Failed to delete dir: "+dir.getAbsolutePath());
96       }
97
98       return success;
99    }
100
101    /**
102     * Delete a file or directory and all of its contents.
103     *
104     * @param dirname The name of the file or directory to delete.
105     * @return True if all delete operations were successfull.
106     */

107    public static boolean delete(final String JavaDoc dirname)
108    {
109       return delete(new File JavaDoc(dirname));
110    }
111
112    /**
113     * Delete a directory contaning the given file and all its contents.
114     *
115     * @param filename a file or directory in the containing directory to delete
116     * @return true if all delete operations were successfull, false if any
117     * delete failed.
118     */

119    public static boolean deleteContaining(final String JavaDoc filename)
120    {
121       File JavaDoc file = new File JavaDoc(filename);
122       File JavaDoc containingDir = file.getParentFile();
123       return delete(containingDir);
124    }
125
126    /**
127     * Copy a file.
128     *
129     * @param source Source file to copy.
130     * @param target Destination target file.
131     * @param buff The copy buffer.
132     *
133     * @throws IOException Failed to copy file.
134     */

135    public static void copy(final File JavaDoc source,
136          final File JavaDoc target,
137          final byte buff[])
138          throws IOException JavaDoc
139    {
140       BufferedInputStream JavaDoc in = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(source));
141       BufferedOutputStream JavaDoc out = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(target));
142
143       int read;
144
145       try
146       {
147          while ((read = in.read(buff)) != -1)
148          {
149             out.write(buff, 0, read);
150          }
151       }
152       finally
153       {
154          Streams.flush(out);
155          Streams.close(in);
156          Streams.close(out);
157       }
158    }
159
160    /**
161     * Copy a file.
162     *
163     * @param source Source file to copy.
164     * @param target Destination target file.
165     * @param size The size of the copy buffer.
166     *
167     * @throws IOException Failed to copy file.
168     */

169    public static void copy(final File JavaDoc source,
170          final File JavaDoc target,
171          final int size)
172          throws IOException JavaDoc
173    {
174       copy(source, target, new byte[size]);
175    }
176
177    /**
178     * Copy a file.
179     *
180     * @param source Source file to copy.
181     * @param target Destination target file.
182     *
183     * @throws IOException Failed to copy file.
184     */

185    public static void copy(final File JavaDoc source, final File JavaDoc target)
186          throws IOException JavaDoc
187    {
188       copy(source, target, DEFAULT_BUFFER_SIZE);
189    }
190    
191    /**
192     * Copy a remote/local URL to a local file
193     *
194     * @param src the remote or local URL
195     * @param dest the local file
196     * @throws IOException upon error
197     */

198    public static void copy(URL JavaDoc src, File JavaDoc dest) throws IOException JavaDoc
199    {
200       log.debug("Copying " + src + " -> " + dest);
201       
202       // Validate that the dest parent directory structure exists
203
File JavaDoc dir = dest.getParentFile();
204       if (!dir.exists())
205       {
206          if (!dir.mkdirs())
207          {
208             throw new IOException JavaDoc("mkdirs failed for: " + dir.getAbsolutePath());
209          }
210       }
211       // Remove any existing dest content
212
if (dest.exists())
213       {
214          if (!Files.delete(dest))
215          {
216             throw new IOException JavaDoc("delete of previous content failed for: " + dest.getAbsolutePath());
217          }
218       }
219       // Treat local and remote URLs the same
220
// prepare streams, do the copy and flush
221
InputStream JavaDoc in = new BufferedInputStream JavaDoc(src.openStream());
222       OutputStream JavaDoc out = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(dest));
223       Streams.copy(in, out);
224       out.flush();
225       out.close();
226       in.close();
227    }
228    
229    /**
230     * Used to encode any string into a string that is safe to use as
231     * a file name on most operating systems.
232     *
233     * Use decodeFileName() to get back the original string.
234     *
235     * Copied by Adrian's org.jboss.mq.pm.file.PersistenceManager
236     * and adapted to use hex instead of decimal digits
237     *
238     * @param name the filename to encode
239     * @return a filesystem-friendly filename
240     */

241    public static String JavaDoc encodeFileName(String JavaDoc name)
242    {
243       return encodeFileName(name, '@');
244    }
245    
246    /**
247     * Used to decode a file system friendly filename produced
248     * by encodeFileName() method, above.
249     *
250     * Copied by Adrian's org.jboss.mq.pm.file.PersistenceManager
251     * and adapted to use hex instead of decimal digits
252     *
253     * Note:
254     * Decoding will not work if encoding produced
255     * multi-byte encoded characters. If this is truly
256     * needed we'll have to revise the encoding.
257     *
258     * @param name the filename to decode
259     * @return the original name
260     */

261    public static String JavaDoc decodeFileName(String JavaDoc name)
262    {
263       return decodeFileName(name, '@');
264    }
265    
266    /**
267     * See encodeFileName(String) above.
268     *
269     * @param name the filename to encode
270     * @param escape the escape character to use
271     * @return a filesystem-friendly filename
272     */

273    public static String JavaDoc encodeFileName(String JavaDoc name, char escape)
274    {
275       StringBuffer JavaDoc rc = new StringBuffer JavaDoc();
276       for (int i = 0; i < name.length(); i++ )
277       {
278          switch (name.charAt(i))
279          {
280             // These are the safe characters...
281
case 'a': case 'A': case 'b': case 'B': case 'c': case 'C':
282             case 'd': case 'D': case 'e': case 'E': case 'f': case 'F':
283             case 'g': case 'G': case 'h': case 'H': case 'i': case 'I':
284             case 'j': case 'J': case 'k': case 'K': case 'l': case 'L':
285             case 'm': case 'M': case 'n': case 'N': case 'o': case 'O':
286             case 'p': case 'P': case 'q': case 'Q': case 'r': case 'R':
287             case 's': case 'S': case 't': case 'T': case 'u': case 'U':
288             case 'v': case 'V': case 'w': case 'W': case 'x': case 'X':
289             case 'y': case 'Y': case 'z': case 'Z':
290             case '1': case '2': case '3': case '4': case '5':
291             case '6': case '7': case '8': case '9': case '0':
292             case '-': case '_': case '.':
293                rc.append(name.charAt(i));
294                break;
295
296             // Any other character needs to be encoded.
297
default:
298             
299                // We encode the characters as <esc>hh,
300
// where <esc> is the passed escape character and
301
// hh is the hex value of the UTF8 byte of the character.
302
// You might get <esc>hh<esc>hh since UTF8 can produce multiple
303
// bytes for a single character.
304
try
305                {
306                   byte data[] = ("" + name.charAt(i)).getBytes("UTF8");
307                   for (int j = 0; j < data.length; j++)
308                   {
309                      rc.append(escape);
310                      rc.append(hexDigits[ (data[j] >> 4) & 0xF ]); // high order digit
311
rc.append(hexDigits[ (data[j] ) & 0xF ]); // low order digit
312
}
313                }
314                catch (UnsupportedEncodingException JavaDoc wonthappen)
315                {
316                   // nada
317
}
318          }
319       }
320       return rc.toString();
321    }
322
323    /**
324     * See decodeFileName(String) above.
325     *
326     * @param name the filename to decode
327     * @param escape the escape character to use
328     * @return the original name
329     */

330    public static String JavaDoc decodeFileName(String JavaDoc name, char escape)
331    {
332       if (name == null)
333       {
334          return null;
335       }
336       StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc(name.length());
337       
338       for (int i = 0; i < name.length(); i++)
339       {
340          char c = name.charAt(i);
341          if (c == escape)
342          {
343             char h1 = name.charAt(++i);
344             char h2 = name.charAt(++i);
345
346             // convert hex digits to integers
347
int d1 = (h1 >= 'a') ? (10 + h1 - 'a')
348                   : ((h1 >= 'A') ? (10 + h1 - 'A')
349                                      : (h1 - '0'));
350             
351             int d2 = (h2 >= 'a') ? (10 + h2 - 'a')
352                   : ((h2 >= 'A') ? (10 + h2 - 'A')
353                                       : (h2 - '0'));
354             
355             // handling only the <esc>hh case here, as we don't know
356
// if <esc>hh<esc>hh belong to the same character
357
// (and we are lazy to change the encoding) - REVISIT
358
byte[] bytes = new byte[] { (byte)(d1 * 16 + d2) };
359             
360             try
361             {
362                String JavaDoc s = new String JavaDoc(bytes, "UTF8");
363                sbuf.append(s);
364             }
365             catch (UnsupportedEncodingException JavaDoc wonthappen)
366             {
367                // nada
368
}
369          }
370          else
371          {
372             sbuf.append(c);
373          }
374       }
375       return sbuf.toString();
376    }
377
378    /**
379     * Build a relative path to the given base path.
380     * @param base - the path used as the base
381     * @param path - the path to compute relative to the base path
382     * @return A relative path from base to path
383     * @throws IOException
384     */

385    public static String JavaDoc findRelativePath(String JavaDoc base, String JavaDoc path)
386       throws IOException JavaDoc
387    {
388       String JavaDoc a = new File JavaDoc(base).getCanonicalFile().toURI().getPath();
389       String JavaDoc b = new File JavaDoc(path).getCanonicalFile().toURI().getPath();
390       String JavaDoc[] basePaths = a.split("/");
391       String JavaDoc[] otherPaths = b.split("/");
392       int n = 0;
393       for(; n < basePaths.length && n < otherPaths.length; n ++)
394       {
395          if( basePaths[n].equals(otherPaths[n]) == false )
396             break;
397       }
398       System.out.println("Common length: "+n);
399       StringBuffer JavaDoc tmp = new StringBuffer JavaDoc("../");
400       for(int m = n; m < basePaths.length - 1; m ++)
401          tmp.append("../");
402       for(int m = n; m < otherPaths.length; m ++)
403       {
404          tmp.append(otherPaths[m]);
405          tmp.append("/");
406       }
407
408       return tmp.toString();
409    }
410 }
411
Popular Tags