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