build results now in subdir of project dir instead of in subdir of build
[utils] / support / test / org / wamblee / io / FileSystemUtils.java
1 /*
2  * Copyright 2006 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.wamblee.io;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.UnsupportedEncodingException;
22 import java.net.URL;
23 import java.net.URLDecoder;
24 import java.security.CodeSource;
25
26 import junit.framework.TestCase;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 /**
32  * File system utilities.
33  */
34 public final class FileSystemUtils {
35
36     private static final Log LOG = LogFactory.getLog(FileSystemUtils.class);
37
38     /**
39      * Test output directory relative to the sub project.
40      */
41     private static final String TEST_OUTPUT_DIR = "resources/testoutput";
42     
43     /**
44      * Test input directory relative to the sub project. 
45      */
46     private static final String TEST_INPUT_DIR = "../resources/test";
47
48     /*
49      * Disabled.
50      * 
51      */
52     private FileSystemUtils() {
53         // Empty
54     }
55
56     /**
57      * Deletes a directory recursively. The test case will fail if the directory
58      * does not exist or if deletion fails.
59      * 
60      * @param aDir
61      *            Directory to delete.
62      */
63     public static void deleteDirRecursively(String aDir) {
64         deleteDirRecursively(new File(aDir));
65     }
66
67     /**
68      * Deletes a directory recursively. See {@link #deleteDirRecursively}.
69      * 
70      * @param aDir
71      *            Directory.
72      */
73     public static void deleteDirRecursively(File aDir) {
74         TestCase.assertTrue(aDir.isDirectory());
75
76         for (File file : aDir.listFiles()) {
77             if (file.isDirectory()) {
78                 deleteDirRecursively(file);
79             } else {
80                 delete(file);
81             }
82         }
83
84         delete(aDir);
85     }
86
87     /**
88      * Deletes a file or directory. The test case will fail if the file or
89      * directory does not exist or if deletion fails. Deletion of a non-empty
90      * directory will always fail.
91      * 
92      * @param aFile
93      *            File or directory to delete.
94      */
95     public static void delete(File aFile) {
96         TestCase.assertTrue(aFile.delete());
97     }
98
99     /**
100      * Gets a path relative to a sub project. This utility should be used to
101      * easily access file paths within a subproject without requiring any
102      * specific Eclipse configuration.
103      * 
104      * @param aRelativePath
105      *            Relative path.
106      * @param aTestClass
107      *            Test class.
108      */
109     public static File getPath(String aRelativePath, Class aTestClass) {
110         CodeSource source = aTestClass.getProtectionDomain().getCodeSource();
111         if (source == null) {
112             LOG.warn("Could not obtain path for '" + aRelativePath
113                     + "' for class " + aTestClass
114                     + ", using relative path as is");
115             return new File(aRelativePath);
116         }
117         URL location = source.getLocation();
118         String protocol = location.getProtocol();
119         if (!protocol.equals("file")) {
120             LOG.warn("protocol is not 'file': " + location);
121             return new File(aRelativePath);
122         }
123
124         String path = location.getPath();
125         try {
126             path = URLDecoder.decode(location.getPath(), "UTF-8");
127         } catch (UnsupportedEncodingException e) {
128             // ignore it.. just don't decode
129             LOG.warn("Decoding path failed: '" + location.getPath() + "'", e );
130         }
131
132         return new File(new File(path).getParentFile(), aRelativePath);
133     }
134
135     /**
136      * Ensures that a directory hierarchy exists (recursively if needed). If it
137      * is not possible to create the directory, then the test case will fail.
138      * 
139      * @param aDir
140      *            Directory to create.
141      */
142     public static void createDir(File aDir) {
143         if (aDir.exists() && !aDir.isDirectory()) {
144             TestCase.fail("'" + aDir
145                     + "' already exists and is not a directory");
146         }
147         if (aDir.exists()) {
148             return;
149         }
150         createDir(aDir.getParentFile());
151         TestCase.assertTrue("Could not create '" + aDir + "'", aDir.mkdir());
152     }
153
154     /**
155      * Gets the test output directory for a specific test class.
156      * 
157      * @param aTestClass
158      *            Test class.
159      * @return Test output directory.
160      */
161     public static File getTestOutputDir(Class aTestClass) {
162         File file = getPath(TEST_OUTPUT_DIR, aTestClass);
163         String packageName = aTestClass.getPackage().getName();
164         String packagePath = packageName.replaceAll("\\.", "/");
165         return new File(file, packagePath);
166     }
167     
168     /**
169      * Gets the test input directory for a specific test class.
170      * 
171      * @param aTestClass
172      *            Test class.
173      * @return Test input directory.
174      */
175     public static File getTestInputDir(Class aTestClass) {
176         File file = getPath(TEST_INPUT_DIR, aTestClass);
177         String packageName = aTestClass.getPackage().getName();
178         String packagePath = packageName.replaceAll("\\.", "/");
179         return new File(file, packagePath);
180     }
181
182     /**
183      * Creates a directory hierarchy for the output directory of a test class if
184      * needed.
185      * 
186      * @param aTestClass
187      *            Test class
188      * @return Test directory.
189      */
190     public static File createTestOutputDir(Class aTestClass) {
191         File file = getTestOutputDir(aTestClass);
192         createDir(file);
193         return file;
194     }
195
196     /**
197      * Gets a test output file name. This returns a File object representing the
198      * output file and ensures that the directory where the file will be created
199      * already exists.
200      * 
201      * @param aName
202      *            Name of the file.
203      * @param aTestClass
204      *            Test class.
205      * @return File.
206      */
207     public static File getTestOutputFile(String aName, Class aTestClass) {
208         File file = new File(getTestOutputDir(aTestClass), aName);
209         createDir(file.getParentFile());
210         return file;
211     }
212
213     public static String read(InputStream aIs) throws IOException {
214         try {
215             StringBuffer buffer = new StringBuffer();
216             int c;
217             while ((c = aIs.read()) != -1) {
218                 buffer.append((char)c);
219             }
220             return buffer.toString();
221         } finally {
222             aIs.close();
223         }
224     }
225 }