首页

基于apache的tomcat应用如何实现项目扫描加载/WEB-INF/lib/下的所有jar文件的源码分析

标签:tomcat-util,apache,JarInputStream,JarEntry,ZipEntry,jar扫描     发布时间:2017-12-22   

一、前言

对于apache-tomcat的应用服务器项目应用基于其tomcat-util包中实现web项目/WEB-INF/lib/依赖包加载解析,主要实现功能是org.apache.tomcat.util.scan包路径下,主要涉及代码有org.apache.tomcat.util.scan.StandardJarScanner、org.apache.tomcat.util.scan.Jar、org.apache.tomcat.JarScanner等

二、源码说明

1.org.apache.tomcat.util.scan.Constants配置

package org.apache.tomcat.util.scan;@b@@b@public final class Constants@b@{@b@  public static final String Package = "org.apache.tomcat.util.scan";@b@  public static final String SKIP_JARS_PROPERTY = "tomcat.util.scan.DefaultJarScanner.jarsToSkip";@b@  public static final String JAR_EXT = ".jar";@b@  public static final String WEB_INF_LIB = "/WEB-INF/lib/";@b@  public static final String MERGED_WEB_XML = "org.apache.tomcat.util.scan.MergedWebXml";@b@}

2.org.apache.tomcat.JarScanner接口

package org.apache.tomcat;@b@@b@import java.util.Set;@b@import javax.servlet.ServletContext;@b@@b@public abstract interface JarScanner@b@{@b@  public abstract void scan(ServletContext paramServletContext, ClassLoader paramClassLoader, JarScannerCallback paramJarScannerCallback, Set<String> paramSet);@b@}

3.标准接口实现类StandardJarScanner

