|
16 | 16 |
|
17 | 17 | package com.google.cloud.dataflow.sdk.util; |
18 | 18 |
|
| 19 | +import static com.google.common.base.Preconditions.checkArgument; |
| 20 | +import static com.google.common.base.Preconditions.checkNotNull; |
| 21 | + |
19 | 22 | import com.google.api.client.util.BackOff; |
20 | 23 | import com.google.api.client.util.BackOffUtils; |
21 | 24 | import com.google.api.client.util.Sleeper; |
|
36 | 39 |
|
37 | 40 | import java.io.File; |
38 | 41 | import java.io.IOException; |
| 42 | +import java.io.OutputStream; |
39 | 43 | import java.nio.channels.Channels; |
40 | 44 | import java.nio.channels.WritableByteChannel; |
41 | 45 | import java.nio.charset.StandardCharsets; |
@@ -253,46 +257,84 @@ private static String computeContentHash(File classpathElement) throws IOExcepti |
253 | 257 | private static void copyContent(String classpathElement, WritableByteChannel outputChannel) |
254 | 258 | throws IOException { |
255 | 259 | final File classpathElementFile = new File(classpathElement); |
256 | | - if (!classpathElementFile.isDirectory()) { |
| 260 | + if (classpathElementFile.isDirectory()) { |
| 261 | + zipDirectory(classpathElementFile, Channels.newOutputStream(outputChannel)); |
| 262 | + } else { |
257 | 263 | Files.asByteSource(classpathElementFile).copyTo(Channels.newOutputStream(outputChannel)); |
258 | | - return; |
259 | 264 | } |
| 265 | + } |
260 | 266 |
|
261 | | - ZipOutputStream zos = new ZipOutputStream(Channels.newOutputStream(outputChannel)); |
262 | | - zipDirectoryRecursive(classpathElementFile, classpathElementFile, zos); |
| 267 | + /** |
| 268 | + * Zips an entire directory specified by the path. |
| 269 | + * |
| 270 | + * @param sourceDirectory the directory to read from. This directory and all |
| 271 | + * subdirectories will be added to the zip-file. The path within the zip |
| 272 | + * file is relative to the directory given as parameter, not absolute. |
| 273 | + * @param outputStream the stream to write the zip-file to. This method does not close |
| 274 | + * outputStream. |
| 275 | + * @throws IOException the zipping failed, e.g. because the input was not |
| 276 | + * readable. |
| 277 | + */ |
| 278 | + private static void zipDirectory( |
| 279 | + File sourceDirectory, |
| 280 | + OutputStream outputStream) throws IOException { |
| 281 | + checkNotNull(sourceDirectory); |
| 282 | + checkNotNull(outputStream); |
| 283 | + checkArgument( |
| 284 | + sourceDirectory.isDirectory(), |
| 285 | + "%s is not a valid directory", |
| 286 | + sourceDirectory.getAbsolutePath()); |
| 287 | + ZipOutputStream zos = new ZipOutputStream(outputStream); |
| 288 | + for (File file : sourceDirectory.listFiles()) { |
| 289 | + zipDirectoryInternal(file, "", zos); |
| 290 | + } |
263 | 291 | zos.finish(); |
264 | 292 | } |
265 | 293 |
|
266 | 294 | /** |
267 | | - * Private helper function for zipping files. This one goes recursively through the input |
268 | | - * directory and all of its subdirectories and adds the single zip entries. |
| 295 | + * Private helper function for zipping files. This one goes recursively |
| 296 | + * through the input directory and all of its subdirectories and adds the |
| 297 | + * single zip entries. |
269 | 298 | * |
270 | | - * @param file the file or directory to be added to the zip file. |
271 | | - * @param root each file uses the root directory to generate its relative path within the zip. |
272 | | - * @param zos the zipstream to write to. |
273 | | - * @throws IOException the zipping failed, e.g. because the output was not writable. |
| 299 | + * @param inputFile the file or directory to be added to the zip file |
| 300 | + * @param directoryName the string-representation of the parent directory |
| 301 | + * name. Might be an empty name, or a name containing multiple directory |
| 302 | + * names separated by "/". The directory name must be a valid name |
| 303 | + * according to the file system limitations. |
| 304 | + * @param zos the zipstream to write to |
| 305 | + * @throws IOException the zipping failed, e.g. because the output was not |
| 306 | + * writeable. |
274 | 307 | */ |
275 | | - private static void zipDirectoryRecursive(File file, File root, ZipOutputStream zos) |
276 | | - throws IOException { |
277 | | - final String entryName = relativize(file, root); |
278 | | - if (file.isDirectory()) { |
279 | | - // We are hitting a directory. Start the recursion. |
280 | | - // Add the empty entry if it is a subdirectory and the subdirectory has no children. |
281 | | - // Don't add it otherwise, as this is incompatible with certain implementations of unzip. |
282 | | - if (file.list().length == 0 && !file.equals(root)) { |
| 308 | + private static void zipDirectoryInternal( |
| 309 | + File inputFile, |
| 310 | + String directoryName, |
| 311 | + ZipOutputStream zos) throws IOException { |
| 312 | + final String entryName; |
| 313 | + if ("".equals(directoryName)) { |
| 314 | + // no parent directories yet. |
| 315 | + entryName = inputFile.getName(); |
| 316 | + } else { |
| 317 | + entryName = directoryName + "/" + inputFile.getName(); |
| 318 | + } |
| 319 | + if (inputFile.isDirectory()) { |
| 320 | + // We are hitting a sub-directory. Start the recursion. |
| 321 | + // Add the empty entry for a subdirectory if we have no children files. |
| 322 | + // Don't add it if we have them, as this is incompatible with certain |
| 323 | + // implementations of unzip. |
| 324 | + if (inputFile.list().length == 0) { |
283 | 325 | ZipEntry entry = new ZipEntry(entryName + "/"); |
284 | 326 | zos.putNextEntry(entry); |
285 | 327 | } else { |
286 | 328 | // loop through the directory content, and zip the files |
287 | | - for (File currentFile : file.listFiles()) { |
288 | | - zipDirectoryRecursive(currentFile, root, zos); |
| 329 | + for (File file : inputFile.listFiles()) { |
| 330 | + zipDirectoryInternal(file, entryName, zos); |
289 | 331 | } |
290 | 332 | } |
291 | 333 | } else { |
292 | 334 | // Put the next zip-entry into the zipoutputstream. |
293 | 335 | ZipEntry entry = new ZipEntry(entryName); |
294 | 336 | zos.putNextEntry(entry); |
295 | | - Files.asByteSource(file).copyTo(zos); |
| 337 | + Files.asByteSource(inputFile).copyTo(zos); |
296 | 338 | } |
297 | 339 | } |
298 | 340 |
|
|
0 commit comments