From 81962db0ef46ebcf57f2ef9a44c8fc9d5d9d4898 Mon Sep 17 00:00:00 2001
From: Thorsten Vitt <thorsten.vitt@uni-wuerzburg.de>
Date: Mon, 2 Jun 2014 18:18:31 +0200
Subject: [PATCH] Add all missing directory entries to zip output.

---
 .../services/aggregator/zip/ZipResult.java    | 56 ++++++++++++++++---
 1 file changed, 49 insertions(+), 7 deletions(-)

diff --git a/src/main/java/info/textgrid/services/aggregator/zip/ZipResult.java b/src/main/java/info/textgrid/services/aggregator/zip/ZipResult.java
index 5b0c31e..6ae5d63 100644
--- a/src/main/java/info/textgrid/services/aggregator/zip/ZipResult.java
+++ b/src/main/java/info/textgrid/services/aggregator/zip/ZipResult.java
@@ -297,10 +297,10 @@ private boolean isAllowedFormat(final String format) {
 
 	private void writeFile(final ZipOutputStream zip,
 			final ImportEntry importEntry) throws IOException {
-		
+
 		writeMetadata(zip, importEntry);
-		
-		
+		writeMissingDirectories(zip, importEntry.getLocalData(), importEntry.getLastModified());
+
 		final ZipEntry zipEntry = new ZipEntry(importEntry.getLocalData());
 		zipEntry.setTime(importEntry.getTreeEntry().getMetadata().getGeneric()
 				.getGenerated().getLastModified().toGregorianCalendar()
@@ -309,7 +309,7 @@ private void writeFile(final ZipOutputStream zip,
 		try {
 			final InputStream content = repository.getContent(importEntry
 					.getTreeEntry().getTextGridURI(), getSid().orNull());
-			
+
 			// Content options:
 			// (1) Transformation, e.g. to text. Only for xml and if configured.
 			if (transformation.isPresent()
@@ -327,8 +327,9 @@ private void writeFile(final ZipOutputStream zip,
 				transformer.setSource(source);
 				transformer.setDestination(serializer);
 				transformer.transform();
-				
-			// (2) Link rewriting, using XML. Only if rewrite method configured.
+
+				// (2) Link rewriting, using XML. Only if rewrite method
+				// configured.
 			} else if (importEntry.getRewriteMethod().equals(RewriteMethod.XML)) {
 				final ConfigurableXMLRewriter rewriter = new ConfigurableXMLRewriter(
 						mapping, true);
@@ -371,7 +372,9 @@ private void writeMetadata(final ZipOutputStream zip,
 			final ImportEntry importEntry) throws IOException {
 		if (!includeMeta)
 			return;
-
+		
+		writeMissingDirectories(zip, importEntry.getLocalMetadata(), importEntry.getLastModified());
+		
 		final ZipEntry zipEntry = new ZipEntry(importEntry.getLocalMetadata());
 		zipEntry.setTime(importEntry.getLastModified());
 		zip.putNextEntry(zipEntry);
@@ -397,4 +400,43 @@ private void writeMetadata(final ZipOutputStream zip,
 		}
 		zip.closeEntry();
 	}
+
+	private final Set<String> writtenDirectoryNames = Sets.newHashSet();
+
+	/**
+	 * This writes 'parent directory' entries to the zip stream for all
+	 * directory names required for the given filename.
+	 * 
+	 * @param zip
+	 *            The zip stream.
+	 * @param filename
+	 *            The filename for which to create directory entries
+	 * @param lastModified
+	 *            The modification date to use for the directory entries created
+	 *            in this step.
+	 */
+	private void writeMissingDirectories(final ZipOutputStream zip,
+			final String filename, final long lastModified) {
+		String[] components = filename.split("/");
+		StringBuilder dir = new StringBuilder();
+		for (int i = 0; i < components.length - 1; i++) {
+			dir.append(components[i]).append('/');
+			String path = dir.toString();
+			if (!writtenDirectoryNames.contains(path)) {
+				ZipEntry zipEntry = new ZipEntry(path);
+				zipEntry.setTime(lastModified);
+				writtenDirectoryNames.add(path);
+				try {
+					zip.putNextEntry(zipEntry);
+					zip.closeEntry();
+				} catch (IOException e) {
+					logger.log(
+							Level.WARNING,
+							MessageFormat
+									.format("Failed to write parent directory entry {0} for {1}. Skipping.",
+											path, filename), e);
+				}
+			}
+		}
+	}
 }
-- 
GitLab