View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2.filter;
18  
19  import static org.junit.Assert.fail;
20  
21  import java.io.BufferedInputStream;
22  import java.io.BufferedOutputStream;
23  import java.io.File;
24  import java.io.FileFilter;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.nio.file.Files;
28  import java.util.Arrays;
29  import java.util.List;
30  import java.util.Objects;
31  import java.util.zip.ZipEntry;
32  import java.util.zip.ZipOutputStream;
33  
34  import org.apache.commons.vfs2.FileObject;
35  import org.apache.commons.vfs2.FileSelectInfo;
36  import org.apache.commons.vfs2.FileSystemException;
37  import org.apache.commons.vfs2.FileSystemManager;
38  import org.apache.commons.vfs2.VFS;
39  import org.junit.Assert;
40  
41  /**
42   * Base class for test cases.
43   */
44  public abstract class BaseFilterTest {
45  
46      /**
47       * Verifies at least all given objects are in the list.
48       *
49       * @param list    List to use.
50       * @param objects Objects to find.
51       */
52      protected static void assertContains(final List<?> list, final Object... objects) {
53          for (final Object obj : objects) {
54              Assert.assertTrue("Couldn't find " + obj + " in " + Arrays.asList(objects), list.indexOf(obj) > -1);
55          }
56      }
57  
58      /**
59       * Verifies only the given objects are in the list.
60       *
61       * @param list    List to scan.
62       * @param objects Objects to find.
63       */
64      protected static void assertContainsOnly(final List<?> list, final Object... objects) {
65          for (final Object obj : objects) {
66              Assert.assertTrue("Couldn't find " + obj + " in " + Arrays.asList(objects), list.indexOf(obj) > -1);
67          }
68          Assert.assertEquals(objects.length, list.size());
69      }
70  
71      /**
72       * Concatenate a path and a file name taking {@code null} and empty string
73       * values into account.
74       *
75       * @param path      Path - Can be {@code null} or an empty string.
76       * @param fileName  Filename - Cannot be {@code null}.
77       * @param separator Separator for directories - Can be {@code null} or an
78       *                  empty string.
79       *
80       * @return Path and file name divided by the separator.
81       */
82      public static String concatPathAndFilename(final String path, final String fileName, final String separator) {
83  
84          if (fileName == null) {
85              throw new IllegalArgumentException("file name cannot be null");
86          }
87          if (fileName.trim().isEmpty()) {
88              throw new IllegalArgumentException("file name cannot be empty");
89          }
90          if (separator == null) {
91              throw new IllegalArgumentException("separator cannot be null");
92          }
93          if (separator.trim().isEmpty()) {
94              throw new IllegalArgumentException("separator cannot be empty");
95          }
96  
97          if (path == null) {
98              return fileName;
99          }
100         final String trimmedPath = path.trim();
101         if (trimmedPath.isEmpty()) {
102             return fileName;
103         }
104         final String trimmedFilename = fileName.trim();
105         if (trimmedPath.endsWith(separator)) {
106             return trimmedPath + trimmedFilename;
107         }
108         return trimmedPath + separator + trimmedFilename;
109 
110     }
111 
112     /**
113      * Creates a file select info object for the given file.
114      *
115      * @param file File to create an info for.
116      * @return File select info.
117      */
118     protected static FileSelectInfo createFileSelectInfo(final File file) {
119         try {
120             final FileSystemManager fsManager = VFS.getManager();
121             final FileObject fileObject = fsManager.toFileObject(file);
122             return new FileSelectInfo() {
123                 @Override
124                 public FileObject getBaseFolder() {
125                     try {
126                         return fileObject.getParent();
127                     } catch (final FileSystemException ex) {
128                         throw new RuntimeException(ex);
129                     }
130                 }
131 
132                 @Override
133                 public int getDepth() {
134                     return 0;
135                 }
136 
137                 @Override
138                 public FileObject getFile() {
139                     return fileObject;
140                 }
141 
142                 @Override
143                 public String toString() {
144                     return Objects.toString(fileObject);
145                 }
146             };
147         } catch (final FileSystemException ex) {
148             throw new RuntimeException(ex);
149         }
150     }
151 
152     /**
153      * Returns the temporary directory.
154      *
155      * @return java.io.tmpdir
156      */
157     protected static File getTempDir() {
158         return new File(System.getProperty("java.io.tmpdir"));
159     }
160 
161     /**
162      * Returns a sub directory of the temporary directory.
163      *
164      * @param name Name of the sub directory.
165      *
166      * @return Sub directory of java.io.tmpdir.
167      */
168     protected static File getTestDir(final String name) {
169         return new File(getTempDir(), name);
170     }
171 
172     /**
173      * Returns a ZIP file object.
174      *
175      * @param file File to resolve.
176      *
177      * @return File object.
178      *
179      * @throws FileSystemException Error resolving the file.
180      */
181     protected static FileObject getZipFileObject(final File file) throws FileSystemException {
182         final FileSystemManager fsManager = VFS.getManager();
183         return fsManager.resolveFile("zip:" + file.toURI());
184     }
185 
186     /**
187      * List all files for a directory.
188      *
189      * @param srcDir Directory to list the files for - Cannot be {@code null}
190      *               and must be a valid directory.
191      * @param filter Filter or {@code null} for all files.
192      *
193      * @return List of child entries of the directory.
194      */
195     private static File[] listFiles(final File srcDir, final FileFilter filter) {
196 
197         final File[] files;
198         if (filter == null) {
199             files = srcDir.listFiles();
200         } else {
201             files = srcDir.listFiles(filter);
202         }
203         return files;
204 
205     }
206 
207     /**
208      * Creates a ZIP file and adds all files in a directory and all it's sub
209      * directories to the archive. Only entries are added that comply to the file
210      * filter.
211      *
212      * @param srcDir   Directory to add - Cannot be {@code null} and must be a
213      *                 valid directory.
214      * @param filter   Filter or {@code null} for all files/directories.
215      * @param destPath Path to use for the ZIP archive - May be {@code null} or
216      *                 an empyt string.
217      * @param destFile Target ZIP file - Cannot be {@code null}.
218      *
219      * @throws IOException Error writing to the output stream.
220      */
221     public static void zipDir(final File srcDir, final FileFilter filter, final String destPath, final File destFile)
222             throws IOException {
223 
224         if (srcDir == null) {
225             throw new IllegalArgumentException("srcDir cannot be null");
226         }
227         if (!srcDir.exists()) {
228             throw new IllegalArgumentException("srcDir does not exist");
229         }
230         if (!srcDir.isDirectory()) {
231             throw new IllegalArgumentException("srcDir is not a directory");
232         }
233         if (destFile == null) {
234             throw new IllegalArgumentException("destFile cannot be null");
235         }
236 
237         try (final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(destFile.toPath())))) {
238             zipDir(srcDir, filter, destPath, out);
239         }
240 
241     }
242 
243     /**
244      * Add a directory to a ZIP output stream.
245      *
246      * @param srcDir   Directory to add - Cannot be {@code null} and must be a
247      *                 valid directory.
248      * @param filter   Filter or {@code null} for all files.
249      * @param destPath Path to use for the ZIP archive - May be {@code null} or
250      *                 an empyt string.
251      * @param out      Destination stream - Cannot be {@code null}.
252      *
253      * @throws IOException Error writing to the output stream.
254      */
255     private static void zipDir(final File srcDir, final FileFilter filter, final String destPath,
256             final ZipOutputStream out) throws IOException {
257 
258         final File[] files = listFiles(srcDir, filter);
259         for (final File file : files) {
260             if (file.isDirectory()) {
261                 zipDir(file, filter, concatPathAndFilename(destPath, file.getName(), File.separator), out);
262             } else {
263                 zipFile(file, destPath, out);
264             }
265         }
266 
267     }
268 
269     /**
270      * Creates a ZIP file and adds all files in a directory and all it's sub
271      * directories to the archive.
272      *
273      * @param srcDir   Directory to add - Cannot be {@code null} and must be a
274      *                 valid directory.
275      * @param destPath Path to use for the ZIP archive - May be {@code null} or
276      *                 an empyt string.
277      * @param destFile Target ZIP file - Cannot be {@code null}.
278      *
279      * @throws IOException Error writing to the output stream.
280      */
281     public static void zipDir(final File srcDir, final String destPath, final File destFile) throws IOException {
282 
283         zipDir(srcDir, null, destPath, destFile);
284 
285     }
286 
287     /**
288      * Adds a file to a ZIP output stream.
289      *
290      * @param srcFile  File to add - Cannot be {@code null}.
291      * @param destPath Path to use for the file - May be {@code null} or empty.
292      * @param out      Destination stream - Cannot be {@code null}.
293      *
294      * @throws IOException Error writing to the output stream.
295      */
296     private static void zipFile(final File srcFile, final String destPath, final ZipOutputStream out)
297             throws IOException {
298 
299         final byte[] buf = new byte[1024];
300         try (final InputStream in = new BufferedInputStream(Files.newInputStream(srcFile.toPath()))) {
301             final ZipEntry zipEntry = new ZipEntry(concatPathAndFilename(destPath, srcFile.getName(), File.separator));
302             zipEntry.setTime(srcFile.lastModified());
303             out.putNextEntry(zipEntry);
304             int len;
305             while ((len = in.read(buf)) > 0) {
306                 out.write(buf, 0, len);
307             }
308             out.closeEntry();
309         }
310     }
311 
312     /**
313      * Asserts that the array contains the given file names.
314      *
315      * @param files     Array to check.
316      * @param fileNames names File names to find.
317      */
318     protected void assertContains(final FileObject[] files, final String... fileNames) {
319         for (final String fileName : fileNames) {
320             if (!find(files, fileName)) {
321                 fail("File '" + fileName + "' not found in: " + Arrays.asList(files));
322             }
323         }
324     }
325 
326     private boolean find(final FileObject[] files, final String fileName) {
327         for (final FileObject file : files) {
328             final String name = file.getName().getBaseName();
329             if (name.equals(fileName)) {
330                 return true;
331             }
332         }
333         return false;
334     }
335 
336 }