cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ff...@apache.org
Subject cxf git commit: [CXF-6435]Support base64 for attachment encoding in CXF
Date Mon, 07 Mar 2016 00:55:00 GMT
Repository: cxf
Updated Branches:
  refs/heads/master 8d3e174ab -> 2e9bf6487


[CXF-6435]Support base64 for attachment encoding in CXF


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/2e9bf648
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/2e9bf648
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/2e9bf648

Branch: refs/heads/master
Commit: 2e9bf6487060dc79d837b3f35c09cd8ad71ff60e
Parents: 8d3e174
Author: Freeman Fang <freeman.fang@gmail.com>
Authored: Mon Mar 7 08:54:31 2016 +0800
Committer: Freeman Fang <freeman.fang@gmail.com>
Committed: Mon Mar 7 08:54:31 2016 +0800

----------------------------------------------------------------------
 .../cxf/attachment/AttachmentSerializer.java    |  44 +++++-
 .../interceptor/AttachmentOutInterceptor.java   |   5 +
 .../java/org/apache/cxf/message/Message.java    |   6 +
 .../apache/cxf/systest/jaxb/MTOMBase64Test.java | 146 +++++++++++++++++++
 .../cxf/systest/jaxrs/JAXRSAsyncClientTest.java |   2 +-
 5 files changed, 200 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/2e9bf648/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java b/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java
index d01f209..97e880e 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java
@@ -20,6 +20,7 @@
 package org.apache.cxf.attachment;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.StringWriter;
 import java.io.Writer;
@@ -33,13 +34,20 @@ import java.util.Map;
 
 import javax.activation.DataHandler;
 
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.message.Attachment;
 import org.apache.cxf.message.Message;
 
