/* * Copyright 2016 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.test.classloader; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentContext; import com.navercorp.pinpoint.profiler.instrument.InstrumentEngine; import com.navercorp.pinpoint.profiler.instrument.ASMEngine; import com.navercorp.pinpoint.profiler.instrument.classloading.ClassInjector; import com.navercorp.pinpoint.profiler.instrument.classloading.DebugTransformerClassInjector; import com.navercorp.pinpoint.profiler.instrument.JavassistEngine; import com.navercorp.pinpoint.profiler.plugin.ClassFileTransformerLoader; import com.navercorp.pinpoint.profiler.plugin.MatchableClassFileTransformerGuardDelegate; import com.navercorp.pinpoint.profiler.plugin.PluginInstrumentContext; import com.navercorp.pinpoint.test.MockApplicationContext; import javassist.ClassPool; import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher; import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers; import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformCallback; import com.navercorp.pinpoint.common.util.Asserts; /** * @author emeroad * @author hyungil.jeong */ public class TestClassLoader extends TransformClassLoader { private final Logger logger = Logger.getLogger(TestClassLoader.class.getName()); private final MockApplicationContext applicationContext; private Translator instrumentTranslator; private final List<String> delegateClass; private final ClassFileTransformerLoader classFileTransformerLoader; private final InstrumentContext instrumentContext; public TestClassLoader(MockApplicationContext applicationContext) { Asserts.notNull(applicationContext, "applicationContext"); this.applicationContext = applicationContext; this.classFileTransformerLoader = new ClassFileTransformerLoader(applicationContext.getProfilerConfig(), applicationContext.getDynamicTransformTrigger()); // ClassInjector classInjector = new LegacyProfilerPluginClassInjector(getClass().getClassLoader()); ClassInjector classInjector = new DebugTransformerClassInjector(); this.instrumentContext = new PluginInstrumentContext(applicationContext.getProfilerConfig(), applicationContext.getInstrumentEngine(), applicationContext.getDynamicTransformTrigger(), classInjector, classFileTransformerLoader); this.delegateClass = new ArrayList<String>(); } public void addDelegateClass(String className) { if (className == null) { throw new NullPointerException("className must not be null"); } this.delegateClass.add(className); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { if (logger.isLoggable(Level.FINE)) { logger.fine("findClass className:{}" + name); } return super.findClass(name); } public void initialize() { addDefaultDelegateLoadingOf(); addCustomDelegateLoadingOf(); addTranslator(); } private void addCustomDelegateLoadingOf() { for (String className : delegateClass) { this.delegateLoadingOf(className); } } public ProfilerConfig getProfilerConfig() { return applicationContext.getProfilerConfig(); } public void addTransformer(final String targetClassName, final TransformCallback transformer) { if (logger.isLoggable(Level.FINE)) { logger.fine("addTransformer targetClassName:{}" + targetClassName + " callback:{}" + transformer); } final Matcher matcher = Matchers.newClassNameMatcher(targetClassName); final MatchableClassFileTransformerGuardDelegate guard = new MatchableClassFileTransformerGuardDelegate(applicationContext.getProfilerConfig(), instrumentContext, matcher, transformer); this.instrumentTranslator.addTransformer(guard); } private void addDefaultDelegateLoadingOf() { TestClassList testClassList = new TestClassList(); for (String className : testClassList.getTestClassList()) { this.delegateLoadingOf(className); } } @Override protected Class<?> loadClassByDelegation(String name) throws ClassNotFoundException { if (logger.isLoggable(Level.FINE)) { logger.fine("loadClassByDelegation className:{}" + name); } return super.loadClassByDelegation(name); } public void addTranslator() { final InstrumentEngine instrumentEngine = applicationContext.getInstrumentEngine(); if (instrumentEngine instanceof JavassistEngine) { logger.info("JAVASSIST BCI engine"); ClassPool classPool = ((JavassistEngine) instrumentEngine).getClassPool(this); this.instrumentTranslator = new JavassistTranslator(this, classPool, applicationContext.getClassFileTransformerDispatcher()); this.addTranslator(instrumentTranslator); } else if (instrumentEngine instanceof ASMEngine) { logger.info("ASM BCI engine"); this.instrumentTranslator = new DefaultTranslator(this, applicationContext.getClassFileTransformerDispatcher()); this.addTranslator(instrumentTranslator); } else { logger.info("Unknown BCI engine"); this.instrumentTranslator = new DefaultTranslator(this, applicationContext.getClassFileTransformerDispatcher()); this.addTranslator(instrumentTranslator); } } }