Author: veithen
Date: Sun Jul 12 20:52:39 2009
New Revision: 793405

URL: http://svn.apache.org/viewvc?rev=793405&view=rev
Log:
Optimized DataHandler->base64(String) transformation:
* Use available information about the size of the content to accurately 
allocate the initial capacity of the StringBuffer.
* Use DataHandler#writeTo because getInputStream will create a thread and a 
pipe if the DataHandler was constructed using an object instead of a DataSource.

Added:
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/activation/
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/activation/DataSourceUtils.java
   (with props)
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64StringBufferOutputStream.java
   (with props)
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64Utils.java
   (with props)
Modified:
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/SizeAwareDataSource.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/SizeAwareDataSource.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/SizeAwareDataSource.java?rev=793405&r1=793404&r2=793405&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/SizeAwareDataSource.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/SizeAwareDataSource.java
 Sun Jul 12 20:52:39 2009
@@ -24,9 +24,10 @@
 /**
  * Optional extension interface that can be implemented by data sources that 
support a
  * getSize method.
- * Code working with data sources can use this interface to optimize certain 
operations.
- * An example is
- * {...@link 
org.apache.axiom.attachments.impl.BufferUtils#doesDataHandlerExceedLimit(javax.activation.DataHandler,
 int)}.
+ * Code working with data sources can use this this information to optimize 
certain operations.
+ * Note however that instead of checking of this interface directly, this kind 
of code
+ * should use {...@link 
org.apache.axiom.util.activation.DataSourceUtils#getSize(DataSource)}
+ * because this method is able to determine the size of other types of data 
sources as well.
  * <p>
  * Code using this interface should be aware that some implementations may be 
unable to guarantee
  * 100% accuracy when determining the size of the data source. Situations 
where this can occur

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java?rev=793405&r1=793404&r2=793405&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java
 Sun Jul 12 20:52:39 2009
@@ -18,7 +18,6 @@
  */
 package org.apache.axiom.attachments.impl;
 
-import java.io.ByteArrayInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -28,11 +27,9 @@
 import java.nio.channels.FileLock;
 
 import javax.activation.DataHandler;
-import javax.activation.DataSource;
-import javax.activation.FileDataSource;
 
-import org.apache.axiom.attachments.SizeAwareDataSource;
 import org.apache.axiom.attachments.utils.BAAOutputStream;
+import org.apache.axiom.util.activation.DataSourceUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -277,28 +274,9 @@
         if(limit==0){
             return -1;
         }
