Author: bodewig
Date: Mon Aug  8 11:39:41 2011
New Revision: 1154928

URL: http://svn.apache.org/viewvc?rev=1154928&view=rev
Log:
support writing of BSD dialect AR archives with long file names.  COMPRESS-144

Added:
    
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java
   (with props)
Modified:
    commons/proper/compress/trunk/src/changes/changes.xml
    
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
    
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java
    commons/proper/compress/trunk/src/site/xdoc/examples.xml

Modified: commons/proper/compress/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/changes/changes.xml?rev=1154928&r1=1154927&r2=1154928&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/changes/changes.xml (original)
+++ commons/proper/compress/trunk/src/changes/changes.xml Mon Aug  8 11:39:41 
2011
@@ -46,6 +46,10 @@ The <action> type attribute can be add,u
   <body>
     <release version="1.3" date="unreleased"
              description="Release 1.3 - API compatible to 1.2 but requires 
Java5 at runtime">
+      <action issue="COMPRESS-144" type="update" date="2011-08-08">
+        The AR package now supports the BSD dialect of storing file
+        names longer than 16 chars (both reading and writing).
+      </action> 
       <action type="fix" date="2011-08-08">
         BZip2CompressorInputStream's getBytesRead method always
         returned 0.

Modified: 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java?rev=1154928&r1=1154927&r2=1154928&view=diff
==============================================================================
--- 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
 (original)
+++ 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
 Mon Aug  8 11:39:41 2011
@@ -304,7 +304,7 @@ public class ArArchiveInputStream extend
         return true;
     }
 
-    private static final String BSD_LONGNAME_PREFIX = "#1/";
+    static final String BSD_LONGNAME_PREFIX = "#1/";
     private static final int BSD_LONGNAME_PREFIX_LEN =
         BSD_LONGNAME_PREFIX.length();
     private static final String BSD_LONGNAME_PATTERN =

Modified: 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java?rev=1154928&r1=1154927&r2=1154928&view=diff
==============================================================================
--- 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java
 (original)
+++ 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java
 Mon Aug  8 11:39:41 2011
@@ -32,13 +32,19 @@ import org.apache.commons.compress.utils
  * @NotThreadSafe
  */
 public class ArArchiveOutputStream extends ArchiveOutputStream {
+    /** Fail if a long file name is required in the archive. */
+    public static final int LONGFILE_ERROR = 0;
+
+    /** BSD ar extensions are used to store long file names in the archive. */
+    public static final int LONGFILE_BSD = 1;
 
     private final OutputStream out;
     private long archiveOffset = 0;
     private long entryOffset = 0;
     private ArArchiveEntry prevEntry;
     private boolean haveUnclosedEntry = false;
-    
+    private int longFileMode = LONGFILE_ERROR;
+
     /** indicates if this archive is finished */
     private boolean finished = false;
 
@@ -46,6 +52,18 @@ public class ArArchiveOutputStream exten
         this.out = pOut;
     }
 
