You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by sc...@apache.org on 2008/04/23 03:34:43 UTC

svn commit: r650719 - in /webservices/commons/trunk/modules/axiom/modules: axiom-api/src/main/java/org/apache/axiom/attachments/ axiom-api/src/main/java/org/apache/axiom/om/util/ axiom-tests/src/test/java/org/apache/axiom/attachments/

Author: scheu
Date: Tue Apr 22 18:34:41 2008
New Revision: 650719

URL: http://svn.apache.org/viewvc?rev=650719&view=rev
Log:
WSCOMMONS-330
Contributor:Rich Scheuerle
Provide a mechanism to get the content length of the incoming message from the attachments object

Added:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/DetachableInputStream.java
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
    webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java?rev=650719&r1=650718&r2=650719&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java Tue Apr 22 18:34:41 2008
@@ -24,6 +24,7 @@
 import org.apache.axiom.attachments.lifecycle.impl.LifecycleManagerImpl;
 import org.apache.axiom.om.OMException;
 import org.apache.axiom.om.impl.MTOMConstants;
+import org.apache.axiom.om.util.DetachableInputStream;
 import org.apache.axiom.om.util.UUIDGenerator;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -64,6 +65,7 @@
      */
     PushbackInputStream pushbackInStream;
     int PUSHBACK_SIZE = 4 * 1024;