-        DataSource ds = dh.getDataSource();
-        if (ds instanceof SizeAwareDataSource) {
-            long size = ((SizeAwareDataSource)ds).getSize();
-            if (size != -1) {
-                return size > limit ? 1 : 0;
-            }
-        }
-        if (ds instanceof javax.mail.util.ByteArrayDataSource) {
-            // Special optimization for JavaMail's ByteArrayDataSource 
(Axiom's ByteArrayDataSource
-            // already implements SizeAwareDataSource and doesn't need further 
optimization):
-            // we know that ByteArrayInputStream#available() directly returns 
the size of the
-            // data source.
-            try {
-                return ((ByteArrayInputStream)ds.getInputStream()).available() 
> limit ? 1 : 0;
-            } catch (IOException ex) {
-                // We will never get here...
-                return -1;
-            }
-        } else if (ds instanceof FileDataSource) {
-            // Special optimization for FileDataSources: no need to open and 
read the file
-            // to know its size!
-            return ((FileDataSource)ds).getFile().length() > limit ? 1 : 0;
+        long size = DataSourceUtils.getSize(dh.getDataSource());
+        if (size != -1) {
+            return size > limit ? 1 : 0;
         } else {
             // In all other cases, we prefer DataHandler#writeTo over 
DataSource#getInputStream.
             // The reason is that if the DataHandler was constructed from an 
Object rather than

Added: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/activation/DataSourceUtils.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/activation/DataSourceUtils.java?rev=793405&view=auto
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/activation/DataSourceUtils.java
 (added)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/activation/DataSourceUtils.java
 Sun Jul 12 20:52:39 2009
@@ -0,0 +1,71 @@
+/*
+ * 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.util.activation;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.activation.DataSource;
+import javax.activation.FileDataSource;
+import javax.mail.util.ByteArrayDataSource;
+
+import org.apache.axiom.attachments.SizeAwareDataSource;
+
+/**
+ * Contains utility methods to work with {...@link DataSource} objects.
+ */
+public class DataSourceUtils {
+    /**
+     * Determine the size of the data represented by a {...@link DataSource} 
object.
+     * The method will try to determine the size without reading the data 
source.
+     * It will do so by looking for the {...@link SizeAwareDataSource} 
interface. In addition, it
+     * supports some other well known data source implementations for which it 
is possible to
+     * get the size of the data without reading it.
+     * <p>
+     * As noted in the documentation of the {...@link SizeAwareDataSource}, 
the returned value
+     * may be an estimation that is not 100% accurate, and code using this 
method must be prepared
+     * to receive more or less data from the data source.
+     * 
+     * @param ds the data source
+     * @return (an estimation of) the size of the data or <code>-1</code> if 
the size is unknown
+     */
+    public static long getSize(DataSource ds) {
+        if (ds instanceof SizeAwareDataSource) {
+            return ((SizeAwareDataSource)ds).getSize();
+        } else if (ds instanceof ByteArrayDataSource) {
+            // Special optimization for JavaMail's ByteArrayDataSource 
(Axiom's ByteArrayDataSource
+            // already implements SizeAwareDataSource and doesn't need further 
optimization):
+            // we know that ByteArrayInputStream#available() directly returns 
the size of the
+            // data source.
+            try {
+                return ((ByteArrayInputStream)ds.getInputStream()).available();
+            } catch (IOException ex) {
+                // We will never get here...
+                return -1;
+            }
+        } else if (ds instanceof FileDataSource) {
+            // Special optimization for FileDataSources: no need to open and 
read the file
+            // to know its size!
+            return ((FileDataSource)ds).getFile().length();
+        } else {
+            return -1;
+        }
+    }
+}

Propchange: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/activation/DataSourceUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64StringBufferOutputStream.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64StringBufferOutputStream.java?rev=793405&view=auto
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64StringBufferOutputStream.java
 (added)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64StringBufferOutputStream.java
 Sun Jul 12 20:52:39 2009
@@ -0,0 +1,57 @@
+/*
+ * 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.util.base64;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * {...@link OutputStream} implementation that writes base64 encoded data to a 
{...@link StringBuffer}.
+ */
+public class Base64StringBufferOutputStream extends AbstractBase64OutputStream 
{
+    private final StringBuffer buffer;
+
+    /**
+     * Constructor.
+     * 
+     * @param buffer the buffer to append the encoded data to
+     */
+    public Base64StringBufferOutputStream(StringBuffer buffer) {
+        this.buffer = buffer;
+    }
+
+    protected void doWrite(byte[] b) throws IOException {
+        for (int i=0; i<4; i++) {
+            buffer.append((char)(b[i] & 0xFF));
+        }
+    }
+
+    protected void flushBuffer() throws IOException {
+        // Nothing to do
+    }
+    
+    protected void doClose() throws IOException {
+        // Nothing to do
+    }
+
+    protected void doFlush() throws IOException {
+        // Nothing to do
+    }
+}

Propchange: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64StringBufferOutputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64Utils.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64Utils.java?rev=793405&view=auto
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64Utils.java
 (added)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64Utils.java
 Sun Jul 12 20:52:39 2009
@@ -0,0 +1,62 @@
+/*
+ * 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.util.base64;
+
+import java.io.IOException;
+
+import javax.activation.DataHandler;
+
+import org.apache.axiom.util.activation.DataSourceUtils;
+
+/**
+ * Contains utility methods to work with base64 encoded data.
+ */
+public class Base64Utils {
+    private static int getEncodedSize(int unencodedSize) {
+        return (unencodedSize+2) / 3 * 4;
+    }
+    
+    /**
+     * Get a base64 representation of the content of a given {...@link 
DataHandler}.
+     * This method will try to carry out the encoding operation in the most 
efficient way.
+     * 
+     * @param dh the data handler with the content to encode
+     * @return the base64 encoded content
+     * @throws IOException if an I/O error occurs when reading the content of 
the data handler
+     */
+    public static String encode(DataHandler dh) throws IOException {
+        long size = DataSourceUtils.getSize(dh.getDataSource());
+        StringBuffer buffer;
+        if (size == -1) {
+            // Use a reasonable default capacity (better than the default of 
16).
+            buffer = new StringBuffer(4096);
+        } else if (size > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("DataHandler is too large to 
encode to string");
+        } else {
+            buffer = new StringBuffer(getEncodedSize((int)size));
+        }
+        Base64StringBufferOutputStream out = new 
Base64StringBufferOutputStream(buffer);
+        // Always prefer writeTo, because getInputStream will create a thread 
and a pipe if
+        // the DataHandler was constructed using an object instead of a 
DataSource
+        dh.writeTo(out);
+        out.complete();
+        return buffer.toString();
+    }
+}

Propchange: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/base64/Base64Utils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java?rev=793405&r1=793404&r2=793405&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
 Sun Jul 12 20:52:39 2009
@@ -20,7 +20,6 @@
 package org.apache.axiom.util.stax.xop;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 
@@ -34,7 +33,7 @@
 import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
 import org.apache.axiom.ext.stax.datahandler.DataHandlerReader;
 import org.apache.axiom.om.util.StAXUtils;
-import org.apache.axiom.om.util.TextHelper;
+import org.apache.axiom.util.base64.Base64Utils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -390,13 +389,7 @@
 
     private static String toBase64(DataHandler dh) throws XMLStreamException {
         try {
-            InputStream in = dh.getInputStream();
-            try {
-                // TODO: we should also move the base64 stuff to 
org.apache.axiom.util
-                return TextHelper.toString(in);
-            } finally {
-                in.close();
-            }
+            return Base64Utils.encode(dh);
         } catch (IOException ex) {
             throw new XMLStreamException("Exception when encoding data handler 
as base64", ex);
         }

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java?rev=793405&r1=793404&r2=793405&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java
 Sun Jul 12 20:52:39 2009
@@ -34,6 +34,7 @@
 import org.apache.axiom.om.impl.builder.XOPBuilder;
 import org.apache.axiom.om.util.TextHelper;
 import org.apache.axiom.om.util.UUIDGenerator;
+import org.apache.axiom.util.base64.Base64Utils;
 import org.apache.axiom.util.stax.XMLStreamWriterUtil;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Node;
@@ -363,7 +364,7 @@
             return getTextFromProperPlace();
         } else {
             try {
-                return TextHelper.toString(getInputStream());
+                return Base64Utils.encode((DataHandler)getDataHandler());
             } catch (Exception e) {
                 throw new OMException(e);
             }
@@ -413,7 +414,8 @@
             return new QName(getTextFromProperPlace());
         } else {
             try {
-                return new QName(TextHelper.toString(getInputStream()));
+                // TODO: do we really want to build a QName from base64 
encoded data?!?
+                return new 
QName(Base64Utils.encode((DataHandler)getDataHandler()));
             } catch (Exception e) {
                 throw new OMException(e);
             }

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java?rev=793405&r1=793404&r2=793405&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java
 Sun Jul 12 20:52:39 2009
@@ -34,8 +34,8 @@
 import org.apache.axiom.om.impl.OMNamespaceImpl;
 import org.apache.axiom.om.impl.builder.XOPBuilder;
 import org.apache.axiom.om.impl.util.OMSerializerUtil;
-import org.apache.axiom.om.util.TextHelper;
 import org.apache.axiom.om.util.UUIDGenerator;
+import org.apache.axiom.util.base64.Base64Utils;
 import org.apache.axiom.util.stax.XMLStreamWriterUtil;
 
 import javax.activation.DataHandler;
@@ -285,7 +285,7 @@
             return getTextFromProperPlace();
         } else {
             try {
-                return TextHelper.toString(getInputStream());
+                return Base64Utils.encode((DataHandler)getDataHandler());
             } catch (Exception e) {
                 throw new OMException(e);
             }


Reply via email to