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.spring.aop.AnnotationChainableMethodAdvice;
031 import com.liferay.portal.util.ClassLoaderUtil;
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 Class<?> identifiableBeanClass = identifiableBean.getClass();
103
104 ClassLoader contextClassLoader = identifiableBeanClass.getClassLoader();
105
106 String servletContextName = ClassLoaderPool.getContextName(
107 contextClassLoader);
108
109 Map<String, Serializable> context =
110 ClusterableContextThreadLocal.collectThreadLocalContext();
111
112 return new MethodHandler(
113 _invokeMethodKey, methodHandler, servletContextName,
114 identifiableBean.getBeanIdentifier(), clusterInvokeAcceptorClass,
115 context);
116 }
117
118 @SuppressWarnings("unused")
119 private static Object _invoke(
120 MethodHandler methodHandler, String servletContextName,
121 String beanIdentifier,
122 Class<? extends ClusterInvokeAcceptor> clusterInvokeAcceptorClass,
123 Map<String, Serializable> context)
124 throws Exception {
125
126 if (clusterInvokeAcceptorClass != null) {
127 Constructor<? extends ClusterInvokeAcceptor> constructor =
128 clusterInvokeAcceptorClass.getDeclaredConstructor();
129
130 if (!constructor.isAccessible()) {
131 constructor.setAccessible(true);
132 }
133
134 ClusterInvokeAcceptor clusterInvokeAcceptor =
135 constructor.newInstance();
136
137 if (!clusterInvokeAcceptor.accept(context)) {
138 return null;
139 }
140 }
141
142 if (Validator.isNull(servletContextName)) {
143 if (Validator.isNull(beanIdentifier)) {
144 return methodHandler.invoke(true);
145 }
146
147 Object bean = PortalBeanLocatorUtil.locate(beanIdentifier);
148
149 return methodHandler.invoke(bean);
150 }
151
152 ClassLoader contextClassLoader =
153 ClassLoaderUtil.getContextClassLoader();
154
155 try {
156 ClassLoader classLoader = ClassLoaderPool.getClassLoader(
157 servletContextName);
158
159 ClassLoaderUtil.setContextClassLoader(classLoader);
160
161 if (Validator.isNull(beanIdentifier)) {
162 return methodHandler.invoke(true);
163 }
164
165 Object bean = PortletBeanLocatorUtil.locate(
166 servletContextName, beanIdentifier);
167
168 return methodHandler.invoke(bean);
169 }
170 finally {
171 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
172 }
173 }
174
175 private static Log _log = LogFactoryUtil.getLog(ClusterableAdvice.class);
176
177 private static MethodKey _invokeMethodKey = new MethodKey(
178 ClusterableAdvice.class, "_invoke", MethodHandler.class, String.class,
179 String.class, Class.class, Map.class);
180
181 private static Clusterable _nullClusterable = new Clusterable() {
182
183 @Override
184 public Class<? extends ClusterInvokeAcceptor> acceptor() {
185 return null;
186 }
187
188 @Override
189 public Class<? extends Annotation> annotationType() {
190 return Clusterable.class;
191 }
192
193 };
194
195 }