View Javadoc

1   package com.explosion.utilities;
2   
3   /*
4    * =============================================================================
5    * 
6    * Copyright 2004 Stephen Cowx
7    * 
8    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9    * use this file except in compliance with the License. You may obtain a copy of
10   * the License at
11   * 
12   * http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   * 
20   * =============================================================================
21   */
22  
23  import java.awt.Component;
24  import java.awt.Image;
25  import java.awt.MediaTracker;
26  import java.awt.Toolkit;
27  import java.io.File;
28  import java.io.FileInputStream;
29  import java.io.InputStream;
30  import java.net.URL;
31  import java.util.Collection;
32  import java.util.Iterator;
33  import java.util.Set;
34  import java.util.StringTokenizer;
35  import java.util.Vector;
36  import java.util.jar.Attributes;
37  import java.util.jar.JarEntry;
38  import java.util.jar.JarFile;
39  import java.util.jar.Manifest;
40  
41  import javax.swing.JFileChooser;
42  
43  import org.apache.log4j.LogManager;
44  import org.apache.log4j.Logger;
45  
46  import com.explosion.utilities.exception.ExceptionManagerFactory;
47  import com.explosion.utilities.process.threads.ProcessThread;
48  import com.explosion.utilities.regex.RegExpFileAndDirectoryFilter;
49  import com.explosion.utilities.regex.RegExpFileNameFilter;
50  
51  public class FileSystemUtils
52  {
53  
54      private static Logger log = LogManager.getLogger(FileSystemUtils.class);
55  
56      public static final int SAVETYPE = 0;
57  
58      public static final int OPENTYPE = 1;
59  
60      public static final int FILES_ONLY = 0;
61  
62      public static final int FILES_AND_DIRECTORIES = 1;
63  
64      public static final int DIRECTORIES_ONLY = 2;
65  
66      private static Vector jarFileOnClassPath = null;
67      
68      private static Set jarFileNamesOnClassPath = null;
69  
70      private static Vector allManifestEntries = null;
71      
72  
73      /***
74       * The mode refers to FILES_ONLY, DIRECTORIES_ONLY or FILES_AND_DIRECTORIES
75       * The type refers to SAVE or OPEN The rest is pretty self explanatory
76       * 
77       * @param parent
78       * @param type
79       * @param multipleFiles
80       * @param defaultFile
81       * @param mode
82       * @return @throws Exception
83       */
84      public static File[] chooseFiles(Component parent, int type, boolean multipleFiles, File defaultFile, int mode) throws Exception
85      {
86          return chooseFiles(parent, type, multipleFiles, defaultFile, mode, null);
87      }
88  
89      /***
90       * The mode refers to FILES_ONLY, DIRECTORIES_ONLY or FILES_AND_DIRECTORIES
91       * The type refers to SAVE or OPEN The rest is pretty self explanatory
92       * 
93       * @param parent
94       * @param type
95       * @param multipleFiles
96       * @param defaultFile
97       * @param mode
98       * @param title
99       * @return @throws Exception
100      */
101     public static File[] chooseFiles(Component parent, int type, boolean multipleFiles, File defaultFile, int mode, String title) throws Exception
102     {
103         JFileChooser fc = new JFileChooser();
104         fc.setDoubleBuffered(true);
105         fc.setMultiSelectionEnabled(multipleFiles);
106         File currentFile = null;
107 
108         if (defaultFile != null && defaultFile.exists())
109         {
110             currentFile = defaultFile;
111         } else
112         {
113             currentFile = new File(System.getProperty("user.dir"));
114         }
115 
116         if (currentFile.exists())
117         {
118             if (currentFile.getParent() != null)
119             {
120                 fc.setCurrentDirectory(currentFile);
121             }
122         }
123 
124         switch (mode)
125         {
126         case (FileSystemUtils.FILES_ONLY):
127             fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
128             break;
129         case (FileSystemUtils.FILES_AND_DIRECTORIES):
130             fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
131             break;
132         case (FileSystemUtils.DIRECTORIES_ONLY):
133             fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
134             break;
135         }
136 
137         if (title != null) fc.setDialogTitle(title);
138 
139         int result = -999;
140         if (type == SAVETYPE)
141             result = fc.showSaveDialog(parent);
142         else if (type == OPENTYPE) result = fc.showOpenDialog(parent);
143 
144         if (result == JFileChooser.APPROVE_OPTION)
145         {
146             File[] selectedfiles = new File[1];
147             if (multipleFiles)
148                 selectedfiles = fc.getSelectedFiles();
149             else
150                 selectedfiles[0] = fc.getSelectedFile();
151 
152             System.setProperty("user.dir", selectedfiles[0].getAbsolutePath());
153             return selectedfiles;
154         }
155         return null;
156     }
157 
158     /***
159      * This method returns a list of all the jar files which are on the
160      * classpath. It is optimized and only actually parses the classpath once per VM.
161      * 
162      * @return Vector - a list of the JarFile instance.
163      */
164     public static Vector getJarFileListFromClasspath() throws Exception
165     {
166         if (jarFileOnClassPath != null) return jarFileOnClassPath;
167 
168         StringTokenizer tokenizer = new StringTokenizer(System.getProperty("java.class.path"), System.getProperty("path.separator"));
169 
170         jarFileOnClassPath = new Vector();
171         while (tokenizer.hasMoreTokens())
172         {
173             String jarFilePath = tokenizer.nextToken();
174             try
175             {
176                 JarFile jarFile = new JarFile(jarFilePath.trim());
177                 jarFileOnClassPath.addElement(jarFile);
178             } catch (java.util.zip.ZipException e)
179             { /*
180                * This exception will be because it was looking at a filepath
181                * rather than a file so I am ignoring it
182                */
183             }
184         }
185         return jarFileOnClassPath;
186     }
187    
188     /***
189      * This method returns a list of File objects in a Vector. It only returns
190      * those Files that are not in Jar files and are not jar files. ie all the
191      * free files
192      * 
193      * @return Vector free files
194      */
195     public static Vector getFreeFileListFromClassPath() throws Exception
196     {
197         return getFreeFileListFromClassPath("");
198     }
199 
200     /***
201      * This method returns a list of File objects in a Vector. It only returns
202      * those Files that are not in Jar files and are not jar files. ie all the
203      * free files and also only returns those ofthefreefiles that match the
204      * given pattern This method is not optimized and the classpath freefiles
205      * will be searched every time this method is called.
206      * 
207      * @param pattern of files to include in the list
208      */
209     public static Vector getFreeFileListFromClassPath(String pattern) throws Exception
210     {
211         /* First things first obtain the classpath */
212         String classPath = System.getProperty("java.class.path");
213         Vector list = new Vector();
214 
215         StringTokenizer tokenizer = new StringTokenizer(classPath, System.getProperty("path.separator"));
216 
217         /*
218          * Loop through all the directories on the classpath, add the path to
219          * the config file and see if it exists.
220          */
221         while (tokenizer.hasMoreElements())
222         {
223             String tokenPath = tokenizer.nextToken();
224             File directory = new File(tokenPath);
225 
226             if (directory.exists() && directory.isDirectory())
227             {
228                 Vector v = getFileList(true, directory.getAbsolutePath(), pattern, false);
229                 for (int i = 0; i < v.size(); i++)
230                     list.addElement(v.elementAt(i));
231             }
232         }
233         return list;
234     }
235 
236     /***
237      * This method hunts down a mainfest file with an entry with the given name
238      * and returns the atributes for that entry
239      * 
240      * @param manifestEntryName
241      * @return Attributes froentry
242      * @throws Exception
243      */
244     public static Attributes getManifestAttributesForEntry(String manifestEntryName) throws Exception
245     {
246         boolean found = false;
247         Attributes attributes = null;
248 
249         /* First search the jar files */
250         Vector jarFileList = getJarFileListFromClasspath();
251         for (int i = 0; i < jarFileList.size(); i++)
252         {
253             JarFile jarFile = (JarFile) jarFileList.elementAt(i);
254 
255             if (jarFile != null)
256             {
257                 Manifest manifest = jarFile.getManifest();
258                 if (manifest != null)
259                 {
260                     attributes = (Attributes) manifest.getEntries().get(manifestEntryName);
261 
262                     if (attributes != null)
263                     {
264                         found = true;
265                         break;
266                     }
267                 }
268             }
269         }
270         /* And then search the free files */
271         if (!found)
272         {
273             Vector freeFiles = getFreeFileListFromClassPath("manifest.mf");
274             for (int i = 0; i < freeFiles.size(); i++)
275             {
276                 Manifest manifest = new Manifest(new FileInputStream((File) freeFiles.elementAt(i)));
277                 attributes = (Attributes) manifest.getEntries().get(manifestEntryName);
278                 if (attributes != null) break;
279             }
280         }
281         return attributes;
282     }
283 
284     /***
285      * This method hunts down all Entries in all manifest files on the class
286      * path. This is optimized to only perform the operation once.
287      * 
288      * @return Vector of Attributes objects one for each Entry in all manifest
289      *         files
290      * @throws Exception
291      */
292     public static Vector getAllManifestEntries(String manifestMustHave) throws Exception
293     {
294         if (allManifestEntries != null) return allManifestEntries;
295 
296         allManifestEntries = new Vector();
297 
298         /* First search the jar files */
299         Vector jarFileList = getJarFileListFromClasspath();
300         for (int i = 0; i < jarFileList.size(); i++)
301         {
302             JarFile jarFile = (JarFile) jarFileList.elementAt(i);
303 
304             if (jarFile != null)
305             {
306                 Manifest manifest = jarFile.getManifest();
307                 if (manifest != null)
308                 {
309                     if (manifest.getMainAttributes().getValue(manifestMustHave) != null)
310                     {
311                         if (manifest.getEntries() != null)
312                         {
313                             Collection collection = manifest.getEntries().values();
314                             Iterator it = collection.iterator();
315                             while (it.hasNext())
316                                 allManifestEntries.addElement(it.next());
317                         }
318                     }
319                 }
320             }
321         }
322         Vector freeFiles = getFreeFileListFromClassPath("manifest.mf");
323         for (int i = 0; i < freeFiles.size(); i++)
324         {
325             Manifest manifest = new Manifest(new FileInputStream((File) freeFiles.elementAt(i)));
326             Set set = manifest.getMainAttributes().keySet();
327             Iterator tit = set.iterator();
328 
329             if (manifest.getMainAttributes().getValue(manifestMustHave) != null)
330             {
331                 if (manifest.getEntries() != null)
332                 {
333                     Collection collection = manifest.getEntries().values();
334                     Iterator it = collection.iterator();
335                     while (it.hasNext())
336                         allManifestEntries.addElement(it.next());
337                 }
338             }
339         }
340 
341         return allManifestEntries;
342     }
343 
344     /***
345      * The following method loads an image from the classes on the classpath.
346      * It uses the classloader which loaded the component to search for the image.
347      * If that doesn;t work it tries the system classloader
348      */
349     public static synchronized Image loadImage(String imagePath, Component component ) throws Exception
350     {
351         URL url = null;
352         Image img = null;
353 
354         try
355         {
356             url = component.getClass().getClassLoader().getResource(imagePath);
357             
358             if (url == null) url = ClassLoader.getSystemResource(imagePath);
359 
360             if (url == null) url = component.getClass().getClassLoader().getResource(GeneralConstants.UNAVAILABLE_IMAGE);
361             
362             if (url == null) url = ClassLoader.getSystemResource(GeneralConstants.UNAVAILABLE_IMAGE);
363 
364             if (url == null) throw new Exception("Can find neither image '" + imagePath + "' nor image '" + GeneralConstants.UNAVAILABLE_IMAGE + "'");
365 
366             img = Toolkit.getDefaultToolkit().getImage(url);
367             MediaTracker tracker = new MediaTracker(component);
368             tracker.addImage(img, 0);
369             try
370             {
371                 tracker.waitForID(0);
372             } catch (InterruptedException exc)
373             {} catch (Exception e)
374             {
375                 ExceptionManagerFactory.getExceptionManager().manageException(e, "Unable to load image '" + imagePath + "'.");
376             }
377         } catch (Exception e)
378         {
379             log.debug("Exception while getting image " + imagePath + " for " + component + ".  You should check that the image you are looking for is on the classpath.");
380             throw e;
381         }
382         return img;
383     }
384     
385     /***
386      * The following method builds the file list of files to be processed
387      */
388     public static Vector getFileList(boolean recursive, String directory, String pattern, boolean caseSensitive) throws Exception
389     {
390         return getFileList(null, recursive, directory, pattern, caseSensitive);
391     }
392 
393     /***
394      * The following method builds the file list of files to be processed
395      */
396     public static Vector getFileList(ProcessThread controller, boolean recursive, String directory, String pattern, boolean caseSensitive) throws Exception
397     {
398         /* Initialisation */
399         String fileNamePattern = (pattern == null ? "" : pattern);
400         RegExpFileAndDirectoryFilter regExpAndDirectoryFilter;
401         RegExpFileNameFilter regExpFilter = new RegExpFileNameFilter(fileNamePattern, caseSensitive);
402         File sourceDirectory = new File(directory);
403         Vector fileVector = new Vector();
404         File[] fileList;
405 
406         /* Checking */
407         if (!sourceDirectory.exists()) throw new Exception("Unable to find path specified for creating a list of files: " + directory);
408 
409         if (!sourceDirectory.isDirectory()) throw new Exception("Path specified for creating a list of files is not a directory : " + directory);
410 
411         if (!recursive)
412         {
413             /* Initilaise the regExpAndDirectoryFilter */
414             regExpAndDirectoryFilter = new RegExpFileAndDirectoryFilter(regExpFilter);
415 
416             /*
417              * Obtain a list of files in the directory and insert them into the
418              * return vector
419              */
420             if (controller != null) controller.getProcess().setStatusText("Listing directory " + sourceDirectory.getAbsolutePath());
421 
422             fileList = sourceDirectory.listFiles(regExpAndDirectoryFilter);
423             for (int i = 0; i < fileList.length; i++)
424                 fileVector.addElement(fileList[i]);
425 
426         } else
427         {
428             buildFileListRecursive(controller, sourceDirectory, regExpFilter, fileVector);
429         }
430 
431         return fileVector;
432     }
433 
434     /***
435      * The following recursive method assists in the building of the list of
436      * files to process. Adapted from code written by Michael Liu
437      */
438     private static void buildFileListRecursive(ProcessThread controller, File directory, RegExpFileNameFilter regExpFilter, Vector fileVector) throws Exception
439     {
440         if (controller != null)
441         {
442             if (controller.getStatus() == ProcessThread.THREAD_STOPPED) return;
443         }
444 
445         //log.debug(directory.toString());
446         /*
447          * This is not a directory, if it matches the desired pattern, add it to
448          * the fileList
449          */
450         if (directory.isFile())
451         {
452             if (regExpFilter.accept(directory.getParentFile(), directory.getName())) fileVector.addElement(directory);
453         } else
454         {
455             if (controller != null) controller.getProcess().setStatusText("Listing directory " + directory.getAbsolutePath());
456 
457             /* This is a directory, list all of the files in it. */
458             File[] fileArray = directory.listFiles();
459             Vector directoryList = new Vector();
460 
461             if (fileArray != null)
462             {
463                 /*
464                  * If the File object is a file add it to the toProcessList else
465                  * add it to the list of directories
466                  */
467                 for (int i = 0; i < fileArray.length; i++)
468                 {
469 
470                     if (controller != null)
471                     {
472                         if (controller.getStatus() == ProcessThread.THREAD_STOPPED) return;
473                     }
474 
475                     if (fileArray[i].isFile())
476                     {
477                         if (regExpFilter.accept(fileArray[i].getParentFile(), fileArray[i].getName())) fileVector.addElement(fileArray[i]);
478                     } else
479                         directoryList.addElement(fileArray[i]);
480                 }
481             }
482             /*
483              * Run through the directories one by one performing the
484              * findChildren method
485              */
486             for (int i = 0; i < directoryList.size(); i++)
487                 buildFileListRecursive(controller, (File) directoryList.elementAt(i), regExpFilter, fileVector);
488         }
489     }
490 
491     /***
492      * The following method obtains an input stream to a file in a Zip/Jar file
493      * 
494      * @param jarFile
495      * @param pathOfFileToGet (format eg: com/explosion/utils/FileUtils.java
496      * @return InputStream or null if the file was not found
497      */
498     public static InputStream getInputStreamFromJarFile(JarFile jarFile, String pathOfFileToGet) throws Exception
499     {
500         if (jarFile != null)
501         {
502             JarEntry entry = jarFile.getJarEntry(pathOfFileToGet);
503             if (entry != null) return jarFile.getInputStream(entry);
504         }
505 
506         return null;
507     }
508 
509     /***
510      * Method checkGivenPathValid. Checks to see that the given path points to a
511      * valid filepath It may notbe null or point to a directory. An exception
512      * will bethrown if it doesn't
513      * 
514      * @param filePath
515      * @return File
516      * @throws IllegalArgumentException if the filePath provided is not valid
517      */
518     public static File checkGivenPathValid(String filePath) throws IllegalArgumentException
519     {
520         /* Integrity check arguments */
521         if (filePath == null) throw new IllegalArgumentException("Path to file is null.");
522 
523         File file = new File(filePath);
524         if (file.exists())
525         {
526             if (file.isDirectory()) throw new IllegalArgumentException("The path '" + filePath + "' supplied points to a directory and not a file.");
527         }
528 
529         return file;
530     }
531 
532 }
533