+
+
+
 public class AttachmentSerializer {
     // http://tools.ietf.org/html/rfc2387
     private static final String DEFAULT_MULTIPART_TYPE = "multipart/related";
     
+    private static String contentTransferEncoding = "binary";
+    
     private Message message;
     private String bodyBoundary;
     private OutputStream out;
@@ -50,6 +58,7 @@ public class AttachmentSerializer {
     private boolean xop = true;
     private boolean writeOptionalTypeParameters = true;
     
+        
     public AttachmentSerializer(Message messageParam) {
         message = messageParam;
     }
@@ -176,6 +185,10 @@ public class AttachmentSerializer {
     private static String escapeQuotes(String s) {
         return s.indexOf('"') != 0 ? s.replace("\"", "\\\"") : s;    
     }
+    
+    public static void setContentTransferEncoding(String cte) {
+        contentTransferEncoding = cte;
+    }
 
     private String getHeaderValue(String name, String defaultValue) {
         List<String> value = rootHeaders.get(name);
@@ -196,7 +209,7 @@ public class AttachmentSerializer {
                                      Map<String, List<String>> headers, Writer
writer) throws IOException {
         writer.write("\r\nContent-Type: ");
         writer.write(contentType);
-        writer.write("\r\nContent-Transfer-Encoding: binary\r\n");
+        writer.write("\r\nContent-Transfer-Encoding: " + contentTransferEncoding + "\r\n");
 
         if (attachmentId != null) {
             attachmentId = checkAngleBrackets(attachmentId);
@@ -263,7 +276,11 @@ public class AttachmentSerializer {
                 writeHeaders(handler.getContentType(), a.getId(),
                              headers, writer);
                 out.write(writer.getBuffer().toString().getBytes(encoding));
-                handler.writeTo(out);
+                if ("base64".equals(contentTransferEncoding)) {
+                    encodeBase64(handler.getInputStream(), out, IOUtils.DEFAULT_BUFFER_SIZE);
+                } else {
+                    handler.writeTo(out);
+                }
             }
         }
         StringWriter writer = new StringWriter();                
@@ -274,6 +291,29 @@ public class AttachmentSerializer {
         out.flush();
     }
 
+    private int encodeBase64(InputStream input, OutputStream output, int bufferSize) throws
IOException {
+        int avail = input.available();
+        if (avail > 262144) {
+            avail = 262144;
+        }
+        if (avail > bufferSize) {
+            bufferSize = avail;
+        }
+        final byte[] buffer = new byte[bufferSize];
+        int n = 0;
+        n = input.read(buffer);
+        int total = 0;
+        while (-1 != n) {
+            if (n == 0) {
+                throw new IOException("0 bytes read in violation of InputStream.read(byte[])");
+            }
+            Base64Utility.encodeAndStream(buffer, 0, n, out);
+            total += n;
+            n = input.read(buffer);
+        }
+        return total;
+    }
+    
     public boolean isXop() {
         return xop;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/2e9bf648/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java b/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java
index 53abda0..16b7d79 100644
--- a/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java
+++ b/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java
@@ -67,6 +67,11 @@ public class AttachmentOutInterceptor extends AbstractPhaseInterceptor<Message>
                                      writeOptionalTypeParameters(),
                                      getRootHeaders());
         serializer.setXop(mtomEnabled);
+        String contentTransferEncoding = (String)message.getContextualProperty(
+                                            org.apache.cxf.message.Message.CONTENT_TRANSFER_ENCODING);
+        if (contentTransferEncoding != null) {
+            AttachmentSerializer.setContentTransferEncoding(contentTransferEncoding);
+        }
         
         try {
             serializer.writeProlog();

http://git-wip-us.apache.org/repos/asf/cxf/blob/2e9bf648/core/src/main/java/org/apache/cxf/message/Message.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/cxf/message/Message.java b/core/src/main/java/org/apache/cxf/message/Message.java
index b748eb8..0c68178 100644
--- a/core/src/main/java/org/apache/cxf/message/Message.java
+++ b/core/src/main/java/org/apache/cxf/message/Message.java
@@ -171,6 +171,12 @@ public interface Message extends StringMap {
      */
     String INTERCEPTOR_PROVIDERS = Message.class.getName() + ".INTERCEPTOR_PROVIDER";
     
+    /**
+     * Content-Transfer-Encoding used for MTOM attachment
+     * binary, base64, etc
+     */
+    String CONTENT_TRANSFER_ENCODING = Message.class.getName() + ".CONTENT_TRANSFER_ENCODING";
+    
     /*
      * The properties to allow configure the client timeout
      */

http://git-wip-us.apache.org/repos/asf/cxf/blob/2e9bf648/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/MTOMBase64Test.java
----------------------------------------------------------------------
diff --git a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/MTOMBase64Test.java
b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/MTOMBase64Test.java
new file mode 100644
index 0000000..73503cb
--- /dev/null
+++ b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/MTOMBase64Test.java
@@ -0,0 +1,146 @@
+/**
+ * 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.cxf.systest.jaxb;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.jws.WebService;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import javax.xml.namespace.QName;
+import javax.xml.ws.Endpoint;
+import javax.xml.ws.Service;
+import javax.xml.ws.soap.MTOM;
+import javax.xml.ws.soap.SOAPBinding;
+
+import org.apache.cxf.annotations.Logging;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.interceptor.LoggingInInterceptor;
+import org.apache.cxf.interceptor.LoggingOutInterceptor;
+import org.apache.cxf.jaxws.EndpointImpl;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * 
+ */
+public class MTOMBase64Test extends AbstractBusClientServerTestBase {
+    static final String PORT = allocatePort(MTOMTest.class);
+    static final String ADDRESS = "http://localhost:" + PORT + "/MTOMBase64";
+
+    public static class ObjectWithHashMapData {
+        private String name;
+        private Map<String, byte[]> keyData = new LinkedHashMap<String, byte[]>();
+
+        public ObjectWithHashMapData() {
+        }
+        
+        @XmlJavaTypeAdapter(HashMapAdapter.class)
+        public Map<String, byte[]> getKeyData() {
+            return keyData;
+        }
+        
+        public void setKeyData(Map<String, byte[]> d) {
+            keyData = d;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+    }
+    
+    @Logging(pretty = true)
+    @WebService
+    @MTOM(threshold = 1)
+    public interface MTOMService {
+        ObjectWithHashMapData getHashMapData(int y);
+    }
+    @WebService
+    public static class MTOMServer implements MTOMService {
+        public ObjectWithHashMapData getHashMapData(int y) {
+            ObjectWithHashMapData ret = new ObjectWithHashMapData();
+            ret.setName("Test");
+            for (int x = 1; x < y; x++) {
+                ret.getKeyData().put(Integer.toHexString(x), generateByteData(x));
+            }
+            return ret;
+        }
+
+        private byte[] generateByteData(int x) {
+            byte bytes[] = new byte[x];
+            for (int y = 0; y < x; y++) {
+                int z = 'A' + y;
+                if (z > 'z') {
+                    z -= 'A';
+                }
+                bytes[y] = (byte)z;
+            }
+            return bytes;
+        }        
+    }
+    public static class Server extends AbstractBusTestServerBase {        
+
+        protected void run() {
+            EndpointImpl endpointImpl = (EndpointImpl)Endpoint.publish(ADDRESS, new MTOMServer());
+            endpointImpl.getProperties().put(Message.CONTENT_TRANSFER_ENCODING, "base64");
+        }
+        public static void main(String[] args) {
+            try {
+                Server s = new Server();
+                s.start();
+            } catch (Exception ex) {
+                ex.printStackTrace();
+                System.exit(-1);
+            } finally {
+                System.out.println("done!");
+            }
+        }
+    }
+    @BeforeClass
+    public static void startServers() throws Exception {
+        assertTrue("server did not launch correctly", launchServer(Server.class, true));
+    }
+    
+       
+    @Test
+    public void testMTOMInHashMapWithBase64() throws Exception {
+        Service service = Service.create(new QName("http://foo", "bar"));
+        service.addPort(new QName("http://foo", "bar"), SOAPBinding.SOAP11HTTP_BINDING, 
+                        ADDRESS);
+        MTOMService port = service.getPort(new QName("http://foo", "bar"),
+                                           MTOMService.class);
+        ClientProxy.getClient(port).getOutInterceptors().add(new LoggingOutInterceptor());
+        ClientProxy.getClient(port).getInInterceptors().add(new LoggingInInterceptor());
+        final int count = 99;
+        ObjectWithHashMapData data = port.getHashMapData(count);
+        for (int y = 1;  y < count; y++) {
+            byte bytes[] = data.getKeyData().get(Integer.toHexString(y));
+            assertEquals(y, bytes.length);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/2e9bf648/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSAsyncClientTest.java
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSAsyncClientTest.java
index d02e117..8ad675e 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSAsyncClientTest.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSAsyncClientTest.java
@@ -201,7 +201,7 @@ public class JAXRSAsyncClientTest extends AbstractBusClientServerTestBase
{
     @Test
     public void testNonExistentJaxrs20WithPost() throws Exception {
         Client client = ClientBuilder.newClient();
-        WebTarget target = client.target("http://test.test/");
+        WebTarget target = client.target("http://test-test/");
         Invocation.Builder builder = target.request();
         Entity<String> entity = Entity.entity("entity", MediaType.WILDCARD_TYPE);
         Invocation invocation = builder.buildPost(entity);


Mime
View raw message