You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by ve...@apache.org on 2009/02/27 02:28:43 UTC
svn commit: r748368 - in
/webservices/commons/trunk/modules/transport/modules:
base/src/main/java/org/apache/axis2/format/
jms/src/main/java/org/apache/axis2/transport/jms/
Author: veithen
Date: Fri Feb 27 01:28:42 2009
New Revision: 748368
URL: http://svn.apache.org/viewvc?rev=748368&view=rev
Log:
Optimized processing of JMS BytesMessages with content type application/octet-stream by allowing the transport to pass a DataSource object instead of an InputStream to the message builder (BinaryBuilder in this case). The corresponding method is defined by a new optional interface DataSourceMessageBuilder. When this method is used, the message builder can process the message without creating a copy of the data.
Added:
webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/DataSourceMessageBuilder.java (with props)
webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageDataSource.java (with props)
Modified:
webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/BinaryBuilder.java
webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageInputStream.java
webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/JMSUtils.java
Modified: webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/BinaryBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/BinaryBuilder.java?rev=748368&r1=748367&r2=748368&view=diff
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/BinaryBuilder.java (original)
+++ webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/BinaryBuilder.java Fri Feb 27 01:28:42 2009
@@ -22,6 +22,7 @@
import java.io.InputStream;
import javax.activation.DataHandler;
+import javax.activation.DataSource;
import javax.xml.namespace.QName;
import org.apache.axiom.attachments.ByteArrayDataSource;
@@ -29,7 +30,6 @@
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axis2.AxisFault;
-import org.apache.axis2.builder.Builder;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.Parameter;
import org.apache.commons.io.IOUtils;
@@ -44,8 +44,8 @@
* be configured as a service parameter (see {@link BaseConstants#WRAPPER_PARAM}).
* It defaults to {@link BaseConstants#DEFAULT_BINARY_WRAPPER}.
*/
-public class BinaryBuilder implements Builder {
- public OMElement processDocument(InputStream inputStream,
+public class BinaryBuilder implements DataSourceMessageBuilder {
+ public OMElement processDocument(DataSource dataSource,
String contentType,
MessageContext msgContext) throws AxisFault {
QName wrapperQName = BaseConstants.DEFAULT_BINARY_WRAPPER;
@@ -57,15 +57,22 @@
}
OMFactory factory = OMAbstractFactory.getOMFactory();
OMElement wrapper = factory.createOMElement(wrapperQName, null);
+ DataHandler dataHandler = new DataHandler(dataSource);
+ wrapper.addChild(factory.createOMText(dataHandler, true));
+ msgContext.setDoingMTOM(true);
+ return wrapper;
+ }
+
+ public OMElement processDocument(InputStream inputStream,
+ String contentType,
+ MessageContext msgContext) throws AxisFault {
+ // TODO: this could be further optimized by deferring the read operation
byte[] msgBytes;
try {
msgBytes = IOUtils.toByteArray(inputStream);
} catch (IOException ex) {
throw new AxisFault("Unable to read message payload", ex);
}
- DataHandler dataHandler = new DataHandler(new ByteArrayDataSource(msgBytes));
- wrapper.addChild(factory.createOMText(dataHandler, true));
- msgContext.setDoingMTOM(true);
- return wrapper;
+ return processDocument(new ByteArrayDataSource(msgBytes), contentType, msgContext);
}
}
Added: webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/DataSourceMessageBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/DataSourceMessageBuilder.java?rev=748368&view=auto
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/DataSourceMessageBuilder.java (added)
+++ webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/DataSourceMessageBuilder.java Fri Feb 27 01:28:42 2009
@@ -0,0 +1,57 @@
+/*
+ * 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.axis2.format;
+
+import javax.activation.DataSource;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.builder.Builder;
+import org.apache.axis2.context.MessageContext;
+
+/**
+ * Message builder able to build messages from {@link DataSource} objects.
+ * This interface can be optionally implemented by {@link Builder}
+ * implementations that support building messages from {@link DataSource} objects.
+ * Since by definition the data from a {@link DataSource} can be read multiple
+ * times, this interface can be used by message builders to avoid storing the
+ * message content in memory.
+ * <p>
+ * If a message builder implements this interface and the transport is able to
+ * provide the message payload as a data source, then the method defined by this
+ * interface should be preferred over the method defined by {@link Builder}.
+ * <p>
+ * When a message builder is invoked through the basic {@link Builder} interface,
+ * it is the responsibility of the transport to close the input stream once the
+ * message has been processed, and the builder is not required to consume the input
+ * stream immediately. On the other hand, when the builder is invoked through this extension
+ * interface, the transport is only responsible for ensuring that the {@link DataSource}
+ * remains valid for the whole lifecycle of the message. It is the responsibility of the
+ * builder to acquire the input stream and to make sure that it is closed when no longer
+ * needed. This important difference is the reason why there is no
+ * DataSourceMessageBuilderAdapter class.
+ * <p>
+ * Implementing this interface helps optimizing message processing with transports
+ * that use messaging providers that store messages in memory or on the file system.
+ * Examples are JMS and VFS.
+ */
+public interface DataSourceMessageBuilder extends Builder {
+ public OMElement processDocument(DataSource dataSource, String contentType,
+ MessageContext messageContext) throws AxisFault;
+}
Propchange: webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/DataSourceMessageBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageDataSource.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageDataSource.java?rev=748368&view=auto
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageDataSource.java (added)
+++ webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageDataSource.java Fri Feb 27 01:28:42 2009
@@ -0,0 +1,74 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed 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.axis2.transport.jms;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.jms.BytesMessage;
+import javax.jms.JMSException;
+
+import org.apache.axiom.attachments.SizeAwareDataSource;
+
+/**
+ * Data source implementation wrapping a JMS {@link BytesMessage}.
+ * <p>
+ * Note that two input streams created by the same instance of this
+ * class can not be used at the same time.
+ */
+public class BytesMessageDataSource implements SizeAwareDataSource {
+ private final BytesMessage message;
+ private final String contentType;
+
+ public BytesMessageDataSource(BytesMessage message, String contentType) {
+ this.message = message;
+ this.contentType = contentType;
+ }
+
+ public BytesMessageDataSource(BytesMessage message) {
+ this(message, "application/octet-stream");
+ }
+
+ public long getSize() {
+ try {
+ return message.getBodyLength();
+ } catch (JMSException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ try {
+ message.reset();
+ } catch (JMSException ex) {
+ throw new JMSExceptionWrapper(ex);
+ }
+ return new BytesMessageInputStream(message);
+ }
+
+ public String getName() {
+ return null;
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+}
Propchange: webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageDataSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageInputStream.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageInputStream.java?rev=748368&r1=748367&r2=748368&view=diff
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageInputStream.java (original)
+++ webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/BytesMessageInputStream.java Fri Feb 27 01:28:42 2009
@@ -23,6 +23,10 @@
/**
* Input stream that reads data from a JMS {@link BytesMessage}.
+ * Note that since the current position in the message is managed by
+ * the underlying {@link BytesMessage} object, it is not possible to
+ * use several instances of this class operating on a single
+ * {@link BytesMessage} at the same time.
*/
public class BytesMessageInputStream extends InputStream {
private final BytesMessage message;
Modified: webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/JMSUtils.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/JMSUtils.java?rev=748368&r1=748367&r2=748368&view=diff
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/JMSUtils.java (original)
+++ webservices/commons/trunk/modules/transport/modules/jms/src/main/java/org/apache/axis2/transport/jms/JMSUtils.java Fri Feb 27 01:28:42 2009
@@ -25,6 +25,7 @@
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
+import org.apache.axis2.format.DataSourceMessageBuilder;
import org.apache.axis2.format.TextMessageBuilder;
import org.apache.axis2.format.TextMessageBuilderAdapter;
import org.apache.commons.logging.Log;
@@ -164,55 +165,51 @@
public static void setSOAPEnvelope(Message message, MessageContext msgContext, String contentType)
throws AxisFault, JMSException {
- if (message instanceof BytesMessage) {
- if (contentType == null) {
- log.debug("No content type specified; assuming application/octet-stream.");
- contentType = "application/octet-stream";
+ if (contentType == null) {
+ if (message instanceof TextMessage) {
+ contentType = "text/plain";
} else {
- // Extract the charset encoding from the content type and
- // set the CHARACTER_SET_ENCODING property as e.g. SOAPBuilder relies on this.
- String charSetEnc = null;
- try {
- if (contentType != null) {
- charSetEnc = new ContentType(contentType).getParameter("charset");
- }
- } catch (ParseException ex) {
- // ignore
- }
- msgContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, charSetEnc);
+ contentType = "application/octet-stream";
}
-
- SOAPEnvelope envelope;
- try {
- envelope = TransportUtils.createSOAPMessage(msgContext,
- new BytesMessageInputStream((BytesMessage)message), contentType);
- } catch (XMLStreamException ex) {
- handleException("Error parsing XML", ex);
- return; // Make compiler happy
+ if (log.isDebugEnabled()) {
+ log.debug("No content type specified; assuming " + contentType);
}
- msgContext.setEnvelope(envelope);
-
- } else if (message instanceof TextMessage) {
- String type;
- if (contentType == null) {
- log.debug("No content type specified; assuming text/plain.");
- type = contentType = "text/plain";
- } else {
- int index = contentType.indexOf(';');
- if (index > 0) {
- type = contentType.substring(0, index);
- } else {
- type = contentType;
- }
+ }
+
+ int index = contentType.indexOf(';');
+ String type = index > 0 ? contentType.substring(0, index) : contentType;
+ Builder builder = BuilderUtil.getBuilderFromSelector(type, msgContext);
+ if (builder == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("No message builder found for type '" + type + "'. Falling back to SOAP.");
}
- Builder builder = BuilderUtil.getBuilderFromSelector(type, msgContext);
- if (builder == null) {
- if (log.isDebugEnabled()) {
- log.debug("No message builder found for type '" + type + "'. Falling back to SOAP.");
+ builder = new SOAPBuilder();
+ }
+
+ OMElement documentElement;
+ if (message instanceof BytesMessage) {
+ // Extract the charset encoding from the content type and
+ // set the CHARACTER_SET_ENCODING property as e.g. SOAPBuilder relies on this.
+ String charSetEnc = null;
+ try {
+ if (contentType != null) {
+ charSetEnc = new ContentType(contentType).getParameter("charset");
}
- builder = new SOAPBuilder();
+ } catch (ParseException ex) {
+ // ignore
}
-
+ msgContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, charSetEnc);
+
+ if (builder instanceof DataSourceMessageBuilder) {
+ documentElement = ((DataSourceMessageBuilder)builder).processDocument(
+ new BytesMessageDataSource((BytesMessage)message), contentType,
+ msgContext);
+ } else {
+ documentElement = builder.processDocument(
+ new BytesMessageInputStream((BytesMessage)message), contentType,
+ msgContext);
+ }
+ } else if (message instanceof TextMessage) {
TextMessageBuilder textMessageBuilder;
if (builder instanceof TextMessageBuilder) {
textMessageBuilder = (TextMessageBuilder)builder;
@@ -220,10 +217,12 @@
textMessageBuilder = new TextMessageBuilderAdapter(builder);
}
String content = ((TextMessage)message).getText();
- OMElement documentElement
- = textMessageBuilder.processDocument(content, contentType, msgContext);
- msgContext.setEnvelope(TransportUtils.createSOAPEnvelope(documentElement));
+ documentElement = textMessageBuilder.processDocument(content, contentType, msgContext);
+ } else {
+ handleException("Unsupported JMS message type " + message.getClass().getName());
+ return; // Make compiler happy
}
+ msgContext.setEnvelope(TransportUtils.createSOAPEnvelope(documentElement));
}
/**