[jboss-svn-commits] JBoss Common SVN: r3934 - in shrinkwrap/trunk: impl-base/src/main/java/org/jboss/shrinkwrap/impl/base and 3 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Tue Jan 19 16:10:37 EST 2010
Author: ALRubinger
Date: 2010-01-19 16:10:36 -0500 (Tue, 19 Jan 2010)
New Revision: 3934
Added:
shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/exporter/ZipExportHandle.java
shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/IsReadReportingInputStream.java
shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExportHandleImpl.java
Modified:
shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/exporter/ZipExporter.java
shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveInputStreamFactory.java
shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipArchiveInputStreamFactory.java
shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExportDelegate.java
shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterImpl.java
shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterTestCase.java
shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImplTestCase.java
Log:
[SHRINKWRAP-116] Avoid OOM and encode as ZIP incrementally as the caller reads
Added: shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/exporter/ZipExportHandle.java
===================================================================
--- shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/exporter/ZipExportHandle.java (rev 0)
+++ shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/exporter/ZipExportHandle.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.shrinkwrap.api.exporter;
+
+import java.io.InputStream;
+
+/**
+ * Handle returned to callers from a request to export via
+ * the {@link ZipExporter}. As the encoding process is an asynchronous
+ * operation, here we provide the user access to read the
+ * content as well as check for completeness and integrity.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ */
+public interface ZipExportHandle
+{
+ /**
+ * Obtains an {@link InputStream} from which the encoded
+ * content may be read.
+ *
+ * @return
+ */
+ InputStream getContent();
+
+ /**
+ * Blocking operation which will wait until the encoding process's internal
+ * streams have been closed and verified for integrity. Do not call this method
+ * until all bytes have been read from {@link ZipExportHandle#getContent()}; otherwise
+ * this may introduce a deadlock. Any problems with the encoding process will be reported
+ * by throwing {@link ArchiveExportException}.
+ * @return
+ * @throws ArchiveExportException If an error occurred during export
+ * @throws IllegalStateException If invoked before {@link ZipExportHandle#getContent()} has been
+ * fully-read
+ */
+ void checkComplete() throws ArchiveExportException, IllegalStateException;
+}
Modified: shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/exporter/ZipExporter.java
===================================================================
--- shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/exporter/ZipExporter.java 2010-01-19 17:32:38 UTC (rev 3933)
+++ shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/exporter/ZipExporter.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -22,7 +22,7 @@
import org.jboss.shrinkwrap.api.Assignable;
/**
- * Exporter used to represent an Archive as a ZIP format.
+ * Exporter used to represent an {@link Assignable} in ZIP format.
*
* @see http://www.pkware.com/documents/casestudies/APPNOTE.TXT
* @author <a href="mailto:baileyje at gmail.com">John Bailey</a>
@@ -37,13 +37,11 @@
//-------------------------------------------------------------------------------------||
/**
- * Exports provided archive as a Zip archive.
+ * Exports this reference as a Zip archive.
*
- * @param archive
* @return {@link InputStream} for exported Zip
- * @throws ArchiveExportException if the export process fails
*/
- InputStream exportZip() throws ArchiveExportException;
+ ZipExportHandle exportZip();
/**
* Exports provided archive as a ZIP archive, written to the
Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveInputStreamFactory.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveInputStreamFactory.java 2010-01-19 17:32:38 UTC (rev 3933)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveInputStreamFactory.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -49,7 +49,7 @@
*
* @throws IllegalArgumentException if the Archive is null
*/
- public static InputStream getInputStream(Archive<?> archive)
+ public static InputStream getInputStream(final Archive<?> archive)
{
Validate.notNull(archive, "archive was not provided");
Added: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/IsReadReportingInputStream.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/IsReadReportingInputStream.java (rev 0)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/IsReadReportingInputStream.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -0,0 +1,116 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.shrinkwrap.impl.base.exporter;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+
+/**
+ * {@link PipedInputStream} which may report whether or not
+ * it has been fully read.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ */
+class IsReadReportingInputStream extends PipedInputStream
+{
+
+ //-------------------------------------------------------------------------------------||
+ // Class Members ----------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Number of bytes read signaling the end has been reached
+ */
+ private static final int EOF = -1;
+
+ //-------------------------------------------------------------------------------------||
+ // Instance Members -------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Flag showing whether or not we've been fully-read
+ */
+ private boolean isRead;
+
+ //-------------------------------------------------------------------------------------||
+ // Constructor ------------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Creates a new Stream
+ */
+ public IsReadReportingInputStream()
+ {
+ super();
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see java.io.PipedInputStream#read()
+ */
+ @Override
+ public synchronized int read() throws IOException
+ {
+ final int bytesRead = super.read();
+ this.markReadOnStreamEnd(bytesRead);
+ return bytesRead;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see java.io.PipedInputStream#read(byte[], int, int)
+ */
+ @Override
+ public synchronized int read(byte[] b, int off, int len) throws IOException
+ {
+ final int bytesRead = super.read(b, off, len);
+ this.markReadOnStreamEnd(bytesRead);
+ return bytesRead;
+ }
+
+ //-------------------------------------------------------------------------------------||
+ // Internal Helper Methods ------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Marks this stream as read
+ * if the number of bytes specified is equal to {@link IsReadReportingInputStream#EOF}
+ */
+ private void markReadOnStreamEnd(final int bytesRead)
+ {
+ if (bytesRead == EOF)
+ {
+ try
+ {
+ isRead = true;
+ }
+ catch (final Exception e)
+ {
+ throw new RuntimeException("Encountered exception in callback", e);
+ }
+ }
+ }
+
+ /**
+ * Returns whether or not this stream has been fully read
+ * @return
+ */
+ boolean isRead()
+ {
+ return isRead;
+ }
+}
Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipArchiveInputStreamFactory.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipArchiveInputStreamFactory.java 2010-01-19 17:32:38 UTC (rev 3933)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipArchiveInputStreamFactory.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -36,7 +36,7 @@
//-------------------------------------------------------------------------------------||
// Required Implementations - ArchiveInputStreamFactory ------------------------------||
//-------------------------------------------------------------------------------------||
-
+
/**
* {@inheritDoc}
* @see org.jboss.shrinkwrap.impl.base.ArchiveInputStreamFactory#doGetInputStream(Archive)
@@ -45,7 +45,7 @@
protected InputStream doGetInputStream(Archive<?> archive)
{
// Get InputStream from the ZipExporter
- final InputStream inputStream = archive.as(ZipExporter.class).exportZip();
+ final InputStream inputStream = archive.as(ZipExporter.class).exportZip().getContent();
// Return input stream
return inputStream;
}
Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExportDelegate.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExportDelegate.java 2010-01-19 17:32:38 UTC (rev 3933)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExportDelegate.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -16,11 +16,16 @@
*/
package org.jboss.shrinkwrap.impl.base.exporter;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedOutputStream;
import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
@@ -28,16 +33,17 @@
import java.util.zip.ZipOutputStream;
import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
import org.jboss.shrinkwrap.api.Asset;
-import org.jboss.shrinkwrap.api.ArchivePath;
import org.jboss.shrinkwrap.api.exporter.ArchiveExportException;
+import org.jboss.shrinkwrap.api.exporter.ZipExportHandle;
import org.jboss.shrinkwrap.impl.base.asset.DirectoryAsset;
import org.jboss.shrinkwrap.impl.base.io.IOUtil;
import org.jboss.shrinkwrap.impl.base.io.StreamErrorHandler;
import org.jboss.shrinkwrap.impl.base.io.StreamTask;
import org.jboss.shrinkwrap.impl.base.path.PathUtil;
-public class ZipExportDelegate extends AbstractExporterDelegate<InputStream>
+public class ZipExportDelegate extends AbstractExporterDelegate<ZipExportHandle>
{
//-------------------------------------------------------------------------------------||
// Class Members ----------------------------------------------------------------------||
@@ -48,19 +54,28 @@
*/
private static final Logger log = Logger.getLogger(ZipExportDelegate.class.getName());
+ /**
+ * Services used to submit new jobs (encoding occurs in a separate Thread)
+ */
+ private static final ExecutorService service;
+ static
+ {
+ service = Executors.newCachedThreadPool();
+ }
+
//-------------------------------------------------------------------------------------||
// Instance Members -------------------------------------------------------------------||
//-------------------------------------------------------------------------------------||
/**
- * OutputStream to hold the output contents
+ * ZipOutputStream used to write the zip entries
*/
- private final ByteArrayOutputStream output = new ByteArrayOutputStream(8192);
+ private ZipOutputStream zipOutputStream;
/**
- * ZipOutputStream used to write the zip entries
+ * Handle to be returned to the caller
*/
- private ZipOutputStream zipOutputStream;
+ private ZipExportHandle handle;
/**
* A Set of Paths we've exported so far (so that we don't write
@@ -88,30 +103,61 @@
* {@inheritDoc}
* @see org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate#export()
*/
- @Override
protected void export()
{
- zipOutputStream = new ZipOutputStream(output);
- // Enclose every IO Operation so we can close up cleanly
- IOUtil.closeOnComplete(zipOutputStream, new StreamTask<ZipOutputStream>()
+
+ // Define the task to operate in another Thread so we can pipe the output to an InStream
+ final Callable<Void> exportTask = new Callable<Void>()
{
@Override
- public void execute(ZipOutputStream stream) throws Exception
+ public Void call() throws Exception
{
- ZipExportDelegate.super.export();
+ try
+ {
+ ZipExportDelegate.super.export();
+ }
+ finally
+ {
+ try
+ {
+ zipOutputStream.close();
+ }
+ catch (final IOException ioe)
+ {
+ // Ignore
+ log.warning("Got exception on closing the ZIP out stream: " + ioe.getMessage());
+ }
+ }
+
+ return null;
}
+ };
- }, new StreamErrorHandler()
+ // Stream to return to the caller
+ final IsReadReportingInputStream input = new IsReadReportingInputStream();
+
+ /**
+ * OutputStream which will be associated with the returned InStream, and the
+ * chained IO point for the Zip OutStrea,
+ */
+ final OutputStream output;
+ try
{
+ output = new PipedOutputStream(input);
+ }
+ catch (final IOException e)
+ {
+ throw new RuntimeException("Error in setting up output stream", e);
+ }
- @Override
- public void handle(Throwable t)
- {
- throw new ArchiveExportException("Failed to export Zip: " + getArchive().getName(), t);
- }
+ // Set up the stream to which we'll write entries, backed by the piped stream
+ zipOutputStream = new ZipOutputStream(output);
- });
+ // Get a handle and return it to the caller
+ final Future<Void> job = service.submit(exportTask);
+ final ZipExportHandle handle = new ZipExportHandleImpl(input, job);
+ this.handle = handle;
}
/**
@@ -127,11 +173,11 @@
throw new IllegalArgumentException("Path must be specified");
}
- if(isParentOfAnyPathsExported(path))
+ if (isParentOfAnyPathsExported(path))
{
return;
}
-
+
/*
* SHRINKWRAP-94
* Add entries for all parents of this Path
@@ -179,12 +225,13 @@
final ZipEntry entry = new ZipEntry(resolvedPath);
// Write the Asset under the same Path name in the Zip
- try{
+ try
+ {
zipOutputStream.putNextEntry(entry);
}
- catch(final ZipException ze)
+ catch (final ZipException ze)
{
- log.log(Level.SEVERE,pathsExported.toString());
+ log.log(Level.SEVERE, pathsExported.toString());
throw new RuntimeException(ze);
}
@@ -219,22 +266,11 @@
* @see org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate#getResult()
*/
@Override
- protected InputStream getResult()
+ protected ZipExportHandle getResult()
{
- // Flush the output to a byte array
- final byte[] zipContent = output.toByteArray();
- if (log.isLoggable(Level.FINE))
- {
- log.fine("Created Zip of size: " + zipContent.length + " bytes");
- }
+ return handle;
+ }
- // Make an instream
- final InputStream inputStream = new ByteArrayInputStream(zipContent);
-
- // Return
- return inputStream;
- }
-
/**
* Returns whether or not this Path is a parent of any Paths exported
* @param path
@@ -244,35 +280,37 @@
private boolean isParentOfAnyPathsExported(final ArchivePath path)
{
// For all Paths already exported
- for(final ArchivePath exportedPath :this.pathsExported)
+ for (final ArchivePath exportedPath : this.pathsExported)
{
- if( this.isParentOfSpecifiedHierarchy(path, exportedPath)){
+ if (this.isParentOfSpecifiedHierarchy(path, exportedPath))
+ {
return true;
}
}
-
+
return false;
}
-
+
/**
*
* @param path
* @param compare
* @return
*/
- private boolean isParentOfSpecifiedHierarchy(final ArchivePath path,final ArchivePath compare){
+ private boolean isParentOfSpecifiedHierarchy(final ArchivePath path, final ArchivePath compare)
+ {
// If we've reached the root, we're not a parent of any paths already exported
final ArchivePath parent = PathUtil.getParent(compare);
- if(parent==null)
+ if (parent == null)
{
return false;
}
// If equal to me, yes
- if(path.equals(compare))
+ if (path.equals(compare))
{
return true;
}
-
+
// Check my parent
return this.isParentOfSpecifiedHierarchy(path, parent);
}
Added: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExportHandleImpl.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExportHandleImpl.java (rev 0)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExportHandleImpl.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -0,0 +1,136 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.shrinkwrap.impl.base.exporter;
+
+import java.io.InputStream;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.logging.Logger;
+
+import org.jboss.shrinkwrap.api.exporter.ArchiveExportException;
+import org.jboss.shrinkwrap.api.exporter.ZipExportHandle;
+
+/**
+ * Implementation of a {@link ZipExportHandle}
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ */
+class ZipExportHandleImpl implements ZipExportHandle
+{
+ //-------------------------------------------------------------------------------------||
+ // Instance Members -------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Contents of the export process
+ */
+ private final IsReadReportingInputStream content;
+
+ /**
+ * Underlying job carrying out the encoding process; we never expose
+ * this because if the user blocks on {@link Future#get()} than this could
+ * deadlock the process (the writer Thread would be waiting for the reader Thread
+ * to pull off the buffer). So just provide a mechanism for the caller to see
+ * if we're done, and if there was an exception raised via {@link ZipExportHandle#isDone()}
+ */
+ private final Future<Void> job;
+
+ //-------------------------------------------------------------------------------------||
+ // Constructor ------------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Creates a new handle with the specified content and pointer to the encoding
+ * job. Both arguments must be specified.
+ */
+ ZipExportHandleImpl(final IsReadReportingInputStream content, final Future<Void> job)
+ {
+ // Precondition checks
+ assert content != null : "Contents must be specified";
+ assert job != null : "job must be specified";
+
+ // Set
+ final Logger log = Logger.getAnonymousLogger();
+ log.info("Content: " + content + "; JOB: " + job);
+ this.content = content;
+ this.job = job;
+ }
+
+ //-------------------------------------------------------------------------------------||
+ // Required Implementations -----------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * @see org.jboss.shrinkwrap.api.exporter.ZipExportHandle#getContent()
+ */
+ @Override
+ public InputStream getContent()
+ {
+ return content;
+ }
+
+ /**
+ * @see org.jboss.shrinkwrap.api.exporter.ZipExportHandle#checkComplete()
+ */
+ @Override
+ public void checkComplete() throws ArchiveExportException, IllegalStateException
+ {
+ // Ensure we can be called; the Stream must have been fully-read
+ if (!this.content.isRead())
+ {
+ throw new IllegalStateException(
+ "Cannot invoke until the stream has been fully-read; otherwise we might lead to deadlock");
+ }
+
+ // See if we're done
+ final boolean done = job.isDone();
+
+ // If done (either completed or exception)
+ if (done)
+ {
+ try
+ {
+ // Block until the streams have been closed in the underlying job
+ job.get();
+ }
+ catch (final InterruptedException e)
+ {
+ Thread.interrupted();
+ }
+ // Some error
+ catch (final ExecutionException ee)
+ {
+ // Unwrap and rethrow
+ final Throwable cause = ee.getCause();
+ if (cause == null)
+ {
+ throw new IllegalStateException("Cause of execution failure not specified: ", ee);
+ }
+ // Wrap as our exception type and rethrow
+ throw new ArchiveExportException(cause);
+ }
+ }
+
+ // Return
+ return;
+ }
+}
Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterImpl.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterImpl.java 2010-01-19 17:32:38 UTC (rev 3933)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterImpl.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -27,6 +27,7 @@
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.exporter.ArchiveExportException;
import org.jboss.shrinkwrap.api.exporter.FileExistsException;
+import org.jboss.shrinkwrap.api.exporter.ZipExportHandle;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.impl.base.AssignableBase;
import org.jboss.shrinkwrap.impl.base.Validate;
@@ -89,7 +90,7 @@
* @see org.jboss.shrinkwrap.api.exporter.ZipExporter#exportZip()
*/
@Override
- public InputStream exportZip()
+ public ZipExportHandle exportZip()
{
// Create export delegate
ZipExportDelegate exportDelegate = new ZipExportDelegate(archive);
@@ -97,10 +98,10 @@
// Execute export
exportDelegate.export();
// Get results
- InputStream inputStream = exportDelegate.getResult();
+ ZipExportHandle handle = exportDelegate.getResult();
- // Return input stream
- return inputStream;
+ // Return
+ return handle;
}
/**
@@ -124,7 +125,8 @@
}
// Get Streams
- final InputStream in = this.exportZip();
+ final ZipExportHandle handle = this.exportZip();
+ final InputStream in = handle.getContent();
final OutputStream out;
try
{
@@ -145,6 +147,8 @@
throw new ArchiveExportException("Error encountered in exporting archive to " + target.getAbsolutePath(), e);
}
+ // Ensure done and no exceptions (this also will throw ArchiveExportException)
+ handle.checkComplete();
}
/**
Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterTestCase.java 2010-01-19 17:32:38 UTC (rev 3933)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterTestCase.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -34,6 +34,7 @@
import org.jboss.shrinkwrap.api.Asset;
import org.jboss.shrinkwrap.api.exporter.ArchiveExportException;
import org.jboss.shrinkwrap.api.exporter.FileExistsException;
+import org.jboss.shrinkwrap.api.exporter.ZipExportHandle;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.impl.base.asset.ByteArrayAsset;
@@ -82,16 +83,39 @@
Archive<?> archive = createArchiveWithAssets();
// Export as Zip InputStream
- InputStream zipStream = archive.as(ZipExporter.class).exportZip();
+ final ZipExportHandle handle = archive.as(ZipExporter.class).exportZip();
+ final InputStream zipStream = handle.getContent();
// Write zip content to temporary file
ZipFile expectedZip = getExportedZipFile(NAME_ARCHIVE, zipStream, tempDirectory);
+ // Ensure all's OK
+ handle.checkComplete();
+
// Validate
ensureZipFileInExpectedForm(expectedZip);
}
/**
+ * Test to make sue an archive can be exported to Zip and all contents are correctly located in the Zip.
+ * @throws Exception
+ */
+ @Test(expected = IllegalStateException.class)
+ public void checkCompleteBeforeReadingContents() throws Exception
+ {
+ log.info("checkCompleteBeforeReadingContents");
+
+ // Get an archive instance
+ Archive<?> archive = createArchiveWithAssets();
+
+ // Export as Zip InputStream
+ final ZipExportHandle handle = archive.as(ZipExporter.class).exportZip();
+ // We cannot check complete until we fully read the instream from the handle
+ handle.checkComplete();
+
+ }
+
+ /**
* Ensures that we can export archives of large sizes without
* leading to {@link OutOfMemoryError}
*/
@@ -203,7 +227,7 @@
Archive<?> archive = createArchiveWithNestedArchives();
// Export as Zip InputStream
- InputStream zipStream = archive.as(ZipExporter.class).exportZip();
+ InputStream zipStream = archive.as(ZipExporter.class).exportZip().getContent();
// Write out and retrieve Zip
ZipFile expectedZip = getExportedZipFile(NAME_ARCHIVE, zipStream, tempDirectory);
@@ -251,7 +275,7 @@
}
@Test(expected = ArchiveExportException.class)
- public void testExportThrowsArchiveExceptionOnAssetWriteFailure()
+ public void testExportThrowsArchiveExceptionOnAssetWriteFailure() throws IOException
{
log.info("testExportThrowsArchiveExcepitonOnAssetWriteFailure");
Archive<?> archive = createArchiveWithAssets();
@@ -266,7 +290,23 @@
}, PATH_ONE);
- archive.as(ZipExporter.class).exportZip();
+ // Export
+ final ZipExportHandle handle = archive.as(ZipExporter.class).exportZip();
+
+ // Read in the full content (to in turn empty the underlying buffer and ensure we complete)
+ final InputStream in = handle.getContent();
+ final OutputStream sink = new OutputStream()
+ {
+
+ @Override
+ public void write(int b) throws IOException
+ {
+ }
+ };
+ IOUtil.copyWithClose(in, sink);
+ // Get access to the underlying exception
+ handle.checkComplete();
+
}
//-------------------------------------------------------------------------------------||
Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImplTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImplTestCase.java 2010-01-19 17:32:38 UTC (rev 3933)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImplTestCase.java 2010-01-19 21:10:36 UTC (rev 3934)
@@ -114,7 +114,7 @@
File tempFile = new File("target/test.zip");
tempFile.deleteOnExit();
- InputStream zipStream = archive.as(ZipExporter.class).exportZip();
+ InputStream zipStream = archive.as(ZipExporter.class).exportZip().getContent();
IOUtil.copyWithClose(zipStream, new FileOutputStream(tempFile));
assertContent(archive, tempFile.toURI());
More information about the jboss-svn-commits
mailing list