package com.navercorp.pinpoint.plugin.resin.interceptor; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.servlet.ServletContext; import com.navercorp.pinpoint.bootstrap.context.ServerMetaDataHolder; import com.navercorp.pinpoint.bootstrap.context.TraceContext; import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor; import com.navercorp.pinpoint.bootstrap.logging.PLogger; import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; import com.navercorp.pinpoint.common.util.StringUtils; /** * * @author huangpengjie@fang.com * */ public class WebAppInterceptor implements AroundInterceptor { private PLogger logger = PLoggerFactory.getLogger(this.getClass()); private final boolean isDebug = logger.isDebugEnabled(); private final TraceContext traceContext; public WebAppInterceptor(TraceContext traceContext) { super(); this.traceContext = traceContext; } @Override public void before(Object target, Object[] args) { // DO nothing } @Override public void after(Object target, Object[] args, Object result, Throwable throwable) { if (isDebug) { logger.afterInterceptor(target, args, result, throwable); } if (target instanceof ServletContext) { ServletContext servletContext = (ServletContext) target; try { String contextKey = extractContextKey(servletContext); List<String> loadedJarNames = extractLibJars(servletContext); if (isDebug) { logger.debug("{} jars : {}", contextKey, Arrays.toString(loadedJarNames.toArray())); } dispatchLibJars(contextKey, loadedJarNames, servletContext); } catch (Exception e) { logger.warn(e.getMessage(), e); } } else { logger.warn("Webapp loader is not an instance of javax.servlet.ServletContext , Found [{}]", target.getClass().toString()); } } private String extractContextKey(ServletContext webapp) { String context = webapp.getContextPath(); return StringUtils.isEmpty(context) ? "/ROOT" : context; } private List<String> extractLibJarNamesFromURLs(URL[] urls) { if (urls == null) { return Collections.emptyList(); } List<String> libJarNames = new ArrayList<String>(urls.length); for (URL url : urls) { try { URI uri = url.toURI(); String libJarName = extractLibJarName(uri); if (libJarName.length() > 0) { libJarNames.add(libJarName); } } catch (URISyntaxException e) { // ignore invalid formats logger.warn("Invalid library url found : [{}]", url, e); } catch (Exception e) { logger.warn("Error extracting library name", e); } } return libJarNames; } private String extractLibJarName(URI uri) { String jarName = uri.toString(); int lastIndexOfSeparator = jarName.lastIndexOf("/"); if (lastIndexOfSeparator < 0) { return jarName; } else { int lastIndexOfExclamatory = jarName.lastIndexOf("!"); if (lastIndexOfExclamatory == lastIndexOfSeparator - 1) { jarName = jarName.substring(0, lastIndexOfExclamatory); return jarName.substring(jarName.lastIndexOf("/") + 1); } else if (jarName.startsWith("jar:") || jarName.endsWith(".jar")) { return jarName.substring(lastIndexOfSeparator + 1); } else { return ""; } } } private void dispatchLibJars(String contextKey, List<String> libJars, ServletContext webapp) { ServerMetaDataHolder holder = this.traceContext.getServerMetaDataHolder(); holder.addServiceInfo(contextKey, libJars); holder.setServerName(webapp.getServerInfo()); holder.notifyListeners(); } private List<String> extractLibJars(ServletContext webapp) { ClassLoader classLoader = webapp.getClassLoader(); if (classLoader instanceof URLClassLoader) { URL[] urls = ((URLClassLoader) classLoader).getURLs(); return extractLibJarNamesFromURLs(urls); } else { return Collections.emptyList(); } } }