You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by da...@apache.org on 2006/11/30 20:19:37 UTC
svn commit: r481043 [1/2] - in /incubator/cxf/trunk:
api/src/main/java/org/apache/cxf/message/
rt/bindings/http/src/test/java/org/apache/cxf/binding/http/
rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/
rt/bindings/soap/src/main/java/org/ap...
Author: dandiep
Date: Thu Nov 30 11:19:29 2006
New Revision: 481043
URL: http://svn.apache.org/viewvc?view=rev&rev=481043
Log:
o Rewrite MTOM support to be completely streamed based. If attachments
are accessed out of order, they are cached. This is done through a
LazyAttachmentCollection. The iterator will iterate over attachments
as they are accessed, loading them one at a time until the correct
one is found. On the outgoing side the AttachmentSerializer allows
us to write out the attachments in steps.
o Move MTOM interceptors into core as they are dependent on SOAP and
some people would like to use it with XML over HTTP.
o Unify handling of Message.CONTENT_TYPE, transports are now expected
to deal with it correctly and we shouldn't have to muck with the protocol
headers to set the content type (like we were doing in
OutgoingChainSetupInterceptor).
o Rename some message properties to make it easier for configuration.
o Rewrite server side mtom test to not use the client to make it easy
to test and debug.
o Remove ugly Message.getAttachmentMimeType() method
o Try to use IOUtils.copy() in more places to reduce duplication
o This has not been interop tested. I think there may be an issue or two
when using with .NET 2.0, but I need to test and track down the issue
(will do so soon).
Added:
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/
- copied from r480652, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java
- copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDataSource.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
- copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDeserializer.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java
- copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentImpl.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java
- copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentSerializer.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
- copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentUtil.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java
- copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/ByteDataSource.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java
- copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/CachedOutputStream.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java (with props)
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java (with props)
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java (with props)
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java (with props)
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java
- copied, changed from r480652, incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java
- copied, changed from r480652, incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/Data.java (with props)
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/EchoService.java (with props)
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/MtomServerTest.java (with props)
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/request (with props)
Removed:
incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java
incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java
incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/attachments/
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/ServerMtomXopTest.java
Modified:
incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java
incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java
incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java
incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java
incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java
incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java
incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java
incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java
incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java
incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java
incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java
incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java
incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java
incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java
incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/test/AbstractCXFTest.java
incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBDataBinding.java
incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java
incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/attachment/JAXBAttachmentMarshaller.java
incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/attachment/JAXBAttachmentUnmarshaller.java
incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/MessageDataReader.java
incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/JettyHTTPDestination.java
incubator/cxf/trunk/rt/transports/local/src/main/java/org/apache/cxf/transport/local/LocalConduit.java
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopTest.java
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/TestAttachmentOutInterceptor.java
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/TestMultipartMessageInterceptor.java
Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java Thu Nov 30 11:19:29 2006
@@ -68,10 +68,18 @@
return message.getAttachments();
}
- public String getAttachmentMimeType() {
- return message.getAttachmentMimeType();
+ public void setAttachments(Collection<Attachment> attachments) {
+ message.setAttachments(attachments);
}
-
+
+ public Message getMessage() {
+ return message;
+ }
+
+ public void setMessage(Message message) {
+ this.message = message;
+ }
+
public Conduit getConduit() {
return message.getConduit();
}
Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java Thu Nov 30 11:19:29 2006
@@ -45,10 +45,10 @@
String HTTP_REQUEST_METHOD = Message.class.getName() + ".HTTP_REQUEST_METHOD";
String PATH_INFO = Message.class.getName() + ".PATH_INFO";
String QUERY_STRING = Message.class.getName() + ".QUERY_STRING";
- String MTOM_ENABLED = Message.class.getName() + ".isMtomEnabled";
+ String MTOM_ENABLED = "mtom-enabled";
String SCHEMA_VALIDATION_ENABLED = Message.class.getCanonicalName() + ".schemaValidationEnabled";
String FAULT_STACKTRACE_ENABLED = "faultStackTraceEnabled";
- String CONTENT_TYPE = Message.class.getName() + ".ContentType";
+ String CONTENT_TYPE = "Content-Type";
String BASE_PATH = Message.class.getName() + ".BASE_PATH";
String ENCODING = Message.class.getName() + ".ENCODING";
String FIXED_PARAMETER_ORDER = Message.class.getName() + "FIXED_PARAMETER_ORDER";
@@ -75,11 +75,8 @@
Collection<Attachment> getAttachments();
- /**
- * @return the mime type string
- */
- String getAttachmentMimeType();
-
+ void setAttachments(Collection<Attachment> attachments);
+
/**
* Retrieve the encapsulated content as a particular type (a result type
* if message is outbound, a source type if message is inbound)
Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java Thu Nov 30 11:19:29 2006
@@ -19,10 +19,8 @@
package org.apache.cxf.message;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -34,7 +32,7 @@
import org.apache.cxf.transport.Destination;
public class MessageImpl extends HashMap<String, Object> implements Message {
- private List<Attachment> attachments = new ArrayList<Attachment>();
+ private Collection<Attachment> attachments;
private Conduit conduit;
private Destination destination;
private Exchange exchange;
@@ -44,6 +42,10 @@
public Collection<Attachment> getAttachments() {
return attachments;
+ }
+
+ public void setAttachments(Collection<Attachment> attachments) {
+ this.attachments = attachments;
}
public String getAttachmentMimeType() {
Modified: incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java (original)
+++ incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java Thu Nov 30 11:19:29 2006
@@ -36,6 +36,7 @@
import org.apache.cxf.BusException;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.test.AbstractCXFTest;
public abstract class AbstractRestTest extends AbstractCXFTest {
@@ -91,8 +92,10 @@
InputStream msgIs = getResourceAsStream(message);
assertNotNull(msgIs);
- copy(msgIs, out);
-
+ IOUtils.copy(msgIs, out);
+ out.close();
+ msgIs.close();
+
InputStream is = c.getInputStream();
Document res = DOMUtils.readXml(is);
Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java Thu Nov 30 11:19:29 2006
@@ -60,11 +60,7 @@
public static Soap11 getInstance() {
return INSTANCE;
}
-
- public String getSoapMimeType() {
- return "\"text/xml\"; charset=utf-8";
- }
-
+
public double getVersion() {
return version;
}
Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java Thu Nov 30 11:19:29 2006
@@ -42,7 +42,6 @@
private final String ultimateReceiverRole = namespace + "/role/ultimateReceiver";
private final String nextRole = namespace + "/role/next";
-
private final String soapEncodingStyle = "http://www.w3.org/2003/05/soap-encoding";
@@ -62,10 +61,6 @@
return instance;
}
- public String getSoapMimeType() {
- return "\"application/soap+xml\"; charset=utf-8";
- }
-
public double getVersion() {
return version;
}
Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java Thu Nov 30 11:19:29 2006
@@ -49,8 +49,10 @@
SoapMessage soapMessage = new SoapMessage(m);
soapMessage.setVersion(version);
- soapMessage.put(Message.CONTENT_TYPE, version.getContentType());
-
+ if (!soapMessage.containsKey(Message.CONTENT_TYPE)) {
+ soapMessage.put(Message.CONTENT_TYPE, version.getContentType());
+ }
+
return soapMessage;
}
Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java Thu Nov 30 11:19:29 2006
@@ -39,8 +39,6 @@
import org.apache.cxf.binding.AbstractBindingFactory;
import org.apache.cxf.binding.Binding;
import org.apache.cxf.binding.BindingFactoryManager;
-import org.apache.cxf.binding.soap.interceptor.AttachmentOutInterceptor;
-import org.apache.cxf.binding.soap.interceptor.MultipartMessageInterceptor;
import org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor;
import org.apache.cxf.binding.soap.interceptor.RPCInInterceptor;
import org.apache.cxf.binding.soap.interceptor.RPCOutInterceptor;
@@ -57,8 +55,10 @@
import org.apache.cxf.binding.soap.model.SoapHeaderInfo;
import org.apache.cxf.binding.soap.model.SoapOperationInfo;
import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.interceptor.AttachmentOutInterceptor;
import org.apache.cxf.interceptor.BareInInterceptor;
import org.apache.cxf.interceptor.BareOutInterceptor;
+import org.apache.cxf.interceptor.MultipartMessageInterceptor;
import org.apache.cxf.interceptor.StaxInInterceptor;
import org.apache.cxf.interceptor.StaxOutInterceptor;
import org.apache.cxf.interceptor.URIMappingInterceptor;
Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java Thu Nov 30 11:19:29 2006
@@ -72,9 +72,4 @@
public <T> void setHeaders(Class<T> format, T content) {
headers.put(format, content);
}
-
- public String getAttachmentMimeType() {
- return version.getSoapMimeType();
- }
-
}
Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java Thu Nov 30 11:19:29 2006
@@ -64,7 +64,5 @@
String getNextRole();
- String getSoapMimeType();
-
String getContentType();
}
Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java Thu Nov 30 11:19:29 2006
@@ -22,16 +22,15 @@
import java.util.HashMap;
import java.util.List;
-
import org.apache.cxf.binding.soap.Soap11;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.SoapVersion;
+import org.apache.cxf.interceptor.AttachmentOutInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import static org.apache.cxf.message.Message.MIME_HEADERS;
-
/**
* This interceptor is responsible for setting up the SOAP version
* and header, so that this is available to any pre-protocol interceptors
@@ -41,7 +40,8 @@
public SoapPreProtocolOutInterceptor() {
super();
- setPhase(Phase.PRE_PROTOCOL);
+ setPhase(Phase.PRE_STREAM);
+ getBefore().add(AttachmentOutInterceptor.class.getName());
}
/**
Modified: incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java Thu Nov 30 11:19:29 2006
@@ -29,8 +29,8 @@
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
-import org.apache.cxf.binding.attachment.AttachmentImpl;
-import org.apache.cxf.binding.attachment.AttachmentUtil;
+import org.apache.cxf.attachment.AttachmentImpl;
+import org.apache.cxf.attachment.AttachmentUtil;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor;
import org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor;
Modified: incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java Thu Nov 30 11:19:29 2006
@@ -30,8 +30,8 @@
import org.w3c.dom.Element;
-import org.apache.cxf.binding.attachment.AttachmentImpl;
-import org.apache.cxf.binding.attachment.AttachmentUtil;
+import org.apache.cxf.attachment.AttachmentImpl;
+import org.apache.cxf.attachment.AttachmentUtil;
import org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor;
import org.apache.cxf.interceptor.StaxInInterceptor;
import org.apache.cxf.message.Attachment;
Modified: incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java Thu Nov 30 11:19:29 2006
@@ -38,6 +38,8 @@
assertEquals("text/xml", soapMessage.get(Message.CONTENT_TYPE));
+ soapMessage.remove(Message.CONTENT_TYPE);
+
sb.setSoapVersion(Soap12.getInstance());
soapMessage = (SoapMessage) sb.createMessage(soapMessage);
assertEquals(Soap12.getInstance(), soapMessage.getVersion());
Modified: incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java Thu Nov 30 11:19:29 2006
@@ -23,13 +23,14 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Collection;
import javax.activation.DataHandler;
import javax.mail.util.ByteArrayDataSource;
-import org.apache.cxf.binding.attachment.AttachmentImpl;
-import org.apache.cxf.binding.attachment.AttachmentUtil;
+import org.apache.cxf.attachment.AttachmentImpl;
+import org.apache.cxf.attachment.AttachmentUtil;
import org.apache.cxf.interceptor.InterceptorChain;
import org.apache.cxf.message.Attachment;
import org.apache.cxf.message.Exchange;
@@ -70,7 +71,8 @@
soapMessage.setContent(Attachment.class, new AttachmentImpl(cid, new DataHandler(bads)));
// setup the message attachments
- Collection<Attachment> attachments = soapMessage.getAttachments();
+ Collection<Attachment> attachments = new ArrayList<Attachment>();
+ soapMessage.setAttachments(attachments);
// String cidAtt1 = "cid:http://cxf.apache.org/me.bmp";
// bads = new ByteArrayDataSource(clazz.getResourceAsStream("me.bmp"), "image/bmp");
// AttachmentImpl att1 = new AttachmentImpl(cidAtt1, new DataHandler(bads));
Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDataSource.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDataSource.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDataSource.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java Thu Nov 30 11:19:29 2006
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
import java.io.IOException;
import java.io.InputStream;
@@ -29,12 +29,7 @@
private final String ct;
private final InputStream in;
-
- public AttachmentDataSource(String ctParam, CachedOutputStream cosParam) throws IOException {
- this.ct = ctParam;
- this.in = cosParam.getInputStream();
- }
-
+
public AttachmentDataSource(String ctParam, InputStream inParam) {
this.ct = ctParam;
this.in = inParam;
Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDeserializer.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDeserializer.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDeserializer.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java Thu Nov 30 11:19:29 2006
@@ -17,33 +17,23 @@
* under the License.
*/
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
import javax.activation.DataHandler;
import javax.activation.DataSource;
-
import javax.mail.Header;
import javax.mail.MessagingException;
import javax.mail.internet.InternetHeaders;
-import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.helpers.HttpHeaderHelper;
-import org.apache.cxf.io.AbstractCachedOutputStream;
+import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.message.Attachment;
import org.apache.cxf.message.Message;
-
public class AttachmentDeserializer {
public static final String ATTACHMENT_DIRECTORY = "attachment-directory";
@@ -52,139 +42,129 @@
public static final int THRESHHOLD = 1024 * 100;
+ private boolean lazyLoading = true;
+
private PushbackInputStream stream;
private String boundary;
private String contentType;
- private List<CachedOutputStream> cache;
+ private LazyAttachmentCollection attachments;
private Message message;
- public AttachmentDeserializer(Message messageParam) {
- message = messageParam;
- }
+ private InputStream body;
-
- public boolean preprocessMessage() {
- InputStream input;
- Map<String, List<String>> httpHeaders;
- // processing message if its multi-part/form-related
- try {
- httpHeaders = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
- if (httpHeaders == null) {
- return false;
- } else {
- List ctList = (List) HttpHeaderHelper.getHeader(httpHeaders, HttpHeaderHelper.CONTENT_TYPE);
- if (ctList != null) {
- for (int x = 0; x < ctList.size(); x++) {
- if (x == 0) {
- contentType = (String) ctList.get(x);
- } else {
- contentType += "; " + (String) ctList.get(x);
- }
- }
- }
- if (contentType == null) {
- return false;
- }
- input = message.getContent(InputStream.class);
- if (input == null) {
- return false;
- }
- }
- //printStream(input);
- if (contentType.toLowerCase().indexOf("multipart/related") != -1) {
- cache = new ArrayList<CachedOutputStream>();
- int i = contentType.indexOf("boundary=\"");
- int end;
- int len;
- if (i == -1) {
- i = contentType.indexOf("boundary=");
- end = contentType.indexOf(";", i + 9);
- if (end == -1) {
- end = contentType.length();
- }
- len = 9;
- } else {
- end = contentType.indexOf("\"", i + 10);
- len = 10;
- }
- if (i == -1 || end == -1) {
- throw new IOException("Invalid content type: missing boundary! " + contentType);
- }
- boundary = "--" + contentType.substring(i + len, end);
- stream = new PushbackInputStream(input, boundary.length());
- if (!readTillFirstBoundary(stream, boundary.getBytes())) {
- throw new IOException("Couldn't find MIME boundary: " + boundary);
- }
- processSoapBody();
- return true;
- }
- } catch (IOException ioe) {
- message.setContent(Exception.class, ioe);
- } catch (MessagingException me) {
- message.setContent(Exception.class, me);
- }
- return false;
+ public AttachmentDeserializer(Message message) {
+ this.message = message;
}
- /**
- * release the resource
- */
- public void dispose() {
- if (cache != null) {
- for (CachedOutputStream cos : cache) {
- cos.dispose();
- }
- }
+ public void initializeAttachments() throws IOException {
+ initializeRootMessage();
+
+ attachments = new LazyAttachmentCollection(this);
+ message.setAttachments(attachments);
}
- public void process() throws MessagingException, IOException {
- processSoapBody();
- processAttachments();
- }
+ protected void initializeRootMessage() throws IOException {
+ contentType = (String) message.get(Message.CONTENT_TYPE);
- /**
- * construct the primary soap body part and attachments
- */
- public void processSoapBody() throws MessagingException, IOException {
+ if (contentType == null) {
+ throw new IllegalStateException("Content-Type can not be empty!");
+ }
+
+ InputStream input = message.getContent(InputStream.class);
+ if (input == null) {
+ throw new IllegalStateException("An InputStream must be provided!");
+ }
- Attachment soapMimePart = readMimePart();
- message.setContent(Attachment.class, soapMimePart);
- InputStream in = soapMimePart.getDataHandler().getInputStream();
- message.setContent(InputStream.class, in);
- }
+ if (contentType.toLowerCase().indexOf("multipart/related") != -1) {
+ int i = contentType.indexOf("boundary=\"");
+ int end;
+ int len;
+ if (i == -1) {
+ i = contentType.indexOf("boundary=");
+ end = contentType.indexOf(";", i + 9);
+ if (end == -1) {
+ end = contentType.length();
+ }
+ len = 9;
+ } else {
+ end = contentType.indexOf("\"", i + 10);
+ len = 10;
+ }
+ if (i == -1 || end == -1) {
+ throw new IOException("Invalid content type: missing boundary! " + contentType);
+ }
+ boundary = "--" + contentType.substring(i + len, end);
+ stream = new PushbackInputStream(input, boundary.length());
+ if (!readTillFirstBoundary(stream, boundary.getBytes())) {
+ throw new IOException("Couldn't find MIME boundary: " + boundary);
+ }
- public void processAttachments() throws MessagingException, IOException {
- Collection<Attachment> attachments = message.getAttachments();
- Attachment att = readMimePart();
- while (att != null && att.getId() != null) {
- attachments.add(att);
- att = readMimePart();
+ try {
+ // TODO: Do we need to copy these headers somewhere?
+ new InternetHeaders(stream);
+ } catch (MessagingException e) {
+ throw new RuntimeException(e);
+ }
+
+ body = new DelegatingInputStream(new MimeBodyPartInputStream(stream, boundary.getBytes()));
+ message.setContent(InputStream.class, body);
}
}
- public Attachment getAttachment(String cid) throws MessagingException, IOException {
- Collection<Attachment> attachments = message.getAttachments();
- for (Attachment att : attachments) {
- if (att.getId().equals(cid)) {
- return att;
- }
+ public AttachmentImpl readNext() throws IOException {
+ // Cache any mime parts that are currently being streamed
+ cacheStreamedAttachments();
+
+ int v = stream.read();
+ if (v == -1) {
+ return null;
}
- Attachment att = readMimePart();
- while (att != null && att.getId() != null) {
- attachments.add(att);
- String convertId = cid.substring(0, 4).equals("cid:") ? cid.substring(4) : cid;
- if (att.getId().equals(convertId)) {
- return att;
- }
- att = readMimePart();
+ stream.unread(v);
+
+
+ InternetHeaders headers;
+ try {
+ headers = new InternetHeaders(stream);
+ } catch (MessagingException e) {
+ // TODO create custom IOException
+ throw new RuntimeException(e);
+ }
+
+ String id = headers.getHeader("Content-ID", null);
+ if (id != null && id.startsWith("<")) {
+ id = id.substring(1, id.length() - 1);
+ }
+ id = id.startsWith("cid:") ? id.substring(4) : id;
+
+ AttachmentImpl att = new AttachmentImpl(id);
+ setupAttachment(att, headers);
+ return att;
+ }
+
+ private void cacheStreamedAttachments() throws IOException {
+ if (body instanceof DelegatingInputStream
+ && !((DelegatingInputStream) body).isClosed()) {
+
+ cache((DelegatingInputStream) body, true);
+ message.setContent(InputStream.class, body);
+ }
+
+ for (Attachment a : attachments.getLoadedAttachments()) {
+ DataSource s = a.getDataHandler().getDataSource();
+ cache((DelegatingInputStream) s.getInputStream(), false);
}
- return null;
}
+ private void cache(DelegatingInputStream input, boolean deleteOnClose) throws IOException {
+ CachedOutputStream out = new CachedOutputStream();
+ IOUtils.copy(input, out);
+ input.setInputStream(out.getInputStream());
+ }
+
/**
* Move the read pointer to the begining of the first part read till the end
* of first boundary
@@ -222,142 +202,35 @@
return false;
}
- private Attachment readMimePart() throws MessagingException, IOException {
-
- int v = stream.read();
- if (v == -1) {
- return null;
- }
- stream.unread(v);
- InternetHeaders iheaders = new InternetHeaders(stream);
- Map<String, List<String>> internalHeaders = new HashMap<String, List<String>>();
- for (Enumeration e = iheaders.getAllHeaders(); e.hasMoreElements();) {
- Header header = (Header)e.nextElement();
- List<String> values = new ArrayList<String>();
- String headerName = HttpHeaderHelper.getHeaderKey(header.getName());
- internalHeaders.put(headerName, values);
- values.add(header.getValue());
- }
+ /**
+ * Create an Attachment from the MIME stream. If there is a previous attachment
+ * that is not read, cache that attachment.
+ *
+ * @return
+ * @throws IOException
+ */
+ private void setupAttachment(AttachmentImpl att, InternetHeaders headers) throws IOException {
MimeBodyPartInputStream partStream = new MimeBodyPartInputStream(stream, boundary.getBytes());
- final CachedOutputStream cos = new CachedOutputStream();
- cos.setThreshold(THRESHHOLD);
- AbstractCachedOutputStream.copyStream(partStream, cos, THRESHHOLD);
- cos.close();
- final String ct = constructHeaderValue(HttpHeaderHelper.getHeader(internalHeaders,
- HttpHeaderHelper.CONTENT_TYPE));
- cache.add(cos);
- DataSource source = new AttachmentDataSource(ct, cos);
- DataHandler dh = new DataHandler(source);
- String id = internalHeaders.get(HttpHeaderHelper.getHeaderKey(HttpHeaderHelper.CONTENT_ID)).get(0);
- if (id != null && id.startsWith("<")) {
- id = id.substring(1, id.length() - 1);
- }
- AttachmentImpl att = new AttachmentImpl(id, dh);
- for (Iterator<String> it = internalHeaders.keySet().iterator(); it.hasNext();) {
- String headerName = it.next();
- List values = internalHeaders.get(headerName);
- if (headerName.equalsIgnoreCase("Content-Transfer-Encoding")
- && values.size() == 1 && values.get(0).equals("binary")) {
+
+ final String ct = headers.getHeader("Content-Type", null);
+ DataSource source = new AttachmentDataSource(ct, new DelegatingInputStream(partStream));
+ att.setDataHandler(new DataHandler(source));
+
+ for (Enumeration<?> e = headers.getAllHeaders(); e.hasMoreElements();) {
+ Header header = (Header) e.nextElement();
+ if (header.getName().equalsIgnoreCase("Content-Transfer-Encoding")
+ && header.getValue().equalsIgnoreCase("binary")) {
att.setXOP(true);
}
- att.setHeader(headerName, constructHeaderValue(values));
+ att.setHeader(header.getName(), header.getValue());
}
- return att;
}
- private static String constructHeaderValue(List values) {
- StringBuffer sb = new StringBuffer(200);
- for (int i = 0; i < values.size(); i++) {
- sb.append(values.get(i));
- }
- return sb.toString();
+ public boolean isLazyLoading() {
+ return lazyLoading;
}
-
- private class MimeBodyPartInputStream extends InputStream {
-
- PushbackInputStream inStream;
-
- boolean boundaryFound;
-
- byte[] boundary;
-
- public MimeBodyPartInputStream(PushbackInputStream inStreamParam, byte[] boundaryParam) {
- super();
- this.inStream = inStreamParam;
- this.boundary = boundaryParam;
- }
- public int read() throws IOException {
- boolean needUnread0d0a = false;
- if (boundaryFound) {
- return -1;
- }
-
- // read the next value from stream
- int value = inStream.read();
- // A problem occured because all the mime parts tends to have a /r/n
- // at the end. Making it hard to transform them to correct
- // DataSources.
- // This logic introduced to handle it
- if (value == 13) {
- value = inStream.read();
- if (value != 10) {
- inStream.unread(value);
- return 13;
- } else {
- value = inStream.read();
- if ((byte) value != boundary[0]) {
- inStream.unread(value);
- inStream.unread(10);
- return 13;
- } else {
- needUnread0d0a = true;
- }
- }
- } else if ((byte) value != boundary[0]) {
- return value;
- }
- // read value is the first byte of the boundary. Start matching the
- // next characters to find a boundary
- int boundaryIndex = 0;
- while ((boundaryIndex < boundary.length) && ((byte) value == boundary[boundaryIndex])) {
- value = inStream.read();
- boundaryIndex++;
- }
- if (boundaryIndex == boundary.length) {
- // boundary found
- boundaryFound = true;
- // read the end of line character
- if (inStream.read() == 45 && value == 45) {
- // Last mime boundary should have a succeeding "--"
- // as we are on it, read the terminating CRLF
- inStream.read();
- inStream.read();
- }
- return -1;
- }
- // Boundary not found. Restoring bytes skipped.
- // write first skipped byte, push back the rest
- if (value != -1) {
- // Stream might have ended
- inStream.unread(value);
- }
- if (needUnread0d0a) {
- inStream.unread(boundary, 0, boundaryIndex);
- inStream.unread(10);
- value = 13;
- } else {
- inStream.unread(boundary, 1, boundaryIndex - 1);
- value = boundary[0];
- }
- return value;
- }
- }
-
- protected static void printStream(InputStream in) throws IOException {
- for (int i = in.read(); i != -1; i = in.read()) {
- System.out.write(i);
- }
- System.out.println("print stream");
+ public void setLazyLoading(boolean lazyLoading) {
+ this.lazyLoading = lazyLoading;
}
}
Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentImpl.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentImpl.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentImpl.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java Thu Nov 30 11:19:29 2006
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
import java.util.HashMap;
import java.util.Iterator;
@@ -29,14 +29,18 @@
public class AttachmentImpl implements Attachment {
- private DataHandler handler;
+ private DataHandler dataHandler;
private String id;
private Map<String, String> headers = new HashMap<String, String>();
private boolean xop;
+ public AttachmentImpl(String idParam) {
+ this.id = idParam;
+ }
+
public AttachmentImpl(String idParam, DataHandler handlerParam) {
this.id = idParam;
- this.handler = handlerParam;
+ this.dataHandler = handlerParam;
}
public String getId() {
@@ -44,7 +48,11 @@
}
public DataHandler getDataHandler() {
- return handler;
+ return dataHandler;
+ }
+
+ public void setDataHandler(DataHandler dataHandler) {
+ this.dataHandler = dataHandler;
}
public void setHeader(String name, String value) {
Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentSerializer.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentSerializer.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentSerializer.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java Thu Nov 30 11:19:29 2006
@@ -17,101 +17,100 @@
* under the License.
*/
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
-import java.io.InputStream;
-import java.io.ObjectOutputStream;
+import java.io.IOException;
import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.helpers.HttpHeaderHelper;
-import org.apache.cxf.interceptor.Fault;
-import org.apache.cxf.io.AbstractCachedOutputStream;
+import java.io.OutputStreamWriter;
+
+import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.message.Attachment;
import org.apache.cxf.message.Message;
public class AttachmentSerializer {
+ private static final String BODY_ATTACHMENT_ID = "root.message@cxf.apache.org";
private Message message;
-
- private InputStream in;
-
+ private String bodyBoundary;
+ private OutputStreamWriter writer;
private OutputStream out;
-
- public AttachmentSerializer(Message messageParam, InputStream inParam, OutputStream outParam) {
+
+ public AttachmentSerializer(Message messageParam) {
message = messageParam;
- in = inParam;
- out = outParam;
}
/**
- * Using result in soapMessage & attachment to write to output stream
- *
- * @param soapMessage
- * @param in
- * input stream contain the attachment
- * @param out
- * @throws CxfRioException
+ * Serialize the beginning of the attachment which includes the MIME
+ * beginning and headers for the root message.
*/
+ public void writeProlog() throws IOException {
+ // Create boundary for body
+ bodyBoundary = AttachmentUtil.getUniqueBoundaryValue(0);
+
+ String bodyCt = (String) message.get(Message.CONTENT_TYPE);
+
+ // Set transport mime type
+ StringBuilder ct = new StringBuilder();
+ ct.append("multipart/related; boundary=\"")
+ .append(bodyBoundary)
+ .append("\"; ")
+ .append("type=\"application/xop+xml\"; ")
+ .append("start=\"<")
+ .append(BODY_ATTACHMENT_ID)
+ .append(">\"; ")
+ .append("start-info=\"")
+ .append(bodyCt)
+ .append("\"");
+
+ message.put(Message.CONTENT_TYPE, ct.toString());
+
+ // 2. write headers
+ out = message.getContent(OutputStream.class);
+ String encoding = (String) message.get(Message.ENCODING);
+ if (encoding == null) {
+ encoding = "UTF-8";
+ }
+ writer = new OutputStreamWriter(out, encoding);
+ writer.write("--");
+ writer.write(bodyBoundary);
+
+ writeHeaders(bodyCt, BODY_ATTACHMENT_ID);
+ }
- public String serializeMultipartMessage() {
+ private void writeHeaders(String contentType, String attachmentId) throws IOException {
+ writer.write("\n");
+ writer.write("Content-Type: ");
+ writer.write(contentType);
+ writer.write("\n");
+
+ writer.write("Content-Transfer-Encoding: binary\n");
+
+ writer.write("Content-ID: <");
+ writer.write(attachmentId);
+ writer.write(">\n\n");
+ writer.flush();
+ }
- String soapPartId;
- String boundary = AttachmentUtil.getUniqueBoundaryValue(0);
- try {
- soapPartId = AttachmentUtil.createContentID(null);
- } catch (UnsupportedEncodingException e) {
- throw new Fault(e);
- }
- try {
- Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>) message
- .get(Message.PROTOCOL_HEADERS));
- if (headers == null) {
- // this is the case of server out (response)
- headers = new HashMap<String, List<String>>();
- message.put(Message.PROTOCOL_HEADERS, headers);
- }
- AttachmentUtil.setMimeRequestHeader(headers, message, soapPartId,
- "soap message with attachments", boundary);
- //finish prepare header, call flush to flush headers and resetOut to get wire stream
- out.flush();
+ /**
+ * Write the end of the body boundary and any attachments included.
+ * @throws IOException
+ */
+ public void writeAttachments() throws IOException {
+ writer.write('\n');
+ writer.write("--");
+ writer.write(bodyBoundary);
+
+ for (Attachment a : message.getAttachments()) {
+ writeHeaders(a.getDataHandler().getContentType(), a.getId());
+
+ IOUtils.copy(a.getDataHandler().getInputStream(), out);
- String soapHeader = AttachmentUtil.getSoapPartHeader(message, soapPartId, "");
- out.write(("--" + boundary + "\r\n").getBytes());
- out.write(soapHeader.getBytes());
- AbstractCachedOutputStream.copyStream(in, out, 64 * 1024);
- for (Attachment att : message.getAttachments()) {
- soapHeader = AttachmentUtil.getAttchmentPartHeader(att);
- out.write(("--" + boundary + "\r\n").getBytes());
- out.write(soapHeader.getBytes());
- Object content = att.getDataHandler().getContent();
- if (content instanceof InputStream) {
- InputStream insAtt = (InputStream) content;
- AbstractCachedOutputStream.copyStream(insAtt, out, 64 * 1024);
- } else {
- ObjectOutputStream oos = new ObjectOutputStream(out);
- oos.writeObject(content);
- }
- out.write("\r\n".getBytes());
- }
- out.write(("--" + boundary + "--\r\n").getBytes());
- out.flush();
- // build contentType string for return
- List<String> contentType = (List<String>) headers.get(HttpHeaderHelper.getHeaderKey(
- HttpHeaderHelper.CONTENT_TYPE));
- StringBuffer sb = new StringBuffer(120);
- for (String s : contentType) {
- sb.append(s);
- }
- return sb.toString();
- } catch (Exception e) {
- throw new Fault(e);
+ writer.write("--");
+ writer.write(bodyBoundary);
+ writer.write('\n');
}
-
+
+ writer.flush();
}
}
Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentUtil.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentUtil.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentUtil.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java Thu Nov 30 11:19:29 2006
@@ -17,21 +17,17 @@
* under the License.
*/
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
import java.util.UUID;
import org.apache.cxf.helpers.HttpHeaderHelper;
import org.apache.cxf.message.Attachment;
-import org.apache.cxf.message.Message;
public final class AttachmentUtil {
@@ -70,21 +66,6 @@
return s.toString();
}
- public static String getSoapPartHeader(Message message, String soapPartId, String action) {
- StringBuffer buffer = new StringBuffer(200);
- buffer.append(HttpHeaderHelper.getHeaderKey(HttpHeaderHelper.CONTENT_TYPE)
- + ": application/xop+xml; charset=utf-8; ");
- buffer.append("type=\"" + message.getAttachmentMimeType());
- if (action != null) {
- buffer.append("; action=" + action + "\"\r\n");
- } else {
- buffer.append("\"\r\n");
- }
- buffer.append("Content-Transfer-Encoding: binary\r\n");
- buffer.append("Content-ID: <" + soapPartId + ">\r\n\r\n");
- return buffer.toString();
- }
-
public static String getAttchmentPartHeader(Attachment att) {
StringBuffer buffer = new StringBuffer(200);
buffer.append(HttpHeaderHelper.getHeaderKey(HttpHeaderHelper.CONTENT_TYPE) + ": "
@@ -96,26 +77,4 @@
return buffer.toString();
}
- public static void setMimeRequestHeader(Map<String, List<String>> reqHeaders, Message message,
- String soapPartId, String contentDesc, String boundary) {
- List<String> header1 = new ArrayList<String>();
- header1.add("1.0");
- reqHeaders.put("MIME-Version", header1);
- List<String> header2 = new ArrayList<String>();
- header2.add("Multipart/" + getMimeSubType(message, soapPartId, boundary));
- reqHeaders.put(HttpHeaderHelper.getHeaderKey(HttpHeaderHelper.CONTENT_TYPE), header2);
- List<String> header3 = new ArrayList<String>();
- header3.add(contentDesc);
- reqHeaders.put("Content-Description", header3);
-
- }
-
- public static String getMimeSubType(Message message, String soapPartId, String boundary) {
- StringBuffer ct = new StringBuffer();
- ct.append("related; boundary=\"" + boundary + "\"; ");
- ct.append("type=\"application/xop+xml\"; ");
- ct.append("start=\"<" + soapPartId + ">\"; ");
- ct.append("start-info=" + message.getAttachmentMimeType());
- return ct.toString();
- }
}
Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/ByteDataSource.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/ByteDataSource.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/ByteDataSource.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java Thu Nov 30 11:19:29 2006
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
import java.io.ByteArrayInputStream;
import java.io.IOException;
Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/CachedOutputStream.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/CachedOutputStream.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/CachedOutputStream.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java Thu Nov 30 11:19:29 2006
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
import java.io.IOException;
import java.io.PipedInputStream;
Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java?view=auto&rev=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java Thu Nov 30 11:19:29 2006
@@ -0,0 +1,98 @@
+/**
+ * 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.attachment;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+
+final class DelegatingInputStream extends InputStream {
+ private InputStream is;
+ private boolean isClosed;
+
+ /**
+ * @param source
+ */
+ DelegatingInputStream(InputStream is) {
+ this.is = is;
+ }
+
+ @Override
+ public void close() throws IOException {
+ is.close();
+ isClosed = true;
+ }
+
+ public boolean isClosed() {
+ return isClosed;
+ }
+
+ public void setClosed(boolean closed) {
+ this.isClosed = closed;
+ }
+
+ public int read() throws IOException {
+ return this.is.read();
+ }
+
+ @Override
+ public int available() throws IOException {
+ return this.is.available();
+ }
+
+ @Override
+ public synchronized void mark(int arg0) {
+ this.is.mark(arg0);
+ }
+
+ @Override
+ public boolean markSupported() {
+ return this.is.markSupported();
+ }
+
+ @Override
+ public int read(byte[] bytes, int arg1, int arg2) throws IOException {
+ return this.is.read(bytes, arg1, arg2);
+ }
+
+ @Override
+ public int read(byte[] bytes) throws IOException {
+ return this.is.read(bytes);
+ }
+
+ @Override
+ public synchronized void reset() throws IOException {
+ this.is.reset();
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ return this.is.skip(n);
+ }
+
+ public void setInputStream(InputStream inputStream) {
+ this.is = inputStream;
+ }
+
+
+ public InputStream getInputStream() {
+ return is;
+ }
+}
\ No newline at end of file
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java?view=auto&rev=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java Thu Nov 30 11:19:29 2006
@@ -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.attachment;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cxf.message.Attachment;
+
+public class LazyAttachmentCollection implements Collection<Attachment> {
+ private AttachmentDeserializer deserializer;
+ private final List<Attachment> attachments = new ArrayList<Attachment>();
+
+ public LazyAttachmentCollection(AttachmentDeserializer deserializer) {
+ super();
+ this.deserializer = deserializer;
+ }
+
+ public List<Attachment> getLoadedAttachments() {
+ return attachments;
+ }
+
+ private void loadAll() {
+ try {
+ Attachment a = deserializer.readNext();
+ while (a != null) {
+ attachments.add(a);
+ a = deserializer.readNext();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Iterator<Attachment> iterator() {
+ return new Iterator<Attachment>() {
+ int current;
+
+ public boolean hasNext() {
+ if (attachments.size() > current) {
+ return true;
+ }
+
+ // check if there is another attachment
+ try {
+ Attachment a = deserializer.readNext();
+ if (a == null) {
+ return false;
+ } else {
+ attachments.add(a);
+ return true;
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Attachment next() {
+ Attachment a = attachments.get(current);
+ current++;
+ return a;
+ }
+
+ public void remove() {
+ attachments.remove(current);
+ }
+
+ };
+ }
+
+ public int size() {
+ loadAll();
+
+ return attachments.size();
+ }
+
+ public boolean add(Attachment arg0) {
+ return attachments.add(arg0);
+ }
+
+ public boolean addAll(Collection<? extends Attachment> arg0) {
+ return attachments.addAll(arg0);
+ }
+
+ public void clear() {
+ attachments.clear();
+ }
+
+ public boolean contains(Object arg0) {
+ return attachments.contains(arg0);
+ }
+
+ public boolean containsAll(Collection<?> arg0) {
+ return attachments.containsAll(arg0);
+ }
+
+ public boolean isEmpty() {
+ return attachments.isEmpty();
+ }
+
+ public boolean remove(Object arg0) {
+ return attachments.remove(arg0);
+ }
+
+ public boolean removeAll(Collection<?> arg0) {
+ return attachments.removeAll(arg0);
+ }
+
+ public boolean retainAll(Collection<?> arg0) {
+ return attachments.retainAll(arg0);
+ }
+
+ public Object[] toArray() {
+ loadAll();
+
+ return attachments.toArray();
+ }
+
+ public <T> T[] toArray(T[] arg0) {
+ loadAll();
+
+ return attachments.toArray(arg0);
+ }
+
+
+
+}
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java?view=auto&rev=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java Thu Nov 30 11:19:29 2006
@@ -0,0 +1,89 @@
+/**
+ * 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.attachment;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+
+import javax.activation.DataSource;
+
+import org.apache.cxf.message.Attachment;
+
+/**
+ * A DataSource which will search through a Collection of attachments so as to
+ * lazily load the attachment from the collection. This allows streaming attachments
+ * with databinding toolkits like JAXB.
+ */
+public class LazyDataSource implements DataSource {
+ private DataSource dataSource;
+ private Collection<Attachment> attachments;
+ private String id;
+
+ public LazyDataSource(String id, Collection<Attachment> attachments) {
+ super();
+ this.id = id;
+ this.attachments = attachments;
+ }
+
+ private synchronized void load() {
+ if (dataSource == null) {
+ for (Attachment a : attachments) {
+ if (a.getId().equals(id)) {
+ this.dataSource = a.getDataHandler().getDataSource();
+ break;
+ }
+ }
+ }
+ }
+
+ public String getContentType() {
+ load();
+
+ return dataSource.getContentType();
+ }
+
+ public InputStream getInputStream() throws IOException {
+ load();
+
+ return dataSource.getInputStream();
+ }
+
+ public String getName() {
+ load();
+
+ return dataSource.getName();
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ load();
+
+ return dataSource.getOutputStream();
+ }
+
+ public DataSource getDataSource() {
+ return dataSource;
+ }
+
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+}
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java?view=auto&rev=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java Thu Nov 30 11:19:29 2006
@@ -0,0 +1,105 @@
+/**
+ * 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.attachment;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+
+public class MimeBodyPartInputStream extends InputStream {
+
+ PushbackInputStream inStream;
+
+ boolean boundaryFound;
+
+ byte[] boundary;
+
+ public MimeBodyPartInputStream(PushbackInputStream inStreamParam, byte[] boundaryParam) {
+ super();
+ this.inStream = inStreamParam;
+ this.boundary = boundaryParam;
+ }
+
+ public int read() throws IOException {
+ boolean needUnread0d0a = false;
+ if (boundaryFound) {
+ return -1;
+ }
+
+ // read the next value from stream
+ int value = inStream.read();
+ // A problem occured because all the mime parts tends to have a /r/n
+ // at the end. Making it hard to transform them to correct
+ // DataSources.
+ // This logic introduced to handle it
+ if (value == 13) {
+ value = inStream.read();
+ if (value != 10) {
+ inStream.unread(value);
+ return 13;
+ } else {
+ value = inStream.read();
+ if ((byte) value != boundary[0]) {
+ inStream.unread(value);
+ inStream.unread(10);
+ return 13;
+ } else {
+ needUnread0d0a = true;
+ }
+ }
+ } else if ((byte) value != boundary[0]) {
+ return value;
+ }
+ // read value is the first byte of the boundary. Start matching the
+ // next characters to find a boundary
+ int boundaryIndex = 0;
+ while ((boundaryIndex < boundary.length) && ((byte) value == boundary[boundaryIndex])) {
+ value = inStream.read();
+ boundaryIndex++;
+ }
+ if (boundaryIndex == boundary.length) {
+ // boundary found
+ boundaryFound = true;
+ // read the end of line character
+ if (inStream.read() == 45 && value == 45) {
+ // Last mime boundary should have a succeeding "--"
+ // as we are on it, read the terminating CRLF
+ inStream.read();
+ inStream.read();
+ }
+ return -1;
+ }
+ // Boundary not found. Restoring bytes skipped.
+ // write first skipped byte, push back the rest
+ if (value != -1) {
+ // Stream might have ended
+ inStream.unread(value);
+ }
+ if (needUnread0d0a) {
+ inStream.unread(boundary, 0, boundaryIndex);
+ inStream.unread(10);
+ value = 13;
+ } else {
+ inStream.unread(boundary, 1, boundaryIndex - 1);
+ value = boundary[0];
+ }
+ return value;
+ }
+}
\ No newline at end of file
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java (from r480652, incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java&r1=480652&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java Thu Nov 30 11:19:29 2006
@@ -17,24 +17,18 @@
* under the License.
*/
-package org.apache.cxf.binding.soap.interceptor;
+package org.apache.cxf.interceptor;
import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Collection;
import java.util.ResourceBundle;
-import org.apache.cxf.binding.attachment.AttachmentSerializer;
-import org.apache.cxf.binding.soap.SoapFault;
-import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.attachment.AttachmentSerializer;
import org.apache.cxf.common.i18n.BundleUtils;
-import org.apache.cxf.common.i18n.Message;
-import org.apache.cxf.interceptor.Fault;
-import org.apache.cxf.io.AbstractCachedOutputStream;
-import org.apache.cxf.message.Attachment;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
-public class AttachmentOutInterceptor extends AbstractSoapInterceptor {
+public class AttachmentOutInterceptor extends AbstractPhaseInterceptor<Message> {
private static final ResourceBundle BUNDLE = BundleUtils.getBundle(AttachmentOutInterceptor.class);
@@ -43,54 +37,22 @@
setPhase(Phase.PRE_STREAM);
}
- public void handleMessage(SoapMessage message) throws Fault {
-
+ public void handleMessage(Message message) throws Fault {
if (!Boolean.TRUE.equals(message.getContextualProperty(
org.apache.cxf.message.Message.MTOM_ENABLED))) {
return;
}
- OutputStream os = message.getContent(OutputStream.class);
- CachedStream cs = new CachedStream();
- message.setContent(OutputStream.class, cs);
-
- // Calling for soap out interceptor
- if (!message.getInterceptorChain().doIntercept(message)
- && message.getContent(Exception.class) != null) {
- if (message.getContent(Exception.class) instanceof Fault) {
- throw (Fault) message.getContent(Exception.class);
- } else {
- throw new Fault(message.getContent(Exception.class));
- }
- }
- // Set back the output stream
- message.setContent(OutputStream.class, os);
+ AttachmentSerializer serializer = new AttachmentSerializer(message);
try {
- Collection<Attachment> attachments = message.getAttachments();
- cs.flush();
- if (attachments.size() > 0) {
- AttachmentSerializer as = new AttachmentSerializer(message, cs.getInputStream(), os);
- as.serializeMultipartMessage();
- } else {
- // get wire connection, and copy xml infoset directly into it
- os.flush();
- AbstractCachedOutputStream.copyStream(cs.getInputStream(), os, 64 * 1024);
- }
- } catch (IOException ioe) {
- throw new SoapFault(new Message("ATTACHMENT_IO", BUNDLE, ioe.toString()),
- SoapFault.ATTACHMENT_IO);
+ serializer.writeProlog();
+
+ message.getInterceptorChain().doIntercept(message);
+
+ serializer.writeAttachments();
+ } catch (IOException e) {
+ throw new Fault(new org.apache.cxf.common.i18n.Message("WRITE_ATTACHMENTS", BUNDLE), e);
}
}
- private class CachedStream extends AbstractCachedOutputStream {
- protected void doFlush() throws IOException {
- currentStream.flush();
- }
-
- protected void doClose() throws IOException {
- }
-
- protected void onWrite() throws IOException {
- }
- }
}
Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties Thu Nov 30 11:19:29 2006
@@ -29,3 +29,4 @@
COULD_NOT_SEND=Could not send Message.
NO_PART_FOUND=Message part {0} was not recognized.
ORDERED_PARAM_REQUIRED=Parameter should be ordered in the following sequence: {0}
+WRITE_ATTACHMENTS=Could not write attachments.
Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java (from r480652, incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java&r1=480652&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java Thu Nov 30 11:19:29 2006
@@ -17,11 +17,12 @@
* under the License.
*/
-package org.apache.cxf.binding.soap.interceptor;
+package org.apache.cxf.interceptor;
+import java.io.IOException;
import java.util.logging.Logger;
-import org.apache.cxf.binding.attachment.AttachmentDeserializer;
+import org.apache.cxf.attachment.AttachmentDeserializer;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
@@ -49,9 +50,17 @@
LOG.info("MultipartMessageInterceptor skipped in HTTP GET method");
return;
}
+
+ if (!Boolean.TRUE.equals(
+ message.getContextualProperty(org.apache.cxf.message.Message.MTOM_ENABLED))) {
+ return;
+ }
+
AttachmentDeserializer ad = new AttachmentDeserializer(message);
- if (ad.preprocessMessage()) {
- message.put(AttachmentDeserializer.class, ad);
+ try {
+ ad.initializeAttachments();
+ } catch (IOException e) {
+ throw new Fault(e);
}
}
Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java Thu Nov 30 11:19:29 2006
@@ -19,17 +19,12 @@
package org.apache.cxf.interceptor;
-import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.cxf.Bus;
-import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.endpoint.Endpoint;
-import org.apache.cxf.helpers.HttpHeaderHelper;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
@@ -61,36 +56,13 @@
outMessage = ep.getBinding().createMessage();
ex.setOutMessage(outMessage);
}
- setUpContentType(outMessage);
Message faultMessage = message.getExchange().getOutFaultMessage();
if (faultMessage == null) {
faultMessage = ep.getBinding().createMessage();
ex.setOutFaultMessage(faultMessage);
}
-
- setUpContentType(faultMessage);
-
outMessage.setInterceptorChain(getOutInterceptorChain(ex));
- }
-
- @SuppressWarnings("unchecked")
- private void setUpContentType(Message message) {
- if (StringUtils.isEmpty((String)message.get(Message.CONTENT_TYPE))) {
- return;
- }
-
- Map<String, List<String>> headers = (Map<String, List<String>>)message.get(Message.PROTOCOL_HEADERS);
- if (headers == null) {
- headers = new HashMap<String, List<String>>();
- message.put(Message.PROTOCOL_HEADERS, headers);
- }
-
- LOG.info("OutgoingChainSetupInterceptor set the content-type to: "
- + message.get(Message.CONTENT_TYPE));
-
- headers.put(HttpHeaderHelper.CONTENT_TYPE,
- Arrays.asList(new String[] {(String)message.get(Message.CONTENT_TYPE)}));
}
public static InterceptorChain getOutInterceptorChain(Exchange ex) {
Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java Thu Nov 30 11:19:29 2006
@@ -113,7 +113,6 @@
MessagePartInfo part = itr.next();
objects.add(dr.read(part, message));
}
-
}
message.setContent(List.class, objects);
Re: svn commit: r481043 [1/2] - in /incubator/cxf/trunk: api/src/main/java/org/apache/cxf/message/
rt/bindings/http/src/test/java/org/apache/cxf/binding/http/ rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/
rt/bindings/soap/src/main/java/org/ap...
Posted by Andrea Smyth <an...@iona.com>.
dandiep@apache.org wrote:
>Author: dandiep
>Date: Thu Nov 30 11:19:29 2006
>New Revision: 481043
>
>URL: http://svn.apache.org/viewvc?view=rev&rev=481043
>Log:
>o Rewrite MTOM support to be completely streamed based. If attachments
> are accessed out of order, they are cached. This is done through a
> LazyAttachmentCollection. The iterator will iterate over attachments
> as they are accessed, loading them one at a time until the correct
> one is found. On the outgoing side the AttachmentSerializer allows
> us to write out the attachments in steps.
>o Move MTOM interceptors into core as they are dependent on SOAP and
> some people would like to use it with XML over HTTP.
>o Unify handling of Message.CONTENT_TYPE, transports are now expected
> to deal with it correctly and we shouldn't have to muck with the protocol
> headers to set the content type (like we were doing in
> OutgoingChainSetupInterceptor).
>o Rename some message properties to make it easier for configuration.
>o Rewrite server side mtom test to not use the client to make it easy
> to test and debug.
>o Remove ugly Message.getAttachmentMimeType() method
>o Try to use IOUtils.copy() in more places to reduce duplication
>o This has not been interop tested. I think there may be an issue or two
> when using with .NET 2.0, but I need to test and track down the issue
> (will do so soon).
>
>
>
I am seeing the ClientMtomXopTest failing now on Windows:
[surefire] Running org.apache.cxf.systest.mtom.ClientMtomXopTest
[surefire] Tests run: 1, Failures: 1, Errors: 0, Time elapsed: 7.13 sec
[surefire]
[surefire] testMtomXop(org.apache.cxf.systest.mtom.ClientMtomXopTest)
Time elap
sed: 1.463 sec <<< FAILURE!
junit.framework.ComparisonFailure: attachinfo changed expected:<...
> but was:<...>
at junit.framework.Assert.assertEquals(Assert.java:81)
at
org.apache.cxf.systest.mtom.ClientMtomXopTest.testMtomXop(ClientMtomXopTest.java:155)
....
Any ideas?
Andrea.