+    /**
+     * Set the long file mode.
+     * This can be LONGFILE_ERROR(0) or LONGFILE_BSD(1).
+     * This specifies the treatment of long file names (names >= 16).
+     * Default is LONGFILE_ERROR.
+     * @param longFileMode the mode to use
+     * @since Apache Commons Compress 1.3
+     */
+    public void setLongFileMode(int longFileMode) {
+        this.longFileMode = longFileMode;
+    }
+
     private long writeArchiveHeader() throws IOException {
         byte [] header = ArchiveUtils.toAsciiBytes(ArArchiveEntry.HEADER);
         out.write(header);
@@ -74,7 +92,7 @@ public class ArArchiveOutputStream exten
         if(finished) {
             throw new IOException("Stream has already been finished");
         }
-        
+
         ArArchiveEntry pArEntry = (ArArchiveEntry)pEntry;
         if (prevEntry == null) {
             archiveOffset += writeArchiveHeader();
@@ -117,12 +135,20 @@ public class ArArchiveOutputStream exten
     private long writeEntryHeader( final ArArchiveEntry pEntry ) throws 
IOException {
 
         long offset = 0;
+        boolean mustAppendName = false;
 
         final String n = pEntry.getName();
-        if (n.length() > 16) {
+        if (LONGFILE_ERROR == longFileMode && n.length() > 16) {
             throw new IOException("filename too long, > 16 chars: "+n);
         }
-        offset += write(n);
+        if (LONGFILE_BSD == longFileMode && 
+            (n.length() > 16 || n.indexOf(" ") > -1)) {
+            mustAppendName = true;
+            offset += write(ArArchiveInputStream.BSD_LONGNAME_PREFIX
+                            + String.valueOf(n.length()));
+        } else {
+            offset += write(n);
+        }
 
         offset = fill(offset, 16, ' ');
         final String m = "" + (pEntry.getLastModified());
@@ -153,7 +179,9 @@ public class ArArchiveOutputStream exten
         offset += write(fm);
 
         offset = fill(offset, 48, ' ');
-        final String s = "" + pEntry.getLength();
+        final String s =
+            String.valueOf(pEntry.getLength()
+                           + (mustAppendName ? n.length() : 0));
         if (s.length() > 10) {
             throw new IOException("size too long");
         }
@@ -163,6 +191,10 @@ public class ArArchiveOutputStream exten
 
         offset += write(ArArchiveEntry.TRAILER);
 
+        if (mustAppendName) {
+            offset += write(n);
+        }
+
         return offset;
     }
 

Modified: commons/proper/compress/trunk/src/site/xdoc/examples.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/site/xdoc/examples.xml?rev=1154928&r1=1154927&r2=1154928&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/site/xdoc/examples.xml (original)
+++ commons/proper/compress/trunk/src/site/xdoc/examples.xml Mon Aug  8 
11:39:41 2011
@@ -100,9 +100,10 @@ LOOP UNTIL entry.getSize() HAS BEEN READ
           this limitation in different ways, the GNU/SRV4 and the BSD
           variant.  Commons Compress 1.0 to 1.2 can only read archives
           using the GNU/SRV4 variant, support for the BSD variant has
-          been added in Commons Compress 1.3.  It doesn't support
-          writing archives with file names longer than 16 characters
-          at all.</p>
+          been added in Commons Compress 1.3.  Commons Compress 1.3
+          also optionally supports writing archives with file names
+          longer than 16 characters using the BSD dialect, writing
+          the SVR4/GNU dialect is not supported.</p>
 
       </subsection>
 

Added: 
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java?rev=1154928&view=auto
==============================================================================
--- 
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java
 (added)
+++ 
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java
 Mon Aug  8 11:39:41 2011
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.commons.compress.archivers.ar;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.compress.AbstractTestCase;
+
+public class ArArchiveOutputStreamTest extends AbstractTestCase {
+
+    public void testLongFileNamesCauseExceptionByDefault() {
+        try {
+            ArArchiveOutputStream os =
+                new ArArchiveOutputStream(new ByteArrayOutputStream());
+            ArArchiveEntry ae = new ArArchiveEntry("this_is_a_long_name.txt",
+                                                   0);
+            os.putArchiveEntry(ae);
+            fail("Expected an exception");
+        } catch (IOException ex) {
+            assertTrue(ex.getMessage().startsWith("filename too long"));
+        }
+    }
+
+    public void testLongFileNamesWorkUsingBSDDialect() throws Exception {
+        FileOutputStream fos = null;
+        ArArchiveOutputStream os = null;
+        File[] df = createTempDirAndFile();
+        try {
+            fos = new FileOutputStream(df[1]);
+            os = new ArArchiveOutputStream(fos);
+            os.setLongFileMode(ArArchiveOutputStream.LONGFILE_BSD);
+            ArArchiveEntry ae = new ArArchiveEntry("this_is_a_long_name.txt",
+                                                   14);
+            os.putArchiveEntry(ae);
+            os.write(new byte[] {
+                    'H', 'e', 'l', 'l', 'o', ',', ' ',
+                    'w', 'o', 'r', 'l', 'd', '!', '\n'
+                });
+            os.closeArchiveEntry();
+            os.close();
+            os = null;
+            fos = null;
+
+            List<String> expected = new ArrayList<String>();
+            expected.add("this_is_a_long_name.txt");
+            checkArchiveContent(df[1], expected);
+        } finally {
+            if (os != null) {
+                os.close();
+            }
+            if (fos != null) {
+                fos.close();
+            }
+            rmdir(df[0]);
+        }
+    }
+}
\ No newline at end of file

Propchange: 
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to