You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2020/08/12 09:31:23 UTC

[cxf] branch master updated: CXF-8324: Allow wider range of values for attachment properties (#688)

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

coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new f63582f  CXF-8324: Allow wider range of values for attachment properties (#688)
f63582f is described below

commit f63582f4f39c76c2152ea67626b21326d81e6845
Author: Robin Schimpf <th...@gmail.com>
AuthorDate: Wed Aug 12 11:31:09 2020 +0200

    CXF-8324: Allow wider range of values for attachment properties (#688)
    
    Provide better error if the given value is not allowed
    Document allowed values for properties
---
 .../cxf/attachment/AttachmentDeserializer.java     |  12 ++
 .../org/apache/cxf/attachment/AttachmentUtil.java  |  48 ++++-
 .../apache/cxf/attachment/AttachmentUtilTest.java  | 211 +++++++++++++++++++++
 3 files changed, 263 insertions(+), 8 deletions(-)

diff --git a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
index d3f9895..0f7f6b8 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.attachment;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PushbackInputStream;
@@ -47,10 +48,21 @@ import org.apache.cxf.message.MessageUtils;
 
 public class AttachmentDeserializer {
     public static final String ATTACHMENT_PART_HEADERS = AttachmentDeserializer.class.getName() + ".headers";
+
+    /**
+     * Allowed value is any instance of {@link File} or {@link String}.
+     */
     public static final String ATTACHMENT_DIRECTORY = "attachment-directory";
 
+    /**
+     * The memory threshold of attachments. Allowed value is any instance of {@link Number} or {@link String}.
+     * The default is {@link AttachmentDeserializer#THRESHOLD}.
+     */
     public static final String ATTACHMENT_MEMORY_THRESHOLD = "attachment-memory-threshold";
 
+    /**
+     * The maximum size of the attachment. Allowed value is any of {@link Number} or {@link String}.
+     */
     public static final String ATTACHMENT_MAX_SIZE = "attachment-max-size";
 
     /**
diff --git a/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java b/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
index d5f8e85..e8d0a3e 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
@@ -44,6 +44,7 @@ import java.util.Random;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
 
 import javax.activation.CommandInfo;
 import javax.activation.CommandMap;
@@ -54,6 +55,7 @@ import javax.activation.FileDataSource;
 import javax.activation.MailcapCommandMap;
 import javax.activation.URLDataSource;
 
+import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.helpers.FileUtils;
 import org.apache.cxf.interceptor.Fault;
@@ -65,6 +67,8 @@ import org.apache.cxf.message.MessageUtils;
 public final class AttachmentUtil {
     public static final String BODY_ATTACHMENT_ID = "root.message@cxf.apache.org";
 
+    private static final Logger LOG = LogUtils.getL7dLogger(AttachmentUtil.class);
+
     private static final AtomicInteger COUNTER = new AtomicInteger();
     private static final String ATT_UUID = UUID.randomUUID().toString();
 
@@ -165,18 +169,34 @@ public final class AttachmentUtil {
         Object directory = message.getContextualProperty(AttachmentDeserializer.ATTACHMENT_DIRECTORY);
         if (directory != null) {
             if (directory instanceof File) {
-                bos.setOutputDir((File)directory);
+                bos.setOutputDir((File) directory);
+            } else if (directory instanceof String) {
+                bos.setOutputDir(new File((String) directory));
             } else {
-                bos.setOutputDir(new File((String)directory));
+                throw new IOException("The value set as " + AttachmentDeserializer.ATTACHMENT_DIRECTORY
+                        + " should be either an instance of File or String");
             }
         }
 
         Object threshold = message.getContextualProperty(AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD);
         if (threshold != null) {
-            if (threshold instanceof Long) {
-                bos.setThreshold((Long)threshold);
+            if (threshold instanceof Number) {
+                long t = ((Number) threshold).longValue();
+                if (t >= 0) {
+                    bos.setThreshold(t);
+                } else {
+                    LOG.warning("Threshold value overflowed long. Setting default value!");
+                    bos.setThreshold(AttachmentDeserializer.THRESHOLD);
+                }
+            } else if (threshold instanceof String) {
+                try {
+                    bos.setThreshold(Long.parseLong((String) threshold));
+                } catch (NumberFormatException e) {
+                    throw new IOException("Provided threshold String is not a number", e);
+                }
             } else {
-                bos.setThreshold(Long.parseLong((String)threshold));
+                throw new IOException("The value set as " + AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD
+                        + " should be either an instance of Number or String");
             }
         } else if (!CachedOutputStream.isThresholdSysPropSet()) {
             // Use the default AttachmentDeserializer Threshold only if there is no system property defined
@@ -185,10 +205,22 @@ public final class AttachmentUtil {
 
         Object maxSize = message.getContextualProperty(AttachmentDeserializer.ATTACHMENT_MAX_SIZE);
         if (maxSize != null) {
-            if (maxSize instanceof Long) {
-                bos.setMaxSize((Long) maxSize);
+            if (maxSize instanceof Number) {
+                long size = ((Number) maxSize).longValue();
+                if (size >= 0) {
+                    bos.setMaxSize(size);
+                } else {
+                    LOG.warning("Max size value overflowed long. Do not set max size!");
+                }
+            } else if (maxSize instanceof String) {
+                try {
+                    bos.setMaxSize(Long.parseLong((String) maxSize));
+                } catch (NumberFormatException e) {
+                    throw new IOException("Provided threshold String is not a number", e);
+                }
             } else {
-                bos.setMaxSize(Long.parseLong((String)maxSize));
+                throw new IOException("The value set as " + AttachmentDeserializer.ATTACHMENT_MAX_SIZE
+                        + " should be either an instance of Number or String");
             }
         }
     }
diff --git a/core/src/test/java/org/apache/cxf/attachment/AttachmentUtilTest.java b/core/src/test/java/org/apache/cxf/attachment/AttachmentUtilTest.java
index 547a531..19c3564 100644
--- a/core/src/test/java/org/apache/cxf/attachment/AttachmentUtilTest.java
+++ b/core/src/test/java/org/apache/cxf/attachment/AttachmentUtilTest.java
@@ -18,8 +18,19 @@
  */
 package org.apache.cxf.attachment;
 
+import java.io.File;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.apache.cxf.io.CachedOutputStream;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+
 import org.junit.Test;
 
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 
@@ -122,4 +133,204 @@ public class AttachmentUtilTest {
         assertNotEquals(AttachmentUtil.createContentID(null), AttachmentUtil.createContentID(null));
     }
 
+    private CachedOutputStream testSetStreamedAttachmentProperties(final String property, final Object value)
+            throws IOException {
+        return testSetStreamedAttachmentProperties(property, value, new CachedOutputStream());
+    }
+
+    private CachedOutputStream testSetStreamedAttachmentProperties(final String property, final Object value,
+            final CachedOutputStream cos) throws IOException {
+        Message message = new MessageImpl();
+        message.put(property, value);
+        AttachmentUtil.setStreamedAttachmentProperties(message, cos);
+
+        return cos;
+    }
+
+    @Test
+    public void bigIntAsAttachmentMemoryThreshold() throws IOException {
+        BigInteger bigInteger = new BigInteger(String.valueOf(Long.MAX_VALUE));
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(
+                AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, bigInteger)) {
+            assertEquals(bigInteger.longValue(), cos.getThreshold());
+        }
+        // Overflow long value
+        bigInteger = bigInteger.add(BigInteger.ONE);
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(
+                AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, bigInteger)) {
+            assertEquals(AttachmentDeserializer.THRESHOLD, cos.getThreshold());
+        }
+    }
+
+    @Test
+    public void longAsAttachmentMemoryThreshold() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(
+                AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, Long.MAX_VALUE)) {
+            assertEquals(Long.MAX_VALUE, cos.getThreshold());
+        }
+    }
+
+    @Test
+    public void integerAsAttachmentMemoryThreshold() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(
+                AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, Integer.MAX_VALUE)) {
+            assertEquals(Integer.MAX_VALUE, cos.getThreshold());
+        }
+    }
+
+    @Test
+    public void shortAsAttachmentMemoryThreshold() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(
+                AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, Short.MAX_VALUE)) {
+            assertEquals(Short.MAX_VALUE, cos.getThreshold());
+        }
+    }
+
+    @Test
+    public void byteAsAttachmentMemoryThreshold() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(
+                AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, Byte.MAX_VALUE)) {
+            assertEquals(Byte.MAX_VALUE, cos.getThreshold());
+        }
+    }
+
+    @Test
+    public void numberStringAsAttachmentMemoryThreshold() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(
+                AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, "12345")) {
+            assertEquals(12345, cos.getThreshold());
+        }
+    }
+
+    @Test(expected = IOException.class)
+    public void nonNumberStringAsAttachmentMemoryThreshold() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(
+                AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, "test")) {
+            // Will throw exception
+        }
+    }
+
+    @Test(expected = IOException.class)
+    public void objectAsAttachmentMemoryThreshold() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(
+                AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, new Object())) {
+            // Will throw exception
+        }
+    }
+
+    @Test
+    public void bigIntAsAttachmentMaxSize() throws IOException {
+        CachedOutputStream cos = createMock(CachedOutputStream.class);
+        BigInteger bigInteger = new BigInteger(String.valueOf(Long.MAX_VALUE));
+        cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_MAX_SIZE, bigInteger, cos);
+        replay(cos);
+        cos.setMaxSize(bigInteger.longValue());
+        cos.setThreshold(102400L);
+        verify(cos);
+        // Overflow long value
+        bigInteger = bigInteger.add(BigInteger.ONE);
+        cos = createMock(CachedOutputStream.class);
+        cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_MAX_SIZE, bigInteger, cos);
+        replay(cos);
+        cos.setThreshold(102400L);
+        verify(cos);
+    }
+
+    @Test
+    public void longAsAttachmentMaxSize() throws IOException {
+        CachedOutputStream cos = createMock(CachedOutputStream.class);
+        cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_MAX_SIZE, Long.MAX_VALUE, cos);
+        replay(cos);
+        cos.setMaxSize(Long.MAX_VALUE);
+        cos.setThreshold(102400L);
+        verify(cos);
+    }
+
+    @Test
+    public void integerAsAttachmentMaxSize() throws IOException {
+        CachedOutputStream cos = createMock(CachedOutputStream.class);
+        cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_MAX_SIZE, Integer.MAX_VALUE, cos);
+        replay(cos);
+        cos.setMaxSize(Integer.MAX_VALUE);
+        cos.setThreshold(102400L);
+        verify(cos);
+    }
+
+    @Test
+    public void shortAsAttachmentMaxSize() throws IOException {
+        CachedOutputStream cos = createMock(CachedOutputStream.class);
+        cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_MAX_SIZE, Short.MAX_VALUE, cos);
+        replay(cos);
+        cos.setMaxSize(Short.MAX_VALUE);
+        cos.setThreshold(102400L);
+        verify(cos);
+    }
+
+    @Test
+    public void byteAsAttachmentMaxSize() throws IOException {
+        CachedOutputStream cos = createMock(CachedOutputStream.class);
+        cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_MAX_SIZE, Byte.MAX_VALUE, cos);
+        replay(cos);
+        cos.setMaxSize(Byte.MAX_VALUE);
+        cos.setThreshold(102400L);
+        verify(cos);
+    }
+
+    @Test
+    public void numberStringAsAttachmentMaxSize() throws IOException {
+        CachedOutputStream cos = createMock(CachedOutputStream.class);
+        cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_MAX_SIZE, "12345", cos);
+        replay(cos);
+        cos.setMaxSize(12345);
+        cos.setThreshold(102400L);
+        verify(cos);
+    }
+
+    @Test(expected = IOException.class)
+    public void nonNumberStringAsAttachmentMaxSize() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_MAX_SIZE,
+                "test")) {
+            // Will throw exception
+        }
+    }
+
+    @Test(expected = IOException.class)
+    public void objectAsAttachmentMaxSize() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_MAX_SIZE,
+                new Object())) {
+            // Will throw exception
+        }
+    }
+
+    @Test
+    public void fileAsAttachmentDirectory() throws IOException {
+        File attachmentDirectory = new File("/dev/null");
+        CachedOutputStream cos = createMock(CachedOutputStream.class);
+        cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_DIRECTORY, attachmentDirectory,
+                cos);
+        replay(cos);
+        cos.setOutputDir(attachmentDirectory);
+        cos.setThreshold(102400L);
+        verify(cos);
+    }
+
+    @Test
+    public void stringAsAttachmentDirectory() throws IOException {
+        String attachmentDirectory = "/dev/null";
+        CachedOutputStream cos = createMock(CachedOutputStream.class);
+        cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_DIRECTORY, attachmentDirectory,
+                cos);
+        replay(cos);
+        cos.setOutputDir(new File(attachmentDirectory));
+        cos.setThreshold(102400L);
+        verify(cos);
+    }
+
+    @Test(expected = IOException.class)
+    public void objectAsAttachmentDirectory() throws IOException {
+        try (CachedOutputStream cos = testSetStreamedAttachmentProperties(AttachmentDeserializer.ATTACHMENT_DIRECTORY,
+                new Object())) {
+            // Will throw exception
+        }
+    }
 }