Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9378117865 for ; Mon, 1 Jun 2015 20:34:57 +0000 (UTC) Received: (qmail 34730 invoked by uid 500); 1 Jun 2015 20:34:57 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 34668 invoked by uid 500); 1 Jun 2015 20:34:57 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 34659 invoked by uid 99); 1 Jun 2015 20:34:57 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 Jun 2015 20:34:57 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 4F439E0837; Mon, 1 Jun 2015 20:34:57 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ay@apache.org To: commits@cxf.apache.org Message-Id: <14c83cf54cfe4893a2cae2fb9578d0d3@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cxf git commit: [CXF-6431] Attachment serialization does not conform to the relevant specs Date: Mon, 1 Jun 2015 20:34:57 +0000 (UTC) Repository: cxf Updated Branches: refs/heads/2.7.x-fixes 51f011b24 -> 591cc418a [CXF-6431] Attachment serialization does not conform to the relevant specs Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/591cc418 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/591cc418 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/591cc418 Branch: refs/heads/2.7.x-fixes Commit: 591cc418a5b86c98442bd996cbff3025a46f9295 Parents: 51f011b Author: Akitoshi Yoshida Authored: Mon Jun 1 21:46:43 2015 +0200 Committer: Akitoshi Yoshida Committed: Mon Jun 1 22:33:36 2015 +0200 ---------------------------------------------------------------------- .../cxf/attachment/AttachmentSerializer.java | 56 ++++++++++--------- .../attachment/AttachmentSerializerTest.java | 59 ++++++++++++++++---- 2 files changed, 79 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/591cc418/api/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java b/api/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java index 24b4766..62f2bb6 100644 --- a/api/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java +++ b/api/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java @@ -72,26 +72,19 @@ public class AttachmentSerializer { bodyBoundary = AttachmentUtil.getUniqueBoundaryValue(); String bodyCt = (String) message.get(Message.CONTENT_TYPE); - - // The bodyCt string is used enclosed within "", so if it contains the character ", it - // should be adjusted, like in the following case: - // application/soap+xml; action="urn:ihe:iti:2007:RetrieveDocumentSet" - // The attribute action is added in SoapActionOutInterceptor, when SOAP 1.2 is used - // The string has to be changed in: - // application/soap+xml"; action="urn:ihe:iti:2007:RetrieveDocumentSet - // so when it is enclosed within "", the result must be: - // "application/soap+xml"; action="urn:ihe:iti:2007:RetrieveDocumentSet" - // instead of - // "application/soap+xml; action="urn:ihe:iti:2007:RetrieveDocumentSet"" - // that is wrong because when used it produces: - // type="application/soap+xml; action="urn:ihe:iti:2007:RetrieveDocumentSet"" - if ((bodyCt.indexOf('"') != -1) && (bodyCt.indexOf(';') != -1)) { + String bodyCtParams = null; + // split the bodyCt to its head that is the type and its properties so that we + // can insert the values at the right places based on the soap version and the mtom option + // bodyCt will be of the form + // soap11 -> text/xml + // soap12 -> application/soap+xml; action="urn:ihe:iti:2007:RetrieveDocumentSet" + if (bodyCt.indexOf(';') != -1) { int pos = bodyCt.indexOf(';'); - StringBuilder st = new StringBuilder(bodyCt.substring(0 , pos)); - st.append("\"").append(bodyCt.substring(pos, bodyCt.length() - 1)); - bodyCt = st.toString(); - } - + // get everything from the semi-colon + bodyCtParams = bodyCt.substring(pos); + // keep the type/subtype part in bodyCt + bodyCt = bodyCt.substring(0, pos); + } // Set transport mime type String requestMimeType = multipartType == null ? DEFAULT_MULTIPART_TYPE : multipartType; @@ -131,10 +124,14 @@ public class AttachmentSerializer { // start-info is a required parameter for XOP/MTOM, may be needed for // other WS cases but is redundant in simpler multipart/related cases + // the parameters need to be included within the start-info's value in the escaped form if (writeOptionalTypeParameters || xop) { ct.append("; start-info=\"") - .append(bodyCt) - .append("\""); + .append(bodyCt); + if (bodyCtParams != null) { + ct.append(escapeQuotes(bodyCtParams)); + } + ct.append("\""); } @@ -154,11 +151,14 @@ public class AttachmentSerializer { StringBuilder mimeBodyCt = new StringBuilder(); String bodyType = getHeaderValue("Content-Type", null); if (bodyType == null) { - mimeBodyCt.append(xop ? "application/xop+xml; charset=" : "text/xml; charset=") - .append(encoding) - .append("; type=\"") - .append(bodyCt) - .append("\""); + mimeBodyCt.append(xop ? "application/xop+xml" : bodyCt) + .append("; charset=").append(encoding); + if (xop) { + mimeBodyCt.append("; type=\"").append(bodyCt).append("\""); + } + if (bodyCtParams != null) { + mimeBodyCt.append(bodyCtParams); + } } else { mimeBodyCt.append(bodyType); } @@ -167,6 +167,10 @@ public class AttachmentSerializer { out.write(writer.getBuffer().toString().getBytes(encoding)); } + private static String escapeQuotes(String s) { + return s.indexOf('"') != 0 ? s.replace("\"", "\\\"") : s; + } + private String getHeaderValue(String name, String defaultValue) { List value = rootHeaders.get(name); if (value == null || value.isEmpty()) { http://git-wip-us.apache.org/repos/asf/cxf/blob/591cc418/api/src/test/java/org/apache/cxf/attachment/AttachmentSerializerTest.java ---------------------------------------------------------------------- diff --git a/api/src/test/java/org/apache/cxf/attachment/AttachmentSerializerTest.java b/api/src/test/java/org/apache/cxf/attachment/AttachmentSerializerTest.java index 4ddfb19..7645929 100644 --- a/api/src/test/java/org/apache/cxf/attachment/AttachmentSerializerTest.java +++ b/api/src/test/java/org/apache/cxf/attachment/AttachmentSerializerTest.java @@ -44,16 +44,26 @@ import org.junit.Test; public class AttachmentSerializerTest extends Assert { @Test - public void testMessageWriteXopOn() throws Exception { - doTestMessageWrite(true); + public void testMessageWriteXopOn1() throws Exception { + doTestMessageWrite(true, "text/xml"); } @Test - public void testMessageWriteXopOff() throws Exception { - doTestMessageWrite(false); + public void testMessageWriteXopOn2() throws Exception { + doTestMessageWrite(true, "application/soap+xml; action=\"urn:foo\""); } - private void doTestMessageWrite(boolean xop) throws Exception { + @Test + public void testMessageWriteXopOff1() throws Exception { + doTestMessageWrite(false, "text/xml"); + } + + @Test + public void testMessageWriteXopOff2() throws Exception { + doTestMessageWrite(false, "application/soap+xml; action=\"urn:foo\""); + } + + private void doTestMessageWrite(boolean xop, String soapContentType) throws Exception { MessageImpl msg = new MessageImpl(); Collection atts = new ArrayList(); @@ -68,8 +78,17 @@ public class AttachmentSerializerTest extends Assert { msg.setAttachments(atts); // Set the SOAP content type - msg.put(Message.CONTENT_TYPE, "application/soap+xml"); - + msg.put(Message.CONTENT_TYPE, soapContentType); + String soapCtType = null; + String soapCtParams = null; + int p = soapContentType.indexOf(';'); + if (p != -1) { + soapCtParams = soapContentType.substring(p); + soapCtType = soapContentType.substring(0, p); + } else { + soapCtParams = ""; + soapCtType = soapContentType; + } ByteArrayOutputStream out = new ByteArrayOutputStream(); msg.setContent(OutputStream.class, out); @@ -81,10 +100,22 @@ public class AttachmentSerializerTest extends Assert { serializer.writeProlog(); + // we expect + // - the package header must have type multipart/related + // - the start-info property must be present for mtom but otherwise optional + // - the action property should not appear directly + // - the type property must be application/xop+xml for mtom but otherwise text/xml or application/soap+xml String ct = (String) msg.get(Message.CONTENT_TYPE); + System.out.println("##teset ct=" + ct); assertTrue(ct.indexOf("multipart/related;") == 0); assertTrue(ct.indexOf("start=\"\"") > -1); - assertTrue(ct.indexOf("start-info=\"application/soap+xml\"") > -1); + assertTrue(ct.indexOf("start-info=\"" + escapeQuotes(soapContentType) + "\"") > -1); + assertTrue(ct.indexOf("action=\"") == -1); + if (xop) { + assertTrue(ct.indexOf("type=\"application/xop+xml\"") > -1); + } else { + assertTrue(ct.indexOf("type=\"" + soapCtType + "\"") > -1); + } out.write("".getBytes()); serializer.writeAttachments(); @@ -101,11 +132,15 @@ public class AttachmentSerializerTest extends Assert { MimeMultipart multipart = (MimeMultipart) inMsg.getContent(); MimeBodyPart part = (MimeBodyPart) multipart.getBodyPart(0); + // we expect + // - the envelope header must have type application/xop+xml for mtom but otherwise t + // - the start-info property must be present for mtom but otherwise text/xml or application/soap+xml + // - the action must appear if it was present in the original message if (xop) { - assertEquals("application/xop+xml; charset=UTF-8; type=\"application/soap+xml\"", + assertEquals("application/xop+xml; charset=UTF-8; type=\"" + soapCtType + "\"" + soapCtParams, part.getHeader("Content-Type")[0]); } else { - assertEquals("text/xml; charset=UTF-8; type=\"application/soap+xml\"", + assertEquals(soapCtType + "; charset=UTF-8" + soapCtParams, part.getHeader("Content-Type")[0]); } @@ -192,4 +227,8 @@ public class AttachmentSerializerTest extends Assert { assertEquals("", part2.getHeader("Content-ID")[0]); } + + private static String escapeQuotes(String s) { + return s.indexOf('"') != 0 ? s.replace("\"", "\\\"") : s; + } }