Save This Page
Home » axis2-1.5-src » org.apache » axis2 » receivers » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements. See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership. The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License. You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied. See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.
   18    */
   19   
   20   
   21   package org.apache.axis2.receivers;
   22   
   23   import org.apache.axiom.om.OMAbstractFactory;
   24   import org.apache.axiom.soap.SOAP11Constants;
   25   import org.apache.axiom.soap.SOAP12Constants;
   26   import org.apache.axiom.soap.SOAPFactory;
   27   import org.apache.axis2.AxisFault;
   28   import org.apache.axis2.Constants;
   29   import org.apache.axis2.addressing.EndpointReference;
   30   import org.apache.axis2.classloader.MultiParentClassLoader;
   31   import org.apache.axis2.clustering.ClusteringFault;
   32   import org.apache.axis2.clustering.context.Replicator;
   33   import org.apache.axis2.context.MessageContext;
   34   import org.apache.axis2.context.ServiceContext;
   35   import org.apache.axis2.description.AxisService;
   36   import org.apache.axis2.description.InOnlyAxisOperation;
   37   import org.apache.axis2.description.Parameter;
   38   import org.apache.axis2.description.WSDL2Constants;
   39   import org.apache.axis2.engine.AxisEngine;
   40   import org.apache.axis2.engine.DependencyManager;
   41   import org.apache.axis2.engine.MessageReceiver;
   42   import org.apache.axis2.i18n.Messages;
   43   import org.apache.axis2.util.JavaUtils;
   44   import org.apache.axis2.util.Loader;
   45   import org.apache.axis2.util.MessageContextBuilder;
   46   import org.apache.axis2.wsdl.WSDLUtil;
   47   import org.apache.commons.logging.Log;
   48   import org.apache.commons.logging.LogFactory;
   49   
   50   import java.lang.reflect.Method;
   51   import java.lang.reflect.InvocationTargetException;
   52   import java.net.URL;
   53   import java.security.AccessController;
   54   import java.security.PrivilegedAction;
   55   import java.security.PrivilegedExceptionAction;
   56   
   57   public abstract class AbstractMessageReceiver implements MessageReceiver {
   58       protected static final Log log = LogFactory.getLog(AbstractMessageReceiver.class);
   59   
   60       public static final String SCOPE = "scope";
   61       protected String serviceTCCL = null;
   62       public static final String SAVED_TCCL = "_SAVED_TCCL_";
   63       public static final String SAVED_MC = "_SAVED_MC_";
   64       public static final String DO_ASYNC = "messageReceiver.invokeOnSeparateThread";
   65   
   66       // Place to store previous values
   67       public static class ThreadContextDescriptor {
   68           public ClassLoader oldClassLoader;
   69           public MessageContext oldMessageContext;
   70       }
   71   
   72       protected void replicateState(MessageContext messageContext) throws ClusteringFault {
   73           Replicator.replicate(messageContext);
   74       }
   75   
   76       /**
   77        * Do the actual work of the MessageReceiver.  Must be overridden by concrete subclasses.
   78        *
   79        * @param messageCtx active MessageContext
   80        * @throws AxisFault if a problem occurred
   81        */
   82       protected abstract void invokeBusinessLogic(MessageContext messageCtx) throws AxisFault;
   83   
   84       /**
   85        *
   86        * @param messageCtx active MessageContext
   87        * @throws AxisFault if a problem occurred
   88        */
   89       public void receive(final MessageContext messageCtx) throws AxisFault {
   90       	if (messageCtx.isPropertyTrue(DO_ASYNC)
   91   				|| ((messageCtx.getParameter(DO_ASYNC) != null) &&
   92                       JavaUtils.isTrueExplicitly(messageCtx.getParameter(DO_ASYNC).getValue()))) {
   93   
   94               String mep = messageCtx.getAxisOperation()
   95   					.getMessageExchangePattern();
   96   			EndpointReference replyTo = messageCtx.getReplyTo();
   97   			// In order to invoke the service in the ASYNC mode, the request
   98   			// should contain ReplyTo header if the MEP of the service is not
   99   			// InOnly type
  100   			if ((!WSDLUtil.isOutputPresentForMEP(mep))
  101   					|| (replyTo != null && !replyTo.hasAnonymousAddress())) {
  102   				AsyncMessageReceiverWorker worker = new AsyncMessageReceiverWorker(
  103   						messageCtx);
  104   				messageCtx.getEnvelope().build();
  105   				messageCtx.getConfigurationContext().getThreadPool().execute(
  106   						worker);
  107   				return;
  108   			}
  109   		}
  110   
  111   
  112           ThreadContextDescriptor tc = setThreadContext(messageCtx);
  113           try {
  114               invokeBusinessLogic(messageCtx);
  115           } catch (AxisFault fault) {
  116               // If we're in-only, eat this.  Otherwise, toss it upwards!
  117               if ((messageCtx.getAxisOperation() instanceof InOnlyAxisOperation) &&
  118                       !WSDL2Constants.MEP_URI_ROBUST_IN_ONLY.equals(messageCtx.getAxisOperation().getMessageExchangePattern())) {
  119                   log.error(fault);
  120               } else {
  121                   fault.setFaultType(Constants.APPLICATION_FAULT);
  122                   throw fault;
  123               }
  124           } finally {
  125               restoreThreadContext(tc);
  126           }
  127       }
  128   
  129       /**
  130        * Several pieces of information need to be available to the service
  131        * implementation class.  For one, the ThreadContextClassLoader needs
  132        * to be correct, and for another we need to give the service code
  133        * access to the MessageContext (getCurrentContext()).  So we toss these
  134        * things in TLS.
  135        *
  136        * @param msgContext the current MessageContext
  137        * @return a ThreadContextDescriptor containing the old values
  138        */
  139       protected ThreadContextDescriptor setThreadContext(final MessageContext msgContext) {
  140           ThreadContextDescriptor tc = new ThreadContextDescriptor();
  141           tc.oldMessageContext = (MessageContext) MessageContext.currentMessageContext.get();
  142           final ClassLoader contextClassLoader = getContextClassLoader_doPriv();
  143           tc.oldClassLoader = contextClassLoader;
  144   
  145           AxisService service = msgContext.getAxisService();
  146           String serviceTCCL = (String) service.getParameterValue(Constants.SERVICE_TCCL);
  147           if (serviceTCCL != null) {
  148               serviceTCCL = serviceTCCL.trim().toLowerCase();
  149   
  150               if (serviceTCCL.equals(Constants.TCCL_COMPOSITE)) {
  151                   final ClassLoader loader = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
  152                       public Object run() {
  153                           return new MultiParentClassLoader(new URL[]{},
  154                                   new ClassLoader[]{
  155                                           msgContext.getAxisService().getClassLoader(),
  156                                           contextClassLoader
  157                                   });
  158                       }
  159                   });
  160                   org.apache.axis2.java.security.AccessController.doPrivileged(
  161                           new PrivilegedAction() {
  162                               public Object run() {
  163                                   Thread.currentThread().setContextClassLoader(
  164                                           loader);
  165                                   return null;
  166                               }
  167                           }
  168                   );
  169               } else if (serviceTCCL.equals(Constants.TCCL_SERVICE)) {
  170                   org.apache.axis2.java.security.AccessController.doPrivileged(
  171                           new PrivilegedAction() {
  172                               public Object run() {
  173                                   Thread.currentThread().setContextClassLoader(
  174                                           msgContext.getAxisService().getClassLoader()
  175                                   );
  176                                   return null;
  177                               }
  178                           }
  179                   );
  180               }
  181           }
  182           MessageContext.setCurrentMessageContext(msgContext);
  183           return tc;
  184       }
  185   
  186       private ClassLoader getContextClassLoader_doPriv() {
  187           return (ClassLoader) org.apache.axis2.java.security.AccessController.doPrivileged(
  188                   new PrivilegedAction() {
  189                       public Object run() {
  190                           return Thread.currentThread().getContextClassLoader();
  191                       }
  192                   }
  193           );
  194       }
  195   
  196       protected void restoreThreadContext(final ThreadContextDescriptor tc) {
  197           org.apache.axis2.java.security.AccessController.doPrivileged(
  198                   new PrivilegedAction() {
  199                       public Object run() {
  200                           Thread.currentThread().setContextClassLoader(tc.oldClassLoader);
  201                           return null;
  202                       }
  203                   }
  204           );
  205           MessageContext.currentMessageContext.set(tc.oldMessageContext);
  206       }
  207   
  208       /**
  209        * Create a new service object.  Override if you want to customize how
  210        * this happens in your own MessageReceiver.
  211        *
  212        * @param msgContext
  213        * @return Returns Object.
  214        * @throws AxisFault
  215        */
  216       protected Object makeNewServiceObject(MessageContext msgContext) throws AxisFault {
  217           try {
  218               final AxisService service = msgContext.getAxisService();
  219               ClassLoader classLoader = service.getClassLoader();
  220   
  221               // allow alternative definition of makeNewServiceObject
  222               if (service.getParameter(Constants.SERVICE_OBJECT_SUPPLIER) != null) {
  223                   Parameter serviceObjectParam =
  224                           service.getParameter(Constants.SERVICE_OBJECT_SUPPLIER);
  225                   final Class serviceObjectMaker = Loader.loadClass(classLoader, ((String)
  226                           serviceObjectParam.getValue()).trim());
  227   
  228                   // Find static getServiceObject() method, call it if there
  229                   final Method method = (Method) org.apache.axis2.java.security.AccessController.doPrivileged(
  230                           new PrivilegedExceptionAction() {
  231                               public Object run() throws NoSuchMethodException {
  232                                   return serviceObjectMaker.getMethod("getServiceObject",
  233                                           new Class[]{AxisService.class});
  234                               }
  235                           }
  236                   );
  237                   if (method != null) {
  238                       return org.apache.axis2.java.security.AccessController.doPrivileged(
  239                               new PrivilegedExceptionAction() {
  240                                   public Object run() throws InvocationTargetException, IllegalAccessException, InstantiationException {
  241                                       return method.invoke(serviceObjectMaker.newInstance(), new Object[]{service});
  242                                   }
  243                               }
  244                       );
  245                   }
  246               }
  247   
  248               Parameter implInfoParam = service.getParameter(Constants.SERVICE_CLASS);
  249               if (implInfoParam != null) {
  250                   final Class implClass = Loader.loadClass(
  251                           classLoader,
  252                           ((String) implInfoParam.getValue()).trim());
  253                   return org.apache.axis2.java.security.AccessController.doPrivileged(
  254                           new PrivilegedExceptionAction() {
  255                               public Object run() throws InstantiationException, IllegalAccessException {
  256                                   return implClass.newInstance();
  257                               }
  258                           }
  259                   );
  260               } else {
  261                   throw new AxisFault(
  262                           Messages.getMessage("paramIsNotSpecified", "SERVICE_OBJECT_SUPPLIER"));
  263               }
  264           } catch (Exception e) {
  265               throw AxisFault.makeFault(e);
  266           }
  267       }
  268   
  269       public SOAPFactory getSOAPFactory(MessageContext msgContext) throws AxisFault {
  270           String nsURI = msgContext.getEnvelope().getNamespace().getNamespaceURI();
  271           if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(nsURI)) {
  272               return OMAbstractFactory.getSOAP12Factory();
  273           } else if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(nsURI)) {
  274               return OMAbstractFactory.getSOAP11Factory();
  275           } else {
  276               throw new AxisFault(Messages.getMessage("invalidSOAPversion"));
  277           }
  278       }
  279   
  280       /**
  281        * Retrieve the implementation object.  This will either return a cached
  282        * object if present in the ServiceContext, or create a new one via
  283        * makeNewServiceObject() (and then cache that).
  284        *
  285        * @param msgContext the active MessageContext
  286        * @return the appropriate back-end service object.
  287        * @throws AxisFault if there's a problem
  288        */
  289       protected Object getTheImplementationObject(MessageContext msgContext) throws AxisFault {
  290           ServiceContext serviceContext = msgContext.getServiceContext();
  291           Object serviceimpl = serviceContext.getProperty(ServiceContext.SERVICE_OBJECT);
  292           if (serviceimpl != null) {
  293               // since service impl is there in service context , take that from there
  294               return serviceimpl;
  295           } else {
  296               // create a new service impl class for that service
  297               serviceimpl = makeNewServiceObject(msgContext);
  298               //Service initialization
  299               DependencyManager.initServiceObject(serviceimpl, msgContext.getServiceContext());
  300               serviceContext.setProperty(ServiceContext.SERVICE_OBJECT, serviceimpl);
  301               return serviceimpl;
  302           }
  303       }
  304   
  305       public class AsyncMessageReceiverWorker implements Runnable {
  306       	private MessageContext messageCtx;
  307   
  308       	public AsyncMessageReceiverWorker(MessageContext messageCtx){
  309       		this.messageCtx = messageCtx;
  310       	}
  311   
  312           public void run() {
  313               try {
  314                   ThreadContextDescriptor tc = setThreadContext(messageCtx);
  315                   try {
  316                       invokeBusinessLogic(messageCtx);
  317                   } finally {
  318                       restoreThreadContext(tc);
  319                   }
  320               } catch (AxisFault e) {
  321                   // If we're IN-ONLY, swallow this.  Otherwise, send it.
  322                   if (messageCtx.getAxisOperation() instanceof InOnlyAxisOperation) {
  323                       log.debug(e.getMessage(), e);
  324                   } else {
  325                       try {
  326                           MessageContext faultContext =
  327                                   MessageContextBuilder.createFaultMessageContext(messageCtx, e);
  328   
  329                           AxisEngine.sendFault(faultContext);
  330                       } catch (AxisFault axisFault) {
  331                           log.error(e.getMessage(), e);
  332                       }
  333                       log.error(e.getMessage(), e);
  334                   }
  335               }
  336           }
  337       }
  338   }

Save This Page
Home » axis2-1.5-src » org.apache » axis2 » receivers » [javadoc | source]