support for CAPTCHAs
[mir.git] / source / mir / util / FileRoutines.java
1 /*
2  * Copyright (C) 2001-2006 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * and distribute linked combinations including the two.  You must obey the
23  * GNU General Public License in all respects for all of the code used other than
24  * the above mentioned libraries.  If you modify this file, you may extend this
25  * exception to your version of the file, but you are not obligated to do so.
26  * If you do not wish to do so, delete this exception statement from your version.
27  */
28 package mir.util;
29
30 import org.apache.oro.text.regex.MalformedPatternException;
31 import org.apache.oro.text.regex.Pattern;
32 import org.apache.oro.text.regex.Perl5Compiler;
33 import org.apache.oro.text.regex.Perl5Matcher;
34
35 import java.io.BufferedInputStream;
36 import java.io.BufferedOutputStream;
37 import java.io.ByteArrayInputStream;
38 import java.io.ByteArrayOutputStream;
39 import java.io.File;
40 import java.io.FileInputStream;
41 import java.io.FileOutputStream;
42 import java.io.FilenameFilter;
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.io.OutputStream;
46 import java.util.Arrays;
47 import java.util.Collections;
48 import java.util.List;
49
50 public class FileRoutines {
51   protected static final int FILE_COPY_BUFFER_SIZE = 65536;
52
53   protected FileRoutines() {
54   }
55
56   /**
57    * Copy a file
58    */
59   public static void copyFile(File aSourceFile, File aDestinationFile) throws IOException {
60     BufferedInputStream inputStream;
61     BufferedOutputStream outputStream;
62     int nrBytesRead;
63     byte[] buffer = new byte[FILE_COPY_BUFFER_SIZE];
64
65     inputStream = new BufferedInputStream(new FileInputStream(aSourceFile));
66     try {
67       createParentDirectories(aDestinationFile);
68
69       outputStream = new BufferedOutputStream(new FileOutputStream(aDestinationFile), 8192);
70       try {
71         do {
72           nrBytesRead = inputStream.read(buffer);
73           if (nrBytesRead > 0) {
74             outputStream.write(buffer, 0, nrBytesRead);
75           }
76         }
77         while (nrBytesRead >= 0);
78       }
79       finally {
80         outputStream.close();
81       }
82     }
83     finally {
84       inputStream.close();
85     }
86   }
87
88   /**
89    * Copy a directory recursively
90    */
91   public static void copyDirectory(File aSourceDirectory, File aDestinationDirectory) throws IOException {
92     int i;
93     File sourceFile;
94     File destinationFile;
95     File[] files = aSourceDirectory.listFiles();
96
97     if (!aDestinationDirectory.exists())
98       aDestinationDirectory.mkdirs();
99
100     for (i = 0; i < files.length; i++) {
101       sourceFile = files[i];
102       destinationFile = new File(aDestinationDirectory, sourceFile.getName());
103       if (sourceFile.isDirectory()) {
104         if (!destinationFile.exists())
105           destinationFile.mkdir();
106         copyDirectory(sourceFile, destinationFile);
107       }
108       else {
109         copyFile(sourceFile, destinationFile);
110       }
111     }
112   }
113
114   /**
115    * Copy a file or directory. If the source is a file and the destination
116    * a directory, the file is copied using the same file name into the\
117    * directory.
118    *
119    * @param aSource the source file
120    * @param aDestination the destination file
121    */
122   public static void copy(File aSource, File aDestination) throws IOException {
123     if (aSource.isDirectory()) {
124       copyDirectory(aSource, aDestination);
125     }
126     else if (aDestination.isDirectory()) {
127       copyFile(aSource, new File(aDestination, aSource.getName()));
128     }
129     else {
130       copyFile(aSource, aDestination);
131     }
132   }
133
134   /**
135    * Copy the contents of an {@link InputStream} to a {@link File}
136    */
137   public static void copy(InputStream aSource, File aDestination) throws IOException {
138     BufferedOutputStream outputStream =
139         new BufferedOutputStream(new FileOutputStream(aDestination), 8192);
140
141     int read;
142     byte[] buf = new byte[8 * 1024];
143
144     while ((read = aSource.read(buf)) != -1) {
145       outputStream.write(buf, 0, read);
146     }
147
148     aSource.close();
149     outputStream.close();
150   }
151
152   /**
153    * Moves a {@link File} to a new location
154    */
155   public static void move(File aSource, File aDestination) throws IOException {
156     aDestination.getParentFile().mkdirs();
157     if (!aSource.renameTo(aDestination)) {
158       byte[] buffer = new byte[16384];
159       FileInputStream inputStream = new FileInputStream(aSource);
160       FileOutputStream outputStream = new FileOutputStream(aDestination);
161       try {
162         int count = inputStream.read(buffer);
163         while (count > 0) {
164           outputStream.write(buffer, 0, count);
165           count = inputStream.read(buffer);
166         }
167       }
168       finally {
169         outputStream.close();
170         inputStream.close();
171       }
172       aSource.delete();
173     }
174   }
175
176   public static class RegExpFileFilter implements FilenameFilter {
177     private Pattern expression;
178
179     public RegExpFileFilter(String anExpression) throws MalformedPatternException {
180       Perl5Compiler compiler = new Perl5Compiler();
181
182       expression = compiler.compile(anExpression, Perl5Compiler.READ_ONLY_MASK);
183     }
184
185     public boolean accept(File aDir, String aName) {
186       Perl5Matcher matcher = new Perl5Matcher();
187
188       return !new File(aDir, aName).isDirectory() && matcher.matches(aName, expression);
189     }
190   }
191
192   public static class DirectoryFilter implements FilenameFilter {
193     public DirectoryFilter() {
194     }
195
196     public boolean accept(File aDir, String aName) {
197       return new File(aDir, aName).isDirectory();
198     }
199   }
200
201   /**
202    * Return all files in a directory
203    *
204    * @param aDirectory The directory to list
205    * @param aFilter    the filter to apply to files
206    * @return a <code>List</code> of filenames of type <code>String</code>
207    */
208   public static List getDirectoryContentsAsList(File aDirectory, FilenameFilter aFilter) {
209     Object[] contents = aDirectory.list(aFilter);
210
211     if (contents == null) {
212       return Collections.EMPTY_LIST;
213     }
214
215     return Arrays.asList(contents);
216   }
217
218   /**
219    * Returns the extension of a path. (e.g. <code>getExtension("example.txt")</code> will
220    * return <code>"txt"</code>
221    */
222   public static String getExtension(String aPath) {
223     int position = aPath.lastIndexOf('.');
224
225     if (position >= 0) {
226       return aPath.substring(position + 1);
227     }
228
229     return "";
230   }
231
232   /**
233    * Returns <code>true</code> if the given path is absolute
234    */
235   public static boolean isAbsolutePath(String aPath) {
236     return new File(aPath).isAbsolute();
237   }
238
239   /**
240    * Transforms an absolute or relative path into an absolute
241    * {@link File}.
242    *
243    * @param aBasePath The base path to use for relative paths
244    * @param aPath     The path to transform
245    * @return An absolute representation of the supplied path
246    */
247   public static File getAbsoluteOrRelativeFile(File aBasePath, String aPath) {
248     if (isAbsolutePath(aPath)) {
249       return new File(aPath);
250     }
251
252     return new File(aBasePath, aPath);
253   }
254
255   /**
256    * Reads the content of a file into an array of bytes
257    */
258   public static byte[] readFileIntoByteArray(File aFile) throws IOException {
259     InputStream input = new FileInputStream(aFile);
260     ByteArrayOutputStream result = new ByteArrayOutputStream();
261
262     IORoutines.copyStream(input, result);
263
264     return result.toByteArray();
265   }
266
267   /**
268    * Reads the content of a file into an array of bytes
269    */
270   public static void writeByteArrayIntoFile(byte[] anArray, File aFile) throws IOException {
271     OutputStream output = new FileOutputStream(aFile);
272     try {
273       ByteArrayInputStream input = new ByteArrayInputStream(anArray);
274       try {
275         IORoutines.copyStream(input, output);
276       }
277       finally {
278         input.close();
279       }
280     }
281     finally {
282       output.close();
283     }
284   }
285
286   /**
287    * Creates all parent directories of a file if they do not exist
288    */
289   public static void createParentDirectories(File aFile) {
290     if (aFile.getParentFile() != null && !aFile.getParentFile().exists()) {
291       aFile.getParentFile().mkdirs();
292     }
293   }
294 }