| /* |
| * 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.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.databinding.JAXBBlockContext; |
| import org.apache.axis2.jaxws.message.factory.BlockFactory; |
| import org.apache.axis2.jaxws.message.factory.JAXBBlockFactory; |
| import org.apache.axis2.jaxws.message.factory.MessageFactory; |
| import org.apache.axis2.jaxws.registry.FactoryRegistry; |
| import org.apache.axis2.jaxws.spi.ServiceDelegate; |
| import org.apache.axis2.jaxws.utility.XMLRootElementUtil; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import javax.xml.bind.JAXBContext; |
| import javax.xml.namespace.QName; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.ws.Service.Mode; |
| import javax.xml.ws.WebServiceException; |
| import javax.xml.ws.WebServiceFeature; |
| |
| public class JAXBDispatch<T> extends BaseDispatch<T> { |
| private static final Log log = LogFactory.getLog(JAXBDispatch.class); |
| private JAXBContext jaxbContext; |
| private QName elementQName; |
| |
| public JAXBDispatch(ServiceDelegate svcDelegate, |
| EndpointDescription epDesc, |
| WebServiceFeature... features) { |
| this(svcDelegate, epDesc, null, null, features); |
| } |
| |
| public JAXBDispatch(ServiceDelegate svcDelegate, |
| EndpointDescription epDesc, |
| EndpointReference epr, |
| String addressingNamespace, |
| WebServiceFeature... features) { |
| super(svcDelegate, epDesc, epr, addressingNamespace, features); |
| } |
| |
| public JAXBContext getJAXBContext() { |
| return jaxbContext; |
| } |
| |
| public void setJAXBContext(JAXBContext jbc) { |
| jaxbContext = jbc; |
| } |
| |
| public AsyncResponse createAsyncResponseListener() { |
| JAXBDispatchAsyncListener listener = |
| new JAXBDispatchAsyncListener(getEndpointDescription()); |
| listener.setJAXBContext(jaxbContext); |
| listener.setMode(mode); |
| return listener; |
| } |
| |
| public Message createMessageFromValue(Object value) { |
| Message message = null; |
| |
| if (value == null) { |
| if (log.isDebugEnabled()) { |
| log.debug("Dispatch invoked with null parameter Value"); |
| log.debug("creating empty soap message"); |
| } |
| try { |
| return createEmptyMessage( |
| Protocol.getProtocolForBinding(endpointDesc.getClientBindingID())); |
| |
| } catch (XMLStreamException e) { |
| throw ExceptionFactory.makeWebServiceException(e); |
| } |
| } |
| |
| try { |
| JAXBBlockFactory factory = |
| (JAXBBlockFactory)FactoryRegistry.getFactory(JAXBBlockFactory.class); |
| |
| Class clazz = value.getClass(); |
| JAXBBlockContext context = null; |
| if (jaxbContext != null) { |
| context = new JAXBBlockContext(jaxbContext); |
| } else { |
| context = new JAXBBlockContext(clazz.getPackage().getName()); |
| } |
| // The protocol of the Message that is created should be based |
| // on the binding information available. |
| Protocol proto = Protocol.getProtocolForBinding(endpointDesc.getClientBindingID()); |
| |
| // Create a block from the value |
| elementQName = XMLRootElementUtil.getXmlRootElementQNameFromObject(value); |
| Block block = factory.createFrom(value, context, elementQName); |
| MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class); |
| |
| if (mode.equals(Mode.PAYLOAD)) { |
| // Normal case |
| |
| message = mf.create(proto); |
| message.setBodyBlock(block); |
| } else { |
| // Message mode..rare case |
| |
| // Create Message from block |
| message = mf.createFrom(block, null, proto); |
| } |
| |
| } catch (Exception e) { |
| throw ExceptionFactory.makeWebServiceException(e); |
| } |
| |
| return message; |
| } |
| |
| // For a JAXB element we don't need to parse the message to get the element QName (which is |
| // slow); we saved the element QName from the JAXBElement earlier. If for some reason it was not |
| // saved, we'll try parsing the message to get it. |
| QName getBodyElementQNameFromDispatchMessage(MessageContext requestMessageCtx) { |
| QName returnElementQName = null; |
| if (elementQName != null) { |
| returnElementQName = elementQName; |
| } else { |
| returnElementQName = super.getBodyElementQNameFromDispatchMessage(requestMessageCtx); |
| } |
| return returnElementQName; |
| } |
| public Object getValueFromMessage(Message message) { |
| return getValue(message, mode, jaxbContext); |
| } |
| |
| /** |
| * Common code to get the value for JAXBDispatch and JAXBDispatchAsyncListener |
| * |
| * @param message |
| * @param mode |
| * @param jaxbContext |
| * @return |
| */ |
| static Object getValue(Message message, Mode mode, JAXBContext jaxbContext) { |
| Object value = null; |
| try { |
| if (mode.equals(Mode.PAYLOAD)) { |
| // Normal Case |
| JAXBBlockFactory factory = |
| (JAXBBlockFactory)FactoryRegistry.getFactory(JAXBBlockFactory.class); |
| JAXBBlockContext context = new JAXBBlockContext(jaxbContext); |
| Block block = message.getBodyBlock(context, factory); |
| |
| if (block != null) { |
| value = block.getBusinessObject(true); |
| } 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. JAXBDispatch returns a null value"); |
| } |
| value = null; |
| } |
| } else { |
| BlockFactory factory = |
| (BlockFactory)FactoryRegistry.getFactory(JAXBBlockFactory.class); |
| JAXBBlockContext context = new JAXBBlockContext(jaxbContext); |
| value = message.getValue(context, factory); |
| if (value == null) { |
| if (log.isDebugEnabled()) { |
| log.debug( |
| "There are no elements to unmarshal. JAXBDispatch returns a null value"); |
| } |
| } |
| } |
| } catch (Exception e) { |
| throw ExceptionFactory.makeWebServiceException(e); |
| } finally { |
| message.close(); |
| } |
| |
| return value; |
| } |
| |
| private Message createEmptyMessage(Protocol protocol) |
| throws WebServiceException, XMLStreamException { |
| MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class); |
| Message m = mf.create(protocol); |
| return m; |
| } |
| } |