/* | |
* 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.core.controller.impl; | |
import org.apache.axis2.jaxws.ExceptionFactory; | |
import org.apache.axis2.jaxws.core.InvocationContext; | |
import org.apache.axis2.jaxws.core.MessageContext; | |
import org.apache.axis2.jaxws.core.controller.InvocationController; | |
import org.apache.axis2.jaxws.core.controller.InvocationPattern; | |
import org.apache.axis2.jaxws.core.util.MessageContextUtils; | |
import org.apache.axis2.jaxws.handler.AttachmentsAdapter; | |
import org.apache.axis2.jaxws.handler.HandlerChainProcessor; | |
import org.apache.axis2.jaxws.handler.HandlerInvokerUtils; | |
import org.apache.axis2.jaxws.handler.SOAPHeadersAdapter; | |
import org.apache.axis2.jaxws.handler.TransportHeadersAdapter; | |
import org.apache.axis2.jaxws.i18n.Messages; | |
import org.apache.axis2.jaxws.util.Constants; | |
import org.apache.commons.logging.Log; | |
import org.apache.commons.logging.LogFactory; | |
import javax.xml.ws.AsyncHandler; | |
import javax.xml.ws.Response; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Future; | |
/** | |
* An abstract implementation of the InvocationController interface. | |
*/ | |
public abstract class InvocationControllerImpl implements InvocationController { | |
private static final Log log = LogFactory.getLog(InvocationControllerImpl.class); | |
/* | |
* (non-Javadoc) | |
* @see org.apache.axis2.jaxws.core.controller.InvocationController#invoke(org.apache.axis2.jaxws.core.InvocationContext) | |
*/ | |
public InvocationContext invoke(InvocationContext ic) { | |
if (log.isDebugEnabled()) { | |
log.debug("Invocation pattern: synchronous"); | |
} | |
// Check to make sure we at least have a valid InvocationContext | |
// and request MessageContext | |
if (ic == null) { | |
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr1")); | |
} | |
if (ic.getRequestMessageContext() == null) { | |
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr2")); | |
} | |
MessageContext request = ic.getRequestMessageContext(); | |
MessageContext response = null; | |
request.setProperty(Constants.INVOCATION_PATTERN, InvocationPattern.SYNC); | |
// Invoke outbound handlers. | |
boolean success = | |
HandlerInvokerUtils.invokeOutboundHandlers(request.getMEPContext(), | |
ic.getHandlers(), | |
HandlerChainProcessor.MEP.REQUEST, | |
false); | |
if (success) { | |
prepareRequest(request); | |
response = doInvoke(request); | |
prepareResponse(response); | |
// make sure request and response contexts share a single parent | |
response.setMEPContext(request.getMEPContext()); | |
/* | |
* TODO TODO TODO review | |
* | |
* In most cases we are adding the endpointDesc to the | |
* MessageContext. Notice here that the "response" object is set by | |
* the call to doInvoke. It's a new context we are now working with. | |
* The invokeInboundHandlers uses that context way down in | |
* createMessageContext --> ContextUtils.addProperties() | |
* | |
* This may also occur in the AsyncResponse class when calling | |
* invokeInboundHandlers | |
* | |
* For now, make sure the endpointDesc is set on the response | |
* context. | |
*/ | |
response.setEndpointDescription(request.getEndpointDescription()); | |
// Invoke inbound handlers. | |
TransportHeadersAdapter.install(response); | |
AttachmentsAdapter.install(response); | |
SOAPHeadersAdapter.install(response); | |
HandlerInvokerUtils.invokeInboundHandlers(response.getMEPContext(), | |
ic.getHandlers(), | |
HandlerChainProcessor.MEP.RESPONSE, | |
false); | |
} else { // the outbound handler chain must have had a problem, and | |
// we've reversed directions | |
response = MessageContextUtils.createMinimalResponseMessageContext(request); | |
// since we've reversed directions, the message has "become a | |
// make sure request and response contexts share a single parent | |
response.setMEPContext(request.getMEPContext()); | |
response.setMessage(request.getMessage()); | |
} | |
ic.setResponseMessageContext(response); | |
return ic; | |
} | |
protected abstract MessageContext doInvoke(MessageContext request); | |
/* | |
* (non-Javadoc) | |
* @see org.apache.axis2.jaxws.core.controller.InvocationController#invokeOneWay(org.apache.axis2.jaxws.core.InvocationContext) | |
*/ | |
public void invokeOneWay(InvocationContext ic) throws Exception { | |
if (log.isDebugEnabled()) { | |
log.debug("Invocation pattern: one-way"); | |
} | |
// Check to make sure we at least have a valid InvocationContext | |
// and request MessageContext | |
if (ic == null) { | |
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr1")); | |
} | |
if (ic.getRequestMessageContext() == null) { | |
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr2")); | |
} | |
MessageContext request = ic.getRequestMessageContext(); | |
request.setProperty(Constants.INVOCATION_PATTERN, InvocationPattern.ONEWAY); | |
// Invoke outbound handlers. | |
boolean success = | |
HandlerInvokerUtils.invokeOutboundHandlers(request.getMEPContext(), | |
ic.getHandlers(), | |
HandlerChainProcessor.MEP.REQUEST, | |
true); | |
if (success) { | |
prepareRequest(request); | |
doInvokeOneWay(request); | |
} else { // the outbound handler chain must have had a problem, and we've reversed directions | |
// check to see if problem is due to a handler throwing an exception. If so, throw it, | |
// even in this oneWay invoke. | |
Exception e = request.getCausedByException(); | |
if (e != null) { | |
throw (Exception)e.getCause(); | |
} | |
} | |
return; | |
} | |
protected abstract void doInvokeOneWay(MessageContext mc); | |
/* | |
* (non-Javadoc) | |
* @see org.apache.axis2.jaxws.core.controller.InvocationController#invokeAsync(org.apache.axis2.jaxws.core.InvocationContext) | |
*/ | |
public Response invokeAsync(InvocationContext ic) { | |
if (log.isDebugEnabled()) { | |
log.debug("Invocation pattern: asynchronous(polling)"); | |
} | |
// Check to make sure we at least have a valid InvocationContext | |
// and request MessageContext | |
if (ic == null) { | |
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr1")); | |
} | |
if (ic.getRequestMessageContext() == null) { | |
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr2")); | |
} | |
MessageContext request = ic.getRequestMessageContext(); | |
request.setProperty(Constants.INVOCATION_PATTERN, InvocationPattern.ASYNC_POLLING); | |
Response resp = null; | |
// Invoke outbound handlers. | |
// TODO uncomment, and get the EndpointDescription from the request context, which should soon be available | |
boolean success = | |
HandlerInvokerUtils.invokeOutboundHandlers(request.getMEPContext(), | |
ic.getHandlers(), | |
HandlerChainProcessor.MEP.REQUEST, | |
false); | |
if (success) { | |
prepareRequest(request); | |
resp = doInvokeAsync(request); | |
} else | |
{ // the outbound handler chain must have had a problem, and we've reversed directions | |
// since we've reversed directions, the message has "become a response message" (section 9.3.2.1, footnote superscript 2) | |
// TODO we know the message is a fault message, we should | |
// convert it to an exception and throw it. | |
// something like: | |
//throw new AxisFault(request.getMessage()); | |
} | |
return resp; | |
} | |
public abstract Response doInvokeAsync(MessageContext mc); | |
/* | |
* (non-Javadoc) | |
* @see org.apache.axis2.jaxws.core.controller.InvocationController#invokeAsync(org.apache.axis2.jaxws.core.InvocationContext, javax.xml.ws.AsyncHandler) | |
*/ | |
public Future<?> invokeAsync(InvocationContext ic, AsyncHandler asyncHandler) { | |
if (log.isDebugEnabled()) { | |
log.debug("Invocation pattern: asynchronous(callback)"); | |
} | |
// Check to make sure we at least have a valid InvocationContext | |
// and request MessageContext | |
if (ic == null) { | |
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr1")); | |
} | |
if (ic.getRequestMessageContext() == null) { | |
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr2")); | |
} | |
if ((ic.getExecutor() != null) && (ic.getExecutor() instanceof ExecutorService)) { | |
ExecutorService es = (ExecutorService) ic.getExecutor(); | |
if (es.isShutdown()) { | |
// the executor service is shutdown and won't accept new tasks | |
// so return an error back to the client | |
throw ExceptionFactory.makeWebServiceException(Messages | |
.getMessage("ExecutorShutdown")); | |
} | |
} | |
MessageContext request = ic.getRequestMessageContext(); | |
request.setProperty(Constants.INVOCATION_PATTERN, InvocationPattern.ASYNC_CALLBACK); | |
Future<?> future = null; | |
// Invoke outbound handlers. | |
boolean success = | |
HandlerInvokerUtils.invokeOutboundHandlers(request.getMEPContext(), | |
ic.getHandlers(), | |
HandlerChainProcessor.MEP.REQUEST, | |
false); | |
if (success) { | |
prepareRequest(request); | |
future = doInvokeAsync(request, asyncHandler); | |
} else { // the outbound handler chain must have had a problem, and | |
// we've reversed directions | |
// since we've reversed directions, the message has "become a | |
// response message" (section 9.3.2.1, footnote superscript 2) | |
// TODO: how do we deal with this? The response message may or may | |
// not be a fault | |
// message. We do know that the direction has reversed, so somehow | |
// we need to | |
// flow immediately out of the async and give the exception and/or | |
// response object | |
// back to the client app without calling | |
// AsyncResponse.processResponse or processFault | |
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("invokeAsyncErr")); | |
// throw new AxisFault(request.getMessage()); | |
} | |
return future; | |
} | |
public abstract Future<?> doInvokeAsync(MessageContext mc, AsyncHandler asyncHandler); | |
/** | |
* Abstract method that must be implemented by whoever is providing the specific client binding. | |
* Once this is called, everything that is needed to invoke the operation must be available in | |
* the MessageContext. | |
* | |
* @param mc | |
*/ | |
protected abstract void prepareRequest(MessageContext mc); | |
/** | |
* Abstract method that must be implemented by whoever is providing the specific client binding. | |
* This is called after the response has come back and allows the client binding to put | |
* whatever info it has in the response MessageContext. | |
* | |
* @param mc | |
*/ | |
protected abstract void prepareResponse(MessageContext mc); | |
} |