Home » openejb-3.1.2-src » org.apache » openejb » server » axis » [javadoc | source]

    1   /**
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.openejb.server.axis;
   18   
   19   import org.apache.axis.AxisFault;
   20   import org.apache.axis.Constants;
   21   import org.apache.axis.Handler;
   22   import org.apache.axis.Message;
   23   import org.apache.axis.MessageContext;
   24   import org.apache.axis.description.OperationDesc;
   25   import org.apache.axis.description.ParameterDesc;
   26   import org.apache.axis.description.ServiceDesc;
   27   import org.apache.axis.encoding.XMLType;
   28   import org.apache.axis.encoding.DeserializationContext;
   29   import org.apache.axis.message.RPCElement;
   30   import org.apache.axis.message.RPCParam;
   31   import org.apache.axis.message.SOAPEnvelope;
   32   import org.apache.axis.message.SOAPBodyElement;
   33   import org.apache.axis.message.SOAPFault;
   34   import org.apache.axis.providers.java.RPCProvider;
   35   import org.apache.axis.utils.JavaUtils;
   36   import org.apache.openejb.ApplicationException;
   37   import org.apache.openejb.DeploymentInfo;
   38   import org.apache.openejb.InvalidateReferenceException;
   39   import org.apache.openejb.RpcContainer;
   40   import org.apache.openejb.InterfaceType;
   41   import org.xml.sax.SAXException;
   42   import org.xml.sax.InputSource;
   43   
   44   import javax.interceptor.AroundInvoke;
   45   import javax.interceptor.InvocationContext;
   46   import javax.xml.rpc.handler.HandlerChain;
   47   import javax.xml.rpc.handler.HandlerInfo;
   48   import javax.xml.rpc.holders.IntHolder;
   49   import javax.xml.rpc.soap.SOAPFaultException;
   50   import javax.xml.soap.SOAPMessage;
   51   import javax.xml.namespace.QName;
   52   import java.io.ByteArrayOutputStream;
   53   import java.io.ByteArrayInputStream;
   54   import java.util.ArrayList;
   55   import java.util.List;
   56   import java.util.Vector;
   57   
   58   public class EjbContainerProvider extends RPCProvider {
   59   
   60       private final DeploymentInfo ejbDeployment;
   61       private final List<HandlerInfo> handlerInfos;
   62   
   63       public EjbContainerProvider(DeploymentInfo ejbDeployment) {
   64           this.ejbDeployment = ejbDeployment;
   65           this.handlerInfos = new ArrayList<HandlerInfo>();
   66       }
   67   
   68       public EjbContainerProvider(DeploymentInfo ejbDeployment, List<HandlerInfo> handlerInfos) {
   69           this.ejbDeployment = ejbDeployment;
   70           this.handlerInfos = handlerInfos;
   71       }
   72   
   73       public void processMessage(MessageContext msgContext, SOAPEnvelope reqEnv, SOAPEnvelope resEnv, Object obj) throws Exception {
   74   
   75           RPCElement body = getBody(reqEnv, msgContext);
   76           OperationDesc operation = getOperationDesc(msgContext, body);
   77   
   78           AxisRpcInterceptor interceptor = new AxisRpcInterceptor(operation, msgContext);
   79           SOAPMessage message = msgContext.getMessage();
   80   
   81           try {
   82               message.getSOAPPart().getEnvelope();
   83               msgContext.setProperty(org.apache.axis.SOAPPart.ALLOW_FORM_OPTIMIZATION, Boolean.FALSE);
   84   
   85               RpcContainer container = (RpcContainer) ejbDeployment.getContainer();
   86   
   87               Object[] arguments = {msgContext, interceptor};
   88   
   89               Class callInterface = ejbDeployment.getServiceEndpointInterface();
   90               Object result = container.invoke(ejbDeployment.getDeploymentID(), InterfaceType.SERVICE_ENDPOINT, callInterface, operation.getMethod(), arguments, null);
   91   
   92               interceptor.createResult(result);
   93           } catch (InvalidateReferenceException e) {
   94               interceptor.createExceptionResult(e.getCause());
   95           } catch (ApplicationException e) {
   96               interceptor.createExceptionResult(e.getCause());
   97           } catch (Throwable throwable) {
   98               throw new AxisFault("Web Service EJB Invocation failed: method " + operation.getMethod(), throwable);
   99           }
  100       }
  101   
  102       public Object getServiceObject(MessageContext msgContext, Handler service, String clsName, IntHolder scopeHolder) throws Exception {
  103           return ejbDeployment;
  104       }
  105   
  106       /**
  107        * This class is intentionally not static  or top level class
  108        * as it leverages logic in RPCProvider
  109        *
  110        * @see org.apache.axis.providers.java.RPCProvider
  111        */
  112       public class AxisRpcInterceptor {
  113   
  114           private OperationDesc operation;
  115           private MessageContext messageContext;
  116   
  117           public AxisRpcInterceptor(OperationDesc operation, MessageContext msgContext) throws Exception {
  118               this.messageContext = msgContext;
  119               this.operation = operation;
  120           }
  121   
  122           @AroundInvoke
  123           public Object intercept(InvocationContext context) throws Exception {
  124               HandlerChain handlerChain = new HandlerChainImpl(handlerInfos);
  125               try {
  126                   Object invocationResult = null;
  127   
  128                   try {
  129                       if (handlerChain.handleRequest(messageContext)) {
  130                           // update arguments as handlers could change the soap msg
  131                           context.setParameters(getArguments());
  132   
  133                           invocationResult = context.proceed();
  134   
  135                           // update the soap msg so that handlers see invocation result
  136                           if (!handlerChain.isEmpty()) {
  137                               createResult(invocationResult);
  138                           }
  139   
  140                       } else {
  141                           /* The Handler implementation class has the responsibility of setting
  142                            * the response SOAP message in the handleRequest method and perform
  143                            * additional processing in the handleResponse method.
  144                            */
  145                           invocationResult = null;
  146                       }
  147                   } catch (SOAPFaultException e) {
  148                       handlerChain.handleFault(messageContext);
  149                       throw e;
  150                   }
  151   
  152                   handlerChain.handleResponse(messageContext);
  153   
  154                   if (!handlerChain.isEmpty()) {
  155                       /*
  156                        * Deserialize the result value from soap msg as handers could have
  157                        * changed it.
  158                        */
  159                       try {
  160                           invocationResult = demarshallResult();
  161                       } catch (Exception e) {
  162                           // if this fails, return invocationResult from above
  163                       }
  164                   }
  165   
  166                   return invocationResult;
  167               } finally {
  168                   handlerChain.destroy();
  169               }
  170           }
  171   
  172           public Object[] getArguments() {
  173               try {
  174                   return demarshallArguments();
  175               } catch (Exception e) {
  176                   throw (IllegalStateException) new IllegalStateException("Cannot demarshal the soap parts into arguments").initCause(e);
  177               }
  178           }
  179   
  180           private Object[] demarshallArguments() throws Exception {
  181               SOAPMessage message = messageContext.getMessage();
  182               messageContext.setProperty(org.apache.axis.SOAPPart.ALLOW_FORM_OPTIMIZATION, Boolean.TRUE);
  183               if (message != null) {
  184                   message.saveChanges();
  185               }
  186   
  187               try {
  188                   Message reqMsg = messageContext.getRequestMessage();
  189                   SOAPEnvelope requestEnvelope = reqMsg.getSOAPEnvelope();
  190                   RPCElement body = getBody(requestEnvelope, messageContext);
  191                   body.setNeedDeser(true);
  192                   Vector args = null;
  193                   try {
  194                       args = body.getParams();
  195                   } catch (SAXException e) {
  196                       if (e.getException() != null) {
  197                           throw e.getException();
  198                       }
  199                       throw e;
  200                   }
  201   
  202                   Object[] argValues = new Object[operation.getNumParams()];
  203   
  204                   for (int i = 0; i < args.size(); i++) {
  205                       RPCParam rpcParam = (RPCParam) args.get(i);
  206                       Object value = rpcParam.getObjectValue();
  207   
  208                       ParameterDesc paramDesc = rpcParam.getParamDesc();
  209   
  210                       if (paramDesc != null && paramDesc.getJavaType() != null) {
  211                           value = JavaUtils.convert(value, paramDesc.getJavaType());
  212                           rpcParam.setObjectValue(value);
  213                       }
  214                       int order = (paramDesc == null || paramDesc.getOrder() == -1) ? i : paramDesc.getOrder();
  215                       argValues[order] = value;
  216                   }
  217                   return argValues;
  218               } finally {
  219                   messageContext.setProperty(org.apache.axis.SOAPPart.ALLOW_FORM_OPTIMIZATION, Boolean.FALSE);
  220               }
  221           }
  222   
  223           private Object demarshallResult() throws Exception {
  224               Message resMsg = messageContext.getResponseMessage();
  225   
  226               /*
  227                * This is not the most efficient way to deserialize the result
  228                * but could not find better or more reliable way to do this.
  229                */
  230               ByteArrayOutputStream out = new ByteArrayOutputStream();
  231               resMsg.writeTo(out);
  232               ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
  233   
  234               DeserializationContext dser =
  235                   new DeserializationContext(new InputSource(in), resMsg.getMessageContext(), null);
  236               dser.parse();
  237               SOAPEnvelope responseEnvelope = dser.getEnvelope();
  238   
  239               SOAPBodyElement bodyEl = responseEnvelope.getFirstBody();
  240               if (bodyEl == null) {
  241                   return null;
  242               }
  243   
  244               QName returnType = operation.getReturnType();
  245               if (XMLType.AXIS_VOID.equals(returnType)) {
  246                   return null;
  247               }
  248   
  249               Object result = null;
  250   
  251               if (bodyEl instanceof RPCElement) {
  252                   RPCElement body = (RPCElement)bodyEl;
  253                   body.setNeedDeser(true);
  254                   Vector args = null;
  255                   try {
  256                       args = body.getParams();
  257                   } catch (SAXException e) {
  258                       if (e.getException() != null) {
  259                           throw e.getException();
  260                       }
  261                       throw e;
  262                   }
  263   
  264                   QName returnParamQName = operation.getReturnQName();
  265                   if (args != null && args.size() > 0) {
  266   
  267                       if (returnParamQName == null) {
  268                           RPCParam param = (RPCParam) args.get(0);
  269                           result = param.getObjectValue();
  270                       } else {
  271                           for (int i = 0; i < args.size(); i++) {
  272                               RPCParam param = (RPCParam) args.get(i);
  273                               if (returnParamQName.equals(param.getQName())) {
  274                                   result = param.getObjectValue();
  275                                   break;
  276                               }
  277                           }
  278                       }
  279   
  280                   }
  281               } else {
  282                   try {
  283                       result = bodyEl.getValueAsType(returnType);
  284                   } catch (Exception e) {
  285                       result = bodyEl;
  286                   }
  287               }
  288   
  289               if (operation.getReturnClass() != null) {
  290                   result = JavaUtils.convert(result, operation.getReturnClass());
  291               }
  292   
  293               return result;
  294           }
  295   
  296           public void createResult(Object object) {
  297               messageContext.setPastPivot(true);
  298               try {
  299                   Message requestMessage = messageContext.getRequestMessage();
  300                   SOAPEnvelope requestEnvelope = requestMessage.getSOAPEnvelope();
  301                   RPCElement requestBody = getBody(requestEnvelope, messageContext);
  302   
  303                   Message responseMessage = messageContext.getResponseMessage();
  304                   SOAPEnvelope responseEnvelope = responseMessage.getSOAPEnvelope();
  305                   ServiceDesc serviceDescription = messageContext.getService().getServiceDescription();
  306                   RPCElement responseBody = createResponseBody(requestBody, messageContext, operation, serviceDescription, object, responseEnvelope, getInOutParams());
  307   
  308                   responseEnvelope.removeBody();
  309                   responseEnvelope.addBodyElement(responseBody);
  310               } catch (Exception e) {
  311                   throw new RuntimeException("Failed while creating response message body", e);
  312               }
  313           }
  314   
  315           public void createExceptionResult(Throwable exception) {
  316               messageContext.setPastPivot(true);
  317   
  318               AxisFault axisFault = null;
  319               if (exception instanceof Exception) {
  320                   axisFault = AxisFault.makeFault((Exception)exception);
  321                   axisFault.setFaultCodeAsString(Constants.FAULT_SERVER_GENERAL);
  322               } else {
  323                   axisFault = new AxisFault("Server", "Server Error", null, null);
  324               }
  325   
  326               SOAPFault fault = new SOAPFault(axisFault);
  327               SOAPEnvelope envelope = new SOAPEnvelope();
  328               envelope.addBodyElement(fault);
  329               Message message = new Message(envelope);
  330               message.setMessageType(Message.RESPONSE);
  331               messageContext.setResponseMessage(message);
  332           }
  333   
  334           public ArrayList getInOutParams() {
  335               return new ArrayList(); //TODO collect out an inout params in demarshalArguments
  336           }
  337       }
  338   
  339   }

Home » openejb-3.1.2-src » org.apache » openejb » server » axis » [javadoc | source]