Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2011, Red Hat, Inc., and individual contributors
   * as indicated by the @author tags. See the copyright.txt file in the
   * distribution for a full listing of individual contributors.
   *
   * This is free software; you can redistribute it and/or modify it
   * under the terms of the GNU Lesser General Public License as
   * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
 
 package org.jboss.as.ejb3.remote.protocol.versionone;
 
 import java.util.Map;
 import java.util.Set;
 
 import  org.jboss.invocation.InterceptorContext;

Author(s):
Jaikiran Pai
 
 
     private static final Logger logger = Logger.getLogger(MethodInvocationMessageHandler.class);
 
     private static final char METHOD_PARAM_TYPE_SEPARATOR = ',';
 
     private static final byte HEADER_METHOD_INVOCATION_RESPONSE = 0x05;
     private static final byte HEADER_ASYNC_METHOD_NOTIFICATION = 0x0E;
 
     private final ExecutorService executorService;
     private final MarshallerFactory marshallerFactory;
 
     MethodInvocationMessageHandler(final DeploymentRepository deploymentRepositoryfinal org.jboss.marshalling.MarshallerFactory marshallerFactoryfinal ExecutorService executorService) {
         super(deploymentRepository);
         this. = marshallerFactory;
         this. = executorService;
     }
 
     @Override
     public void processMessage(final ChannelAssociation channelAssociationfinal MessageInputStream messageInputStreamthrows IOException {
 
         final DataInputStream input = new DataInputStream(messageInputStream);
         // read the invocation id
         final short invocationId = input.readShort();
 
         // read the method name
         final String methodName = input.readUTF();
         // method signature
         String[] methodParamTypes = null;
         final String signature = input.readUTF();
         if (signature.isEmpty()) {
             methodParamTypes = new String[0];
         } else {
            methodParamTypes = signature.split(String.valueOf());
        }
        // read the Locator
        // we use a mutable ClassResolver, so that we can switch to a different (and correct deployment CL)
        // midway through the unmarshalling of the stream
        final Unmarshaller unmarshaller = this.prepareForUnMarshalling(this.classResolverinput);
        // read the EJB info
        final String appName;
        final String moduleName;
        final String distinctName;
        final String beanName;
        try {
            appName = (Stringunmarshaller.readObject();
            moduleName = (Stringunmarshaller.readObject();
            distinctName = (Stringunmarshaller.readObject();
            beanName = (Stringunmarshaller.readObject();
        } catch (ClassNotFoundException e) {
            throw ..classNotFoundException(e);
        }
        final EjbDeploymentInformation ejbDeploymentInformation = this.findEJB(appNamemoduleNamedistinctNamebeanName);
        if (ejbDeploymentInformation == null) {
            this.writeNoSuchEJBFailureMessage(channelAssociationinvocationIdappNamemoduleNamedistinctNamebeanNamenull);
            return;
        }
        final ClassLoader tccl = SecurityActions.getContextClassLoader();
        Runnable runnable = null;
        try {
            //set the correct TCCL for unmarshalling
            SecurityActions.setContextClassLoader(ejbDeploymentInformation.getDeploymentClassLoader());
            // now switch the CL to the EJB deployment's CL so that the unmarshaller can use the
            // correct CL for the rest of the unmarshalling of the stream
            classResolver.switchClassLoader(ejbDeploymentInformation.getDeploymentClassLoader());
            // read the Locator
            final EJBLocator<?> locator;
            try {
                locator = (EJBLocator<?>) unmarshaller.readObject();
            } catch (ClassNotFoundException e) {
                throw ..classNotFoundException(e);
            }
            final String viewClassName = locator.getViewType().getName();
            // Make sure it's a remote view
            if (!ejbDeploymentInformation.isRemoteView(viewClassName)) {
                this.writeNoSuchEJBFailureMessage(channelAssociationinvocationIdappNamemoduleNamedistinctNamebeanNameviewClassName);
                return;
            }
            final ComponentView componentView = ejbDeploymentInformation.getView(viewClassName);
            final Method invokedMethod = this.findMethod(componentViewmethodNamemethodParamTypes);
            if (invokedMethod == null) {
                this.writeNoSuchEJBMethodFailureMessage(channelAssociationinvocationIdappNamemoduleNamedistinctNamebeanNameviewClassNamemethodNamemethodParamTypes);
                return;
            }
            final Object[] methodParams = new Object[methodParamTypes.length];
            // un-marshall the method arguments
            if (methodParamTypes.length > 0) {
                for (int i = 0; i < methodParamTypes.lengthi++) {
                    try {
                        methodParams[i] = unmarshaller.readObject();
                    } catch (ClassNotFoundException cnfe) {
                        // write out the failure
                        MethodInvocationMessageHandler.this.writeException(channelAssociationMethodInvocationMessageHandler.this.invocationIdcnfenull);
                        return;
                    }
                }
            }
            // read the attachments
            final Map<StringObjectattachments;
            try {
                attachments = this.readAttachments(unmarshaller);
            } catch (ClassNotFoundException cnfe) {
                // write out the failure
                MethodInvocationMessageHandler.this.writeException(channelAssociationMethodInvocationMessageHandler.this.invocationIdcnfenull);
                return;
            }
            // done with unmarshalling
            unmarshaller.finish();
            runnable = new Runnable() {
                @Override
                public void run() {
                    // check if it's async. If yes, then notify the client that's it's async method (so that
                    // it can unblock if necessary)
                    if (componentView.isAsynchronous(invokedMethod)) {
                        try {
                            MethodInvocationMessageHandler.this.writeAsyncMethodNotification(channelAssociationinvocationId);
                        } catch (Throwable t) {
                            // catch Throwable, so that we don't skip invoking the method, just because we
                            // failed to send a notification to the client that the method is an async method
                            ..failedToSendAsyncMethodIndicatorToClient(tinvokedMethod);
                        }
                    }
                    // invoke the method
                    Object result = null;
                    RemotingContext.setConnection(channelAssociation.getChannel().getConnection());
                    try {
                        result = invokeMethod(componentViewinvokedMethodmethodParamslocatorattachments);
                    } catch (Throwable throwable) {
                        try {
                            // write out the failure
                            MethodInvocationMessageHandler.this.writeException(channelAssociationMethodInvocationMessageHandler.this.invocationIdthrowableattachments);
                        } catch (IOException ioe) {
                            // we couldn't write out a method invocation failure message. So let's at least log the
                            // actual method invocation exception, for debugging/reference
                            .error("Error invoking method " + invokedMethod + " on bean named " + beanName
                                    + " for appname " + appName + " modulename " + moduleName + " distinctname " + distinctNamethrowable);
                            // now log why we couldn't send back the method invocation failure message
                            .error("Could not write method invocation failure for method " + invokedMethod + " on bean named " + beanName
                                    + " for appname " + appName + " modulename " + moduleName + " distinctname " + distinctName + " due to "ioe);
                            // close the channel unless this is a NotSerializableException
                            //as this does not represent a problem with the channel there is no
                            //need to close it (see AS7-3402)
                            if(!(ioe instanceof ObjectStreamException)) {
                                IoUtils.safeClose(channelAssociation.getChannel());
                            }
                            return;
                        }
                    } finally {
                        RemotingContext.clear();
                    }
                    // write out the (successful) method invocation result to the channel output stream
                    try {
                        // attach any weak affinity if available
                        Affinity weakAffinity = null;
                        if (locator instanceof StatefulEJBLocator && componentView.getComponent() instanceof StatefulSessionComponent) {
                            final StatefulSessionComponent statefulSessionComponent = (StatefulSessionComponentcomponentView.getComponent();
                            weakAffinity = MethodInvocationMessageHandler.this.getWeakAffinity(statefulSessionComponent, (StatefulEJBLocator<?>) locator);
                        } else if (componentView.getComponent() instanceof StatelessSessionComponent) {
                            final StatelessSessionComponent statelessSessionComponent = (StatelessSessionComponentcomponentView.getComponent();
                            weakAffinity = statelessSessionComponent.getWeakAffinity();
                        }
                        if (weakAffinity != null) {
                            attachments.put(.weakAffinity);
                        }
                        writeMethodInvocationResponse(channelAssociationinvocationIdresultattachments);
                    } catch (IOException ioe) {
                        .error("Could not write method invocation result for method " + invokedMethod + " on bean named " + beanName
                                + " for appname " + appName + " modulename " + moduleName + " distinctname " + distinctName + " due to "ioe);
                        // close the channel unless this is a NotSerializableException
                        //as this does not represent a problem with the channel there is no
                        //need to close it (see AS7-3402)
                        if(!(ioe instanceof ObjectStreamException)) {
                            IoUtils.safeClose(channelAssociation.getChannel());
                        }
                        return;
                    }
                }
            };
        } finally {
            SecurityActions.setContextClassLoader(tccl);
        }
        // invoke the method and write out the response on a separate thread
        .submit(runnable);
    }
    private Affinity getWeakAffinity(final StatefulSessionComponent statefulSessionComponentfinal StatefulEJBLocator<?> statefulEJBLocator) {
        final SessionID sessionID = statefulEJBLocator.getSessionId();
        return statefulSessionComponent.getCache().getWeakAffinity(sessionID);
    }
    private Object invokeMethod(final ComponentView componentViewfinal Method methodfinal Object[] argsfinal EJBLocator<?> ejbLocatorfinal Map<StringObjectattachmentsthrows Throwable {
        final InterceptorContext interceptorContext = new InterceptorContext();
        interceptorContext.setParameters(args);
        interceptorContext.setMethod(method);
        interceptorContext.setContextData(new HashMap<StringObject>());
        interceptorContext.putPrivateData(Component.classcomponentView.getComponent());
        interceptorContext.putPrivateData(ComponentView.classcomponentView);
        interceptorContext.putPrivateData(InvocationType.class.);
        if (attachments != null) {
            // attach the attachments which were passed from the remote client
            for (final Map.Entry<StringObjectattachment : attachments.entrySet()) {
                if (attachment == null) {
                    continue;
                }
                final String key = attachment.getKey();
                final Object value = attachment.getValue();
                // add it to the context
                interceptorContext.putPrivateData(keyvalue);
            }
        }
        // add the session id to the interceptor context, if it's a stateful ejb locator
        if (ejbLocator instanceof StatefulEJBLocator) {
            interceptorContext.putPrivateData(SessionID.class, ((StatefulEJBLocator<?>) ejbLocator).getSessionId());
        } else if (ejbLocator instanceof EntityEJBLocator) {
            final Object primaryKey = ((EntityEJBLocator<?>) ejbLocator).getPrimaryKey();
            interceptorContext.putPrivateData(.primaryKey);
        }
        if (componentView.isAsynchronous(method)) {
            final Component component = componentView.getComponent();
            if (!(component instanceof SessionBeanComponent)) {
                ..asyncMethodSupportedOnlyForSessionBeans(component.getComponentClass(), method);
                // just invoke normally
                return componentView.invoke(interceptorContext);
            }
            return ((Future)componentView.invoke(interceptorContext)).get();
        } else {
            return componentView.invoke(interceptorContext);
        }
    }
    private Method findMethod(final ComponentView componentViewfinal String methodNamefinal String[] paramTypes) {
        final Set<MethodviewMethods = componentView.getViewMethods();
        for (final Method method : viewMethods) {
            if (method.getName().equals(methodName)) {
                final Class<?>[] methodParamTypes = method.getParameterTypes();
                if (methodParamTypes.length != paramTypes.length) {
                    continue;
                }
                boolean found = true;
                for (int i = 0; i < methodParamTypes.lengthi++) {
                    if (!methodParamTypes[i].getName().equals(paramTypes[i])) {
                        found = false;
                        break;
                    }
                }
                if (found) {
                    return method;
                }
            }
        }
        return null;
    }
    private void writeMethodInvocationResponse(final ChannelAssociation channelAssociationfinal short invocationIdfinal Object resultfinal Map<StringObjectattachmentsthrows IOException {
        final DataOutputStream outputStream;
        final MessageOutputStream messageOutputStream;
        try {
            messageOutputStream = channelAssociation.acquireChannelMessageOutputStream();
        } catch (Exception e) {
            throw ..failedToOpenMessageOutputStream(e);
        }
        outputStream = new DataOutputStream(messageOutputStream);
        try {
            // write invocation response header
            outputStream.write();
            // write the invocation id
            outputStream.writeShort(invocationId);
            // write out the result
            final Marshaller marshaller = this.prepareForMarshalling(this.outputStream);
            marshaller.writeObject(result);
            // write the attachments
            this.writeAttachments(marshallerattachments);
            // finish marshalling
            marshaller.finish();
        } finally {
            channelAssociation.releaseChannelMessageOutputStream(messageOutputStream);
            outputStream.close();
        }
    }
    private void writeAsyncMethodNotification(final ChannelAssociation channelAssociationfinal short invocationIdthrows IOException {
        final DataOutputStream outputStream;
        final MessageOutputStream messageOutputStream;
        try {
            messageOutputStream = channelAssociation.acquireChannelMessageOutputStream();
        } catch (Exception e) {
            throw ..failedToOpenMessageOutputStream(e);
        }
        outputStream = new DataOutputStream(messageOutputStream);
        try {
            // write the header
            outputStream.write();
            // write the invocation id
            outputStream.writeShort(invocationId);
        } finally {
            channelAssociation.releaseChannelMessageOutputStream(messageOutputStream);
            outputStream.close();
        }
    }

    
A mutable org.jboss.marshalling.ClassResolver
    private class ClassLoaderSwitchingClassResolver extends AbstractClassResolver {
        private ClassLoader currentClassLoader;
        ClassLoaderSwitchingClassResolver(final ClassLoader classLoader) {
            this. = classLoader;
        }

        
Sets the passed newCL as the classloader which will be returned on subsequent calls to getClassLoader()

Parameters:
newCL
        void switchClassLoader(final ClassLoader newCL) {
            this. = newCL;
        }
        @Override
        protected ClassLoader getClassLoader() {
            return this.;
        }
    }
New to GrepCode? Check out our FAQ X