blob: de258103d06f0d55cee10f9e3d50cf7410998a4a [file] [log] [blame]
/*
* 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.jaxws.client.dispatch;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.utility.DataSourceFormatter;
import org.apache.axis2.jaxws.client.async.AsyncResponse;
import org.apache.axis2.jaxws.core.MessageContext;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.message.Block;
import org.apache.axis2.jaxws.message.Message;
import org.apache.axis2.jaxws.message.Protocol;
import org.apache.axis2.jaxws.message.factory.BlockFactory;
import org.apache.axis2.jaxws.message.factory.DataSourceBlockFactory;
import org.apache.axis2.jaxws.message.factory.MessageFactory;
import org.apache.axis2.jaxws.message.factory.OMBlockFactory;
import org.apache.axis2.jaxws.message.factory.SOAPEnvelopeBlockFactory;
import org.apache.axis2.jaxws.message.factory.SourceBlockFactory;
import org.apache.axis2.jaxws.message.factory.XMLStringBlockFactory;
import org.apache.axis2.jaxws.registry.FactoryRegistry;
import org.apache.axis2.jaxws.spi.ServiceDelegate;
import org.apache.axis2.Constants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axis2.jaxws.message.databinding.OMBlock;
import org.apache.axis2.jaxws.message.databinding.impl.OMBlockFactoryImpl;
import javax.activation.DataSource;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Source;
import javax.xml.ws.Service.Mode;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
public class XMLDispatch<T> extends BaseDispatch<T> {
private static final Log log = LogFactory.getLog(XMLDispatch.class);
private Class type;
private Class blockFactoryType;
public XMLDispatch(ServiceDelegate svcDelegate,
EndpointDescription endpointDesc,
WebServiceFeature... features) {
this(svcDelegate, endpointDesc, null, null, features);
}
public XMLDispatch(ServiceDelegate svcDelegate,
EndpointDescription endpointDesc,
EndpointReference epr,
String addressingNamespace,
WebServiceFeature... features) {
super(svcDelegate, endpointDesc, epr, addressingNamespace, features);
}
public Class getType() {
return type;
}
public void setType(Class c) {
type = c;
}
public AsyncResponse createAsyncResponseListener() {
if (log.isDebugEnabled()) {
log.debug("Creating new AsyncListener for XMLDispatch");
}
XMLDispatchAsyncListener al = new XMLDispatchAsyncListener(getEndpointDescription());
al.setMode(mode);
al.setType(type);
al.setBlockFactoryType(blockFactoryType);
return al;
}
public Message createMessageFromValue(Object value) {
if (value != null) {
type = value.getClass();
if (log.isDebugEnabled()) {
log.debug("Parameter type: " + type.getName());
log.debug("Message mode: " + mode.name());
}
} else {
if (log.isDebugEnabled()) {
log.debug("Dispatch invoked with null parameter Value");
log.debug("creating empty soap message");
}
try {
blockFactoryType = getBlockFactory();
return createEmptyMessage(
Protocol.getProtocolForBinding(endpointDesc.getClientBindingID()));
} catch (XMLStreamException e) {
throw ExceptionFactory.makeWebServiceException(e);
}
}
Block block = null;
blockFactoryType = getBlockFactory(value);
BlockFactory factory = (BlockFactory)FactoryRegistry.getFactory(blockFactoryType);
if (log.isDebugEnabled()) {
log.debug("Loaded block factory type [" + blockFactoryType.getName());
}
// The protocol of the Message that is created should be based
// on the binding information available.
Protocol proto = Protocol.getProtocolForBinding(endpointDesc.getClientBindingID());
Message message = null;
if (mode.equals(Mode.PAYLOAD)) {
try {
MessageFactory mf =
(MessageFactory)FactoryRegistry.getFactory(MessageFactory.class);
block = factory.createFrom(value, null, null);
message = mf.create(proto);
message.setBodyBlock(block);
} catch (Exception e) {
throw ExceptionFactory.makeWebServiceException(e);
}
} else if (mode.equals(Mode.MESSAGE)) {
try {
MessageFactory mf =
(MessageFactory)FactoryRegistry.getFactory(MessageFactory.class);
// If the value contains just the xml data, then you can create the Message directly from the
// Block. If the value contains attachments, you need to do more.
// TODO For now the only value that contains Attachments is SOAPMessage
if (value instanceof SOAPMessage) {
message = mf.createFrom((SOAPMessage)value);
} else {
block = factory.createFrom(value, null, null);
message = mf.createFrom(block, null, proto);
}
} catch (Exception e) {
throw ExceptionFactory.makeWebServiceException(e);
}
}
return message;
}
public Object getValueFromMessage(Message message) {
return getValue(message, mode, blockFactoryType);
}
/**
* Common code used by XMLDispatch and XMLDispatchAsyncListener
*
* @param message
* @return object
*/
static Object getValue(Message message, Mode mode, Class blockFactoryType) {
Object value = null;
Block block = null;
if (log.isDebugEnabled()) {
log.debug("Attempting to get the value object from the returned message");
}
try {
if (mode.equals(Mode.PAYLOAD)) {
BlockFactory factory = (BlockFactory)FactoryRegistry
.getFactory(blockFactoryType);
block = message.getBodyBlock(null, factory);
if (block != null) {
value = block.getBusinessObject(true);
if (value instanceof OMBlockFactoryImpl) {
value = ((OMBlock)value).getOMElement();
}
} else {
// REVIEW This seems like the correct behavior. If the body is empty, return a null
// Any changes here should also be made to XMLDispatch.getValue
if (log.isDebugEnabled()) {
log.debug(
"There are no elements in the body to unmarshal. XMLDispatch returns a null value");
}
value = null;
}
} else if (mode.equals(Mode.MESSAGE)) {
BlockFactory factory = (BlockFactory)FactoryRegistry.getFactory(blockFactoryType);
if (factory instanceof OMBlockFactoryImpl) {
value = (OMElement)message.getAsOMElement();
} else {
value = message.getValue(null, factory);
}
if (value == null) {
if (log.isDebugEnabled()) {
log.debug(
"There are no elements to unmarshal. XMLDispatch returns a null value");
}
}
}
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("An error occured while creating the block");
}
throw ExceptionFactory.makeWebServiceException(e);
} finally {
if (!(value instanceof OMElement)) {
message.close();
}
}
if (log.isDebugEnabled()) {
if (value == null)
log.debug("Returning a null value");
else
log.debug("Returning value of type: " + value.getClass().getName());
}
return value;
}
private Class getBlockFactory(Object o) {
if (o instanceof String) {
if (log.isDebugEnabled()) {
log.debug(">> returning XMLStringBlockFactory");
}
return XMLStringBlockFactory.class;
} else if (Source.class.isAssignableFrom(o.getClass())) {
if (log.isDebugEnabled()) {
log.debug(">> returning SourceBlockFactory");
}
return SourceBlockFactory.class;
} else if (DataSource.class.isAssignableFrom(o.getClass())) {
if (log.isDebugEnabled()) {
log.debug(">> returning DataSourceBlockFactory");
}
return DataSourceBlockFactory.class;
} else if (SOAPMessage.class.isAssignableFrom(o.getClass())) {
if (log.isDebugEnabled()) {
log.debug(">> returning SOAPMessageFactory");
}
return SOAPEnvelopeBlockFactory.class;
} else if (SOAPEnvelope.class.isAssignableFrom(o.getClass())) {
if (log.isDebugEnabled()) {
log.debug(">> returning SOAPEnvelope");
}
return SOAPEnvelopeBlockFactory.class;
} else if (OMElement.class.isAssignableFrom(o.getClass())) {
if (log.isDebugEnabled()) {
log.debug(">> returning OMBlockFactory");
}
return OMBlockFactory.class;
}
if (log.isDebugEnabled()) {
log.debug(">> ERROR: Factory not found");
}
return null;
}
private Class getBlockFactory() {
if (String.class.isAssignableFrom(type)) {
if (log.isDebugEnabled()) {
log.debug(">> returning XMLStringBlockFactory");
}
return XMLStringBlockFactory.class;
} else if (Source.class.isAssignableFrom(type)) {
if (log.isDebugEnabled()) {
log.debug(">> returning SourceBlockFactory");
}
return SourceBlockFactory.class;
} else if (SOAPMessage.class.isAssignableFrom(type)) {
if (log.isDebugEnabled()) {
log.debug(">> returning SOAPMessageFactory");
}
return SOAPEnvelopeBlockFactory.class;
} else if (SOAPEnvelope.class.isAssignableFrom(type)) {
if (log.isDebugEnabled()) {
log.debug(">> returning SOAPEnvelope");
}
return SOAPEnvelopeBlockFactory.class;
} else if (OMElement.class.isAssignableFrom(type)) {
if (log.isDebugEnabled()) {
log.debug(">> returning OMBlockFactory");
}
return OMBlockFactory.class;
}
if (log.isDebugEnabled()) {
log.debug(">> ERROR: Factory not found");
}
return null;
}
private Message createEmptyMessage(Protocol protocol)
throws WebServiceException, XMLStreamException {
MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class);
Message m = mf.create(protocol);
return m;
}
protected void initMessageContext(Object obj, MessageContext requestMsgCtx) {
super.initMessageContext(obj, requestMsgCtx);
if(obj instanceof DataSource){
requestMsgCtx.setProperty(Constants.Configuration.MESSAGE_FORMATTER,
new DataSourceFormatter(((DataSource)obj).getContentType()));
}
}
}