You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by ve...@apache.org on 2022/10/31 23:08:19 UTC

[ws-axiom] branch master updated: [AXIOM-506] Add code to convert between Blob and DataHandler

This is an automated email from the ASF dual-hosted git repository.

veithen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-axiom.git


The following commit(s) were added to refs/heads/master by this push:
     new 21210fa65 [AXIOM-506] Add code to convert between Blob and DataHandler
21210fa65 is described below

commit 21210fa65c0559051e08ecf887275830bbb5cd19
Author: Andreas Veithen <an...@gmail.com>
AuthorDate: Mon Oct 31 23:08:08 2022 +0000

    [AXIOM-506] Add code to convert between Blob and DataHandler
---
 .../axiom/util/activation/BlobDataSource.java      |  5 ++
 ...OutputStream.java => CountingOutputStream.java} | 18 ++++--
 .../axiom/util/activation/DataHandlerBlob.java     | 72 ++++++++++++++++++++++
 .../axiom/util/activation/DataHandlerUtils.java    | 33 +++++++++-
 .../activation/SizeLimitExceededException.java     |  2 +-
 5 files changed, 123 insertions(+), 7 deletions(-)

diff --git a/axiom-api/src/main/java/org/apache/axiom/util/activation/BlobDataSource.java b/axiom-api/src/main/java/org/apache/axiom/util/activation/BlobDataSource.java
index 7f6468480..52f176a1e 100644
--- a/axiom-api/src/main/java/org/apache/axiom/util/activation/BlobDataSource.java
+++ b/axiom-api/src/main/java/org/apache/axiom/util/activation/BlobDataSource.java
@@ -29,6 +29,7 @@ import org.apache.axiom.ext.activation.SizeAwareDataSource;
 /**
  * Data source backed by a {@link Blob}.
  */
