Author: dkulp
Date: Thu Feb 21 10:40:00 2008
New Revision: 629910
URL: http://svn.apache.org/viewvc?rev=629910&view=rev
Log:
[CXF-421, CXF-422, CXF-423, CXF-424] Bunch of updates for Provider based
attachment handling
Modified:
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchInDatabindingInterceptor.java
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutDatabindingInterceptor.java
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/ContextPropertiesMapping.java
incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/support/ContextPropertiesMappingTest.java
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentProviderXMLClientServerTest.java
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentStreamSourceXMLProvider.java
Modified:
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?rev=629910&r1=629909&r2=629910&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
(original)
+++
incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
Thu Feb 21 10:40:00 2008
@@ -19,14 +19,22 @@
package org.apache.cxf.attachment;
import java.io.IOException;
+import java.util.AbstractCollection;
+import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.activation.DataHandler;
import org.apache.cxf.message.Attachment;
-public class LazyAttachmentCollection implements Collection<Attachment> {
+public class LazyAttachmentCollection
+ implements Collection<Attachment> {
+
private AttachmentDeserializer deserializer;
private final List<Attachment> attachments = new ArrayList<Attachment>();
@@ -140,7 +148,175 @@
return attachments.toArray(arg0);
}
+
+ public Map<String, DataHandler> createDataHandlerMap() {
+ return new LazyAttachmentMap(this);
+ }
+
+ private static class LazyAttachmentMap implements Map<String, DataHandler>
{
+ LazyAttachmentCollection collection;
+
+ LazyAttachmentMap(LazyAttachmentCollection c) {
+ collection = c;
+ }
+
+ public void clear() {
+ collection.clear();
+ }
+
+ public boolean containsKey(Object key) {
+ Iterator<Attachment> it = collection.iterator();
+ while (it.hasNext()) {
+ Attachment at = it.next();
+ if (key.equals(at.getId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ public boolean containsValue(Object value) {
+ Iterator<Attachment> it = collection.iterator();
+ while (it.hasNext()) {
+ Attachment at = it.next();
+ if (value.equals(at.getDataHandler())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public DataHandler get(Object key) {
+ Iterator<Attachment> it = collection.iterator();
+ while (it.hasNext()) {
+ Attachment at = it.next();
+ if (key.equals(at.getId())) {
+ return at.getDataHandler();
+ }
+ }
+ return null;
+ }
+
+ public boolean isEmpty() {
+ return collection.isEmpty();
+ }
+ public int size() {
+ return collection.size();
+ }
+
+ public DataHandler remove(Object key) {
+ Iterator<Attachment> it = collection.iterator();
+ while (it.hasNext()) {
+ Attachment at = it.next();
+ if (key.equals(at.getId())) {
+ collection.remove(at);
+ return at.getDataHandler();
+ }
+ }
+ return null;
+ }
+ public DataHandler put(String key, DataHandler value) {
+ Attachment at = new AttachmentImpl(key, value);
+ collection.add(at);
+ return value;
+ }
+
+ public void putAll(Map<? extends String, ? extends DataHandler> t) {
+ for (Map.Entry<? extends String, ? extends DataHandler> ent :
t.entrySet()) {
+ put(ent.getKey(), ent.getValue());
+ }
+ }
+
+
+ public Set<Map.Entry<String, DataHandler>> entrySet() {
+ return new AbstractSet<Map.Entry<String, DataHandler>>() {
+ public Iterator<Map.Entry<String, DataHandler>> iterator() {
+ return new Iterator<Map.Entry<String, DataHandler>>() {
+ Iterator<Attachment> it = collection.iterator();
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+ public Map.Entry<String, DataHandler> next() {
+ return new Map.Entry<String, DataHandler>() {
+ Attachment at = it.next();
+ public String getKey() {
+ return at.getId();
+ }
+ public DataHandler getValue() {
+ return at.getDataHandler();
+ }
+ public DataHandler setValue(DataHandler value)
{
+ if (at instanceof AttachmentImpl) {
+ DataHandler h = at.getDataHandler();
+
((AttachmentImpl)at).setDataHandler(value);
+ return h;
+ } else {
+ throw new
UnsupportedOperationException();
+ }
+ }
+ };
+ }
+ public void remove() {
+ it.remove();
+ }
+ };
+ }
+ public int size() {
+ return collection.size();
+ }
+ };
+ }
+
+ public Set<String> keySet() {
+ return new AbstractSet<String>() {
+ public Iterator<String> iterator() {
+ return new Iterator<String>() {
+ Iterator<Attachment> it = collection.iterator();
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ public String next() {
+ return it.next().getId();
+ }
+
+ public void remove() {
+ it.remove();
+ }
+ };
+ }
+
+ public int size() {
+ return collection.size();
+ }
+ };
+ }
+
+
+ public Collection<DataHandler> values() {
+ return new AbstractCollection<DataHandler>() {
+ public Iterator<DataHandler> iterator() {
+ return new Iterator<DataHandler>() {
+ Iterator<Attachment> it = collection.iterator();
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+ public DataHandler next() {
+ return it.next().getDataHandler();
+ }
+ public void remove() {
+ it.remove();
+ }
+ };
+ }
+
+ public int size() {
+ return collection.size();
+ }
+ };
+ }
+
+ }
}
Modified:
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchInDatabindingInterceptor.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchInDatabindingInterceptor.java?rev=629910&r1=629909&r2=629910&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchInDatabindingInterceptor.java
(original)
+++
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchInDatabindingInterceptor.java
Thu Feb 21 10:40:00 2008
@@ -60,6 +60,7 @@
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.helpers.XMLUtils;
import org.apache.cxf.interceptor.AbstractInDatabindingInterceptor;
+import org.apache.cxf.interceptor.AttachmentInInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.StaxInInterceptor;
import org.apache.cxf.io.CachedOutputStream;
@@ -151,6 +152,7 @@
//LogicalHandler for DataSource payload
message.setContent(DataSource.class, obj);
} else {
+ new AttachmentInInterceptor().handleMessage(message);
new StaxInInterceptor().handleMessage(message);
DataReader<XMLStreamReader> dataReader = new
XMLStreamDataReader();
Modified:
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutDatabindingInterceptor.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutDatabindingInterceptor.java?rev=629910&r1=629909&r2=629910&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutDatabindingInterceptor.java
(original)
+++
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutDatabindingInterceptor.java
Thu Feb 21 10:40:00 2008
@@ -64,6 +64,7 @@
import org.apache.cxf.helpers.XMLUtils;
import org.apache.cxf.interceptor.AbstractInDatabindingInterceptor;
import org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor;
+import org.apache.cxf.interceptor.AttachmentOutInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.jaxws.handler.logical.DispatchLogicalHandlerInterceptor;
import org.apache.cxf.message.Attachment;
@@ -231,8 +232,7 @@
super(Phase.WRITE_ENDING);
}
- public void handleMessage(Message message) throws Fault {
- OutputStream os = message.getContent(OutputStream.class);
+ public void handleMessage(Message message) throws Fault {
XMLStreamWriter xmlWriter =
message.getContent(XMLStreamWriter.class);
SOAPMessage soapMessage = message.getContent(SOAPMessage.class);
@@ -264,15 +264,28 @@
l.add(head.getValue());
}
}
+ OutputStream os = message.getContent(OutputStream.class);
soapMessage.writeTo(os);
+ os.flush();
} else if (source != null) {
+ if (message.getAttachments() != null
+ && !message.getAttachments().isEmpty()) {
+
message.put(AttachmentOutInterceptor.WRITE_ATTACHMENTS, Boolean.TRUE);
+ new AttachmentOutInterceptor().handleMessage(message);
+ }
+ OutputStream os = message.getContent(OutputStream.class);
doTransform(source, os);
+ os.flush();
} else if (dataSource != null) {
+ if (message.getAttachments() != null
+ && !message.getAttachments().isEmpty()) {
+
message.put(AttachmentOutInterceptor.WRITE_ATTACHMENTS, Boolean.TRUE);
+ new AttachmentOutInterceptor().handleMessage(message);
+ }
+ OutputStream os = message.getContent(OutputStream.class);
doTransform(dataSource, os);
+ os.flush();
}
-
- // Finish the message processing, do flush
- os.flush();
} catch (Exception ex) {
ex.printStackTrace();
throw new Fault(new
org.apache.cxf.common.i18n.Message("EXCEPTION_WRITING_OBJECT", LOG, ex));
Modified:
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/ContextPropertiesMapping.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/ContextPropertiesMapping.java?rev=629910&r1=629909&r2=629910&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/ContextPropertiesMapping.java
(original)
+++
incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/ContextPropertiesMapping.java
Thu Feb 21 10:40:00 2008
@@ -18,8 +18,8 @@
*/
package org.apache.cxf.jaxws.support;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -31,6 +31,8 @@
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.MessageContext.Scope;
+import org.apache.cxf.attachment.AttachmentImpl;
+import org.apache.cxf.attachment.LazyAttachmentCollection;
import org.apache.cxf.binding.soap.SoapBindingConstants;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
@@ -235,17 +237,20 @@
Collection<Attachment> attachments = message.getAttachments();
if (attachments != null) {
-
- //preserve the order of iteration
- dataHandlers = new LinkedHashMap<String, DataHandler>();
- for (Attachment attachment : attachments) {
- dataHandlers.put(attachment.getId(),
attachment.getDataHandler());
+ if (attachments instanceof LazyAttachmentCollection) {
+ dataHandlers =
((LazyAttachmentCollection)attachments).createDataHandlerMap();
+ } else {
+ //preserve the order of iteration
+ dataHandlers = new LinkedHashMap<String, DataHandler>();
+ for (Attachment attachment : attachments) {
+ dataHandlers.put(attachment.getId(),
attachment.getDataHandler());
+ }
}
}
ctx.put(propertyName,
- dataHandlers == null ? Collections.EMPTY_MAP
- :
Collections.unmodifiableMap(dataHandlers),
+ dataHandlers == null ? new LinkedHashMap<String, DataHandler>()
+ : dataHandlers,
Scope.APPLICATION);
}
@@ -276,9 +281,27 @@
} else if (!other.isEmpty()) {
exchange.getOutMessage().put(Message.PROTOCOL_HEADERS,
ctx.get(MessageContext.HTTP_RESPONSE_HEADERS));
+ heads = other;
+ }
+ if (heads.containsKey("Content-Type")) {
+ List<String> ct = heads.get("Content-Type");
+ exchange.getOutMessage().put(Message.CONTENT_TYPE, ct.get(0));
+ heads.remove("Content-Type");
+ }
+ }
+ Map<String, DataHandler> dataHandlers
+ = CastUtils.cast((Map<?,
?>)ctx.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS));
+ if (dataHandlers != null && !dataHandlers.isEmpty()) {
+ Collection<Attachment> attachments =
exchange.getOutMessage().getAttachments();
+ if (attachments == null) {
+ attachments = new ArrayList<Attachment>();
+ exchange.getOutMessage().setAttachments(attachments);
+ }
+ for (Map.Entry<String, DataHandler> entry :
dataHandlers.entrySet()) {
+ Attachment att = new AttachmentImpl(entry.getKey(),
entry.getValue());
+ attachments.add(att);
}
}
}
-
}
Modified:
incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/support/ContextPropertiesMappingTest.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/support/ContextPropertiesMappingTest.java?rev=629910&r1=629909&r2=629910&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/support/ContextPropertiesMappingTest.java
(original)
+++
incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/support/ContextPropertiesMappingTest.java
Thu Feb 21 10:40:00 2008
@@ -148,6 +148,9 @@
ctx.containsKey(MessageContext.HTTP_RESPONSE_HEADERS);
EasyMock.expectLastCall().andReturn(false);
+
+ ctx.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
+ EasyMock.expectLastCall().andReturn(null);
EasyMock.replay(ctx);
Modified:
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentProviderXMLClientServerTest.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentProviderXMLClientServerTest.java?rev=629910&r1=629909&r2=629910&view=diff
==============================================================================
---
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentProviderXMLClientServerTest.java
(original)
+++
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentProviderXMLClientServerTest.java
Thu Feb 21 10:40:00 2008
@@ -23,18 +23,15 @@
import java.net.HttpURLConnection;
import java.net.URL;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.apache.cxf.common.util.Base64Utility;
import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.helpers.XMLUtils;
import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
public class AttachmentProviderXMLClientServerTest extends
AbstractBusClientServerTestBase {
@@ -46,7 +43,6 @@
}
@Test
- @Ignore("REVISIT: I do not think it is valid to use Provider to receive a
StreamSource with attachement")
public void testRequestWithAttachment() throws Exception {
HttpURLConnection connection =
@@ -63,20 +59,28 @@
IOUtils.copy(is, connection.getOutputStream());
connection.getOutputStream().close();
is.close();
+
+ assertTrue("wrong content type",
connection.getContentType().contains("multipart/related"));
+ String input = IOUtils.toString(connection.getInputStream());
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- DocumentBuilder builder = factory.newDocumentBuilder();
- assertEquals("wrong content type", "application/xml+custom",
connection.getContentType());
- Document result = builder.parse(connection.getInputStream());
- assertNotNull("result must not be null", result);
+ int idx = input.indexOf("-----");
+ int idx2 = input.indexOf("-----", idx + 5);
+ String root = input.substring(idx, idx2);
+ idx = root.indexOf("\r\n\r\n");
+ root = root.substring(idx).trim();
- connection.getInputStream().close();
+
+ Document result = XMLUtils.parse(root);
NodeList resList =
result.getDocumentElement().getElementsByTagName("att");
assertEquals("Two attachments must've been encoded", 2,
resList.getLength());
verifyAttachment(resList, "foo", "foobar");
verifyAttachment(resList, "bar", "barbaz");
+
+ input = input.substring(idx2);
+ assertTrue(input.contains("<foo>"));
+ assertTrue(input.contains("ABCDEFGHIJKLMNOP"));
}
private void verifyAttachment(NodeList atts, String contentId, String
value) {
Modified:
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentStreamSourceXMLProvider.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentStreamSourceXMLProvider.java?rev=629910&r1=629909&r2=629910&view=diff
==============================================================================
---
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentStreamSourceXMLProvider.java
(original)
+++
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/provider/AttachmentStreamSourceXMLProvider.java
Thu Feb 21 10:40:00 2008
@@ -31,6 +31,7 @@
import javax.activation.DataHandler;
import javax.annotation.Resource;
+import javax.mail.util.ByteArrayDataSource;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
@@ -111,6 +112,15 @@
List<String> contentTypeValues = new ArrayList<String>();
contentTypeValues.add("application/xml+custom");
respHeaders.put(Message.CONTENT_TYPE, contentTypeValues);
+
+ Map<String, DataHandler> outDataHandlers
+ =
CastUtils.cast((Map)mc.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS));
+ byte[] data = new byte[50];
+ for (int x = 0; x < data.length; x++) {
+ data[x] = (byte)(x + (int)'0');
+ }
+ DataHandler foo = new DataHandler(new ByteArrayDataSource(data,
"application/octet-stream"));
+ outDataHandlers.put("foo", foo);
return new StreamSource(new StringReader(buf.toString()));
}