001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.messaging.async;
016    
017    import com.liferay.portal.kernel.bean.IdentifiableBean;
018    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
019    import com.liferay.portal.kernel.bean.PortletBeanLocatorUtil;
020    import com.liferay.portal.kernel.util.ClassLoaderPool;
021    import com.liferay.portal.kernel.util.MethodHandler;
022    import com.liferay.portal.kernel.util.MethodKey;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.util.ClassLoaderUtil;
025    
026    import java.io.Externalizable;
027    import java.io.IOException;
028    import java.io.ObjectInput;
029    import java.io.ObjectOutput;
030    
031    import org.aopalliance.intercept.MethodInvocation;
032    
033    /**
034     * @author Shuyang Zhou
035     */
036    public class AsyncRunnable implements Externalizable, Runnable {
037    
038            public AsyncRunnable() {
039            }
040    
041            public AsyncRunnable(MethodInvocation methodInvocation) {
042                    _methodInvocation = methodInvocation;
043            }
044    
045            @Override
046            public void readExternal(ObjectInput objectInput)
047                    throws ClassNotFoundException, IOException {
048    
049                    _methodHandler = (MethodHandler)objectInput.readObject();
050            }
051    
052            @Override
053            public void run() {
054                    try {
055                            if (_methodInvocation != null) {
056                                    _methodInvocation.proceed();
057                            }
058                            else {
059                                    AsyncInvokeThreadLocal.setEnabled(true);
060    
061                                    try {
062                                            _methodHandler.invoke(null);
063                                    }
064                                    finally {
065                                            AsyncInvokeThreadLocal.setEnabled(false);
066                                    }
067                            }
068                    }
069                    catch (Throwable t) {
070                            throw new RuntimeException(t);
071                    }
072            }
073    
074            @Override
075            public void writeExternal(ObjectOutput objectOutput) throws IOException {
076                    MethodHandler methodHandler = _methodHandler;
077    
078                    if (methodHandler == null) {
079                            Thread currentThread = Thread.currentThread();
080    
081                            ClassLoader contextClassLoader =
082                                    currentThread.getContextClassLoader();
083    
084                            String servletContextName = ClassLoaderPool.getContextName(
085                                    contextClassLoader);
086    
087                            methodHandler = new MethodHandler(
088                                    _methodInvocation.getMethod(),
089                                    _methodInvocation.getArguments());
090    
091                            Object thisObject = _methodInvocation.getThis();
092    
093                            IdentifiableBean identifiableBean = (IdentifiableBean)thisObject;
094    
095                            String beanIdentifier = identifiableBean.getBeanIdentifier();
096    
097                            methodHandler = new MethodHandler(
098                                    _invokeMethodKey, methodHandler, servletContextName,
099                                    beanIdentifier);
100                    }
101    
102                    objectOutput.writeObject(methodHandler);
103            }
104    
105            @SuppressWarnings("unused")
106            private static Object _invoke(
107                            MethodHandler methodHandler, String servletContextName,
108                            String beanIdentifier)
109                    throws Exception {
110    
111                    if (Validator.isNull(servletContextName)) {
112                            if (Validator.isNull(beanIdentifier)) {
113                                    return methodHandler.invoke(true);
114                            }
115                            else {
116                                    Object bean = PortalBeanLocatorUtil.locate(beanIdentifier);
117    
118                                    return methodHandler.invoke(bean);
119                            }
120                    }
121    
122                    ClassLoader contextClassLoader =
123                            ClassLoaderUtil.getContextClassLoader();
124    
125                    try {
126                            ClassLoader classLoader = ClassLoaderPool.getClassLoader(
127                                    servletContextName);
128    
129                            ClassLoaderUtil.setContextClassLoader(classLoader);
130    
131                            if (Validator.isNull(beanIdentifier)) {
132                                    return methodHandler.invoke(true);
133                            }
134                            else {
135                                    Object bean = PortletBeanLocatorUtil.locate(
136                                            servletContextName, beanIdentifier);
137    
138                                    return methodHandler.invoke(bean);
139                            }
140                    }
141                    finally {
142                            ClassLoaderUtil.setContextClassLoader(contextClassLoader);
143                    }
144            }
145    
146            private static MethodKey _invokeMethodKey = new MethodKey(
147                    AsyncRunnable.class, "_invoke", MethodHandler.class, String.class,
148                    String.class);
149    
150            private MethodHandler _methodHandler;
151            private MethodInvocation _methodInvocation;
152    
153    }