001
014
015 package com.liferay.portal.cluster;
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.cluster.ClusterExecutorUtil;
021 import com.liferay.portal.kernel.cluster.ClusterInvokeAcceptor;
022 import com.liferay.portal.kernel.cluster.ClusterRequest;
023 import com.liferay.portal.kernel.cluster.Clusterable;
024 import com.liferay.portal.kernel.log.Log;
025 import com.liferay.portal.kernel.log.LogFactoryUtil;
026 import com.liferay.portal.kernel.util.ClassLoaderPool;
027 import com.liferay.portal.kernel.util.MethodHandler;
028 import com.liferay.portal.kernel.util.MethodKey;
029 import com.liferay.portal.kernel.util.Validator;
030 import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
031 import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice;
032
033 import java.io.Serializable;
034
035 import java.lang.annotation.Annotation;
036 import java.lang.reflect.Constructor;
037
038 import java.util.Map;
039
040 import org.aopalliance.intercept.MethodInvocation;
041
042
045 public class ClusterableAdvice
046 extends AnnotationChainableMethodAdvice<Clusterable> {
047
048 @Override
049 public void afterReturning(MethodInvocation methodInvocation, Object result)
050 throws Throwable {
051
052 if (!ClusterInvokeThreadLocal.isEnabled()) {
053 return;
054 }
055
056 Clusterable clusterable = findAnnotation(methodInvocation);
057
058 if (clusterable == _nullClusterable) {
059 return;
060 }
061
062 Object thisObject = methodInvocation.getThis();
063
064 if (!(thisObject instanceof IdentifiableBean)) {
065 _log.error(
066 "Not clustering calls for " + thisObject.getClass().getName() +
067 " because it does not implement " +
068 IdentifiableBean.class.getName());
069
070 return;
071 }
072
073 MethodHandler methodHandler = createMethodHandler(
074 clusterable.acceptor(), methodInvocation);
075
076 ClusterRequest clusterRequest = ClusterRequest.createMulticastRequest(
077 methodHandler, true);
078
079 ClusterExecutorUtil.execute(clusterRequest);
080 }
081
082 @Override
083 public Clusterable getNullAnnotation() {
084 return _nullClusterable;
085 }
086
087 protected MethodHandler createMethodHandler(
088 Class<? extends ClusterInvokeAcceptor> clusterInvokeAcceptorClass,
089 MethodInvocation methodInvocation) {
090
091 if (clusterInvokeAcceptorClass == ClusterInvokeAcceptor.class) {
092 clusterInvokeAcceptorClass = null;
093 }
094
095 MethodHandler methodHandler = new MethodHandler(
096 methodInvocation.getMethod(), methodInvocation.getArguments());
097
098 Object thisObject = methodInvocation.getThis();
099
100 IdentifiableBean identifiableBean = (IdentifiableBean)thisObject;
101
102 String beanIdentifier = identifiableBean.getBeanIdentifier();
103
104 Thread currentThread = Thread.currentThread();
105
106 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
107
108 String servletContextName = ClassLoaderPool.getContextName(
109 contextClassLoader);
110
111 Map<String, Serializable> context =
112 ClusterableContextThreadLocal.collectThreadLocalContext();
113
114 return new MethodHandler(
115 _invokeMethodKey, methodHandler, beanIdentifier, servletContextName,
116 clusterInvokeAcceptorClass, context);
117 }
118
119 @SuppressWarnings("unused")
120 private static Object _invoke(
121 MethodHandler methodHandler, String servletContextName,
122 String beanIdentifier,
123 Class<? extends ClusterInvokeAcceptor> clusterInvokeAcceptorClass,
124 Map<String, Serializable> context)
125 throws Exception {
126
127 if (clusterInvokeAcceptorClass != null) {
128 Constructor<? extends ClusterInvokeAcceptor> constructor =
129 clusterInvokeAcceptorClass.getDeclaredConstructor();
130
131 if (!constructor.isAccessible()) {
132 constructor.setAccessible(true);
133 }
134
135 ClusterInvokeAcceptor clusterInvokeAcceptor =
136 constructor.newInstance();
137
138 if (!clusterInvokeAcceptor.accept(context)) {
139 return null;
140 }
141 }
142
143 if (servletContextName == null) {
144 if (Validator.isNull(beanIdentifier)) {
145 return methodHandler.invoke(true);
146 }
147 else {
148 Object bean = PortalBeanLocatorUtil.locate(beanIdentifier);
149
150 return methodHandler.invoke(bean);
151 }
152 }
153
154 ClassLoader contextClassLoader =
155 PACLClassLoaderUtil.getContextClassLoader();
156
157 try {
158 ClassLoader classLoader =
159 (ClassLoader)PortletBeanLocatorUtil.locate(
160 servletContextName, "portletClassLoader");
161
162 PACLClassLoaderUtil.setContextClassLoader(classLoader);
163
164 if (Validator.isNull(beanIdentifier)) {
165 return methodHandler.invoke(true);
166 }
167 else {
168 Object bean = PortletBeanLocatorUtil.locate(
169 servletContextName, beanIdentifier);
170
171 return methodHandler.invoke(bean);
172 }
173 }
174 finally {
175 PACLClassLoaderUtil.setContextClassLoader(contextClassLoader);
176 }
177 }
178
179 private static Log _log = LogFactoryUtil.getLog(ClusterableAdvice.class);
180
181 private static MethodKey _invokeMethodKey = new MethodKey(
182 ClusterableAdvice.class, "_invoke", MethodHandler.class, String.class,
183 String.class, Class.class, Map.class);
184
185 private static Clusterable _nullClusterable = new Clusterable() {
186
187 public Class<? extends ClusterInvokeAcceptor> acceptor() {
188 return null;
189 }
190
191 public Class<? extends Annotation> annotationType() {
192 return Clusterable.class;
193 }
194
195 };
196
197 }