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);
}