/*
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.interceptor.factory;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentContext;
import com.navercorp.pinpoint.bootstrap.interceptor.ApiIdAwareAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor0;
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor1;
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor2;
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor3;
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor4;
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor5;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleApiIdAwareAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleAroundInterceptor0;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleAroundInterceptor1;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleAroundInterceptor2;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleAroundInterceptor3;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleAroundInterceptor4;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleAroundInterceptor5;
import com.navercorp.pinpoint.bootstrap.interceptor.ExceptionHandleStaticAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.StaticAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.annotation.Scope;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExceptionHandleScopedApiIdAwareAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExceptionHandleScopedInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExceptionHandleScopedInterceptor0;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExceptionHandleScopedInterceptor1;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExceptionHandleScopedInterceptor2;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExceptionHandleScopedInterceptor3;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExceptionHandleScopedInterceptor4;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExceptionHandleScopedInterceptor5;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExceptionHandleScopedStaticAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ExecutionPolicy;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ScopedApiIdAwareAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ScopedInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ScopedInterceptor0;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ScopedInterceptor1;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ScopedInterceptor2;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ScopedInterceptor3;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ScopedInterceptor4;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ScopedInterceptor5;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.ScopedStaticAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.scope.InterceptorScope;
import com.navercorp.pinpoint.bootstrap.plugin.ObjectFactory;
import com.navercorp.pinpoint.bootstrap.plugin.monitor.DataSourceMonitorRegistry;
import com.navercorp.pinpoint.profiler.metadata.ApiMetaDataService;
import com.navercorp.pinpoint.profiler.objectfactory.AutoBindingObjectFactory;
import com.navercorp.pinpoint.profiler.objectfactory.InterceptorArgumentProvider;
/**
* @author Jongho Moon
* @author jaehong.kim
*/
public class AnnotatedInterceptorFactory implements InterceptorFactory {
private final ProfilerConfig profilerConfig;
private final TraceContext traceContext;
private final DataSourceMonitorRegistry dataSourceMonitorRegistry;
private final ApiMetaDataService apiMetaDataService;
private final InstrumentContext pluginContext;
private final boolean exceptionHandle;
public AnnotatedInterceptorFactory(ProfilerConfig profilerConfig, TraceContext traceContext, DataSourceMonitorRegistry dataSourceMonitorRegistry, ApiMetaDataService apiMetaDataService, InstrumentContext pluginContext, boolean exceptionHandle) {
if (profilerConfig == null) {
throw new NullPointerException("profilerConfig must not be null");
}
if (traceContext == null) {
throw new NullPointerException("traceContext must not be null");
}
if (dataSourceMonitorRegistry == null) {
throw new NullPointerException("dataSourceMonitorRegistry must not be null");
}
if (apiMetaDataService == null) {
throw new NullPointerException("apiMetaDataService must not be null");
}
if (pluginContext == null) {
throw new NullPointerException("pluginContext must not be null");
}
this.profilerConfig = profilerConfig;
this.traceContext = traceContext;
this.dataSourceMonitorRegistry = dataSourceMonitorRegistry;
this.apiMetaDataService = apiMetaDataService;
this.pluginContext = pluginContext;
this.exceptionHandle = exceptionHandle;
}
@Override
public Interceptor getInterceptor(ClassLoader classLoader, String interceptorClassName, Object[] providedArguments, InterceptorScope scope, ExecutionPolicy policy, InstrumentClass target, InstrumentMethod targetMethod) {
Class<? extends Interceptor> interceptorType = pluginContext.injectClass(classLoader, interceptorClassName);
if (scope == null) {
Scope interceptorScope = interceptorType.getAnnotation(Scope.class);
if (interceptorScope != null) {
String scopeName = interceptorScope.value();
scope = pluginContext.getInterceptorScope(scopeName);
policy = interceptorScope.executionPolicy();
}
}
AutoBindingObjectFactory factory = new AutoBindingObjectFactory(profilerConfig, traceContext, pluginContext, classLoader);
ObjectFactory objectFactory = ObjectFactory.byConstructor(interceptorClassName, providedArguments);
InterceptorArgumentProvider interceptorArgumentProvider = new InterceptorArgumentProvider(dataSourceMonitorRegistry, apiMetaDataService, scope, target, targetMethod);
Interceptor interceptor = (Interceptor) factory.createInstance(objectFactory, interceptorArgumentProvider);
if (scope != null) {
if (exceptionHandle) {
interceptor = wrapByExceptionHandleScope(interceptor, scope, policy == null ? ExecutionPolicy.BOUNDARY : policy);
} else {
interceptor = wrapByScope(interceptor, scope, policy == null ? ExecutionPolicy.BOUNDARY : policy);
}
} else {
if (exceptionHandle) {
interceptor = wrapByExceptionHandle(interceptor);
}
}
return interceptor;
}
private Interceptor wrapByScope(Interceptor interceptor, InterceptorScope scope, ExecutionPolicy policy) {
if (interceptor instanceof AroundInterceptor) {
return new ScopedInterceptor((AroundInterceptor) interceptor, scope, policy);
} else if (interceptor instanceof StaticAroundInterceptor) {
return new ScopedStaticAroundInterceptor((StaticAroundInterceptor) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor5) {
return new ScopedInterceptor5((AroundInterceptor5) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor4) {
return new ScopedInterceptor4((AroundInterceptor4) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor3) {
return new ScopedInterceptor3((AroundInterceptor3) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor2) {
return new ScopedInterceptor2((AroundInterceptor2) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor1) {
return new ScopedInterceptor1((AroundInterceptor1) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor0) {
return new ScopedInterceptor0((AroundInterceptor0) interceptor, scope, policy);
} else if (interceptor instanceof ApiIdAwareAroundInterceptor) {
return new ScopedApiIdAwareAroundInterceptor((ApiIdAwareAroundInterceptor) interceptor, scope, policy);
}
throw new IllegalArgumentException("Unexpected interceptor type: " + interceptor.getClass());
}
private Interceptor wrapByExceptionHandleScope(Interceptor interceptor, InterceptorScope scope, ExecutionPolicy policy) {
if (interceptor instanceof AroundInterceptor) {
return new ExceptionHandleScopedInterceptor((AroundInterceptor) interceptor, scope, policy);
} else if (interceptor instanceof StaticAroundInterceptor) {
return new ExceptionHandleScopedStaticAroundInterceptor((StaticAroundInterceptor) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor5) {
return new ExceptionHandleScopedInterceptor5((AroundInterceptor5) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor4) {
return new ExceptionHandleScopedInterceptor4((AroundInterceptor4) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor3) {
return new ExceptionHandleScopedInterceptor3((AroundInterceptor3) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor2) {
return new ExceptionHandleScopedInterceptor2((AroundInterceptor2) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor1) {
return new ExceptionHandleScopedInterceptor1((AroundInterceptor1) interceptor, scope, policy);
} else if (interceptor instanceof AroundInterceptor0) {
return new ExceptionHandleScopedInterceptor0((AroundInterceptor0) interceptor, scope, policy);
} else if (interceptor instanceof ApiIdAwareAroundInterceptor) {
return new ExceptionHandleScopedApiIdAwareAroundInterceptor((ApiIdAwareAroundInterceptor) interceptor, scope, policy);
}
throw new IllegalArgumentException("Unexpected interceptor type: " + interceptor.getClass());
}
private Interceptor wrapByExceptionHandle(Interceptor interceptor) {
if (interceptor instanceof AroundInterceptor) {
return new ExceptionHandleAroundInterceptor((AroundInterceptor) interceptor);
} else if (interceptor instanceof StaticAroundInterceptor) {
return new ExceptionHandleStaticAroundInterceptor((StaticAroundInterceptor) interceptor);
} else if (interceptor instanceof AroundInterceptor5) {
return new ExceptionHandleAroundInterceptor5((AroundInterceptor5) interceptor);
} else if (interceptor instanceof AroundInterceptor4) {
return new ExceptionHandleAroundInterceptor4((AroundInterceptor4) interceptor);
} else if (interceptor instanceof AroundInterceptor3) {
return new ExceptionHandleAroundInterceptor3((AroundInterceptor3) interceptor);
} else if (interceptor instanceof AroundInterceptor2) {
return new ExceptionHandleAroundInterceptor2((AroundInterceptor2) interceptor);
} else if (interceptor instanceof AroundInterceptor1) {
return new ExceptionHandleAroundInterceptor1((AroundInterceptor1) interceptor);
} else if (interceptor instanceof AroundInterceptor0) {
return new ExceptionHandleAroundInterceptor0((AroundInterceptor0) interceptor);
} else if (interceptor instanceof ApiIdAwareAroundInterceptor) {
return new ExceptionHandleApiIdAwareAroundInterceptor((ApiIdAwareAroundInterceptor) interceptor);
}
throw new IllegalArgumentException("Unexpected interceptor type: " + interceptor.getClass());
}
}