+// TODO(AXIOM-506): this should not be public
 public class BlobDataSource implements SizeAwareDataSource {
     private final Blob blob;
     private final String contentType;
@@ -38,6 +39,10 @@ public class BlobDataSource implements SizeAwareDataSource {
         this.contentType = contentType;
     }
 
+    Blob getBlob() {
+        return blob;
+    }
+
     @Override
     public InputStream getInputStream() throws IOException {
         return blob.getInputStream();
diff --git a/axiom-api/src/main/java/org/apache/axiom/util/activation/SizeLimitedOutputStream.java b/axiom-api/src/main/java/org/apache/axiom/util/activation/CountingOutputStream.java
similarity index 83%
rename from axiom-api/src/main/java/org/apache/axiom/util/activation/SizeLimitedOutputStream.java
rename to axiom-api/src/main/java/org/apache/axiom/util/activation/CountingOutputStream.java
index 8ecfce415..91e15fcb2 100644
--- a/axiom-api/src/main/java/org/apache/axiom/util/activation/SizeLimitedOutputStream.java
+++ b/axiom-api/src/main/java/org/apache/axiom/util/activation/CountingOutputStream.java
@@ -22,17 +22,21 @@ import java.io.IOException;
 import java.io.OutputStream;
 
 /**
- * An output stream that counts the number of bytes written to it and throws an exception when the
- * size exceeds a given limit.
+ * An output stream that counts the number of bytes written to it and optionally throws an exception
+ * when the size exceeds a given limit.
  */
-final class SizeLimitedOutputStream extends OutputStream {
+final class CountingOutputStream extends OutputStream {
     private final long maxSize;
     private long size;
     
-    SizeLimitedOutputStream(long maxSize) {
+    CountingOutputStream(long maxSize) {
         this.maxSize = maxSize;
     }
 
+    CountingOutputStream() {
+        this(-1);
+    }
+
     @Override
     public void write(byte[] b, int off, int len) throws IOException {
         size += len;
@@ -52,10 +56,14 @@ final class SizeLimitedOutputStream extends OutputStream {
     }
     
     private void checkSize() throws SizeLimitExceededException {
-        if (size > maxSize) {
+        if (maxSize != -1 && size > maxSize) {
             // Throw a cached exception instance to avoid the overhead of building the
             // stack trace.
             throw SizeLimitExceededException.INSTANCE;
         }
     }
+
+    long getSize() {
+        return size;
+    }
 }
\ No newline at end of file
diff --git a/axiom-api/src/main/java/org/apache/axiom/util/activation/DataHandlerBlob.java b/axiom-api/src/main/java/org/apache/axiom/util/activation/DataHandlerBlob.java
new file mode 100644
index 000000000..ae6c48ced
--- /dev/null
+++ b/axiom-api/src/main/java/org/apache/axiom/util/activation/DataHandlerBlob.java
@@ -0,0 +1,72 @@
+/*
+ * 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.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+
+import org.apache.axiom.blob.Blob;
+import org.apache.axiom.ext.io.StreamCopyException;
+
+final class DataHandlerBlob implements Blob {
+    private final DataHandler dataHandler;
+    
+    DataHandlerBlob(DataHandler dataHandler) {
+        this.dataHandler = dataHandler;
+    }
+
+    DataHandler getDataHandler() {
+        return dataHandler;
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+        return dataHandler.getInputStream();
+    }
+
+    @Override
+    public void writeTo(OutputStream out) throws StreamCopyException {
+        try {
+            dataHandler.writeTo(out);
+        } catch (IOException ex) {
+            // TODO(AXIOM-506): maybe we can do some wrapping to determine the operation that failed
+            throw new StreamCopyException(StreamCopyException.WRITE, ex);
+        }
+    }
+
+    @Override
+    public long getSize() {
+        DataSource ds = dataHandler.getDataSource();
+        long size = DataSourceUtils.getSize(ds);
+        if (size != -1) {
+            return size;
+        }
+        CountingOutputStream out = new CountingOutputStream();
+        try {
+            dataHandler.writeTo(out);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+        return out.getSize();
+    }
+}
diff --git a/axiom-api/src/main/java/org/apache/axiom/util/activation/DataHandlerUtils.java b/axiom-api/src/main/java/org/apache/axiom/util/activation/DataHandlerUtils.java
index 88da0f7bb..4b7e809ee 100644
--- a/axiom-api/src/main/java/org/apache/axiom/util/activation/DataHandlerUtils.java
+++ b/axiom-api/src/main/java/org/apache/axiom/util/activation/DataHandlerUtils.java
@@ -24,6 +24,8 @@ import java.io.OutputStream;
 import javax.activation.DataHandler;
 import javax.activation.DataSource;
 
+import org.apache.axiom.blob.Blob;
+
 /**
  * Contains utility methods to work with {@link DataHandler} objects.
  */
@@ -57,11 +59,40 @@ public final class DataHandlerUtils {
             // getInputStream method. Obviously starting a new thread just to check the size of
             // the data is an overhead that we should avoid.
             try {
-                dh.writeTo(new SizeLimitedOutputStream(limit));
+                dh.writeTo(new CountingOutputStream(limit));
                 return false;
             } catch (SizeLimitExceededException ex) {
                 return true;
             }
         }
     }
+
+    /**
+     * Get a {@link DataHandler} for the given {@link Blob}. If the blob was obtained from {@link
+     * #toBlob(DataHandler)}, the original {@link DataHandler} is returned.
+     * 
+     * @param blob the {@link Blob} to convert
+     * @return a {@link DataHandler} representing the {@link Blob}
+     */
+    public static DataHandler toDataHandler(Blob blob) {
+        if (blob instanceof DataHandlerBlob) {
+            return ((DataHandlerBlob)blob).getDataHandler();
+        }
+        return new DataHandler(new BlobDataSource(blob, "application/octet-stream"));
+    }
+
+    /**
+     * Get a {@link Blob} for the given {@link DataHandler}. If the {@link DataHandler} was obtained from {@link
+     * #toDataHandler(Blob)}, the original {@link Blob} is returned.
+     * 
+     * @param dh the {@link DataHandler} to convert
+     * @return a {@link Blob} representing the {@link DataHandler}
+     */
+    public static Blob toBlob(DataHandler dh) {
+        DataSource ds = dh.getDataSource();
+        if (ds instanceof BlobDataSource) {
+            return ((BlobDataSource)ds).getBlob();
+        }
+        return new DataHandlerBlob(dh);
+    }
 }
diff --git a/axiom-api/src/main/java/org/apache/axiom/util/activation/SizeLimitExceededException.java b/axiom-api/src/main/java/org/apache/axiom/util/activation/SizeLimitExceededException.java
index a49539e55..945bce647 100644
--- a/axiom-api/src/main/java/org/apache/axiom/util/activation/SizeLimitExceededException.java
+++ b/axiom-api/src/main/java/org/apache/axiom/util/activation/SizeLimitExceededException.java
@@ -21,7 +21,7 @@ package org.apache.axiom.util.activation;
 import java.io.IOException;
 
 /**
- * Exception used by {@link SizeLimitedOutputStream} if the size limit has been exceeded.
+ * Exception used by {@link CountingOutputStream} if the size limit has been exceeded.
  */
 final class SizeLimitExceededException extends IOException {
     private static final long serialVersionUID = 1L;