+    DetachableInputStream filterIS = null;
 
     /**
      * <code>attachmentsMap</code> stores the Data Handlers of the already parsed Mime Body Parts.
@@ -196,9 +198,14 @@
             throw new OMException(e);
         }
 
-        // do we need to wrap InputStream from a BufferedInputStream before
-        // wrapping from PushbackStream
-        pushbackInStream = new PushbackInputStream(inStream,
+        // If the length is not known, install a TeeInputStream
+        // so that we can retrieve it later.
+        InputStream is = inStream;
+        if (contentLength <= 0) {
+            filterIS = new DetachableInputStream(inStream);
+            is = filterIS;
+        }
+        pushbackInStream = new PushbackInputStream(is,
                                                    PUSHBACK_SIZE);
 
         // Move the read pointer to the beginning of the first part
@@ -498,7 +505,28 @@
     public List getContentIDList() {
         return cids;
     }
-
+    
+    /**
+     * If the Attachments is backed by an InputStream, then this
+     * method returns the length of the message contents
+     * (Length of the entire message - Length of the Transport Headers)
+     * @return length of message content or -1 if Attachments is not
+     * backed by an InputStream
+     * @see getMessageLength
+     */
+    public long getContentLength() throws IOException {
+        if (contentLength > 0) {
+            return contentLength;
+        } else if (filterIS != null) {
+            // Ensure all parts are read
+            this.getContentIDSet();
+            // Now get the count from the filter
+            return filterIS.length();
+        } else {
+            return -1; // not backed by an input stream
+        }
+    }
+    
     /**
      * endOfStreamReached will be set to true if the message ended in MIME Style having "--" suffix
      * with the last mime boundary

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/DetachableInputStream.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/DetachableInputStream.java?rev=650719&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/DetachableInputStream.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/DetachableInputStream.java Tue Apr 22 18:34:41 2008
@@ -0,0 +1,169 @@
+/*
+ * 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.axiom.om.util;
+
+import org.apache.axiom.attachments.impl.BufferUtils;
+import org.apache.axiom.attachments.utils.BAAInputStream;
+import org.apache.axiom.attachments.utils.BAAOutputStream;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * FilterInputStream that delegates to the original 
+ * InputStream.  When detach() is called, the original
+ * InputStream is consumed, and closed. The unread bytes are
+ * stored in a local stream.
+ * Subsequent requests are serviced by the local stream.
+ * 
+ * Rationale: The detached stream can be closed and its
+ * resources freed, but the consumer of the stream can 
+ * continue to receive data.
+ * 
+ * Cons: If there are a lot of bytes remaining, these are
+ * buffered.  Currently they are buffered incore (this
+ * could be improved to buffer in a file).
+ * 
+ */
+public class DetachableInputStream extends FilterInputStream {
+
+    
+
+    private long count = 0;
+    BAAInputStream localStream = null;
+    public DetachableInputStream(InputStream in) {
+        super(in);
+        count = 0;
+    }
+
+    /**
+     * @return count of bytes read
+     */
+    public long length() throws IOException {
+        if (localStream == null) {
+            detach();
+        }
+        return count;
+        
+    }
+    
+    /**
+     * Consume the input stream and close it.
+     * The bytes in the input stream are buffered.
+     * (Thus the original input stream can release its 
+     * resources, but the consumer of the stream can
+     * still receive data).
+     * @throws IOException
+     */
+    public void detach() throws IOException {
+        if (localStream == null) {
+
+            BAAOutputStream baaos = new BAAOutputStream();
+            BufferUtils.inputStream2OutputStream(in, baaos);
+            super.close();
+            in = null; // GC the incoming stream
+            
+            localStream = new BAAInputStream(baaos.buffers(), baaos.length());
+            count = count + baaos.length();
+        }
+    }
+
+    public int available() throws IOException {
+        if (localStream != null) {
+            return localStream.available();
+        } else {
+            return super.available();
+        }
+    }
+
+    public void close() throws IOException {
+        if (localStream != null) {
+            localStream.close();
+        } else {
+            super.close();
+        }
+    }
+
+    public boolean markSupported() {
+        // Mark is not supported because stream can
+        // switch
+        return false;
+    }
+    
+    public synchronized void mark(int readlimit) {
+        throw new UnsupportedOperationException();
+    }
+
+    public int read() throws IOException {
+        if (localStream == null) {
+            int rc = super.read();
+            if (rc != -1) {
+                count++;
+            }
+            return rc;
+        } else {
+            return localStream.read();
+        }
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException {
+        if (localStream == null) {
+            int rc = super.read(b, off, len);
+            if (rc > 0) {
+                count += rc;
+            }
+            return rc;
+        } else {
+            return localStream.read(b, off, len);
+        }
+    }
+
+    public int read(byte[] b) throws IOException {
+        if (localStream == null) {
+            int rc =  super.read(b);
+            if (rc > 0) {
+                count += rc;
+            }
+            return rc;
+        } else {
+            return localStream.read(b);
+        }
+    }
+
+    public synchronized void reset() throws IOException {
+        throw new IOException();
+    }
+
+    public long skip(long n) throws IOException {
+        if (localStream == null) {
+            long rc = super.skip(n);
+            if (rc > 0) {
+                count += rc;
+            }
+            return rc;
+        } else {
+            return localStream.skip(n);
+        }
+    }
+
+
+
+
+}

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java?rev=650719&r1=650718&r2=650719&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java Tue Apr 22 18:34:41 2008
@@ -24,6 +24,7 @@
 import javax.activation.DataHandler;
 import javax.activation.FileDataSource;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -145,11 +146,11 @@
 
         // Confirm that no more streams are left
         assertEquals(null, ias.getNextStream());
-
+        
         // After all is done, we should *still* be able to access and
         // re-consume the SOAP part stream, as it should be cached.. can we?
         is = attachments.getSOAPPartInputStream();
-        while (is.read() != -1) ;
+        while (is.read() != -1) ;  
     }
 
     private void compareStreams(InputStream data, InputStream expected) throws Exception {
@@ -190,7 +191,8 @@
 
     public void testGetAllContentIDs() throws Exception {
 
-        InputStream inStream = new FileInputStream(getTestResourceFile(inMimeFileName));
+        File f = getTestResourceFile(inMimeFileName);
+        InputStream inStream = new FileInputStream(f);
         Attachments attachments = new Attachments(inStream, contentTypeString);
 
         String[] contentIDs = attachments.getAllContentIDs();
@@ -203,6 +205,12 @@
         assertTrue(idSet.contains("0.urn:uuid:A3ADBAEE51A1A87B2A11443668160702@apache.org"));
         assertTrue(idSet.contains("2.urn:uuid:A3ADBAEE51A1A87B2A11443668160994@apache.org"));
         assertTrue(idSet.contains("1.urn:uuid:A3ADBAEE51A1A87B2A11443668160943@apache.org"));
+        
+        // Make sure the length is correct
+        long length = attachments.getContentLength();
+        long fileSize = f.length();
+        assertTrue("Expected MessageContent Length of " + fileSize + " but received " + length,
+                   length == fileSize);
     }
 
     /**