package org.apache.tomcat.util.scan;@b@@b@import java.io.File;@b@import java.io.IOException;@b@import java.net.JarURLConnection;@b@import java.net.URI;@b@import java.net.URISyntaxException;@b@import java.net.URL;@b@import java.net.URLClassLoader;@b@import java.net.URLConnection;@b@import java.util.HashSet;@b@import java.util.Iterator;@b@import java.util.Set;@b@import java.util.StringTokenizer;@b@import javax.servlet.ServletContext;@b@import org.apache.juli.logging.Log;@b@import org.apache.juli.logging.LogFactory;@b@import org.apache.tomcat.JarScanner;@b@import org.apache.tomcat.JarScannerCallback;@b@import org.apache.tomcat.util.file.Matcher;@b@import org.apache.tomcat.util.res.StringManager;@b@@b@public class StandardJarScanner@b@  implements JarScanner@b@{@b@  private static final Log log = LogFactory.getLog(StandardJarScanner.class);@b@  private static final Set<String> defaultJarsToSkip = new HashSet();@b@  private static final StringManager sm = StringManager.getManager("org.apache.tomcat.util.scan");@b@  private boolean scanClassPath;@b@  private boolean scanAllFiles;@b@  private boolean scanAllDirectories;@b@  private boolean scanBootstrapClassPath;@b@@b@  public StandardJarScanner()@b@  {@b@    this.scanClassPath = true;@b@@b@    this.scanAllFiles = false;@b@@b@    this.scanAllDirectories = false;@b@@b@    this.scanBootstrapClassPath = false;@b@  }@b@@b@  public boolean isScanClassPath()@b@  {@b@    return this.scanClassPath; }@b@@b@  public void setScanClassPath(boolean scanClassPath) {@b@    this.scanClassPath = scanClassPath;@b@  }@b@@b@  public boolean isScanAllFiles()@b@  {@b@    return this.scanAllFiles; }@b@@b@  public void setScanAllFiles(boolean scanAllFiles) {@b@    this.scanAllFiles = scanAllFiles;@b@  }@b@@b@  public boolean isScanAllDirectories()@b@  {@b@    return this.scanAllDirectories; }@b@@b@  public void setScanAllDirectories(boolean scanAllDirectories) {@b@    this.scanAllDirectories = scanAllDirectories;@b@  }@b@@b@  public boolean isScanBootstrapClassPath()@b@  {@b@    return this.scanBootstrapClassPath; }@b@@b@  public void setScanBootstrapClassPath(boolean scanBootstrapClassPath) {@b@    this.scanBootstrapClassPath = scanBootstrapClassPath;@b@  }@b@@b@  public void scan(ServletContext context, ClassLoader classloader, JarScannerCallback callback, Set<String> jarsToSkip)@b@  {@b@    Set ignoredJars;@b@    if (log.isTraceEnabled()) {@b@      log.trace(sm.getString("jarScan.webinflibStart"));@b@    }@b@@b@    if (jarsToSkip == null)@b@      ignoredJars = defaultJarsToSkip;@b@    else {@b@      ignoredJars = jarsToSkip;@b@    }@b@@b@    Set dirList = context.getResourcePaths("/WEB-INF/lib/");@b@    if (dirList != null) {@b@      Iterator it = dirList.iterator();@b@      while (it.hasNext()) {@b@        String path = (String)it.next();@b@        if ((path.endsWith(".jar")) && (!(Matcher.matchName(ignoredJars, path.substring(path.lastIndexOf(47) + 1)))))@b@        {@b@          if (log.isDebugEnabled())@b@            log.debug(sm.getString("jarScan.webinflibJarScan", new Object[] { path }));@b@@b@          URL url = null;@b@          try@b@          {@b@            String realPath = context.getRealPath(path);@b@            if (realPath == null)@b@              url = context.getResource(path);@b@            else@b@              url = new File(realPath).toURI().toURL();@b@@b@            process(callback, url);@b@          } catch (IOException e) {@b@            log.warn(sm.getString("jarScan.webinflibFail", new Object[] { url }), e);@b@          }@b@        }@b@        else if (log.isTraceEnabled()) {@b@          log.trace(sm.getString("jarScan.webinflibJarNoScan", new Object[] { path }));@b@        }@b@@b@      }@b@@b@    }@b@@b@    if ((this.scanClassPath) && (classloader != null)) {@b@      if (log.isTraceEnabled()) {@b@        log.trace(sm.getString("jarScan.classloaderStart"));@b@      }@b@@b@      ClassLoader loader = classloader;@b@@b@      ClassLoader stopLoader = null;@b@      if (!(this.scanBootstrapClassPath))@b@      {@b@        stopLoader = ClassLoader.getSystemClassLoader().getParent();@b@      }@b@@b@      while ((loader != null) && (loader != stopLoader)) {@b@        URL[] urls;@b@        int i;@b@        if (loader instanceof URLClassLoader) {@b@          urls = ((URLClassLoader)loader).getURLs();@b@          for (i = 0; i < urls.length; ++i)@b@          {@b@            String jarName = getJarName(urls[i]);@b@@b@            if ((jarName != null) && (!(Matcher.matchName(ignoredJars, jarName))) && (!(urls[i].toString().contains("/WEB-INF/lib/" + jarName))))@b@            {@b@              if (log.isDebugEnabled())@b@                log.debug(sm.getString("jarScan.classloaderJarScan", new Object[] { urls[i] }));@b@              try@b@              {@b@                process(callback, urls[i]);@b@              } catch (IOException ioe) {@b@                log.warn(sm.getString("jarScan.classloaderFail", new Object[] { urls[i] }), ioe);@b@              }@b@@b@            }@b@            else if (log.isTraceEnabled()) {@b@              log.trace(sm.getString("jarScan.classloaderJarNoScan", new Object[] { urls[i] }));@b@            }@b@          }@b@        }@b@@b@        loader = loader.getParent();@b@      }@b@    }@b@  }@b@@b@  private void process(JarScannerCallback callback, URL url)@b@    throws IOException@b@  {@b@    if (log.isTraceEnabled()) {@b@      log.trace(sm.getString("jarScan.jarUrlStart", new Object[] { url }));@b@    }@b@@b@    URLConnection conn = url.openConnection();@b@    if (conn instanceof JarURLConnection) {@b@      callback.scan((JarURLConnection)conn);@b@    } else {@b@      String urlStr = url.toString();@b@      if ((urlStr.startsWith("file:")) || (urlStr.startsWith("jndi:")) || (urlStr.startsWith("http:")) || (urlStr.startsWith("https:")))@b@      {@b@        if (urlStr.endsWith(".jar")) {@b@          URL jarURL = new URL("jar:" + urlStr + "!/");@b@          callback.scan((JarURLConnection)jarURL.openConnection());@b@        }@b@        else {@b@          try {@b@            File f = new File(url.toURI());@b@            if ((f.isFile()) && (this.scanAllFiles))@b@            {@b@              URL jarURL = new URL("jar:" + urlStr + "!/");@b@              callback.scan((JarURLConnection)jarURL.openConnection());@b@            } else if ((f.isDirectory()) && (this.scanAllDirectories)) {@b@              File metainf = new File(f.getAbsoluteFile() + File.separator + "META-INF");@b@@b@              if (metainf.isDirectory())@b@                callback.scan(f);@b@            }@b@          }@b@          catch (URISyntaxException e)@b@          {@b@            IOException ioe = new IOException();@b@            ioe.initCause(e);@b@            throw ioe;@b@          }@b@        }@b@      }@b@    }@b@  }@b@@b@  private String getJarName(URL url)@b@  {@b@    int start;@b@    String name = null;@b@@b@    String path = url.getPath();@b@    int end = path.indexOf(".jar");@b@    if (end != -1) {@b@      start = path.lastIndexOf(47, end);@b@      name = path.substring(start + 1, end + 4);@b@    } else if (isScanAllDirectories()) {@b@      start = path.lastIndexOf(47);@b@      name = path.substring(start + 1);@b@    }@b@@b@    return name;@b@  }@b@@b@  static@b@  {@b@    String jarList = System.getProperty("tomcat.util.scan.DefaultJarScanner.jarsToSkip");@b@    if (jarList != null) {@b@      StringTokenizer tokenizer = new StringTokenizer(jarList, ",");@b@      while (tokenizer.hasMoreElements()) {@b@        String token = tokenizer.nextToken().trim();@b@        if (token.length() > 0)@b@          defaultJarsToSkip.add(token);@b@      }@b@    }@b@  }@b@}