geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From djen...@apache.org
Subject svn commit: r821961 [9/30] - in /geronimo/sandbox/djencks/osgi/framework: ./ buildsupport/ buildsupport/car-maven-plugin/ buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/ buildsupport/geronimo-maven-plugin/src/main/java...
Date Mon, 05 Oct 2009 18:54:56 GMT
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarBuffer.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarBuffer.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarBuffer.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarBuffer.java Mon Oct  5 18:54:50 2009
@@ -0,0 +1,483 @@
+package org.apache.geronimo.system.plugin.plexus.archiver.tar;
+
+/*
+ * Copyright  2000,2002,2004 The Apache Software Foundation
+ *
+ *  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.
+ *
+ */
+
+/*
+ * This package is based on the work done by Timothy Gerard Endres
+ * (time@ice.com) to whom the Ant project is very grateful for his great code.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * The TarBuffer class implements the tar archive concept
+ * of a buffered input stream. This concept goes back to the
+ * days of blocked tape drives and special io devices. In the
+ * Java universe, the only real function that this class
+ * performs is to ensure that files have the correct "block"
+ * size, or other tars will complain.
+ * <p/>
+ * You should never have a need to access this class directly.
+ * TarBuffers are created by Tar IO Streams.
+ *
+ * @version $Revision$ $Date$
+ *          from org.apache.ant.tools.tar.TarBuffer v1.12
+ */
+
+public class TarBuffer
+{
+
+    public static final int DEFAULT_RCDSIZE = ( 512 );
+
+    public static final int DEFAULT_BLKSIZE = ( DEFAULT_RCDSIZE * 20 );
+
+    private InputStream inStream;
+
+    private OutputStream outStream;
+
+    private byte[] blockBuffer;
+
+    private int currBlkIdx;
+
+    private int currRecIdx;
+
+    private int blockSize;
+
+    private int recordSize;
+
+    private int recsPerBlock;
+
+    private boolean debug;
+
+    public TarBuffer( InputStream inStream )
+    {
+        this( inStream, TarBuffer.DEFAULT_BLKSIZE );
+    }
+
+    public TarBuffer( InputStream inStream, int blockSize )
+    {
+        this( inStream, blockSize, TarBuffer.DEFAULT_RCDSIZE );
+    }
+
+    public TarBuffer( InputStream inStream, int blockSize, int recordSize )
+    {
+        this.inStream = inStream;
+        this.outStream = null;
+
+        this.initialize( blockSize, recordSize );
+    }
+
+    public TarBuffer( OutputStream outStream )
+    {
+        this( outStream, TarBuffer.DEFAULT_BLKSIZE );
+    }
+
+    public TarBuffer( OutputStream outStream, int blockSize )
+    {
+        this( outStream, blockSize, TarBuffer.DEFAULT_RCDSIZE );
+    }
+
+    public TarBuffer( OutputStream outStream, int blockSize, int recordSize )
+    {
+        this.inStream = null;
+        this.outStream = outStream;
+
+        this.initialize( blockSize, recordSize );
+    }
+
+    /**
+     * Initialization common to all constructors.
+     */
+    private void initialize( int blockSize, int recordSize )
+    {
+        this.debug = false;
+        this.blockSize = blockSize;
+        this.recordSize = recordSize;
+        this.recsPerBlock = ( this.blockSize / this.recordSize );
+        this.blockBuffer = new byte[this.blockSize];
+
+        if ( this.inStream != null )
+        {
+            this.currBlkIdx = -1;
+            this.currRecIdx = this.recsPerBlock;
+        }
+        else
+        {
+            this.currBlkIdx = 0;
+            this.currRecIdx = 0;
+        }
+    }
+
+    /**
+     * Get the TAR Buffer's block size. Blocks consist of multiple records.
+     */
+    public int getBlockSize()
+    {
+        return this.blockSize;
+    }
+
+    /**
+     * Get the TAR Buffer's record size.
+     */
+    public int getRecordSize()
+    {
+        return this.recordSize;
+    }
+
+    /**
+     * Set the debugging flag for the buffer.
+     *
+     * @param debug If true, print debugging output.
+     */
+    public void setDebug( boolean debug )
+    {
+        this.debug = debug;
+    }
+
+    /**
+     * Determine if an archive record indicate End of Archive. End of
+     * archive is indicated by a record that consists entirely of null bytes.
+     *
+     * @param record The record data to check.
+     */
+    public boolean isEOFRecord( byte[] record )
+    {
+        for ( int i = 0, sz = this.getRecordSize(); i < sz; ++i )
+        {
+            if ( record[ i ] != 0 )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Skip over a record on the input stream.
+     */
+    public void skipRecord()
+        throws IOException
+    {
+        if ( this.debug )
+        {
+            System.err.println( "SkipRecord: recIdx = " + this.currRecIdx
+                                + " blkIdx = " + this.currBlkIdx );
+        }
+
+        if ( this.inStream == null )
+        {
+            throw new IOException( "reading (via skip) from an output buffer" );
+        }
+
+        if ( this.currRecIdx >= this.recsPerBlock )
+        {
+            if ( !this.readBlock() )
+            {
+                return;    // UNDONE
+            }
+        }
+
+        this.currRecIdx++;
+    }
+
+    /**
+     * Read a record from the input stream and return the data.
+     *
+     * @return The record data.
+     */
+    public byte[] readRecord()
+        throws IOException
+    {
+        if ( this.debug )
+        {
+            System.err.println( "ReadRecord: recIdx = " + this.currRecIdx
+                                + " blkIdx = " + this.currBlkIdx );
+        }
+
+        if ( this.inStream == null )
+        {
+            throw new IOException( "reading from an output buffer" );
+        }
+
+        if ( this.currRecIdx >= this.recsPerBlock )
+        {
+            if ( !this.readBlock() )
+            {
+                return null;
+            }
+        }
+
+        byte[] result = new byte[this.recordSize];
+
+        System.arraycopy( this.blockBuffer,
+                          ( this.currRecIdx * this.recordSize ), result, 0,
+                          this.recordSize );
+
+        this.currRecIdx++;
+
+        return result;
+    }
+
+    /**
+     * @return false if End-Of-File, else true
+     */
+    private boolean readBlock()
+        throws IOException
+    {
+        if ( this.debug )
+        {
+            System.err.println( "ReadBlock: blkIdx = " + this.currBlkIdx );
+        }
+
+        if ( this.inStream == null )
+        {
+            throw new IOException( "reading from an output buffer" );
+        }
+
+        this.currRecIdx = 0;
+
+        int offset = 0;
+        int bytesNeeded = this.blockSize;
+
+        while ( bytesNeeded > 0 )
+        {
+            long numBytes = this.inStream.read( this.blockBuffer, offset,
+                                                bytesNeeded );
+
+            //
+            // NOTE
+            // We have fit EOF, and the block is not full!
+            //
+            // This is a broken archive. It does not follow the standard
+            // blocking algorithm. However, because we are generous, and
+            // it requires little effort, we will simply ignore the error
+            // and continue as if the entire block were read. This does
+            // not appear to break anything upstream. We used to return
+            // false in this case.
+            //
+            // Thanks to 'Yohann.Roussel@alcatel.fr' for this fix.
+            //
+            if ( numBytes == -1 )
+            {
+                break;
+            }
+
+            offset += numBytes;
+            bytesNeeded -= numBytes;
+
+            if ( numBytes != this.blockSize )
+            {
+                if ( this.debug )
+                {
+                    System.err.println( "ReadBlock: INCOMPLETE READ "
+                                        + numBytes + " of " + this.blockSize
+                                        + " bytes read." );
+                }
+            }
+        }
+
+        this.currBlkIdx++;
+
+        return true;
+    }
+
+    /**
+     * Get the current block number, zero based.
+     *
+     * @return The current zero based block number.
+     */
+    public int getCurrentBlockNum()
+    {
+        return this.currBlkIdx;
+    }
+
+    /**
+     * Get the current record number, within the current block, zero based.
+     * Thus, current offset = (currentBlockNum * recsPerBlk) + currentRecNum.
+     *
+     * @return The current zero based record number.
+     */
+    public int getCurrentRecordNum()
+    {
+        return this.currRecIdx - 1;
+    }
+
+    /**
+     * Write an archive record to the archive.
+     *
+     * @param record The record data to write to the archive.
+     */
+    public void writeRecord( byte[] record )
+        throws IOException
+    {
+        if ( this.debug )
+        {
+            System.err.println( "WriteRecord: recIdx = " + this.currRecIdx
+                                + " blkIdx = " + this.currBlkIdx );
+        }
+
+        if ( this.outStream == null )
+        {
+            throw new IOException( "writing to an input buffer" );
+        }
+
+        if ( record.length != this.recordSize )
+        {
+            throw new IOException( "record to write has length '"
+                                   + record.length
+                                   + "' which is not the record size of '"
+                                   + this.recordSize + "'" );
+        }
+
+        if ( this.currRecIdx >= this.recsPerBlock )
+        {
+            this.writeBlock();
+        }
+
+        System.arraycopy( record, 0, this.blockBuffer,
+                          ( this.currRecIdx * this.recordSize ),
+                          this.recordSize );
+
+        this.currRecIdx++;
+    }
+
+    /**
+     * Write an archive record to the archive, where the record may be
+     * inside of a larger array buffer. The buffer must be "offset plus
+     * record size" long.
+     *
+     * @param buf    The buffer containing the record data to write.
+     * @param offset The offset of the record data within buf.
+     */
+    public void writeRecord( byte[] buf, int offset )
+        throws IOException
+    {
+        if ( this.debug )
+        {
+            System.err.println( "WriteRecord: recIdx = " + this.currRecIdx
+                                + " blkIdx = " + this.currBlkIdx );
+        }
+
+        if ( this.outStream == null )
+        {
+            throw new IOException( "writing to an input buffer" );
+        }
+
+        if ( ( offset + this.recordSize ) > buf.length )
+        {
+            throw new IOException( "record has length '" + buf.length
+                                   + "' with offset '" + offset
+                                   + "' which is less than the record size of '"
+                                   + this.recordSize + "'" );
+        }
+
+        if ( this.currRecIdx >= this.recsPerBlock )
+        {
+            this.writeBlock();
+        }
+
+        System.arraycopy( buf, offset, this.blockBuffer,
+                          ( this.currRecIdx * this.recordSize ),
+                          this.recordSize );
+
+        this.currRecIdx++;
+    }
+
+    /**
+     * Write a TarBuffer block to the archive.
+     */
+    private void writeBlock()
+        throws IOException
+    {
+        if ( this.debug )
+        {
+            System.err.println( "WriteBlock: blkIdx = " + this.currBlkIdx );
+        }
+
+        if ( this.outStream == null )
+        {
+            throw new IOException( "writing to an input buffer" );
+        }
+
+        this.outStream.write( this.blockBuffer, 0, this.blockSize );
+        this.outStream.flush();
+
+        this.currRecIdx = 0;
+        this.currBlkIdx++;
+    }
+
+    /**
+     * Flush the current data block if it has any data in it.
+     */
+    private void flushBlock()
+        throws IOException
+    {
+        if ( this.debug )
+        {
+            System.err.println( "TarBuffer.flushBlock() called." );
+        }
+
+        if ( this.outStream == null )
+        {
+            throw new IOException( "writing to an input buffer" );
+        }
+
+        if ( this.currRecIdx > 0 )
+        {
+            this.writeBlock();
+        }
+    }
+
+    /**
+     * Close the TarBuffer. If this is an output buffer, also flush the
+     * current block before closing.
+     */
+    public void close()
+        throws IOException
+    {
+        if ( this.debug )
+        {
+            System.err.println( "TarBuffer.closeBuffer()." );
+        }
+
+        if ( this.outStream != null )
+        {
+            this.flushBlock();
+
+            if ( this.outStream != System.out
+                 && this.outStream != System.err )
+            {
+                this.outStream.close();
+
+                this.outStream = null;
+            }
+        }
+        else if ( this.inStream != null )
+        {
+            if ( this.inStream != System.in )
+            {
+                this.inStream.close();
+
+                this.inStream = null;
+            }
+        }
+    }
+}

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarBuffer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarBuffer.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarBuffer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarCompressionMethod.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarCompressionMethod.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarCompressionMethod.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarCompressionMethod.java Mon Oct  5 18:54:50 2009
@@ -0,0 +1,66 @@
+package org.apache.geronimo.system.plugin.plexus.archiver.tar;
+
+/*
+ * Copyright  2000-2004 The Apache Software Foundation
+ *
+ *  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.
+ *
+ */
+
+import org.apache.geronimo.system.plugin.plexus.archiver.ArchiverException;
+import org.apache.geronimo.system.plugin.plexus.archiver.util.EnumeratedAttribute;
+
+/**
+ * Valid Modes for Compression attribute to Tar Task
+ */
+public final class TarCompressionMethod
+    extends EnumeratedAttribute
+{
+    // permissible values for compression attribute
+
+    /**
+     * No compression
+     */
+    private static final String NONE = "none";
+
+    /**
+     * GZIP compression
+     */
+    private static final String GZIP = "gzip";
+
+    /**
+     * BZIP2 compression
+     */
+    private static final String BZIP2 = "bzip2";
+
+
+    /**
+     * Default constructor
+     */
+    public TarCompressionMethod()
+        throws ArchiverException
+    {
+        super();
+        setValue( NONE );
+    }
+
+    /**
+     * Get valid enumeration values.
+     *
+     * @return valid enumeration values
+     */
+    public String[] getValues()
+    {
+        return new String[]{NONE, GZIP, BZIP2};
+    }
+}

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarCompressionMethod.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarCompressionMethod.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarCompressionMethod.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarConstants.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarConstants.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarConstants.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarConstants.java Mon Oct  5 18:54:50 2009
@@ -0,0 +1,155 @@
+package org.apache.geronimo.system.plugin.plexus.archiver.tar;
+
+/*
+ * Copyright  2000-2002,2004 The Apache Software Foundation
+ *
+ *  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.
+ *
+ */
+
+/*
+ * This package is based on the work done by Timothy Gerard Endres
+ * (time@ice.com) to whom the Ant project is very grateful for his great code.
+ */
+
+/**
+ * This interface contains all the definitions used in the package.
+ *
+ * @version $Revision$ $Date$
+ *          from org.apache.ant.tools.tar.TarConstants v1.13
+ */
+
+public interface TarConstants
+{
+
+    /**
+     * The length of the name field in a header buffer.
+     */
+    int NAMELEN = 100;
+
+    /**
+     * The length of the mode field in a header buffer.
+     */
+    int MODELEN = 8;
+
+    /**
+     * The length of the user id field in a header buffer.
+     */
+    int UIDLEN = 8;
+
+    /**
+     * The length of the group id field in a header buffer.
+     */
+    int GIDLEN = 8;
+
+    /**
+     * The length of the checksum field in a header buffer.
+     */
+    int CHKSUMLEN = 8;
+
+    /**
+     * The length of the size field in a header buffer.
+     */
+    int SIZELEN = 12;
+
+    /**
+     * The length of the magic field in a header buffer.
+     */
+    int MAGICLEN = 8;
+
+    /**
+     * The length of the modification time field in a header buffer.
+     */
+    int MODTIMELEN = 12;
+
+    /**
+     * The length of the user name field in a header buffer.
+     */
+    int UNAMELEN = 32;
+
+    /**
+     * The length of the group name field in a header buffer.
+     */
+    int GNAMELEN = 32;
+
+    /**
+     * The length of the devices field in a header buffer.
+     */
+    int DEVLEN = 8;
+
+    /**
+     * LF_ constants represent the "link flag" of an entry, or more commonly,
+     * the "entry type". This is the "old way" of indicating a normal file.
+     */
+    byte LF_OLDNORM = 0;
+
+    /**
+     * Normal file type.
+     */
+    byte LF_NORMAL = (byte) '0';
+
+    /**
+     * Link file type.
+     */
+    byte LF_LINK = (byte) '1';
+
+    /**
+     * Symbolic link file type.
+     */
+    byte LF_SYMLINK = (byte) '2';
+
+    /**
+     * Character device file type.
+     */
+    byte LF_CHR = (byte) '3';
+
+    /**
+     * Block device file type.
+     */
+    byte LF_BLK = (byte) '4';
+
+    /**
+     * Directory file type.
+     */
+    byte LF_DIR = (byte) '5';
+
+    /**
+     * FIFO (pipe) file type.
+     */
+    byte LF_FIFO = (byte) '6';
+
+    /**
+     * Contiguous file type.
+     */
+    byte LF_CONTIG = (byte) '7';
+
+    /**
+     * The magic tag representing a POSIX tar archive.
+     */
+    String TMAGIC = "ustar";
+
+    /**
+     * The magic tag representing a GNU tar archive.
+     */
+    String GNU_TMAGIC = "ustar  ";
+
+    /**
+     * The namr of the GNU tar entry which contains a long name.
+     */
+    String GNU_LONGLINK = "././@LongLink";
+
+    /**
+     * Identifies the *next* file on the tape as having a long name.
+     */
+    byte LF_GNUTYPE_LONGNAME = (byte) 'L';
+}

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarConstants.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarConstants.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarEntry.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarEntry.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarEntry.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarEntry.java Mon Oct  5 18:54:50 2009
@@ -0,0 +1,755 @@
+package org.apache.geronimo.system.plugin.plexus.archiver.tar;
+
+/*
+ * Copyright  2000-2004 The Apache Software Foundation
+ *
+ *  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.
+ *
+ */
+
+/*
+ * This package is based on the work done by Timothy Gerard Endres
+ * (time@ice.com) to whom the Ant project is very grateful for his great code.
+ */
+
+import java.io.File;
+import java.util.Date;
+import java.util.Locale;
+
+import org.apache.geronimo.system.plugin.plexus.archiver.ArchiveFile;
+
+/**
+ * This class represents an entry in a Tar archive. It consists
+ * of the entry's header, as well as the entry's File. Entries
+ * can be instantiated in one of three ways, depending on how
+ * they are to be used.
+ * <p/>
+ * TarEntries that are created from the header bytes read from
+ * an archive are instantiated with the TarEntry( byte[] )
+ * constructor. These entries will be used when extracting from
+ * or listing the contents of an archive. These entries have their
+ * header filled in using the header bytes. They also set the File
+ * to null, since they reference an archive entry not a file.
+ * <p/>
+ * TarEntries that are created from Files that are to be written
+ * into an archive are instantiated with the TarEntry( File )
+ * constructor. These entries have their header filled in using
+ * the File's information. They also keep a reference to the File
+ * for convenience when writing entries.
+ * <p/>
+ * Finally, TarEntries can be constructed from nothing but a name.
+ * This allows the programmer to construct the entry by hand, for
+ * instance when only an InputStream is available for writing to
+ * the archive, and the header information is constructed from
+ * other information. In this case the header fields are set to
+ * defaults and the File is set to null.
+ * <p/>
+ * <p/>
+ * The C structure for a Tar Entry's header is:
+ * <pre>
+ * struct header {
+ * char name[NAMSIZ];
+ * char mode[8];
+ * char uid[8];
+ * char gid[8];
+ * char size[12];
+ * char mtime[12];
+ * char chksum[8];
+ * char linkflag;
+ * char linkname[NAMSIZ];
+ * char magic[8];
+ * char uname[TUNMLEN];
+ * char gname[TGNMLEN];
+ * char devmajor[8];
+ * char devminor[8];
+ * } header;
+ * </pre>
+ *
+ * @version $Revision$ $Date$
+ *          from org.apache.ant.tools.tar.TarEntry v1.22
+ */
+
+public class TarEntry
+    implements TarConstants, ArchiveFile.Entry
+{
+    /**
+     * The entry's name.
+     */
+    private StringBuffer name;
+
+    /**
+     * The entry's permission mode.
+     */
+    private int mode;
+
+    /**
+     * The entry's user id.
+     */
+    private int userId;
+
+    /**
+     * The entry's group id.
+     */
+    private int groupId;
+
+    /**
+     * The entry's size.
+     */
+    private long size;
+
+    /**
+     * The entry's modification time.
+     */
+    private long modTime;
+
+    /**
+     * The entry's checksum.
+     */
+    private int checkSum;
+
+    /**
+     * The entry's link flag.
+     */
+    private byte linkFlag;
+
+    /**
+     * The entry's link name.
+     */
+    private StringBuffer linkName;
+
+    /**
+     * The entry's magic tag.
+     */
+    private StringBuffer magic;
+
+    /**
+     * The entry's user name.
+     */
+    private StringBuffer userName;
+
+    /**
+     * The entry's group name.
+     */
+    private StringBuffer groupName;
+
+    /**
+     * The entry's major device number.
+     */
+    private int devMajor;
+
+    /**
+     * The entry's minor device number.
+     */
+    private int devMinor;
+
+    /**
+     * The entry's file reference
+     */
+    private File file;
+
+    /**
+     * Maximum length of a user's name in the tar file
+     */
+    public static final int MAX_NAMELEN = 31;
+
+    /**
+     * Default permissions bits for directories
+     */
+    public static final int DEFAULT_DIR_MODE = 040755;
+
+    /**
+     * Default permissions bits for files
+     */
+    public static final int DEFAULT_FILE_MODE = 0100644;
+
+    /**
+     * Convert millis to seconds
+     */
+    public static final int MILLIS_PER_SECOND = 1000;
+
+    /**
+     * Construct an empty entry and prepares the header values.
+     */
+    private TarEntry()
+    {
+        this.magic = new StringBuffer( TMAGIC );
+        this.name = new StringBuffer();
+        this.linkName = new StringBuffer();
+
+        String user = System.getProperty( "user.name", "" );
+
+        if ( user.length() > MAX_NAMELEN )
+        {
+            user = user.substring( 0, MAX_NAMELEN );
+        }
+
+        this.userId = 0;
+        this.groupId = 0;
+        this.userName = new StringBuffer( user );
+        this.groupName = new StringBuffer( "" );
+        this.file = null;
+    }
+
+    /**
+     * Construct an entry with only a name. This allows the programmer
+     * to construct the entry's header "by hand". File is set to null.
+     *
+     * @param name the entry name
+     */
+    public TarEntry( String name )
+    {
+        this();
+
+        boolean isDir = name.endsWith( "/" );
+
+        this.devMajor = 0;
+        this.devMinor = 0;
+        this.name = new StringBuffer( name );
+        this.mode = isDir ? DEFAULT_DIR_MODE : DEFAULT_FILE_MODE;
+        this.linkFlag = isDir ? LF_DIR : LF_NORMAL;
+        this.userId = 0;
+        this.groupId = 0;
+        this.size = 0;
+        this.modTime = ( new Date() ).getTime() / MILLIS_PER_SECOND;
+        this.linkName = new StringBuffer( "" );
+        this.userName = new StringBuffer( "" );
+        this.groupName = new StringBuffer( "" );
+        this.devMajor = 0;
+        this.devMinor = 0;
+    }
+
+    /**
+     * Construct an entry with a name an a link flag.
+     *
+     * @param name     the entry name
+     * @param linkFlag the entry link flag.
+     */
+    public TarEntry( String name, byte linkFlag )
+    {
+        this( name );
+        this.linkFlag = linkFlag;
+    }
+
+    /**
+     * Construct an entry for a file. File is set to file, and the
+     * header is constructed from information from the file.
+     *
+     * @param file The file that the entry represents.
+     */
+    public TarEntry( File file )
+    {
+        this();
+
+        this.file = file;
+
+        String name = file.getPath();
+        String osname = System.getProperty( "os.name" ).toLowerCase( Locale.US );
+
+        if ( osname != null )
+        {
+
+            // Strip off drive letters!
+            // REVIEW Would a better check be "(File.separator == '\')"?
+
+            if ( osname.startsWith( "windows" ) )
+            {
+                if ( name.length() > 2 )
+                {
+                    char ch1 = name.charAt( 0 );
+                    char ch2 = name.charAt( 1 );
+
+                    if ( ch2 == ':'
+                         && ( ( ch1 >= 'a' && ch1 <= 'z' )
+                              || ( ch1 >= 'A' && ch1 <= 'Z' ) ) )
+                    {
+                        name = name.substring( 2 );
+                    }
+                }
+            }
+            else if ( osname.indexOf( "netware" ) > -1 )
+            {
+                int colon = name.indexOf( ':' );
+                if ( colon != -1 )
+                {
+                    name = name.substring( colon + 1 );
+                }
+            }
+        }
+
+        name = name.replace( File.separatorChar, '/' );
+
+        // No absolute pathnames
+        // Windows (and Posix?) paths can start with "\\NetworkDrive\",
+        // so we loop on starting /'s.
+        while ( name.startsWith( "/" ) )
+        {
+            name = name.substring( 1 );
+        }
+
+        this.linkName = new StringBuffer( "" );
+        this.name = new StringBuffer( name );
+
+        if ( file.isDirectory() )
+        {
+            this.mode = DEFAULT_DIR_MODE;
+            this.linkFlag = LF_DIR;
+
+            if ( this.name.charAt( this.name.length() - 1 ) != '/' )
+            {
+                this.name.append( "/" );
+            }
+        }
+        else
+        {
+            this.mode = DEFAULT_FILE_MODE;
+            this.linkFlag = LF_NORMAL;
+        }
+
+        this.size = file.length();
+        this.modTime = file.lastModified() / MILLIS_PER_SECOND;
+        this.devMajor = 0;
+        this.devMinor = 0;
+    }
+
+    /**
+     * Construct an entry from an archive's header bytes. File is set
+     * to null.
+     *
+     * @param headerBuf The header bytes from a tar archive entry.
+     */
+    public TarEntry( byte[] headerBuf )
+    {
+        this();
+        this.parseTarHeader( headerBuf );
+    }
+
+    /**
+     * Determine if the two entries are equal. Equality is determined
+     * by the header names being equal.
+     *
+     * @param it Entry to be checked for equality.
+     * @return True if the entries are equal.
+     */
+    public boolean equals( TarEntry it )
+    {
+        return this.getName().equals( it.getName() );
+    }
+
+    /**
+     * Determine if the two entries are equal. Equality is determined
+     * by the header names being equal.
+     *
+     * @param it Entry to be checked for equality.
+     * @return True if the entries are equal.
+     */
+    public boolean equals( Object it )
+    {
+        if ( it == null || getClass() != it.getClass() )
+        {
+            return false;
+        }
+        return equals( (TarEntry) it );
+    }
+
+    /**
+     * Hashcodes are based on entry names.
+     *
+     * @return the entry hashcode
+     */
+    public int hashCode()
+    {
+        return getName().hashCode();
+    }
+
+    /**
+     * Determine if the given entry is a descendant of this entry.
+     * Descendancy is determined by the name of the descendant
+     * starting with this entry's name.
+     *
+     * @param desc Entry to be checked as a descendent of this.
+     * @return True if entry is a descendant of this.
+     */
+    public boolean isDescendent( TarEntry desc )
+    {
+        return desc.getName().startsWith( this.getName() );
+    }
+
+    /**
+     * Get this entry's name.
+     *
+     * @return This entry's name.
+     */
+    public String getName()
+    {
+        return this.name.toString();
+    }
+
+    /**
+     * Set this entry's name.
+     *
+     * @param name This entry's new name.
+     */
+    public void setName( String name )
+    {
+        this.name = new StringBuffer( name );
+    }
+
+    /**
+     * Set the mode for this entry
+     *
+     * @param mode the mode for this entry
+     */
+    public void setMode( int mode )
+    {
+        this.mode = mode;
+    }
+
+    /**
+     * Get this entry's link name.
+     *
+     * @return This entry's link name.
+     */
+    public String getLinkName()
+    {
+        return this.linkName.toString();
+    }
+
+    /**
+     * Get this entry's user id.
+     *
+     * @return This entry's user id.
+     */
+    public int getUserId()
+    {
+        return this.userId;
+    }
+
+    /**
+     * Set this entry's user id.
+     *
+     * @param userId This entry's new user id.
+     */
+    public void setUserId( int userId )
+    {
+        this.userId = userId;
+    }
+
+    /**
+     * Get this entry's group id.
+     *
+     * @return This entry's group id.
+     */
+    public int getGroupId()
+    {
+        return this.groupId;
+    }
+
+    /**
+     * Set this entry's group id.
+     *
+     * @param groupId This entry's new group id.
+     */
+    public void setGroupId( int groupId )
+    {
+        this.groupId = groupId;
+    }
+
+    /**
+     * Get this entry's user name.
+     *
+     * @return This entry's user name.
+     */
+    public String getUserName()
+    {
+        return this.userName.toString();
+    }
+
+    /**
+     * Set this entry's user name.
+     *
+     * @param userName This entry's new user name.
+     */
+    public void setUserName( String userName )
+    {
+        this.userName = new StringBuffer( userName );
+    }
+
+    /**
+     * Get this entry's group name.
+     *
+     * @return This entry's group name.
+     */
+    public String getGroupName()
+    {
+        return this.groupName.toString();
+    }
+
+    /**
+     * Set this entry's group name.
+     *
+     * @param groupName This entry's new group name.
+     */
+    public void setGroupName( String groupName )
+    {
+        this.groupName = new StringBuffer( groupName );
+    }
+
+    /**
+     * Convenience method to set this entry's group and user ids.
+     *
+     * @param userId  This entry's new user id.
+     * @param groupId This entry's new group id.
+     */
+    public void setIds( int userId, int groupId )
+    {
+        this.setUserId( userId );
+        this.setGroupId( groupId );
+    }
+
+    /**
+     * Convenience method to set this entry's group and user names.
+     *
+     * @param userName  This entry's new user name.
+     * @param groupName This entry's new group name.
+     */
+    public void setNames( String userName, String groupName )
+    {
+        this.setUserName( userName );
+        this.setGroupName( groupName );
+    }
+
+    /**
+     * Set this entry's modification time. The parameter passed
+     * to this method is in "Java time".
+     *
+     * @param time This entry's new modification time.
+     */
+    public void setModTime( long time )
+    {
+        this.modTime = time / MILLIS_PER_SECOND;
+    }
+
+    /**
+     * Set this entry's modification time.
+     *
+     * @param time This entry's new modification time.
+     */
+    public void setModTime( Date time )
+    {
+        this.modTime = time.getTime() / MILLIS_PER_SECOND;
+    }
+
+    /**
+     * Get this entry's modification time.
+     *
+     * @return time This entry's new modification time.
+     */
+    public Date getModTime()
+    {
+        return new Date( this.modTime * MILLIS_PER_SECOND );
+    }
+
+    /**
+     * Get this entry's checksum time.
+     *
+     * @return time This entry's new modification time.
+     */
+    public int getChecksum()
+    {
+        return checkSum;
+    }
+
+    /**
+     * Get this entry's file.
+     *
+     * @return This entry's file.
+     */
+    public File getFile()
+    {
+        return this.file;
+    }
+
+    /**
+     * Get this entry's mode.
+     *
+     * @return This entry's mode.
+     */
+    public int getMode()
+    {
+        return this.mode;
+    }
+
+    /**
+     * Get this entry's file size.
+     *
+     * @return This entry's file size.
+     */
+    public long getSize()
+    {
+        return this.size;
+    }
+
+    /**
+     * Set this entry's file size.
+     *
+     * @param size This entry's new file size.
+     */
+    public void setSize( long size )
+    {
+        this.size = size;
+    }
+
+
+    /**
+     * Indicate if this entry is a GNU long name block
+     *
+     * @return true if this is a long name extension provided by GNU tar
+     */
+    public boolean isGNULongNameEntry()
+    {
+        return linkFlag == LF_GNUTYPE_LONGNAME
+               && name.toString().equals( GNU_LONGLINK );
+    }
+
+    /**
+     * Return whether or not this entry represents a directory.
+     *
+     * @return True if this entry is a directory.
+     */
+    public boolean isDirectory()
+    {
+        if ( this.file != null )
+        {
+            return this.file.isDirectory();
+        }
+
+        if ( this.linkFlag == LF_DIR )
+        {
+            return true;
+        }
+
+        if ( this.getName().endsWith( "/" ) )
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * If this entry represents a file, and the file is a directory, return
+     * an array of TarEntries for this entry's children.
+     *
+     * @return An array of TarEntry's for this entry's children.
+     */
+    public TarEntry[] getDirectoryEntries()
+    {
+        if ( this.file == null || !this.file.isDirectory() )
+        {
+            return new TarEntry[0];
+        }
+
+        String[]   list = this.file.list();
+        TarEntry[] result = new TarEntry[list.length];
+
+        for ( int i = 0; i < list.length; ++i )
+        {
+            result[ i ] = new TarEntry( new File( this.file, list[ i ] ) );
+        }
+
+        return result;
+    }
+
+    /**
+     * Write an entry's header information to a header buffer.
+     *
+     * @param outbuf The tar entry header buffer to fill in.
+     */
+    public void writeEntryHeader( byte[] outbuf )
+    {
+        int offset = 0;
+
+        offset = TarUtils.getNameBytes( this.name, outbuf, offset, NAMELEN );
+        offset = TarUtils.getOctalBytes( this.mode, outbuf, offset, MODELEN );
+        offset = TarUtils.getOctalBytes( this.userId, outbuf, offset, UIDLEN );
+        offset = TarUtils.getOctalBytes( this.groupId, outbuf, offset, GIDLEN );
+        offset = TarUtils.getLongOctalBytes( this.size, outbuf, offset, SIZELEN );
+        offset = TarUtils.getLongOctalBytes( this.modTime, outbuf, offset, MODTIMELEN );
+
+        int csOffset = offset;
+
+        for ( int c = 0; c < CHKSUMLEN; ++c )
+        {
+            outbuf[ offset++ ] = (byte) ' ';
+        }
+
+        outbuf[ offset++ ] = this.linkFlag;
+        offset = TarUtils.getNameBytes( this.linkName, outbuf, offset, NAMELEN );
+        offset = TarUtils.getNameBytes( this.magic, outbuf, offset, MAGICLEN );
+        offset = TarUtils.getNameBytes( this.userName, outbuf, offset, UNAMELEN );
+        offset = TarUtils.getNameBytes( this.groupName, outbuf, offset, GNAMELEN );
+        offset = TarUtils.getOctalBytes( this.devMajor, outbuf, offset, DEVLEN );
+        offset = TarUtils.getOctalBytes( this.devMinor, outbuf, offset, DEVLEN );
+
+        while ( offset < outbuf.length )
+        {
+            outbuf[ offset++ ] = 0;
+        }
+
+        long checkSum = TarUtils.computeCheckSum( outbuf );
+
+        TarUtils.getCheckSumOctalBytes( checkSum, outbuf, csOffset, CHKSUMLEN );
+    }
+
+    /**
+     * Parse an entry's header information from a header buffer.
+     *
+     * @param header The tar entry header buffer to get information from.
+     */
+    public void parseTarHeader( byte[] header )
+    {
+        int offset = 0;
+
+        this.name = TarUtils.parseName( header, offset, NAMELEN );
+        offset += NAMELEN;
+        this.mode = (int) TarUtils.parseOctal( header, offset, MODELEN );
+        offset += MODELEN;
+        this.userId = (int) TarUtils.parseOctal( header, offset, UIDLEN );
+        offset += UIDLEN;
+        this.groupId = (int) TarUtils.parseOctal( header, offset, GIDLEN );
+        offset += GIDLEN;
+        this.size = TarUtils.parseOctal( header, offset, SIZELEN );
+        offset += SIZELEN;
+        this.modTime = TarUtils.parseOctal( header, offset, MODTIMELEN );
+        offset += MODTIMELEN;
+        this.checkSum = (int) TarUtils.parseOctal( header, offset, CHKSUMLEN );
+        offset += CHKSUMLEN;
+        this.linkFlag = header[ offset++ ];
+        this.linkName = TarUtils.parseName( header, offset, NAMELEN );
+        offset += NAMELEN;
+        this.magic = TarUtils.parseName( header, offset, MAGICLEN );
+        offset += MAGICLEN;
+        this.userName = TarUtils.parseName( header, offset, UNAMELEN );
+        offset += UNAMELEN;
+        this.groupName = TarUtils.parseName( header, offset, GNAMELEN );
+        offset += GNAMELEN;
+        this.devMajor = (int) TarUtils.parseOctal( header, offset, DEVLEN );
+        offset += DEVLEN;
+        this.devMinor = (int) TarUtils.parseOctal( header, offset, DEVLEN );
+    }
+
+    public long getLastModificationTime()
+    {
+        return modTime == 0 ? -1 : (modTime * MILLIS_PER_SECOND);
+    }
+}

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarEntry.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarEntry.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarFile.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarFile.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarFile.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarFile.java Mon Oct  5 18:54:50 2009
@@ -0,0 +1,193 @@
+package org.apache.geronimo.system.plugin.plexus.archiver.tar;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.FilterInputStream;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import org.apache.geronimo.system.plugin.plexus.archiver.ArchiveFile;
+
+
+/**
+ * <p>Implementation of {@link ArchiveFile} for tar files.</p>
+ * <p>Compared to
+ * {@link ZipFile}, this one should be used with some care, due to the
+ * nature of a tar file: While a zip file contains a catalog, a tar
+ * file does not. In other words, the only way to read a tar file in
+ * a performant manner is by iterating over it from the beginning to
+ * the end. If you try to open another entry than the "next" entry,
+ * then you force to skip entries, until the requested entry is found.
+ * This may require to reread the entire file!</p>
+ * <p>In other words, the recommended use of this class is to use
+ * {@link #getEntries()} and invoke {@link #getInputStream(TarEntry)}
+ * only for the current entry. Basically, this is to handle it like
+ * {@link TarInputStream}.</p>
+ * <p>The advantage of this class is that you may write code for the
+ * {@link ArchiveFile}, which is valid for both tar files and zip files.</p>
+ */
+public class TarFile
+    implements ArchiveFile
+{
+    private final java.io.File file;
+    private TarInputStream inputStream;
+    private TarEntry currentEntry;
+
+    /**
+     * Creates a new instance with the given file.
+     */
+    public TarFile( File file )
+    {
+        this.file = file;
+    }
+
+    /**
+     * Implementation of {@link ArchiveFile#getEntries()}. Note, that there is
+     * an interaction between this method and {@link #getInputStream(TarEntry)},
+     * or {@link #getInputStream(org.apache.geronimo.system.plugin.plexus.archiver.ArchiveFile.Entry)}:
+     * If an input stream is opened for any other entry than the enumerations
+     * current entry, then entries may be skipped.
+     */
+    public Enumeration getEntries()
+        throws IOException
+    {
+        if ( inputStream != null )
+        {
+            close();
+        }
+        open();
+        return new Enumeration() {
+            boolean currentEntryValid;
+
+            public boolean hasMoreElements()
+            {
+                if ( !currentEntryValid )
+                {
+                    try
+                    {
+                        currentEntry = inputStream.getNextEntry();
+                    }
+                    catch ( IOException  e )
+                    {
+                        throw new UndeclaredThrowableException( e );
+                    }
+                }
+                return currentEntry != null;
+            }
+
+            public Object nextElement()
+            {
+                if ( currentEntry == null )
+                {
+                    throw new NoSuchElementException();
+                }
+                currentEntryValid = false;
+                return currentEntry;
+            }
+        };
+    }
+
+    public void close()
+        throws IOException
+    {
+        if ( inputStream != null )
+        {
+            inputStream.close();
+            inputStream = null;
+        }
+    }
+
+    public InputStream getInputStream( Entry entry )
+        throws IOException
+    {
+        return getInputStream( (TarEntry) entry );
+    }
+
+    /**
+     * Returns an {@link InputStream} with the given entries
+     * contents. This {@link InputStream} may be closed: Nothing
+     * happens in that case, because an actual close would invalidate
+     * the underlying {@link TarInputStream}.
+     */
+    public InputStream getInputStream( TarEntry entry )
+        throws IOException
+    {
+        if ( entry.equals( (Object) currentEntry )  &&  inputStream != null )
+        {
+            return new FilterInputStream( inputStream )
+            {
+                public void close() throws IOException
+                {
+                    // Does nothing.
+                }
+            };
+        }
+        return getInputStream( entry, currentEntry );
+    }
+
+    protected InputStream getInputStream( File file )
+        throws IOException
+    {
+        return new FileInputStream( file );
+    }
+    
+    private InputStream getInputStream( TarEntry entry, TarEntry currentEntry )
+        throws IOException
+    {
+        if ( currentEntry == null  ||  inputStream == null )
+        {
+            // Search for the entry from the beginning of the file to the end.
+            if ( inputStream != null )
+            {
+                close();
+            }
+            open();
+            if ( !findEntry( entry, null ) )
+            {
+                throw new IOException( "Unknown entry: " + entry.getName() );
+            }
+        }
+        else
+        {
+            // Search for the entry from the current position to the end of the file.
+            if ( findEntry( entry, null ) )
+            {
+                return getInputStream( entry );
+            }
+            close();
+            open();
+            if ( !findEntry( entry, currentEntry ) )
+            {
+                throw new IOException( "No such entry: " + entry.getName() );
+            }
+        }
+        return getInputStream( entry );
+    }
+
+    private void open()
+        throws IOException
+    {
+        inputStream = new TarInputStream( getInputStream( file ) );
+    }
+
+    private boolean findEntry( TarEntry entry, TarEntry currentEntry)
+        throws IOException
+    {
+        for (;;)
+        {
+            this.currentEntry = inputStream.getNextEntry();
+            if ( this.currentEntry == null
+                    ||  (currentEntry != null  &&  this.currentEntry.equals( currentEntry ) ) )
+            {
+                return false;
+            }
+            if ( this.currentEntry.equals( entry ) )
+            {
+                return true;
+            }
+        }
+    }
+}

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarFile.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarFile.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarFile.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarGZipUnArchiver.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarGZipUnArchiver.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarGZipUnArchiver.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarGZipUnArchiver.java Mon Oct  5 18:54:50 2009
@@ -0,0 +1,47 @@
+package org.apache.geronimo.system.plugin.plexus.archiver.tar;
+
+/**
+ *
+ * Copyright 2004 The Apache Software Foundation
+ *
+ *  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.
+ */
+
+import java.io.File;
+
+/**
+ * Extract files in tar with gzip compression
+ * @author <a href="mailto:dantran@gmail.com">Dan Tran</a>
+ * @version $Revision$
+ */
+public class TarGZipUnArchiver
+    extends TarUnArchiver
+{
+    public TarGZipUnArchiver()
+    {
+    	this.setupCompressionMethod();
+    }
+
+    public TarGZipUnArchiver( File sourceFile )
+    {
+        super( sourceFile );
+        this.setupCompressionMethod();
+    }
+    
+    private void setupCompressionMethod()
+    {
+    	UntarCompressionMethod untarCompressionMethod = new UntarCompressionMethod( UntarCompressionMethod.GZIP );
+    	this.setCompression( untarCompressionMethod );
+    }
+
+}

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarGZipUnArchiver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarGZipUnArchiver.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarGZipUnArchiver.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarInputStream.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarInputStream.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarInputStream.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarInputStream.java Mon Oct  5 18:54:50 2009
@@ -0,0 +1,437 @@
+package org.apache.geronimo.system.plugin.plexus.archiver.tar;
+
+/*
+ * Copyright  2000-2004 The Apache Software Foundation
+ *
+ *  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.
+ *
+ */
+
+/*
+ * This package is based on the work done by Timothy Gerard Endres
+ * (time@ice.com) to whom the Ant project is very grateful for his great code.
+ */
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * The TarInputStream reads a UNIX tar 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().
+ *
+ * @version $Revision$ $Date$
+ *          from org.apache.ant.tools.tar.TarInputStream v1.16
+ */
+public class TarInputStream
+    extends FilterInputStream
+{
+    protected boolean debug;
+
+    protected boolean hasHitEOF;
+
+    protected int entrySize;
+
+    protected int entryOffset;
+
+    protected byte[] oneBuf;
+
+    protected byte[] readBuf;
+
+    protected TarBuffer buffer;
+
+    protected TarEntry currEntry;
+
+    public TarInputStream( InputStream is )
+    {
+        this( is, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE );
+    }
+
+    public TarInputStream( InputStream is, int blockSize )
+    {
+        this( is, blockSize, TarBuffer.DEFAULT_RCDSIZE );
+    }
+
+    public TarInputStream( InputStream is, int blockSize, int recordSize )
+    {
+        super( is );
+
+        this.buffer = new TarBuffer( is, blockSize, recordSize );
+        this.readBuf = null;
+        this.oneBuf = new byte[1];
+        this.debug = false;
+        this.hasHitEOF = false;
+    }
+
+    /**
+     * Sets the debugging flag.
+     *
+     * @param debug True to turn on debugging.
+     */
+    public void setDebug( boolean debug )
+    {
+        this.debug = debug;
+        this.buffer.setDebug( debug );
+    }
+
+    /**
+     * Closes this stream. Calls the TarBuffer's close() method.
+     */
+    public void close()
+        throws IOException
+    {
+        this.buffer.close();
+    }
+
+    /**
+     * Get the record size being used by this stream's TarBuffer.
+     *
+     * @return The TarBuffer record size.
+     */
+    public int getRecordSize()
+    {
+        return this.buffer.getRecordSize();
+    }
+
+    /**
+     * Get the available data that can be read from the current
+     * entry in the archive. This does not indicate how much data
+     * is left in the entire archive, only in the current entry.
+     * This value is determined from the entry's size header field
+     * and the amount of data already read from the current entry.
+     *
+     * @return The number of available bytes for the current entry.
+     */
+    public int available()
+        throws IOException
+    {
+        return this.entrySize - this.entryOffset;
+    }
+
+    /**
+     * Skip bytes in the input buffer. This skips bytes in the
+     * current entry's data, not the entire archive, and will
+     * stop at the end of the current entry's data if the number
+     * to skip extends beyond that point.
+     *
+     * @param numToSkip The number of bytes to skip.
+     */
+    public long skip( long numToSkip )
+        throws IOException
+    {
+        // REVIEW
+        // This is horribly inefficient, but it ensures that we
+        // properly skip over bytes via the TarBuffer...
+        //
+        byte[] skipBuf = new byte[8 * 1024];
+        long skip = numToSkip;
+        while ( skip > 0 )
+        {
+            int realSkip = (int) ( skip > skipBuf.length ? skipBuf.length : skip );
+            int numRead = this.read( skipBuf, 0, realSkip );
+            if ( numRead == -1 )
+            {
+                break;
+            }
+            skip -= numRead;
+        }
+        return ( numToSkip - skip );
+    }
+
+    /**
+     * 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 )
+    {
+    }
+
+    /**
+     * Since we do not support marking just yet, we do nothing.
+     */
+    public void reset()
+    {
+    }
+
+    /**
+     * Get the next entry in this tar 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
+     * TarEntry 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 TarEntry in the archive, or null.
+     */
+    public TarEntry getNextEntry()
+        throws IOException
+    {
+        if ( this.hasHitEOF )
+        {
+            return null;
+        }
+
+        if ( this.currEntry != null )
+        {
+            int numToSkip = this.entrySize - this.entryOffset;
+
+            if ( this.debug )
+            {
+                System.err.println( "TarInputStream: SKIP currENTRY '"
+                                    + this.currEntry.getName() + "' SZ "
+                                    + this.entrySize + " OFF "
+                                    + this.entryOffset + "  skipping "
+                                    + numToSkip + " bytes" );
+            }
+
+            if ( numToSkip > 0 )
+            {
+                this.skip( numToSkip );
+            }
+
+            this.readBuf = null;
+        }
+
+        byte[] headerBuf = this.buffer.readRecord();
+
+        if ( headerBuf == null )
+        {
+            if ( this.debug )
+            {
+                System.err.println( "READ NULL RECORD" );
+            }
+            this.hasHitEOF = true;
+        }
+        else if ( this.buffer.isEOFRecord( headerBuf ) )
+        {
+            if ( this.debug )
+            {
+                System.err.println( "READ EOF RECORD" );
+            }
+            this.hasHitEOF = true;
+        }
+
+        if ( this.hasHitEOF )
+        {
+            this.currEntry = null;
+        }
+        else
+        {
+            this.currEntry = new TarEntry( headerBuf );
+
+            if ( this.debug )
+            {
+                System.err.println( "TarInputStream: SET CURRENTRY '"
+                                    + this.currEntry.getName()
+                                    + "' size = "
+                                    + this.currEntry.getSize() );
+            }
+
+            this.entryOffset = 0;
+
+            // REVIEW How do we resolve this discrepancy?!
+            this.entrySize = (int) this.currEntry.getSize();
+        }
+
+        if ( this.currEntry != null && this.currEntry.isGNULongNameEntry() )
+        {
+            // read in the name
+            StringBuffer longName = new StringBuffer();
+            byte[] buffer = new byte[256];
+            int length;
+            while ( ( length = read( buffer ) ) >= 0 )
+            {
+                longName.append( new String( buffer, 0, length ) );
+            }
+            getNextEntry();
+
+            // remove trailing null terminator
+            if ( longName.length() > 0
+                 && longName.charAt( longName.length() - 1 ) == 0 )
+            {
+                longName.deleteCharAt( longName.length() - 1 );
+            }
+            this.currEntry.setName( longName.toString() );
+        }
+
+        return this.currEntry;
+    }
+
+    /**
+     * Reads a byte from the current tar archive entry.
+     * <p/>
+     * This method simply calls read( byte[], int, int ).
+     *
+     * @return The byte read, or -1 at EOF.
+     */
+    public int read()
+        throws IOException
+    {
+        int num = this.read( this.oneBuf, 0, 1 );
+
+        if ( num == -1 )
+        {
+            return num;
+        }
+        else
+        {
+            return (int) this.oneBuf[ 0 ];
+        }
+    }
+
+    /**
+     * Reads bytes from the current tar archive entry.
+     * <p/>
+     * This method simply calls read( byte[], int, int ).
+     *
+     * @param buf The buffer into which to place bytes read.
+     * @return The number of bytes read, or -1 at EOF.
+     */
+    public int read( byte[] buf )
+        throws IOException
+    {
+        return this.read( buf, 0, buf.length );
+    }
+
+    /**
+     * Reads bytes from the current tar archive entry.
+     * <p/>
+     * 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 buf       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.
+     */
+    public int read( byte[] buf, int offset, int numToRead )
+        throws IOException
+    {
+        int totalRead = 0;
+
+        if ( this.entryOffset >= this.entrySize )
+        {
+            return -1;
+        }
+
+        if ( ( numToRead + this.entryOffset ) > this.entrySize )
+        {
+            numToRead = ( this.entrySize - this.entryOffset );
+        }
+
+        if ( this.readBuf != null )
+        {
+            int sz = ( numToRead > this.readBuf.length ) ? this.readBuf.length
+                     : numToRead;
+
+            System.arraycopy( this.readBuf, 0, buf, offset, sz );
+
+            if ( sz >= this.readBuf.length )
+            {
+                this.readBuf = null;
+            }
+            else
+            {
+                int newLen = this.readBuf.length - sz;
+                byte[] newBuf = new byte[newLen];
+
+                System.arraycopy( this.readBuf, sz, newBuf, 0, newLen );
+
+                this.readBuf = newBuf;
+            }
+
+            totalRead += sz;
+            numToRead -= sz;
+            offset += sz;
+        }
+
+        while ( numToRead > 0 )
+        {
+            byte[] rec = this.buffer.readRecord();
+
+            if ( rec == null )
+            {
+                // Unexpected EOF!
+                throw new IOException( "unexpected EOF with " + numToRead
+                                       + " bytes unread" );
+            }
+
+            int sz = numToRead;
+            int recLen = rec.length;
+
+            if ( recLen > sz )
+            {
+                System.arraycopy( rec, 0, buf, offset, sz );
+
+                this.readBuf = new byte[recLen - sz];
+
+                System.arraycopy( rec, sz, this.readBuf, 0, recLen - sz );
+            }
+            else
+            {
+                sz = recLen;
+
+                System.arraycopy( rec, 0, buf, offset, recLen );
+            }
+
+            totalRead += sz;
+            numToRead -= sz;
+            offset += sz;
+        }
+
+        this.entryOffset += totalRead;
+
+        return totalRead;
+    }
+
+    /**
+     * Copies the contents of the current tar archive entry directly into
+     * an output stream.
+     *
+     * @param out The OutputStream into which to write the entry's data.
+     */
+    public void copyEntryContents( OutputStream out )
+        throws IOException
+    {
+        byte[] buf = new byte[32 * 1024];
+
+        while ( true )
+        {
+            int numRead = this.read( buf, 0, buf.length );
+
+            if ( numRead == -1 )
+            {
+                break;
+            }
+
+            out.write( buf, 0, numRead );
+        }
+    }
+}

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarInputStream.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarInputStream.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarLongFileMode.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarLongFileMode.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarLongFileMode.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarLongFileMode.java Mon Oct  5 18:54:50 2009
@@ -0,0 +1,117 @@
+package org.apache.geronimo.system.plugin.plexus.archiver.tar;
+
+/*
+ * Copyright  2000-2004 The Apache Software Foundation
+ *
+ *  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.
+ *
+ */
+
+import org.apache.geronimo.system.plugin.plexus.archiver.ArchiverException;
+import org.apache.geronimo.system.plugin.plexus.archiver.util.EnumeratedAttribute;
+
+/**
+ * Set of options for long file handling in the task.
+ */
+public class TarLongFileMode
+    extends EnumeratedAttribute
+{
+
+    /**
+     * permissible values for longfile attribute
+     */
+    public static final String
+        WARN = "warn"
+
+    ,
+
+    FAIL = "fail"
+
+    ,
+
+    TRUNCATE = "truncate"
+
+    ,
+
+    GNU = "gnu"
+
+    ,
+
+    OMIT = "omit";
+
+    private final String[] validModes = {WARN, FAIL, TRUNCATE, GNU, OMIT};
+
+    /**
+     * Constructor, defaults to "warn"
+     */
+    public TarLongFileMode()
+    {
+        super();
+        try
+        {
+            setValue( WARN );
+        }
+        catch ( ArchiverException ae )
+        {
+            //Do nothing
+        }
+    }
+
+    /**
+     * @return the possible values for this enumerated type.
+     */
+    public String[] getValues()
+    {
+        return validModes;
+    }
+
+    /**
+     * @return true if value is "truncate".
+     */
+    public boolean isTruncateMode()
+    {
+        return TRUNCATE.equalsIgnoreCase( getValue() );
+    }
+
+    /**
+     * @return true if value is "warn".
+     */
+    public boolean isWarnMode()
+    {
+        return WARN.equalsIgnoreCase( getValue() );
+    }
+
+    /**
+     * @return true if value is "gnu".
+     */
+    public boolean isGnuMode()
+    {
+        return GNU.equalsIgnoreCase( getValue() );
+    }
+
+    /**
+     * @return true if value is "fail".
+     */
+    public boolean isFailMode()
+    {
+        return FAIL.equalsIgnoreCase( getValue() );
+    }
+
+    /**
+     * @return true if value is "omit".
+     */
+    public boolean isOmitMode()
+    {
+        return OMIT.equalsIgnoreCase( getValue() );
+    }
+}

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarLongFileMode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarLongFileMode.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarLongFileMode.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarOutputStream.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarOutputStream.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarOutputStream.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarOutputStream.java Mon Oct  5 18:54:50 2009
@@ -0,0 +1,370 @@
+package org.apache.geronimo.system.plugin.plexus.archiver.tar;
+
+/*
+ * Copyright  2000-2002,2004 The Apache Software Foundation
+ *
+ *  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.
+ *
+ */
+
+/*
+ * This package is based on the work done by Timothy Gerard Endres
+ * (time@ice.com) to whom the Ant project is very grateful for his great code.
+ */
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * The TarOutputStream writes a UNIX tar archive as an OutputStream.
+ * Methods are provided to put entries, and then write their contents
+ * by writing to this stream using write().
+ *
+ * @version $Revision$ $Date$
+ *          from org.apache.ant.tools.tar.TarOutputStream v1.16
+ */
+public class TarOutputStream
+    extends FilterOutputStream
+{
+    /**
+     * Fail if a long file name is required in the archive.
+     */
+    public static final int LONGFILE_ERROR = 0;
+
+    /**
+     * Long paths will be truncated in the archive.
+     */
+    public static final int LONGFILE_TRUNCATE = 1;
+
+    /**
+     * GNU tar extensions are used to store long file names in the archive.
+     */
+    public static final int LONGFILE_GNU = 2;
+
+    protected boolean debug;
+
+    protected int currSize;
+
+    protected int currBytes;
+
+    protected byte[] oneBuf;
+
+    protected byte[] recordBuf;
+
+    protected int assemLen;
+
+    protected byte[] assemBuf;
+
+    protected TarBuffer buffer;
+
+    protected int longFileMode = LONGFILE_ERROR;
+
+    public TarOutputStream( OutputStream os )
+    {
+        this( os, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE );
+    }
+
+    public TarOutputStream( OutputStream os, int blockSize )
+    {
+        this( os, blockSize, TarBuffer.DEFAULT_RCDSIZE );
+    }
+
+    public TarOutputStream( OutputStream os, int blockSize, int recordSize )
+    {
+        super( os );
+
+        this.buffer = new TarBuffer( os, blockSize, recordSize );
+        this.debug = false;
+        this.assemLen = 0;
+        this.assemBuf = new byte[recordSize];
+        this.recordBuf = new byte[recordSize];
+        this.oneBuf = new byte[1];
+    }
+
+    public void setLongFileMode( int longFileMode )
+    {
+        this.longFileMode = longFileMode;
+    }
+
+
+    /**
+     * Sets the debugging flag.
+     *
+     * @param debugF True to turn on debugging.
+     */
+    public void setDebug( boolean debugF )
+    {
+        this.debug = debugF;
+    }
+
+    /**
+     * Sets the debugging flag in this stream's TarBuffer.
+     *
+     * @param debug True to turn on debugging.
+     */
+    public void setBufferDebug( boolean debug )
+    {
+        this.buffer.setDebug( debug );
+    }
+
+    /**
+     * Ends the TAR archive without closing the underlying OutputStream.
+     * The result is that two EOF record of nulls are written.
+     */
+    public void finish()
+        throws IOException
+    {
+        this.writeEOFRecord();
+        this.writeEOFRecord();
+    }
+
+    /**
+     * Ends the TAR archive and closes the underlying OutputStream.
+     * This means that finish() is called followed by calling the
+     * TarBuffer's close().
+     */
+    public void close()
+        throws IOException
+    {
+        this.finish();
+        this.buffer.close();
+    }
+
+    /**
+     * Get the record size being used by this stream's TarBuffer.
+     *
+     * @return The TarBuffer record size.
+     */
+    public int getRecordSize()
+    {
+        return this.buffer.getRecordSize();
+    }
+
+    /**
+     * 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 TarEntry to be written to the archive.
+     */
+    public void putNextEntry( TarEntry entry )
+        throws IOException
+    {
+        if ( entry.getName().length() >= TarConstants.NAMELEN )
+        {
+
+            if ( longFileMode == LONGFILE_GNU )
+            {
+                // create a TarEntry for the LongLink, the contents
+                // of which are the entry's name
+                TarEntry longLinkEntry = new TarEntry( TarConstants.GNU_LONGLINK,
+                                                       TarConstants.LF_GNUTYPE_LONGNAME );
+
+                longLinkEntry.setSize( entry.getName().length() + 1 );
+                putNextEntry( longLinkEntry );
+                write( entry.getName().getBytes() );
+                write( 0 );
+                closeEntry();
+            }
+            else if ( longFileMode != LONGFILE_TRUNCATE )
+            {
+                throw new RuntimeException( "file name '" + entry.getName()
+                                            + "' is too long ( > "
+                                            + TarConstants.NAMELEN + " bytes)" );
+            }
+        }
+
+        entry.writeEntryHeader( this.recordBuf );
+        this.buffer.writeRecord( this.recordBuf );
+
+        this.currBytes = 0;
+
+        if ( entry.isDirectory() )
+        {
+            this.currSize = 0;
+        }
+        else
+        {
+            this.currSize = (int) entry.getSize();
+        }
+    }
+
+    /**
+     * 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.
+     */
+    public void closeEntry()
+        throws IOException
+    {
+        if ( this.assemLen > 0 )
+        {
+            for ( int i = this.assemLen; i < this.assemBuf.length; ++i )
+            {
+                this.assemBuf[ i ] = 0;
+            }
+
+            this.buffer.writeRecord( this.assemBuf );
+
+            this.currBytes += this.assemLen;
+            this.assemLen = 0;
+        }
+
+        if ( this.currBytes < this.currSize )
+        {
+            throw new IOException( "entry closed at '" + this.currBytes
+                                   + "' before the '" + this.currSize
+                                   + "' bytes specified in the header were written" );
+        }
+    }
+
+    /**
+     * Writes a byte to the current tar archive entry.
+     * <p/>
+     * This method simply calls read( byte[], int, int ).
+     *
+     * @param b The byte written.
+     */
+    public void write( int b )
+        throws IOException
+    {
+        this.oneBuf[ 0 ] = (byte) b;
+
+        this.write( this.oneBuf, 0, 1 );
+    }
+
+    /**
+     * Writes bytes to the current tar archive entry.
+     * <p/>
+     * This method simply calls write( byte[], int, int ).
+     *
+     * @param wBuf The buffer to write to the archive.
+     */
+    public void write( byte[] wBuf )
+        throws IOException
+    {
+        this.write( wBuf, 0, wBuf.length );
+    }
+
+    /**
+     * Writes bytes to the current tar archive entry. This method
+     * is aware of the current entry and will throw an exception if
+     * you attempt to write bytes past the length specified for the
+     * current entry. The method is also (painfully) aware of the
+     * record buffering required by TarBuffer, and manages buffers
+     * that are not a multiple of recordsize in length, including
+     * assembling records from small buffers.
+     *
+     * @param wBuf       The buffer to write to the archive.
+     * @param wOffset    The offset in the buffer from which to get bytes.
+     * @param numToWrite The number of bytes to write.
+     */
+    public void write( byte[] wBuf, int wOffset, int numToWrite )
+        throws IOException
+    {
+        if ( ( this.currBytes + numToWrite ) > this.currSize )
+        {
+            throw new IOException( "request to write '" + numToWrite
+                                   + "' bytes exceeds size in header of '"
+                                   + this.currSize + "' bytes" );
+
+            //
+            // We have to deal with assembly!!!
+            // The programmer can be writing little 32 byte chunks for all
+            // we know, and we must assemble complete records for writing.
+            // REVIEW Maybe this should be in TarBuffer? Could that help to
+            // eliminate some of the buffer copying.
+            //
+        }
+
+        if ( this.assemLen > 0 )
+        {
+            if ( ( this.assemLen + numToWrite ) >= this.recordBuf.length )
+            {
+                int aLen = this.recordBuf.length - this.assemLen;
+
+                System.arraycopy( this.assemBuf, 0, this.recordBuf, 0,
+                                  this.assemLen );
+                System.arraycopy( wBuf, wOffset, this.recordBuf,
+                                  this.assemLen, aLen );
+                this.buffer.writeRecord( this.recordBuf );
+
+                this.currBytes += this.recordBuf.length;
+                wOffset += aLen;
+                numToWrite -= aLen;
+                this.assemLen = 0;
+            }
+            else
+            {
+                System.arraycopy( wBuf, wOffset, this.assemBuf, this.assemLen,
+                                  numToWrite );
+
+                wOffset += numToWrite;
+                this.assemLen += numToWrite;
+                numToWrite -= numToWrite;
+            }
+        }
+
+        //
+        // When we get here we have EITHER:
+        // o An empty "assemble" buffer.
+        // o No bytes to write (numToWrite == 0)
+        //
+        while ( numToWrite > 0 )
+        {
+            if ( numToWrite < this.recordBuf.length )
+            {
+                System.arraycopy( wBuf, wOffset, this.assemBuf, this.assemLen,
+                                  numToWrite );
+
+                this.assemLen += numToWrite;
+
+                break;
+            }
+
+            this.buffer.writeRecord( wBuf, wOffset );
+
+            int num = this.recordBuf.length;
+
+            this.currBytes += num;
+            numToWrite -= num;
+            wOffset += num;
+        }
+    }
+
+    /**
+     * Write an EOF (end of archive) record to the tar archive.
+     * An EOF record consists of a record of all zeros.
+     */
+    private void writeEOFRecord()
+        throws IOException
+    {
+        for ( int i = 0; i < this.recordBuf.length; ++i )
+        {
+            this.recordBuf[ i ] = 0;
+        }
+
+        this.buffer.writeRecord( this.recordBuf );
+    }
+}
+
+

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarOutputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarOutputStream.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/archiver/tar/TarOutputStream.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message