provide archive name if anything goes wrong extracting stuff from 7z archives

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/compress/trunk@1653264 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/AES256SHA256Decoder.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/AES256SHA256Decoder.java
index 91fb486..66d9d96 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/AES256SHA256Decoder.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/AES256SHA256Decoder.java
@@ -30,7 +30,7 @@
 
 class AES256SHA256Decoder extends CoderBase {
     @Override
-    InputStream decode(final InputStream in, long uncompressedLength,
+    InputStream decode(final String archiveName, final InputStream in, long uncompressedLength,
             final Coder coder, final byte[] passwordBytes) throws IOException {
         return new InputStream() {
             private boolean isInitialized = false;
@@ -46,7 +46,7 @@
                 final int ivSize = ((byte0 >> 6) & 1) + (byte1 & 0x0f);
                 final int saltSize = ((byte0 >> 7) & 1) + (byte1 >> 4);
                 if (2 + saltSize + ivSize > coder.properties.length) {
-                    throw new IOException("Salt size + IV size too long");
+                    throw new IOException("Salt size + IV size too long in " + archiveName);
                 }
                 final byte[] salt = new byte[saltSize];
                 System.arraycopy(coder.properties, 2, salt, 0, saltSize);
@@ -54,7 +54,7 @@
                 System.arraycopy(coder.properties, 2 + saltSize, iv, 0, ivSize);
 
                 if (passwordBytes == null) {
-                    throw new PasswordRequiredException();
+                    throw new PasswordRequiredException(archiveName);
                 }
                 final byte[] aesKeyBytes;
                 if (numCyclesPower == 0x3f) {
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/CoderBase.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/CoderBase.java
index a871e52..286cc03 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/CoderBase.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/CoderBase.java
@@ -64,7 +64,8 @@
     /**
      * @return a stream that reads from in using the configured coder and password.
      */
-    abstract InputStream decode(final InputStream in, long uncomressedLength,
+    abstract InputStream decode(final String archiveName,
+        final InputStream in, long uncomressedLength,
         final Coder coder, byte[] password) throws IOException;
 
     /**
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java
index c488dea..fad904c 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java
@@ -67,14 +67,15 @@
         return CODER_MAP.get(method);
     }
 
-    static InputStream addDecoder(final InputStream is, long uncompressedLength,
+    static InputStream addDecoder(final String archiveName, final InputStream is, long uncompressedLength,
             final Coder coder, final byte[] password) throws IOException {
         CoderBase cb = findByMethod(SevenZMethod.byId(coder.decompressionMethodId));
         if (cb == null) {
             throw new IOException("Unsupported compression method " +
-                                  Arrays.toString(coder.decompressionMethodId));
+                                  Arrays.toString(coder.decompressionMethodId)
+                                  + " used in " + archiveName);
         }
-        return cb.decode(is, uncompressedLength, coder, password);
+        return cb.decode(archiveName, is, uncompressedLength, coder, password);
     }
     
     static OutputStream addEncoder(final OutputStream out, final SevenZMethod method,
@@ -88,7 +89,7 @@
 
     static class CopyDecoder extends CoderBase {
         @Override
-        InputStream decode(final InputStream in, long uncompressedLength,
+        InputStream decode(final String archiveName, final InputStream in, long uncompressedLength,
                 final Coder coder, byte[] password) throws IOException {
             return in; 
         }
@@ -100,7 +101,7 @@
 
     static class LZMADecoder extends CoderBase {
         @Override
-        InputStream decode(final InputStream in, long uncompressedLength,
+        InputStream decode(final String archiveName, final InputStream in, long uncompressedLength,
                 final Coder coder, byte[] password) throws IOException {
             byte propsByte = coder.properties[0];
             long dictSize = coder.properties[1];
@@ -108,7 +109,7 @@
                 dictSize |= (coder.properties[i + 1] & 0xffl) << (8 * i);
             }
             if (dictSize > LZMAInputStream.DICT_SIZE_MAX) {
-                throw new IOException("Dictionary larger than 4GiB maximum size");
+                throw new IOException("Dictionary larger than 4GiB maximum size used in " + archiveName);
             }
             return new LZMAInputStream(in, uncompressedLength, propsByte, (int) dictSize);
         }
@@ -121,12 +122,13 @@
         }
 
         @Override
-        InputStream decode(final InputStream in, long uncompressedLength,
+        InputStream decode(final String archiveName, final InputStream in, long uncompressedLength,
                 final Coder coder, byte[] password) throws IOException {
             try {
                 return opts.getInputStream(in);
             } catch (AssertionError e) {
-                IOException ex = new IOException("BCJ filter needs XZ for Java > 1.4 - see "
+                IOException ex = new IOException("BCJ filter used in " + archiveName
+                                                 + " needs XZ for Java > 1.4 - see "
                                                  + "http://commons.apache.org/proper/commons-compress/limitations.html#7Z");
                 ex.initCause(e);
                 throw ex;
@@ -149,7 +151,7 @@
         }
 
         @Override
-        InputStream decode(final InputStream in, long uncompressedLength,
+        InputStream decode(final String archiveName, final InputStream in, long uncompressedLength,
                 final Coder coder, final byte[] password)
             throws IOException {
             return new InflaterInputStream(new DummyByteAddingInputStream(in),
@@ -168,7 +170,7 @@
         }
 
         @Override
-        InputStream decode(final InputStream in, long uncompressedLength,
+        InputStream decode(final String archiveName, final InputStream in, long uncompressedLength,
                 final Coder coder, final byte[] password)
                 throws IOException {
             return new BZip2CompressorInputStream(in);
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/DeltaDecoder.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/DeltaDecoder.java
index 7951e71..e458334 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/DeltaDecoder.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/DeltaDecoder.java
@@ -30,7 +30,7 @@
     }
 
     @Override
-    InputStream decode(final InputStream in, long uncompressedLength,
+    InputStream decode(final String archiveName, final InputStream in, long uncompressedLength,
             final Coder coder, byte[] password) throws IOException {
         return new DeltaOptions(getOptionsFromCoder(coder)).getInputStream(in);
     }
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java
index 7df09f8..d3ffe31 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java
@@ -32,7 +32,7 @@
     }
 
     @Override
-    InputStream decode(final InputStream in, long uncompressedLength,
+    InputStream decode(final String archiveName, final InputStream in, long uncompressedLength,
             final Coder coder, byte[] password) throws IOException {
         try {
             int dictionarySize = getDictionarySize(coder);
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/PasswordRequiredException.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/PasswordRequiredException.java
index 8814d3d..8352443 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/PasswordRequiredException.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/PasswordRequiredException.java
@@ -26,7 +26,7 @@
  */
 public class PasswordRequiredException extends IOException {
 
-    public PasswordRequiredException() {
-        super("Cannot read encrypted files without a password");
+    public PasswordRequiredException(String archiveName) {
+        super("Cannot read encrypted archive " + archiveName + " without a password.");
     }
 }
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
index a8c368c..398783f 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
@@ -67,6 +67,7 @@
 public class SevenZFile implements Closeable {
     static final int SIGNATURE_HEADER_SIZE = 32;
 
+    private final String fileName;
     private RandomAccessFile file;
     private final Archive archive;
     private int currentEntryIndex = -1;
@@ -91,6 +92,7 @@
     public SevenZFile(final File filename, final byte[] password) throws IOException {
         boolean succeeded = false;
         this.file = new RandomAccessFile(filename, "r");
+        this.fileName = filename.getAbsolutePath();
         try {
             archive = readHeaders(password);
             if (password != null) {
@@ -276,8 +278,8 @@
             if (coder.numInStreams != 1 || coder.numOutStreams != 1) {
                 throw new IOException("Multi input/output stream coders are not yet supported");
             }
-            inputStreamStack = Coders.addDecoder(inputStreamStack, folder.getUnpackSizeForCoder(coder),
-                    coder, password);
+            inputStreamStack = Coders.addDecoder(fileName, inputStreamStack,
+                    folder.getUnpackSizeForCoder(coder), coder, password);
         }
         if (folder.hasCrc) {
             inputStreamStack = new CRC32VerifyingInputStream(inputStreamStack,
@@ -859,8 +861,8 @@
                 throw new IOException("Multi input/output stream coders are not yet supported");
             }
             SevenZMethod method = SevenZMethod.byId(coder.decompressionMethodId);
-            inputStreamStack = Coders.addDecoder(inputStreamStack, folder.getUnpackSizeForCoder(coder),
-                    coder, password);
+            inputStreamStack = Coders.addDecoder(fileName, inputStreamStack,
+                    folder.getUnpackSizeForCoder(coder), coder, password);
             methods.addFirst(new SevenZMethodConfiguration(method,
                      Coders.findByMethod(method).getOptionsFromCoder(coder, inputStreamStack)));
         }
diff --git a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
index bc84d44..dd50de8 100644
--- a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
@@ -60,15 +60,6 @@
         }
     }
 
-    public void test7zDecryptUnarchiveWithoutPassword() throws Exception {
-        try {
-            test7zUnarchive(getFile("bla.encrypted.7z"), SevenZMethod.LZMA);
-            fail("Expected a PasswordRequiredException");
-        } catch (PasswordRequiredException ex) {
-            // expected
-        }
-    }
-
     private void test7zUnarchive(File f, SevenZMethod m) throws Exception {
         test7zUnarchive(f, m, null);
     }
@@ -77,9 +68,14 @@
         try {
             new SevenZFile(getFile("bla.encrypted.7z"));
             fail("shouldn't decrypt without a password");
-        } catch (IOException ex) {
-            assertEquals("Cannot read encrypted files without a password",
-                         ex.getMessage());
+        } catch (PasswordRequiredException ex) {
+            String msg = ex.getMessage();
+            assertTrue("Should start with whining about being unable to decrypt",
+                       msg.startsWith("Cannot read encrypted archive "));
+            assertTrue("Should finish the sentence properly",
+                       msg.endsWith(" without a password."));
+            assertTrue("Should contain archive's name",
+                       msg.contains("bla.encrypted.7z"));
         }
     }