• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2  *
3  * This program and the accompanying materials are made available under
4  * the terms of the Common Public License v1.0 which accompanies this distribution,
5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
6  *
7  * $Id: Files.java,v 1.1.1.1.2.1 2004/07/09 01:28:37 vlad_r Exp $
8  */
9 package com.vladium.util;
10 
11 import java.io.BufferedReader;
12 import java.io.File;
13 import java.io.FileReader;
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.HashSet;
17 import java.util.LinkedList;
18 import java.util.List;
19 import java.util.Set;
20 import java.util.StringTokenizer;
21 
22 // ----------------------------------------------------------------------------
23 /**
24  * @author Vlad Roubtsov, (C) 2003
25  */
26 public
27 abstract class Files
28 {
29     // public: ................................................................
30 
31     /**
32      * No duplicate elimination.
33      *
34      * @param atfile
35      */
readFileList(final File atfile)36     public static String [] readFileList (final File atfile)
37         throws IOException
38     {
39         if (atfile == null) throw new IllegalArgumentException ("null input: atfile");
40 
41         List _result = null;
42 
43         BufferedReader in = null;
44         try
45         {
46             in = new BufferedReader (new FileReader (atfile), 8 * 1024); // uses default encoding
47             _result = new LinkedList ();
48 
49             for (String line; (line = in.readLine ()) != null; )
50             {
51                 line = line.trim ();
52                 if ((line.length () == 0) || (line.charAt (0) == '#')) continue;
53 
54                 _result.add (line);
55             }
56         }
57         finally
58         {
59             if (in != null) try { in.close (); } catch (Exception ignore) {}
60         }
61 
62         if ((_result == null) || _result.isEmpty ())
63             return IConstants.EMPTY_STRING_ARRAY;
64         else
65         {
66             final String [] result = new String [_result.size ()];
67             _result.toArray (result);
68 
69             return result;
70         }
71     }
72 
73     /**
74      * Converts an array of path segments to an array of Files. The order
75      * of files follows the original order of path segments, except "duplicate"
76      * entries are removed. The definition of duplicates depends on 'canonical':
77      * <ul>
78      *  <li> if 'canonical'=true, the pathnames are canonicalized via {@link #canonicalizePathname}
79      *  before they are compared for equality
80      *  <li> if 'canonical'=false, the pathnames are compared as case-sensitive strings
81      * </ul>
82      *
83      * Note that duplicate removal in classpaths affects ClassLoader.getResources().
84      * The first mode above makes the most sense, however the last one is what
85      * Sun's java.net.URLClassLoader appears to do. Hence the last mode might be
86      * necessary for reproducing its behavior in Sun-compatible JVMs.
87      */
pathToFiles(final String [] path, final boolean canonical)88     public static File [] pathToFiles (final String [] path, final boolean canonical)
89     {
90         if (path == null) throw new IllegalArgumentException ("null input: path");
91         if (path.length == 0) return IConstants.EMPTY_FILE_ARRAY;
92 
93         final List /* Files */ _result = new ArrayList (path.length);
94         final Set /* String */ pathnames = new HashSet (path.length);
95 
96         final String separators = ",".concat (File.pathSeparator);
97 
98         for (int i = 0; i < path.length; ++ i)
99         {
100             String segment = path [i];
101             if (segment == null) throw new IllegalArgumentException ("null input: path[" + i + "]");
102 
103             final StringTokenizer tokenizer = new StringTokenizer (segment, separators);
104             while (tokenizer.hasMoreTokens ())
105             {
106                 String pathname = tokenizer.nextToken ();
107 
108                 if (canonical) pathname = canonicalizePathname (pathname);
109 
110                 if (pathnames.add (pathname))
111                 {
112                     _result.add (new File (pathname));
113                 }
114             }
115         }
116 
117         final File [] result = new File [_result.size ()];
118         _result.toArray (result);
119 
120         return result;
121     }
122 
123     /**
124      * Converts 'pathname' into the canonical OS form. This wrapper function
125      * will return the absolute form of 'pathname' if File.getCanonicalPath() fails.
126      */
canonicalizePathname(final String pathname)127     public static String canonicalizePathname (final String pathname)
128     {
129         if (pathname == null) throw new IllegalArgumentException ("null input: pathname");
130 
131         try
132         {
133             return new File (pathname).getCanonicalPath ();
134         }
135         catch (Exception e)
136         {
137             return new File (pathname).getAbsolutePath ();
138         }
139     }
140 
canonicalizeFile(final File file)141     public static File canonicalizeFile (final File file)
142     {
143         if (file == null) throw new IllegalArgumentException ("null input: file");
144 
145         try
146         {
147             return file.getCanonicalFile ();
148         }
149         catch (Exception e)
150         {
151             return file.getAbsoluteFile ();
152         }
153     }
154 
155     /**
156      * Invariant: (getFileName (file) + getFileExtension (file)).equals (file.getName ()).
157      *
158      * @param file File input file descriptor [must be non-null]
159      *
160      * @return String file name without the extension [excluding '.' separator]
161      * [if 'file' does not appear to have an extension, the full name is returned].
162      *
163      * @throws IllegalArgumentException if 'file' is null
164      */
getFileName(final File file)165     public static String getFileName (final File file)
166     {
167         if (file == null) throw new IllegalArgumentException ("null input: file");
168 
169         final String name = file.getName ();
170         int lastDot = name.lastIndexOf ('.');
171         if (lastDot < 0) return name;
172 
173         return name.substring (0, lastDot);
174     }
175 
176     /**
177      * Invariant: (getFileName (file) + getFileExtension (file)).equals (file.getName ()).
178      *
179      * @param file File input file descriptor [must be non-null]
180      *
181      * @return String extension [including '.' separator] or "" if 'file' does not
182      * appear to have an extension.
183      *
184      * @throws IllegalArgumentException if 'file' is null
185      */
getFileExtension(final File file)186     public static String getFileExtension (final File file)
187     {
188         if (file == null) throw new IllegalArgumentException ("null input: file");
189 
190         final String name = file.getName ();
191         int lastDot = name.lastIndexOf ('.');
192         if (lastDot < 0) return "";
193 
194         return name.substring (lastDot);
195     }
196 
197     /**
198      *
199      * @param dir [null is ignored]
200      * @param file [absolute overrides 'dir']
201      * @return
202      */
newFile(final File dir, final File file)203     public static File newFile (final File dir, final File file)
204     {
205         if (file == null) throw new IllegalArgumentException ("null input: file");
206 
207         if ((dir == null) || file.isAbsolute ()) return file;
208 
209         return new File (dir, file.getPath ());
210     }
211 
212     /**
213      *
214      * @param dir [null is ignored]
215      * @param file [absolute overrides 'dir']
216      * @return
217      */
newFile(final File dir, final String file)218     public static File newFile (final File dir, final String file)
219     {
220         if (file == null) throw new IllegalArgumentException ("null input: file");
221 
222         final File fileFile  = new File (file);
223         if ((dir == null) || fileFile.isAbsolute ()) return fileFile;
224 
225         return new File (dir, file);
226     }
227 
228     /**
229      *
230      * @param dir [null is ignored]
231      * @param file [absolute overrides 'dir']
232      * @return
233      */
newFile(final String dir, final String file)234     public static File newFile (final String dir, final String file)
235     {
236         if (file == null) throw new IllegalArgumentException ("null input: file");
237 
238         final File fileFile  = new File (file);
239         if ((dir == null) || fileFile.isAbsolute ()) return fileFile;
240 
241         return new File (dir, file);
242     }
243 
244     /**
245      * Renames 'source' to 'target' [intermediate directories are created if necessary]. If
246      * 'target' exists and 'overwrite' is false, the method is a no-op. No exceptions are
247      * thrown except for when input is invalid. If the operation fails half-way it can leave
248      * some file system artifacts behind.
249      *
250      * @return true iff the renaming was actually performed.
251      *
252      * @param source file descriptor [file must exist]
253      * @param target target file descriptor [an existing target may get deleted
254      * if 'overwrite' is true]
255      * @param overwrite if 'true', forces an existing target to be deleted
256      *
257      * @throws IllegalArgumentException if 'source' is null or file does not exist
258      * @throws IllegalArgumentException if 'target' is null
259      */
renameFile(final File source, final File target, final boolean overwrite)260     public static boolean renameFile (final File source, final File target, final boolean overwrite)
261     {
262         if ((source == null) || ! source.exists ())
263             throw new IllegalArgumentException ("invalid input source: [" + source + "]");
264         if (target == null)
265             throw new IllegalArgumentException ("null input: target");
266 
267         final boolean targetExists;
268         if (! (targetExists = target.exists ()) || overwrite)
269         {
270             if (targetExists)
271             {
272                 // need to delete the target first or the rename will fail:
273                 target.delete (); // not checking the result here: let the rename fail later
274             }
275             else
276             {
277                 // note that File.renameTo() does not create intermediate directories on demand:
278                 final File targetDir = target.getParentFile ();
279                 if ((targetDir != null) && ! targetDir.equals (source.getParentFile ()))
280                     targetDir.mkdirs (); // TODO: clean this up on failure?
281             }
282 
283             // note: this can fail for a number of reasons, including the target
284             // being on a different drive/file system:
285             return source.renameTo (target);
286         }
287 
288         return false;
289     }
290 
291     /**
292      * A slightly stricter version of File.createTempFile() in J2SDK 1.3: it requires
293      * that the caller provide an existing parent directory for the temp file.
294      * This defers to File.createTempFile (prefix, extension, parentDir) after
295      * normalizing 'extension'.<P>
296      *
297      * MT-safety: if several threads use this API concurrently, the temp files
298      * created are guaranteed to get created without any collisions and correspond
299      * to files that did not exist before. However, if such a temp file is deleted
300      * at a later point, this method may reuse its file name. These MT-safety
301      * guarantees do not hold if files are created in the same directory outside
302      * of this method.
303      *
304      * @param parentDir parent dir for the temp file [may not be null and must exist]
305      * @param prefix prefix pattern for the temp file name [only the first 3
306      * chars are guaranteed to be used]
307      * @param extension pattern for the temp file name [null is equivalient to
308      * ".tmp"; this is always normalized to start with "."; only the first 3
309      * non-"." chars are guaranteed to be used]
310      *
311      * @return writeable temp file descriptor [incorporates 'parentDir' in its pathname]
312      * @throws IOException if a temp file could not be created
313      */
createTempFile(final File parentDir, final String prefix, String extension)314     public static File createTempFile (final File parentDir, final String prefix, String extension)
315         throws IOException
316     {
317         if ((parentDir == null) || ! parentDir.exists ())
318             throw new IllegalArgumentException ("invalid parent directory: [" + parentDir + "]");
319         if ((prefix == null) || (prefix.length () < 3))
320             throw new IllegalArgumentException ("null or less than 3 chars long: " + prefix);
321 
322         if (extension == null) extension = ".tmp";
323         else if (extension.charAt (0) != '.') extension = ".".concat (extension);
324 
325         return File.createTempFile (prefix, extension, parentDir);
326     }
327 
328     // protected: .............................................................
329 
330     // package: ...............................................................
331 
332     // private: ...............................................................
333 
334 
Files()335     private Files () {} // prevent subclassing
336 
337 } // end of class
338 // ----------------------------------------------------------------------------