/* * Copyright 2017 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.instrument.classloading; import com.navercorp.pinpoint.bootstrap.classloader.LibClass; import com.navercorp.pinpoint.bootstrap.classloader.PinpointClassLoaderFactory; import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin; import com.navercorp.pinpoint.common.util.ClassLoaderUtils; import com.navercorp.pinpoint.profiler.plugin.PluginConfig; import com.navercorp.pinpoint.profiler.plugin.PluginPackageFilter; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Constructor; import java.net.URL; import java.net.URLClassLoader; import java.security.CodeSource; import java.util.Arrays; /** * @author Woonduk Kang(emeroad) */ public class JarProfilerPluginClassInjectorTest { public static final String CONTEXT_TYPE_MATCH_CLASS_LOADER = "org.springframework.context.support.ContextTypeMatchClassLoader"; private final Logger logger = LoggerFactory.getLogger(this.getClass()); private static final String LOG4_IMPL = "org.slf4j.impl"; @Test public void testInjectClass() throws Exception { final URL sampleJar = getSampleJar("org.slf4j.impl.Log4jLoggerAdapter"); final ClassLoader contextTypeMatchClassLoader = createContextTypeMatchClassLoader(new URL[]{sampleJar}); final ProfilerPlugin profilerPlugin = Mockito.mock(ProfilerPlugin.class); final PluginPackageFilter pluginPackageFilter = new PluginPackageFilter(Arrays.asList(LOG4_IMPL)); PluginConfig pluginConfig = new PluginConfig(sampleJar, pluginPackageFilter); logger.debug("pluginConfig:{}", pluginConfig); PlainClassLoaderHandler injector = new PlainClassLoaderHandler(pluginConfig); final Class<?> loggerClass = injector.injectClass(contextTypeMatchClassLoader, logger.getClass().getName()); logger.debug("ClassLoader{}", loggerClass.getClassLoader()); Assert.assertEquals("check className", loggerClass.getName(), "org.slf4j.impl.Log4jLoggerAdapter"); Assert.assertEquals("check ClassLoader", loggerClass.getClassLoader().getClass().getName(), CONTEXT_TYPE_MATCH_CLASS_LOADER); } private ClassLoader createContextTypeMatchClassLoader(URL[] urlArray) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException { final ClassLoader classLoader = this.getClass().getClassLoader(); final Class<ClassLoader> aClass = (Class<ClassLoader>) classLoader.loadClass(CONTEXT_TYPE_MATCH_CLASS_LOADER); final Constructor<ClassLoader> constructor = aClass.getConstructor(ClassLoader.class); ReflectionUtils.makeAccessible(constructor); final LibClass libClassFilter = new LibClass() { @Override public boolean onLoadClass(String clazzName) { if (clazzName.startsWith(LOG4_IMPL)) { logger.debug("Loading {}", clazzName); return ON_LOAD_CLASS; } return DELEGATE_PARENT; } }; URLClassLoader testClassLoader = PinpointClassLoaderFactory.createClassLoader(urlArray, ClassLoader.getSystemClassLoader(), libClassFilter); final ClassLoader contextTypeMatchClassLoader = constructor.newInstance(testClassLoader); logger.debug("cl:{}",contextTypeMatchClassLoader); // final Method excludePackage = aClass.getMethod("excludePackage", String.class); // ReflectionUtils.invokeMethod(excludePackage, contextTypeMatchClassLoader, "org.slf4j"); return contextTypeMatchClassLoader; } private URL getSampleJar(String className) { ClassLoader cl = ClassLoaderUtils.getDefaultClassLoader(); Class<?> clazz = null; try { clazz = cl.loadClass(className); } catch (ClassNotFoundException ex) { throw new RuntimeException(className + " class not found. Caused by:" + ex.getMessage(), ex); } return getSampleJar(clazz); } private URL getSampleJar(Class clazz) { final CodeSource codeSource = clazz.getProtectionDomain().getCodeSource(); final URL location = codeSource.getLocation(); logger.debug("url:{}", location); return location; } }