001
014
015 package com.liferay.portal.systemevent;
016
017 import com.liferay.portal.kernel.lar.StagedModelType;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.systemevent.SystemEvent;
021 import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntry;
022 import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntryThreadLocal;
023 import com.liferay.portal.kernel.util.StringBundler;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.model.AuditedModel;
026 import com.liferay.portal.model.ClassedModel;
027 import com.liferay.portal.model.GroupedModel;
028 import com.liferay.portal.model.StagedModel;
029 import com.liferay.portal.model.SystemEventConstants;
030 import com.liferay.portal.model.TypedModel;
031 import com.liferay.portal.service.SystemEventLocalServiceUtil;
032 import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice;
033
034 import java.io.Serializable;
035
036 import java.lang.annotation.Annotation;
037 import java.lang.reflect.Method;
038
039 import org.aopalliance.intercept.MethodInvocation;
040
041
044 public class SystemEventAdvice
045 extends AnnotationChainableMethodAdvice<SystemEvent> {
046
047 @Override
048 public void afterReturning(MethodInvocation methodInvocation, Object result)
049 throws Throwable {
050
051 SystemEvent systemEvent = findAnnotation(methodInvocation);
052
053 if ((systemEvent == _nullSystemEvent) || !systemEvent.send()) {
054 return;
055 }
056
057 if (!isValid(methodInvocation, PHASE_AFTER_RETURNING)) {
058 return;
059 }
060
061 Object[] arguments = methodInvocation.getArguments();
062
063 ClassedModel classedModel = (ClassedModel)arguments[0];
064
065 long groupId = getGroupId(classedModel);
066
067 String className = getClassName(classedModel);
068
069 String referrerClassName = null;
070
071 if (classedModel instanceof TypedModel) {
072 TypedModel typedModel = (TypedModel)classedModel;
073
074 referrerClassName = typedModel.getClassName();
075 }
076
077 long classPK = getClassPK(classedModel);
078
079 SystemEventHierarchyEntry systemEventHierarchyEntry =
080 SystemEventHierarchyEntryThreadLocal.peek();
081
082 if ((systemEventHierarchyEntry != null) &&
083 systemEventHierarchyEntry.hasTypedModel(className, classPK)) {
084
085 if (groupId > 0) {
086 SystemEventLocalServiceUtil.addSystemEvent(
087 0, groupId, systemEventHierarchyEntry.getClassName(),
088 classPK, systemEventHierarchyEntry.getUuid(),
089 referrerClassName, systemEvent.type(),
090 systemEventHierarchyEntry.getExtraData());
091 }
092 else {
093 SystemEventLocalServiceUtil.addSystemEvent(
094 getCompanyId(classedModel),
095 systemEventHierarchyEntry.getClassName(), classPK,
096 systemEventHierarchyEntry.getUuid(), referrerClassName,
097 systemEvent.type(),
098 systemEventHierarchyEntry.getExtraData());
099 }
100 }
101 else if (groupId > 0) {
102 SystemEventLocalServiceUtil.addSystemEvent(
103 0, groupId, className, classPK, getUuid(classedModel),
104 referrerClassName, systemEvent.type(), StringPool.BLANK);
105 }
106 else {
107 SystemEventLocalServiceUtil.addSystemEvent(
108 getCompanyId(classedModel), className, classPK,
109 getUuid(classedModel), referrerClassName, systemEvent.type(),
110 StringPool.BLANK);
111 }
112 }
113
114 @Override
115 public Object before(MethodInvocation methodInvocation) throws Throwable {
116 SystemEvent systemEvent = findAnnotation(methodInvocation);
117
118 if (systemEvent == _nullSystemEvent) {
119 return null;
120 }
121
122 if (systemEvent.action() != SystemEventConstants.ACTION_NONE) {
123 if (!isValid(methodInvocation, PHASE_BEFORE)) {
124 return null;
125 }
126
127 Object[] arguments = methodInvocation.getArguments();
128
129 ClassedModel classedModel = (ClassedModel)arguments[0];
130
131 SystemEventHierarchyEntry systemEventHierarchyEntry =
132 SystemEventHierarchyEntryThreadLocal.push(
133 getClassName(classedModel), getClassPK(classedModel),
134 systemEvent.action());
135
136 if (systemEventHierarchyEntry != null) {
137 systemEventHierarchyEntry.setUuid(getUuid(classedModel));
138 }
139 }
140
141 return null;
142 }
143
144 @Override
145 public void duringFinally(MethodInvocation methodInvocation) {
146 SystemEvent systemEvent = findAnnotation(methodInvocation);
147
148 if (systemEvent == _nullSystemEvent) {
149 return;
150 }
151
152 if (!isValid(methodInvocation, PHASE_DURING_FINALLY)) {
153 return;
154 }
155
156 if (systemEvent.action() == SystemEventConstants.ACTION_NONE) {
157 return;
158 }
159
160 Object[] arguments = methodInvocation.getArguments();
161
162 ClassedModel classedModel = (ClassedModel)arguments[0];
163
164 long classPK = getClassPK(classedModel);
165
166 if (classPK == 0) {
167 return;
168 }
169
170 SystemEventHierarchyEntryThreadLocal.pop(
171 getClassName(classedModel), classPK);
172 }
173
174 @Override
175 public SystemEvent getNullAnnotation() {
176 return _nullSystemEvent;
177 }
178
179 protected String getClassName(ClassedModel classedModel) {
180 String className = classedModel.getModelClassName();
181
182 if (classedModel instanceof StagedModel) {
183 StagedModel stagedModel = (StagedModel)classedModel;
184
185 StagedModelType stagedModelType = stagedModel.getStagedModelType();
186
187 className = stagedModelType.getClassName();
188 }
189
190 return className;
191 }
192
193 protected long getClassPK(ClassedModel classedModel) {
194 Serializable primaryKeyObj = classedModel.getPrimaryKeyObj();
195
196 if (!(primaryKeyObj instanceof Long)) {
197 return 0;
198 }
199
200 return (Long)primaryKeyObj;
201 }
202
203 protected long getCompanyId(ClassedModel classedModel) {
204 if (classedModel instanceof AuditedModel) {
205 AuditedModel auditedModel = (AuditedModel)classedModel;
206
207 return auditedModel.getCompanyId();
208 }
209
210 if (classedModel instanceof GroupedModel) {
211 GroupedModel groupedModel = (GroupedModel)classedModel;
212
213 return groupedModel.getCompanyId();
214 }
215
216 if (classedModel instanceof StagedModel) {
217 StagedModel stagedModel = (StagedModel)classedModel;
218
219 return stagedModel.getCompanyId();
220 }
221
222 return 0;
223 }
224
225 protected long getGroupId(ClassedModel classedModel) {
226 if (!(classedModel instanceof GroupedModel)) {
227 return 0;
228 }
229
230 GroupedModel groupedModel = (GroupedModel)classedModel;
231
232 return groupedModel.getGroupId();
233 }
234
235 protected String getUuid(ClassedModel classedModel) throws Exception {
236 String uuid = null;
237
238 if (classedModel instanceof StagedModel) {
239 StagedModel stagedModel = (StagedModel)classedModel;
240
241 uuid = stagedModel.getUuid();
242 }
243 else {
244 Class<?> modelClass = classedModel.getClass();
245
246 Method getUuidMethod = modelClass.getMethod(
247 "getUuid", new Class[0]);
248
249 if (getUuidMethod != null) {
250 uuid = (String)getUuidMethod.invoke(
251 classedModel, new Object[0]);
252 }
253 else {
254 uuid = StringPool.BLANK;
255 }
256 }
257
258 return uuid;
259 }
260
261 protected boolean isValid(MethodInvocation methodInvocation, int phase) {
262 Method method = methodInvocation.getMethod();
263
264 Class<?>[] parameterTypes = method.getParameterTypes();
265
266 if (parameterTypes.length == 0) {
267 if (_log.isDebugEnabled() && (phase == PHASE_BEFORE)) {
268 _log.debug(
269 "The method " + methodInvocation +
270 " must have at least one parameter");
271 }
272
273 return false;
274 }
275
276 Class<?> parameterType = parameterTypes[0];
277
278 if (!ClassedModel.class.isAssignableFrom(parameterType)) {
279 if (_log.isDebugEnabled() && (phase == PHASE_BEFORE)) {
280 _log.debug(
281 "The first parameter of " + methodInvocation +
282 " must implement ClassedModel");
283 }
284
285 return false;
286 }
287
288 Object[] arguments = methodInvocation.getArguments();
289
290 ClassedModel classedModel = (ClassedModel)arguments[0];
291
292 if ((classedModel == null) ||
293 !(classedModel.getPrimaryKeyObj() instanceof Long)) {
294
295 if (_log.isDebugEnabled() && (phase == PHASE_BEFORE)) {
296 _log.debug(
297 "The first parameter of " + methodInvocation +
298 " must be a long");
299 }
300
301 return false;
302 }
303
304 if (phase != PHASE_AFTER_RETURNING) {
305 return true;
306 }
307
308 if (!AuditedModel.class.isAssignableFrom(parameterType) &&
309 !GroupedModel.class.isAssignableFrom(parameterType) &&
310 !StagedModel.class.isAssignableFrom(parameterType)) {
311
312 if (_log.isDebugEnabled()) {
313 StringBundler sb = new StringBundler(4);
314
315 sb.append("If send is true, the first parameter of ");
316 sb.append(methodInvocation);
317 sb.append(" must implement AuditedModel, GroupedModel, or ");
318 sb.append("StagedModel");
319
320 _log.debug(sb.toString());
321 }
322
323 return false;
324 }
325
326 return true;
327 }
328
329 private static final int PHASE_AFTER_RETURNING = 1;
330
331 private static final int PHASE_BEFORE = 0;
332
333 private static final int PHASE_DURING_FINALLY = 2;
334
335 private static Log _log = LogFactoryUtil.getLog(SystemEventAdvice.class);
336
337 private static SystemEvent _nullSystemEvent = new SystemEvent() {
338
339 @Override
340 public Class<? extends Annotation> annotationType() {
341 return SystemEvent.class;
342 }
343
344 @Override
345 public int action() {
346 return SystemEventConstants.ACTION_NONE;
347 }
348
349 @Override
350 public boolean send() {
351 return false;
352 }
353
354 @Override
355 public int type() {
356 return 0;
357 }
358
359 };
360
361 }