diff options
author | sliebig | 2007-11-06 14:29:04 +0000 |
---|---|---|
committer | sliebig | 2007-11-06 14:29:04 +0000 |
commit | 2badfd3121cad9b9859a3287cc08b9b4cd07ba93 (patch) | |
tree | 02719b15cd4ac631a6d8ffdca0367711ee64078f /bundles/org.eclipse.equinox.p2.sar/src/org | |
parent | 163fb6a827a525bfe749276a9ee61547b5e46afa (diff) | |
download | rt.equinox.p2-2badfd3121cad9b9859a3287cc08b9b4cd07ba93.tar.gz rt.equinox.p2-2badfd3121cad9b9859a3287cc08b9b4cd07ba93.tar.xz rt.equinox.p2-2badfd3121cad9b9859a3287cc08b9b4cd07ba93.zip |
initial load
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.sar/src/org')
7 files changed, 943 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/Activator.java b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/Activator.java new file mode 100644 index 000000000..9874234f0 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/Activator.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2007 compeople AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * compeople AG (Stefan Liebig) - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.sar; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + } + +} diff --git a/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/DirectByteArrayOutputStream.java b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/DirectByteArrayOutputStream.java new file mode 100644 index 000000000..ab610b31a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/DirectByteArrayOutputStream.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2007 compeople AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * compeople AG (Stefan Liebig) - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.sar; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +/** + * The DirectByteArrayOutputStream discloses its guts (internal byte buffer and + * byte buffer length) to avoid unnecessary allocation of byte arrays usually + * involved with toByteArray(). + */ +public class DirectByteArrayOutputStream extends ByteArrayOutputStream { + + /** + * Creates a new direct byte array output stream. The buffer capacity is + * initially as defined by super class. + */ + public DirectByteArrayOutputStream() { + super(); + } + + /** + * Creates a new byte array output stream, with a buffer capacity of the + * specified size, in bytes. + * + * @param size + * the initial size. + * @throws IllegalArgumentException + * if size is negative. + */ + public DirectByteArrayOutputStream(int size) { + super(size); + } + + /** + * Return the actual internal byte buffer. + * + * @return internal byte buffer + */ + public final byte[] getBuffer() { + return super.buf; + } + + /** + * Return the actual length of the internal byte buffer. + * + * @return actual length of the buffer + */ + public final int getBufferLength() { + return super.count; + } + + /** + * Return an input stream containing all the (shared) bytes this output + * stream has already consumed. + * + * @return + */ + public ByteArrayInputStream getInputStream() { + return new ByteArrayInputStream(super.buf, 0, super.count); + } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarConstants.java b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarConstants.java new file mode 100644 index 000000000..216cb418c --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarConstants.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2007 compeople AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * compeople AG (Stefan Liebig) - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.sar; + +/** + * Sar constants + */ +public interface SarConstants { + + /** <code>SARFILE_MARKER</code> */ + String SARFILE_MARKER = "SarFile"; + + /** <code>SARFILE_VERSION</code> */ + int SARFILE_VERSION = 2; + + /** + * Comment for <code>DEFAULT_ENCODING</code> + */ + String DEFAULT_ENCODING = "UTF-8"; + + /** + * Debug + */ + boolean DEBUG = false; +} diff --git a/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarEntry.java b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarEntry.java new file mode 100644 index 000000000..4644cdda0 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarEntry.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2007 compeople AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * compeople AG (Stefan Liebig) - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.sar; + +import java.io.IOException; +import java.util.zip.ZipEntry; + +/** + * A SarEntry is the header information for an entry within a org.eclipse.equinox.p2.sar stream. + */ +public class SarEntry extends ZipEntry { + + private boolean isEof; + private boolean isZip; + + /** + * The name of the eof org.eclipse.equinox.p2.sar entry. + */ + private static final String EOF_ENTRY_NAME = "<eof-org.eclipse.equinox.p2.sar>"; + + private static final boolean DEBUG = SarConstants.DEBUG; + + /** + * Creates an eof org.eclipse.equinox.p2.sar entry + */ + public SarEntry() { + super( EOF_ENTRY_NAME ); + setMethod( ZipEntry.DEFLATED ); + this.isEof = true; + this.isZip = false; + } + + /** + * @param zipEntry + */ + public SarEntry( ZipEntry zipEntry ) { + super( zipEntry ); + this.isZip = false; + this.isEof = false; + } + + /** + * @param zipEntry + * @param isZip + */ + public SarEntry( ZipEntry zipEntry, boolean isZip ) { + super( zipEntry ); + this.isZip = isZip; + this.isEof = false; + } + + /** + * @param sarInputStream + * @throws IOException + */ + public SarEntry( SarInputStream sarInputStream ) throws IOException { + // read name! + super( sarInputStream.readString() ); + + String comment = sarInputStream.readString(); + long compressedSize = sarInputStream.readLong(); + long crc = sarInputStream.readLong(); + byte[] extra = sarInputStream.readBytes(); + int method = sarInputStream.readInt(); + long size = sarInputStream.readLong(); + long time = sarInputStream.readLong(); + boolean isEof = sarInputStream.readBoolean(); + boolean isZip = sarInputStream.readBoolean(); + + if ( DEBUG ) { + System.out.println( getName() + "," + comment + "," + compressedSize + "," + crc + "," + extra + "," + method + "," + size + "," + time + "," + + isEof + "," + isZip ); + } + + if ( method == ZipEntry.STORED ) { + setCompressedSize( compressedSize ); + setCrc( crc ); + setSize( size ); + } + + setComment( comment ); + setExtra( extra ); + setMethod( method ); + setTime( time ); + setEof( isEof ); + setZip( isZip ); + } + + /** + * @param sarOutputStream + * @throws IOException + */ + public void writeTo( SarOutputStream sarOutputStream ) throws IOException { + String comment = this.getComment(); + long compressedSize = this.getCompressedSize(); + long crc = this.getCrc(); + byte[] extra = this.getExtra(); + int method = this.getMethod(); + String name = this.getName(); + long size = this.getSize(); + long time = this.getTime(); + boolean isZip = this.isZip(); + boolean isEof = this.isEof(); + + if ( DEBUG ) { + System.out.println( name + "," + comment + "," + compressedSize + "," + crc + "," + extra + "," + method + "," + size + "," + time + "," + isEof + + "," + isZip ); + } + + sarOutputStream.writeString( name ); + sarOutputStream.writeString( comment ); + sarOutputStream.writeLong( compressedSize ); + sarOutputStream.writeLong( crc ); + sarOutputStream.writeBytes( extra ); + sarOutputStream.writeInt( method ); + sarOutputStream.writeLong( size ); + sarOutputStream.writeLong( time ); + sarOutputStream.writeBool( isEof ); + sarOutputStream.writeBool( isZip ); + } + + /** + * Is this the eof org.eclipse.equinox.p2.sar entry? + * + * @return the answer + */ + public boolean isEof() { + return isEof; + } + + private void setEof( boolean isEof ) { + this.isEof = isEof; + } + + /** + * @return + */ + public boolean isZip() { + return isZip; + } + + /** + * @param isZip + */ + private void setZip( boolean isZip ) { + this.isZip = isZip; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarInputStream.java b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarInputStream.java new file mode 100644 index 000000000..f69916d9a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarInputStream.java @@ -0,0 +1,207 @@ +/******************************************************************************* + * Copyright (c) 2007 compeople AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * compeople AG (Stefan Liebig) - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.sar; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * The SarInputStream reads a streaming archive as an InputStream. Methods are + * provided to position at each successive entry in the archive, and the read + * each entry as a normal input stream using read(). + */ +public class SarInputStream extends InputStream { + + private final DataInputStream dataInputStream; + private final int version; + private InputStream contentStream; + + /** + * Constructor for SarInputStream. + * + * @param inputStream + * the input stream to use + * @throws IOException + */ + public SarInputStream(InputStream inputStream) throws IOException { + + this.dataInputStream = new DataInputStream(inputStream); + + // SarFile marker + String marker = readString(); + if (!marker.equals(SarConstants.SARFILE_MARKER)) { + throw new IOException( + "Does not contain org.eclipse.equinox.p2.sar marker."); + } + + // SarFile version + version = dataInputStream.readInt(); + if (version != SarConstants.SARFILE_VERSION) { + throw new IOException("Unsupported version."); + } + } + + /** + * Closes this stream. + * + * @throws IOException + * on error + */ + public void close() throws IOException { + dataInputStream.close(); + } + + /** + * Since we do not support marking just yet, we return false. + * + * @return False. + */ + public boolean markSupported() { + return false; + } + + /** + * Since we do not support marking just yet, we do nothing. + * + * @param markLimit + * The limit to mark. + */ + public void mark(int markLimit) { + // nothing + } + + /** + * Since we do not support marking just yet, we do nothing. + */ + public void reset() { + // nothing + } + + /** + * Get the next entry in this org.eclipse.equinox.p2.sar archive. This will skip + * over any remaining data in the current entry, if there is one, and place + * the input stream at the header of the next entry, and read the header and + * instantiate a new SarEntry from the header bytes and return that entry. + * If there are no more entries in the archive, null will be returned to + * indicate that the end of the archive has been reached. + * + * @return the next SarEntry in the archive, or null. + * @throws IOException + * on error + */ + public SarEntry getNextEntry() throws IOException { + SarEntry sarEntry = new SarEntry(this); + if (sarEntry.isEof()) + return null; + + byte[] content = readBytes(); + contentStream = new ByteArrayInputStream(content); + return sarEntry; + + } + + /** + * Close the entry. + * + * @throws IOException + */ + public void closeEntry() throws IOException { + contentStream.close(); + } + + /** + * @return + * @throws IOException + */ + String readString() throws IOException { + byte[] bytes = readBytes(); + if (bytes == null) + return null; + + return new String(bytes, SarConstants.DEFAULT_ENCODING); + } + + /** + * @return + * @throws IOException + */ + byte[] readBytes() throws IOException { + int length = dataInputStream.readInt(); + if (length == -1) + return null; + + byte[] bytes = new byte[length]; + dataInputStream.readFully(bytes, 0, length); + return bytes; + } + + /** + * @return + * @throws IOException + */ + int readInt() throws IOException { + return dataInputStream.readInt(); + } + + /** + * @return + * @throws IOException + */ + boolean readBoolean() throws IOException { + return dataInputStream.readBoolean(); + } + + /** + * @return + * @throws IOException + */ + long readLong() throws IOException { + return dataInputStream.readLong(); + } + + /** + * Reads a byte from the current tar archive entry. + * + * This method simply calls read( byte[], int, int ). + * + * @return The byte read, or -1 at EOF. + * @throws IOException + * on error + */ + public int read() throws IOException { + return contentStream.read(); + } + + /** + * Reads bytes from the current tar archive entry. + * + * This method is aware of the boundaries of the current entry in the + * archive and will deal with them as if they were this stream's start and + * EOF. + * + * @param buffer + * The buffer into which to place bytes read. + * @param offset + * The offset at which to place bytes read. + * @param numToRead + * The number of bytes to read. + * @return The number of bytes read, or -1 at EOF. + * @throws IOException + * on error + */ + public int read(byte[] buffer, int offset, int numToRead) + throws IOException { + return contentStream.read(buffer, offset, numToRead); + } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarOutputStream.java b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarOutputStream.java new file mode 100644 index 000000000..14fa07503 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarOutputStream.java @@ -0,0 +1,208 @@ +/******************************************************************************* + * Copyright (c) 2007 compeople AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * compeople AG (Stefan Liebig) - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.sar; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * The SarOutputStream writes a stream archive as an OutputStream. Methods are + * provided to put entries, and then write their contents by writing to this + * stream using write(). + */ +public class SarOutputStream extends OutputStream { + + private boolean finished; + private final DataOutputStream dataOutputStream; + private final DirectByteArrayOutputStream entryContent; + + /** + * @param outputStream + * @throws IOException + */ + public SarOutputStream(OutputStream outputStream) throws IOException { + dataOutputStream = new DataOutputStream(outputStream); + entryContent = new DirectByteArrayOutputStream(16 * 1024); + writeString(SarConstants.SARFILE_MARKER); + dataOutputStream.writeInt(SarConstants.SARFILE_VERSION); + finished = false; + } + + /** + * Ends the SAR archive and closes the underlying OutputStream. + * + * @see java.io.Closeable#close() + */ + // @Override + public void close() throws IOException { + finish(); + super.close(); + } + + /** + * Finish this SAR archive but does not close the underlying output stream. + * + * @throws IOException + */ + public void finish() throws IOException { + if (finished) + return; + + writeEOFRecord(); + finished = true; + } + + /** + * Put an entry on the output stream. This writes the entry's header record + * and positions the output stream for writing the contents of the entry. + * Once this method is called, the stream is ready for calls to write() to + * write the entry's contents. Once the contents are written, closeEntry() + * <B>MUST </B> be called to ensure that all buffered data is completely + * written to the output stream. + * + * @param entry + * the SarEntry to be written to the archive. + * @throws IOException + */ + public void putNextEntry(SarEntry entry) throws IOException { + entry.writeTo(this); + } + + /** + * Close an entry. This method MUST be called for all file entries that + * contain data. The reason is that we must buffer data written to the + * stream in order to satisfy the buffer's record based writes. Thus, there + * may be data fragments still being assembled that must be written to the + * output stream before this entry is closed and the next entry written. + * + * @throws IOException + */ + public void closeEntry() throws IOException { + writeBytes(entryContent.getBuffer(), entryContent.getBufferLength()); + entryContent.reset(); + } + + /** + * @param s + * @throws IOException + */ + void writeString(String s) throws IOException { + byte[] bytes = null; + if (s != null) + bytes = s.getBytes(SarConstants.DEFAULT_ENCODING); + + writeBytes(bytes); + } + + /** + * @param bytes + * @throws IOException + */ + void writeBytes(byte[] bytes) throws IOException { + writeBytes(bytes, bytes != null ? bytes.length : -1); + } + + /** + * @param bytes + * @throws IOException + */ + void writeBytes(byte[] bytes, int length) throws IOException { + if (bytes != null) { + dataOutputStream.writeInt(length); + dataOutputStream.write(bytes, 0, length); + } else { + dataOutputStream.writeInt(-1); + } + } + + /** + * @param v + * @throws IOException + */ + void writeInt(int v) throws IOException { + dataOutputStream.writeInt(v); + } + + /** + * @param bool + * @throws IOException + */ + public void writeBool(boolean bool) throws IOException { + dataOutputStream.writeBoolean(bool); + } + + /** + * @param v + * @throws IOException + */ + void writeLong(long v) throws IOException { + dataOutputStream.writeLong(v); + } + + /** + * Writes a byte to the current org.eclipse.equinox.p2.sar archive entry. + * + * @param b + * the byte written. + * @throws IOException + * + * @see java.io.OutputStream#write(int) + */ + public void write(int b) throws IOException { + byte[] bytes = new byte[1]; + bytes[0] = (byte) b; + entryContent.write(bytes); + } + + /** + * Writes bytes to the current org.eclipse.equinox.p2.sar archive entry. + * + * @param bytes + * The buffer to write to the archive. + * @throws IOException + * + * @see java.io.OutputStream#write(byte[]) + */ + public void write(byte[] bytes) throws IOException { + entryContent.write(bytes, 0, bytes.length); + } + + /** + * Writes bytes to the current org.eclipse.equinox.p2.sar archive entry. + * + * @param bytes + * The buffer to write to the archive. + * @param offset + * The offset in the buffer from which to get bytes. + * @param numToWrite + * The number of bytes to write. + * + * @throws IOException + * + * @see java.io.OutputStream#write(byte[], int, int) + */ + public void write(byte[] bytes, int offset, int numToWrite) + throws IOException { + entryContent.write(bytes, offset, numToWrite); + } + + /** + * Write an EOF (end of archive) entry to the org.eclipse.equinox.p2.sar archive. + * + * @throws IOException + */ + private void writeEOFRecord() throws IOException { + SarEntry eofEntry = new SarEntry(); + eofEntry.writeTo(this); + } + +} diff --git a/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarUtil.java b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarUtil.java new file mode 100644 index 000000000..1dd31eca0 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.sar/src/org/eclipse/equinox/p2/sar/SarUtil.java @@ -0,0 +1,232 @@ +/******************************************************************************* + * Copyright (c) 2007 compeople AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * compeople AG (Stefan Liebig) - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.sar; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +/** + * Helper class for converting Zips/Jars to Sars and vice versa. + */ +public class SarUtil { + + private static final int BUFFER_SIZE = 8 * 1024; + private static final boolean DEBUG = SarConstants.DEBUG; + + /** + * + */ + private SarUtil() { + // utility class + } + + /** + * Normalize the given zip/jar. + * + * @param zipSource + * @param zipTarget + * @throws IOException + */ + public static void normalize(File zipSource, File zipTarget) + throws IOException { + File tempSar = File.createTempFile("temp", ".sar"); + try { + zipToSar(zipSource, tempSar); + sarToZip(tempSar, zipTarget); + } finally { + tempSar.delete(); + } + } + + /** + * Normalize the given zip/jar. + * + * @param zipSource + * @param zipTarget + * @throws IOException + */ + public static void normalize(InputStream zipSource, OutputStream zipTarget) + throws IOException { + DirectByteArrayOutputStream tempSar = new DirectByteArrayOutputStream(); + zipToSar(zipSource, tempSar); + sarToZip(tempSar.getInputStream(), zipTarget); + } + + /** + * @param zipFile + * @return + * @throws IOException + */ + public static void zipToSar(File zipFile, File sarFile) throws IOException { + InputStream zipInputStream = new BufferedInputStream( + new FileInputStream(zipFile)); + OutputStream sarOutputStream = new BufferedOutputStream( + new FileOutputStream(sarFile)); + SarUtil.zipToSar(zipInputStream, sarOutputStream); + } + + /** + * @param zippedInputStream + * @param saredOutputStream + * @throws IOException + */ + public static void zipToSar(InputStream zippedInputStream, + OutputStream saredOutputStream) throws IOException { + zipToSar(zippedInputStream, true, saredOutputStream, true); + } + + /** + * @param zippedInputStream + * @param closeIn + * @param saredOutputStream + * @param closeOut + * @throws IOException + */ + public static void zipToSar(InputStream zippedInputStream, boolean closeIn, + OutputStream saredOutputStream, boolean closeOut) + throws IOException { + zipToSarNoClose(zippedInputStream, saredOutputStream); + + if (closeIn) + zippedInputStream.close(); + if (closeOut) + saredOutputStream.close(); + } + + /** + * @param sarFile + * @param zipFile + * @throws IOException + */ + public static void sarToZip(File sarFile, File zipFile) throws IOException { + InputStream saredInputStream = new BufferedInputStream( + new FileInputStream(sarFile)); + OutputStream zippedOutputStream = new BufferedOutputStream( + new FileOutputStream(zipFile)); + + sarToZip(saredInputStream, zippedOutputStream); + } + + /** + * @param saredInputStream + * @param zippedOutputStream + * @param level + * @throws IOException + */ + public static void sarToZip(InputStream saredInputStream, + OutputStream zippedOutputStream) throws IOException { + sarToZip(saredInputStream, true, zippedOutputStream, true); + } + + /** + * @param saredInputStream + * @param closeIn + * @param zippedOutputStream + * @param closeOut + * @throws IOException + */ + public static void sarToZip(InputStream saredInputStream, boolean closeIn, + OutputStream zippedOutputStream, boolean closeOut) + throws IOException { + sarToZipNoClose(saredInputStream, zippedOutputStream); + + if (closeIn) + saredInputStream.close(); + if (closeOut) + zippedOutputStream.close(); + } + + /** + * @param zippedInputStream + * @param saredOutputStream + * @throws IOException + */ + private static void zipToSarNoClose(InputStream zippedInputStream, + OutputStream saredOutputStream) throws IOException { + + ZipInputStream zipInputStream = new ZipInputStream(zippedInputStream); + SarOutputStream sarOutputStream = new SarOutputStream(saredOutputStream); + + ZipEntry zipEntry; + byte[] buf = new byte[BUFFER_SIZE]; + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + boolean isZip = isZip(zipEntry); + SarEntry sarEntry = new SarEntry(zipEntry, isZip); + sarOutputStream.putNextEntry(sarEntry); + if (isZip) { + zipToSarNoClose(zipInputStream, sarOutputStream); + } else { + int read; + while ((read = zipInputStream.read(buf)) != -1) { + if (DEBUG) { + System.out.println("Content: " + + new String(buf, 0, read)); + } + sarOutputStream.write(buf, 0, read); + } + } + zipInputStream.closeEntry(); + sarOutputStream.closeEntry(); + } + sarOutputStream.finish(); + } + + /** + * @param saredInputStream + * @param zippedOutputStream + * @param level + * @throws IOException + */ + private static void sarToZipNoClose(InputStream saredInputStream, + OutputStream zippedOutputStream) throws IOException { + + SarInputStream sarInputStream = new SarInputStream(saredInputStream); + ZipOutputStream zipOutputStream = new ZipOutputStream( + zippedOutputStream); + + SarEntry sarEntry; + byte[] buf = new byte[BUFFER_SIZE]; + while ((sarEntry = sarInputStream.getNextEntry()) != null) { + ZipEntry zipEntry = new ZipEntry(sarEntry); + zipOutputStream.putNextEntry(zipEntry); + if (sarEntry.isZip()) { + sarToZipNoClose(sarInputStream, zipOutputStream); + } else { + int read; + while ((read = sarInputStream.read(buf)) != -1) { + if (DEBUG) { + System.out.println("Content: " + + new String(buf, 0, read)); + } + zipOutputStream.write(buf, 0, read); + } + } + sarInputStream.closeEntry(); + zipOutputStream.closeEntry(); + } + + zipOutputStream.finish(); + } + + private static boolean isZip(ZipEntry zipEntry) { + String name = zipEntry.getName().toLowerCase(); + return name.endsWith(".zip") || name.endsWith(".jar"); + } +} |