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.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertTrue;
21  import static org.junit.jupiter.api.Assertions.fail;
22  
23  import java.io.BufferedInputStream;
24  import java.io.BufferedOutputStream;
25  import java.io.File;
26  import java.io.FileFilter;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.nio.file.Files;
30  import java.util.Arrays;
31  import java.util.List;
32  import java.util.Objects;
33  import java.util.zip.ZipEntry;
34  import java.util.zip.ZipOutputStream;
35  
36  import org.apache.commons.io.FileUtils;
37  import org.apache.commons.io.function.Uncheck;
38  import org.apache.commons.vfs2.FileObject;
39  import org.apache.commons.vfs2.FileSelectInfo;
40  import org.apache.commons.vfs2.FileSystemException;
41  import org.apache.commons.vfs2.FileSystemManager;
42  import org.apache.commons.vfs2.VFS;
43  
44  /**
45   * Base class for test cases.
46   */
47  public abstract class BaseFilterTest {
48  
49      /**
50       * Verifies at least all given objects are in the list.
51       *
52       * @param list    List to use.
53       * @param objects Objects to find.
54       */
55      protected static void assertContains(final List<?> list, final Object... objects) {
56          for (final Object obj : objects) {
57              assertTrue(list.indexOf(obj) > -1, () -> "Couldn't find " + obj + " in " + Arrays.asList(objects));
58          }
59      }
60  
61      /**
62       * Verifies only the given objects are in the list.
63       *
64       * @param list    List to scan.
65       * @param objects Objects to find.
66       */
67      protected static void assertContainsOnly(final List<?> list, final Object... objects) {
68          for (final Object obj : objects) {
69              assertTrue(list.indexOf(obj) > -1, () -> "Couldn't find " + obj + " in " + Arrays.asList(objects));
70          }
71          assertEquals(objects.length, list.size());
72      }
73  
74      /**
75       * Concatenate a path and a file name taking {@code null} and empty string
76       * values into account.
77       *
78       * @param path      Path - Can be {@code null} or an empty string.
79       * @param fileName  File name - Cannot be {@code null}.
80       * @param separator Separator for directories - Can be {@code null} or an
81       *                  empty string.
82       *
83       * @return Path and file name divided by the separator.
84       */
85      public static String concatPathAndFileName(final String path, final String fileName, final String separator) {
86  
87          if (fileName == null) {
88              throw new IllegalArgumentException("file name cannot be null");
89          }
90          if (fileName.trim().isEmpty()) {
91              throw new IllegalArgumentException("file name cannot be empty");
92          }
93          if (separator == null) {
94              throw new IllegalArgumentException("separator cannot be null");
95          }
96          if (separator.trim().isEmpty()) {
97              throw new IllegalArgumentException("separator cannot be empty");
98          }
99  
100         if (path == null) {
101             return fileName;
102         }
103         final String trimmedPath = path.trim();
104         if (trimmedPath.isEmpty()) {
105             return fileName;
106         }
107         final String trimmedFileName = fileName.trim();
108         if (trimmedPath.endsWith(separator)) {
109             return trimmedPath + trimmedFileName;
110         }
111         return trimmedPath + separator + trimmedFileName;
112     }
113 
114     /**
115      * Creates a file select info object for the given file.
116      *
117      * @param file File to create an info for.
118      * @return File select info.
119      */
120     protected static FileSelectInfo createFileSelectInfo(final File file) {
121         return Uncheck.get(() -> {
122             final FileObject fileObject = VFS.getManager().toFileObject(file);
123             return new FileSelectInfo() {
124                 @Override
125                 public FileObject getBaseFolder() {
126                     return Uncheck.get(fileObject::getParent);
127                 }
128 
129                 @Override
130                 public int getDepth() {
131                     return 0;
132                 }
133 
134                 @Override
135                 public FileObject getFile() {
136                     return fileObject;
137                 }
138 
139                 @Override
140                 public String toString() {
141                     return Objects.toString(fileObject);
142                 }
143             };
144         });
145     }
146 
147     protected static void delete(final File file) {
148         if (file != null) {
149             file.delete();
150         }
151     }
152 
153     /**
154      * Returns the temporary directory.
155      *
156      * @return java.io.tmpdir
157      */
158     protected static File getTempDir() {
159         return FileUtils.getTempDirectory();
160     }
161 
162     /**
163      * Returns a subdirectory of the temporary directory.
164      *
165      * @param name Name of the subdirectory.
166      * @return Subdirectory of java.io.tmpdir.
167      */
168     protected static File getTestDir(final String name) {
169         final File file = new File(getTempDir(), name);
170         file.mkdirs();
171         return file;
172     }
173 
174     /**
175      * Returns a ZIP file object.
176      *
177      * @param file File to resolve.
178      * @return File object.
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      * @return List of child entries of the directory.
193      */
194     private static File[] listFiles(final File srcDir, final FileFilter filter) {
195         return srcDir.listFiles(filter);
196     }
197 
198     /**
199      * Creates a ZIP file and adds all files in a directory and all it's
200      * subdirectories to the archive. Only entries are added that comply to the file
201      * filter.
202      *
203      * @param srcDir   Directory to add - Cannot be {@code null} and must be a
204      *                 valid directory.
205      * @param filter   Filter or {@code null} for all files/directories.
206      * @param destPath Path to use for the ZIP archive - May be {@code null} or
207      *                 an empty string.
208      * @param destFile Target ZIP file - Cannot be {@code null}.
209      * @throws IOException Error writing to the output stream.
210      */
211     public static void zipDir(final File srcDir, final FileFilter filter, final String destPath, final File destFile)
212             throws IOException {
213         if (srcDir == null) {
214             throw new IllegalArgumentException("srcDir cannot be null");
215         }
216         if (!srcDir.exists()) {
217             throw new IllegalArgumentException("srcDir does not exist");
218         }
219         if (!srcDir.isDirectory()) {
220             throw new IllegalArgumentException("srcDir is not a directory");
221         }
222         if (destFile == null) {
223             throw new IllegalArgumentException("destFile cannot be null");
224         }
225         try (ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(destFile.toPath())))) {
226             zipDir(srcDir, filter, destPath, out);
227         }
228 
229     }
230 
231     /**
232      * Add a directory to a ZIP output stream.
233      *
234      * @param srcDir   Directory to add - Cannot be {@code null} and must be a
235      *                 valid directory.
236      * @param filter   Filter or {@code null} for all files.
237      * @param destPath Path to use for the ZIP archive - May be {@code null} or
238      *                 an empty string.
239      * @param out      Destination stream - Cannot be {@code null}.
240      * @throws IOException Error writing to the output stream.
241      */
242     private static void zipDir(final File srcDir, final FileFilter filter, final String destPath,
243             final ZipOutputStream out) throws IOException {
244 
245         final File[] files = listFiles(srcDir, filter);
246         for (final File file : files) {
247             if (file.isDirectory()) {
248                 zipDir(file, filter, concatPathAndFileName(destPath, file.getName(), File.separator), out);
249             } else {
250                 zipFile(file, destPath, out);
251             }
252         }
253 
254     }
255 
256     /**
257      * Creates a ZIP file and adds all files in a directory and all it's
258      * subdirectories to the archive.
259      *
260      * @param srcDir   Directory to add - Cannot be {@code null} and must be a
261      *                 valid directory.
262      * @param destPath Path to use for the ZIP archive - May be {@code null} or
263      *                 an empty string.
264      * @param destFile Target ZIP file - Cannot be {@code null}.
265      * @throws IOException Error writing to the output stream.
266      */
267     public static void zipDir(final File srcDir, final String destPath, final File destFile) throws IOException {
268 
269         zipDir(srcDir, null, destPath, destFile);
270     }
271 
272     /**
273      * Adds a file to a ZIP output stream.
274      *
275      * @param srcFile  File to add - Cannot be {@code null}.
276      * @param destPath Path to use for the file - May be {@code null} or empty.
277      * @param out      Destination stream - Cannot be {@code null}.
278      * @throws IOException Error writing to the output stream.
279      */
280     private static void zipFile(final File srcFile, final String destPath, final ZipOutputStream out)
281             throws IOException {
282 
283         final byte[] buf = new byte[1024];
284         try (InputStream in = new BufferedInputStream(Files.newInputStream(srcFile.toPath()))) {
285             final ZipEntry zipEntry = new ZipEntry(concatPathAndFileName(destPath, srcFile.getName(), File.separator));
286             zipEntry.setTime(srcFile.lastModified());
287             out.putNextEntry(zipEntry);
288             int len;
289             while ((len = in.read(buf)) > 0) {
290                 out.write(buf, 0, len);
291             }
292             out.closeEntry();
293         }
294     }
295 
296     /**
297      * Asserts that the array contains the given file names.
298      *
299      * @param files     Array to check.
300      * @param fileNames names File names to find.
301      */
302     protected void assertContains(final FileObject[] files, final String... fileNames) {
303         for (final String fileName : fileNames) {
304             if (!find(files, fileName)) {
305                 fail("File '" + fileName + "' not found in: " + Arrays.asList(files));
306             }
307         }
308     }
309 
310     private boolean find(final FileObject[] files, final String fileName) {
311         for (final FileObject file : files) {
312             final String name = file.getName().getBaseName();
313             if (name.equals(fileName)) {
314                 return true;
315             }
316         }
317         return false;
318     }
319 
320 }