001    /**
002     * Copyright (c) 2000-present 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.monitoring.statistics.service;
016    
017    import com.liferay.portal.kernel.monitoring.DataSample;
018    import com.liferay.portal.kernel.monitoring.DataSampleThreadLocal;
019    import com.liferay.portal.kernel.monitoring.MethodSignature;
020    import com.liferay.portal.kernel.monitoring.RequestStatus;
021    import com.liferay.portal.kernel.monitoring.ServiceMonitoringControl;
022    import com.liferay.portal.kernel.util.AutoResetThreadLocal;
023    import com.liferay.portal.spring.aop.ChainableMethodAdvice;
024    
025    import java.lang.reflect.Method;
026    
027    import java.util.Collections;
028    import java.util.HashSet;
029    import java.util.Set;
030    
031    import org.aopalliance.intercept.MethodInvocation;
032    
033    /**
034     * @author Michael C. Han
035     */
036    public class ServiceMonitorAdvice
037            extends ChainableMethodAdvice implements ServiceMonitoringControl {
038    
039            @Override
040            public void addServiceClass(String className) {
041                    _serviceClasses.add(className);
042            }
043    
044            @Override
045            public void addServiceClassMethod(
046                    String className, String methodName, String[] parameterTypes) {
047    
048                    MethodSignature methodSignature = new MethodSignature(
049                            className, methodName, parameterTypes);
050    
051                    _serviceClassMethods.add(methodSignature);
052            }
053    
054            @Override
055            public void afterReturning(MethodInvocation methodInvocation, Object result)
056                    throws Throwable {
057    
058                    DataSample dataSample = _dataSampleThreadLocal.get();
059    
060                    if (dataSample != null) {
061                            dataSample.capture(RequestStatus.SUCCESS);
062                    }
063            }
064    
065            @Override
066            public void afterThrowing(
067                            MethodInvocation methodInvocation, Throwable throwable)
068                    throws Throwable {
069    
070                    DataSample dataSample = _dataSampleThreadLocal.get();
071    
072                    if (dataSample != null) {
073                            dataSample.capture(RequestStatus.ERROR);
074                    }
075            }
076    
077            @Override
078            public Object before(MethodInvocation methodInvocation) throws Throwable {
079                    if (!_monitorServiceRequest) {
080                            serviceBeanAopCacheManager.removeMethodInterceptor(
081                                    methodInvocation, this);
082    
083                            return null;
084                    }
085    
086                    boolean included = isIncluded(methodInvocation);
087    
088                    if ((!_inclusiveMode && included) || (_inclusiveMode && !included)) {
089                            return null;
090                    }
091    
092                    MethodSignature methodSignature = new MethodSignature(
093                            methodInvocation.getMethod());
094    
095                    DataSample dataSample =
096                            DataSampleFactoryUtil.createServiceRequestDataSample(
097                                    methodSignature);
098    
099                    dataSample.prepare();
100    
101                    _dataSampleThreadLocal.set(dataSample);
102    
103                    DataSampleThreadLocal.initialize();
104    
105                    return null;
106            }
107    
108            @Override
109            public void duringFinally(MethodInvocation methodInvocation) {
110                    DataSample dataSample = _dataSampleThreadLocal.get();
111    
112                    if (dataSample!= null) {
113                            _dataSampleThreadLocal.remove();
114    
115                            DataSampleThreadLocal.addDataSample(dataSample);
116                    }
117            }
118    
119            @Override
120            public Set<String> getServiceClasses() {
121                    return Collections.unmodifiableSet(_serviceClasses);
122            }
123    
124            @Override
125            public Set<MethodSignature> getServiceClassMethods() {
126                    return Collections.unmodifiableSet(_serviceClassMethods);
127            }
128    
129            @Override
130            public boolean isInclusiveMode() {
131                    return _inclusiveMode;
132            }
133    
134            @Override
135            public boolean isMonitorServiceRequest() {
136                    return _monitorServiceRequest;
137            }
138    
139            @Override
140            public void setInclusiveMode(boolean inclusiveMode) {
141                    _inclusiveMode = inclusiveMode;
142            }
143    
144            @Override
145            public void setMonitorServiceRequest(boolean monitorServiceRequest) {
146                    if (monitorServiceRequest && !_monitorServiceRequest) {
147                            serviceBeanAopCacheManager.reset();
148                    }
149    
150                    _monitorServiceRequest = monitorServiceRequest;
151            }
152    
153            protected boolean isIncluded(MethodInvocation methodInvocation) {
154                    Method method = methodInvocation.getMethod();
155    
156                    Class<?> declaringClass = method.getDeclaringClass();
157    
158                    String className = declaringClass.getName();
159    
160                    if (_serviceClasses.contains(className)) {
161                            return true;
162                    }
163    
164                    MethodSignature methodSignature = new MethodSignature(method);
165    
166                    if (_serviceClassMethods.contains(methodSignature)) {
167                            return true;
168                    }
169    
170                    return false;
171            }
172    
173            private static final ThreadLocal<DataSample> _dataSampleThreadLocal =
174                    new AutoResetThreadLocal<>(
175                            ServiceMonitorAdvice.class + "._dataSampleThreadLocal");
176            private static boolean _inclusiveMode = true;
177            private static boolean _monitorServiceRequest;
178            private static final Set<String> _serviceClasses = new HashSet<>();
179            private static final Set<MethodSignature> _serviceClassMethods =
180                    new HashSet<>();
181    
182    }