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