| // |
| // ======================================================================== |
| // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.webapp; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.net.URLClassLoader; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Set; |
| import java.util.StringTokenizer; |
| import java.util.regex.Pattern; |
| |
| import org.eclipse.jetty.server.Connector; |
| import org.eclipse.jetty.server.NetworkConnector; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.util.IO; |
| import org.eclipse.jetty.util.PatternMatcher; |
| import org.eclipse.jetty.util.URIUtil; |
| import org.eclipse.jetty.util.log.Log; |
| import org.eclipse.jetty.util.log.Logger; |
| import org.eclipse.jetty.util.resource.JarResource; |
| import org.eclipse.jetty.util.resource.Resource; |
| import org.eclipse.jetty.util.resource.ResourceCollection; |
| |
| public class WebInfConfiguration extends AbstractConfiguration |
| { |
| private static final Logger LOG = Log.getLogger(WebInfConfiguration.class); |
| |
| public static final String TEMPDIR_CONFIGURED = "org.eclipse.jetty.tmpdirConfigured"; |
| public static final String CONTAINER_JAR_PATTERN = "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern"; |
| public static final String WEBINF_JAR_PATTERN = "org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern"; |
| |
| /** |
| * If set, to a list of URLs, these resources are added to the context |
| * resource base as a resource collection. |
| */ |
| public static final String RESOURCE_DIRS = "org.eclipse.jetty.resources"; |
| |
| |
| protected Resource _preUnpackBaseResource; |
| |
| |
| |
| @Override |
| public void preConfigure(final WebAppContext context) throws Exception |
| { |
| //Make a temp directory for the webapp if one is not already set |
| resolveTempDirectory(context); |
| |
| //Extract webapp if necessary |
| unpack (context); |
| |
| |
| //Apply an initial ordering to the jars which governs which will be scanned for META-INF |
| //info and annotations. The ordering is based on inclusion patterns. |
| String tmp = (String)context.getAttribute(WEBINF_JAR_PATTERN); |
| Pattern webInfPattern = (tmp==null?null:Pattern.compile(tmp)); |
| tmp = (String)context.getAttribute(CONTAINER_JAR_PATTERN); |
| Pattern containerPattern = (tmp==null?null:Pattern.compile(tmp)); |
| |
| //Apply ordering to container jars - if no pattern is specified, we won't |
| //match any of the container jars |
| PatternMatcher containerJarNameMatcher = new PatternMatcher () |
| { |
| public void matched(URI uri) throws Exception |
| { |
| context.getMetaData().addContainerResource(Resource.newResource(uri)); |
| } |
| }; |
| ClassLoader loader = null; |
| if (context.getClassLoader() != null) |
| loader = context.getClassLoader().getParent(); |
| |
| while (loader != null && (loader instanceof URLClassLoader)) |
| { |
| URL[] urls = ((URLClassLoader)loader).getURLs(); |
| if (urls != null) |
| { |
| URI[] containerUris = new URI[urls.length]; |
| int i=0; |
| for (URL u : urls) |
| { |
| try |
| { |
| containerUris[i] = u.toURI(); |
| } |
| catch (URISyntaxException e) |
| { |
| containerUris[i] = new URI(u.toString().replaceAll(" ", "%20")); |
| } |
| i++; |
| } |
| containerJarNameMatcher.match(containerPattern, containerUris, false); |
| } |
| loader = loader.getParent(); |
| } |
| |
| //Apply ordering to WEB-INF/lib jars |
| PatternMatcher webInfJarNameMatcher = new PatternMatcher () |
| { |
| @Override |
| public void matched(URI uri) throws Exception |
| { |
| context.getMetaData().addWebInfJar(Resource.newResource(uri)); |
| } |
| }; |
| List<Resource> jars = findJars(context); |
| |
| //Convert to uris for matching |
| URI[] uris = null; |
| if (jars != null) |
| { |
| uris = new URI[jars.size()]; |
| int i=0; |
| for (Resource r: jars) |
| { |
| uris[i++] = r.getURI(); |
| } |
| } |
| webInfJarNameMatcher.match(webInfPattern, uris, true); //null is inclusive, no pattern == all jars match |
| |
| //No pattern to appy to classes, just add to metadata |
| context.getMetaData().setWebInfClassesDirs(findClassDirs(context)); |
| } |
| |
| |
| @Override |
| public void configure(WebAppContext context) throws Exception |
| { |
| //cannot configure if the context is already started |
| if (context.isStarted()) |
| { |
| if (LOG.isDebugEnabled()) |
| LOG.debug("Cannot configure webapp "+context+" after it is started"); |
| return; |
| } |
| |
| Resource web_inf = context.getWebInf(); |
| |
| // Add WEB-INF classes and lib classpaths |
| if (web_inf != null && web_inf.isDirectory() && context.getClassLoader() instanceof WebAppClassLoader) |
| { |
| // Look for classes directory |
| Resource classes= web_inf.addPath("classes/"); |
| if (classes.exists()) |
| ((WebAppClassLoader)context.getClassLoader()).addClassPath(classes); |
| |
| // Look for jars |
| Resource lib= web_inf.addPath("lib/"); |
| if (lib.exists() || lib.isDirectory()) |
| ((WebAppClassLoader)context.getClassLoader()).addJars(lib); |
| } |
| |
| // Look for extra resource |
| @SuppressWarnings("unchecked") |
| Set<Resource> resources = (Set<Resource>)context.getAttribute(RESOURCE_DIRS); |
| if (resources!=null) |
| { |
| Resource[] collection=new Resource[resources.size()+1]; |
| int i=0; |
| collection[i++]=context.getBaseResource(); |
| for (Resource resource : resources) |
| collection[i++]=resource; |
| context.setBaseResource(new ResourceCollection(collection)); |
| } |
| } |
| |
| @Override |
| public void deconfigure(WebAppContext context) throws Exception |
| { |
| //if we're not persisting the temp dir contents delete it |
| if (!context.isPersistTempDirectory()) |
| { |
| IO.delete(context.getTempDirectory()); |
| } |
| |
| //if it wasn't explicitly configured by the user, then unset it |
| Boolean tmpdirConfigured = (Boolean)context.getAttribute(TEMPDIR_CONFIGURED); |
| if (tmpdirConfigured != null && !tmpdirConfigured) |
| context.setTempDirectory(null); |
| |
| //reset the base resource back to what it was before we did any unpacking of resources |
| context.setBaseResource(_preUnpackBaseResource); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.webapp.AbstractConfiguration#cloneConfigure(org.eclipse.jetty.webapp.WebAppContext, org.eclipse.jetty.webapp.WebAppContext) |
| */ |
| @Override |
| public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception |
| { |
| File tmpDir=File.createTempFile(WebInfConfiguration.getCanonicalNameForWebAppTmpDir(context),"",template.getTempDirectory().getParentFile()); |
| if (tmpDir.exists()) |
| { |
| IO.delete(tmpDir); |
| } |
| tmpDir.mkdir(); |
| tmpDir.deleteOnExit(); |
| context.setTempDirectory(tmpDir); |
| } |
| |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Get a temporary directory in which to unpack the war etc etc. |
| * The algorithm for determining this is to check these alternatives |
| * in the order shown: |
| * |
| * <p>A. Try to use an explicit directory specifically for this webapp:</p> |
| * <ol> |
| * <li> |
| * Iff an explicit directory is set for this webapp, use it. Set delete on |
| * exit depends on value of persistTempDirectory. |
| * </li> |
| * <li> |
| * Iff javax.servlet.context.tempdir context attribute is set for |
| * this webapp && exists && writeable, then use it. Set delete on exit depends on |
| * value of persistTempDirectory. |
| * </li> |
| * </ol> |
| * |
| * <p>B. Create a directory based on global settings. The new directory |
| * will be called "Jetty-"+host+"-"+port+"__"+context+"-"+virtualhost+"-"+randomdigits+".dir" |
| * </p> |
| * <p> |
| * If the user has specified the context attribute org.eclipse.jetty.webapp.basetempdir, the |
| * directory specified by this attribute will be the parent of the temp dir created. Otherwise, |
| * the parent dir is $(java.io.tmpdir). Set delete on exit depends on value of persistTempDirectory. |
| * </p> |
| */ |
| public void resolveTempDirectory (WebAppContext context) |
| throws Exception |
| { |
| //If a tmp directory is already set we should use it |
| File tmpDir = context.getTempDirectory(); |
| if (tmpDir != null) |
| { |
| configureTempDirectory(tmpDir, context); |
| context.setAttribute(TEMPDIR_CONFIGURED, Boolean.TRUE); //the tmp dir was set explicitly |
| return; |
| } |
| |
| // No temp directory configured, try to establish one via the javax.servlet.context.tempdir. |
| File servletTmpDir = asFile(context.getAttribute(WebAppContext.TEMPDIR)); |
| if (servletTmpDir != null) |
| { |
| // Use as tmpDir |
| tmpDir = servletTmpDir; |
| configureTempDirectory(tmpDir, context); |
| // Ensure Attribute has File object |
| context.setAttribute(WebAppContext.TEMPDIR,tmpDir); |
| // Set as TempDir in context. |
| context.setTempDirectory(tmpDir); |
| return; |
| } |
| |
| //We need to make a temp dir. Check if the user has set a directory to use instead |
| //of java.io.tmpdir as the parent of the dir |
| File baseTemp = asFile(context.getAttribute(WebAppContext.BASETEMPDIR)); |
| if (baseTemp != null && baseTemp.isDirectory() && baseTemp.canWrite()) |
| { |
| //Make a temp directory as a child of the given base dir |
| makeTempDirectory(baseTemp,context); |
| return; |
| } |
| |
| //Look for a directory named "work" in ${jetty.base} and |
| //treat it as parent of a new temp dir (which we will persist) |
| File jettyBase = asFile(System.getProperty("jetty.base")); |
| if (jettyBase != null) |
| { |
| File work = new File (jettyBase, "work"); |
| if (work.exists() && work.isDirectory() && work.canWrite()) |
| { |
| context.setPersistTempDirectory(true); |
| makeTempDirectory(work,context); |
| return; |
| } |
| } |
| |
| //Make a temp directory in java.io.tmpdir |
| makeTempDirectory(new File(System.getProperty("java.io.tmpdir")),context); |
| } |
| |
| /** |
| * Given an Object, return File reference for object. |
| * Typically used to convert anonymous Object from getAttribute() calls to a File object. |
| * @param fileattr the file attribute to analyze and return from (supports type File and type String, all others return null |
| * @return the File object, null if null, or null if not a File or String |
| */ |
| private File asFile(Object fileattr) |
| { |
| if (fileattr == null) |
| { |
| return null; |
| } |
| if (fileattr instanceof File) |
| { |
| return (File)fileattr; |
| } |
| if (fileattr instanceof String) |
| { |
| return new File((String)fileattr); |
| } |
| return null; |
| } |
| |
| |
| |
| public void makeTempDirectory (File parent, WebAppContext context) |
| throws Exception |
| { |
| if (parent == null || !parent.exists() || !parent.canWrite() || !parent.isDirectory()) |
| throw new IllegalStateException("Parent for temp dir not configured correctly: "+(parent==null?"null":"writeable="+parent.canWrite())); |
| |
| //Create a name for the webapp |
| String temp = getCanonicalNameForWebAppTmpDir(context); |
| File tmpDir = null; |
| if (context.isPersistTempDirectory()) |
| { |
| //if it is to be persisted, make sure it will be the same name |
| //by not using File.createTempFile, which appends random digits |
| tmpDir = new File (parent, temp); |
| } |
| else |
| { |
| //ensure file will always be unique by appending random digits |
| tmpDir = File.createTempFile(temp, ".dir", parent); |
| //delete the file that was created |
| tmpDir.delete(); |
| //and make a directory of the same name |
| tmpDir.mkdirs(); |
| } |
| configureTempDirectory(tmpDir, context); |
| |
| if(LOG.isDebugEnabled()) |
| LOG.debug("Set temp dir "+tmpDir); |
| context.setTempDirectory(tmpDir); |
| } |
| |
| public void configureTempDirectory (File dir, WebAppContext context) |
| { |
| if (dir == null) |
| throw new IllegalArgumentException("Null temp dir"); |
| |
| //if dir exists and we don't want it persisted, delete it |
| if (dir.exists() && !context.isPersistTempDirectory()) |
| { |
| if (!IO.delete(dir)) |
| throw new IllegalStateException("Failed to delete temp dir "+dir); |
| } |
| |
| //if it doesn't exist make it |
| if (!dir.exists()) |
| dir.mkdirs(); |
| |
| if (!context.isPersistTempDirectory()) |
| dir.deleteOnExit(); |
| |
| //is it useable |
| if (!dir.canWrite() || !dir.isDirectory()) |
| throw new IllegalStateException("Temp dir "+dir+" not useable: writeable="+dir.canWrite()+", dir="+dir.isDirectory()); |
| } |
| |
| |
| public void unpack (WebAppContext context) throws IOException |
| { |
| Resource web_app = context.getBaseResource(); |
| _preUnpackBaseResource = context.getBaseResource(); |
| |
| if (web_app == null) |
| { |
| String war = context.getWar(); |
| if (war!=null && war.length()>0) |
| web_app = context.newResource(war); |
| else |
| web_app=context.getBaseResource(); |
| |
| if (web_app == null) |
| throw new IllegalStateException("No resourceBase or war set for context"); |
| |
| // Accept aliases for WAR files |
| if (web_app.getAlias() != null) |
| { |
| LOG.debug(web_app + " anti-aliased to " + web_app.getAlias()); |
| web_app = context.newResource(web_app.getAlias()); |
| } |
| |
| if (LOG.isDebugEnabled()) |
| LOG.debug("Try webapp=" + web_app + ", exists=" + web_app.exists() + ", directory=" + web_app.isDirectory()+" file="+(web_app.getFile())); |
| // Is the WAR usable directly? |
| if (web_app.exists() && !web_app.isDirectory() && !web_app.toString().startsWith("jar:")) |
| { |
| // No - then lets see if it can be turned into a jar URL. |
| Resource jarWebApp = JarResource.newJarResource(web_app); |
| if (jarWebApp.exists() && jarWebApp.isDirectory()) |
| web_app= jarWebApp; |
| } |
| |
| // If we should extract or the URL is still not usable |
| if (web_app.exists() && ( |
| (context.isCopyWebDir() && web_app.getFile() != null && web_app.getFile().isDirectory()) || |
| (context.isExtractWAR() && web_app.getFile() != null && !web_app.getFile().isDirectory()) || |
| (context.isExtractWAR() && web_app.getFile() == null) || |
| !web_app.isDirectory()) |
| ) |
| { |
| // Look for sibling directory. |
| File extractedWebAppDir = null; |
| |
| if (war!=null) |
| { |
| // look for a sibling like "foo/" to a "foo.war" |
| File warfile=Resource.newResource(war).getFile(); |
| if (warfile!=null && warfile.getName().toLowerCase(Locale.ENGLISH).endsWith(".war")) |
| { |
| File sibling = new File(warfile.getParent(),warfile.getName().substring(0,warfile.getName().length()-4)); |
| if (sibling.exists() && sibling.isDirectory() && sibling.canWrite()) |
| extractedWebAppDir=sibling; |
| } |
| } |
| |
| if (extractedWebAppDir==null) |
| // Then extract it if necessary to the temporary location |
| extractedWebAppDir= new File(context.getTempDirectory(), "webapp"); |
| |
| if (web_app.getFile()!=null && web_app.getFile().isDirectory()) |
| { |
| // Copy directory |
| LOG.debug("Copy " + web_app + " to " + extractedWebAppDir); |
| web_app.copyTo(extractedWebAppDir); |
| } |
| else |
| { |
| //Use a sentinel file that will exist only whilst the extraction is taking place. |
| //This will help us detect interrupted extractions. |
| File extractionLock = new File (context.getTempDirectory(), ".extract_lock"); |
| |
| if (!extractedWebAppDir.exists()) |
| { |
| //it hasn't been extracted before so extract it |
| extractionLock.createNewFile(); |
| extractedWebAppDir.mkdir(); |
| LOG.debug("Extract " + web_app + " to " + extractedWebAppDir); |
| Resource jar_web_app = JarResource.newJarResource(web_app); |
| jar_web_app.copyTo(extractedWebAppDir); |
| extractionLock.delete(); |
| } |
| else |
| { |
| //only extract if the war file is newer, or a .extract_lock file is left behind meaning a possible partial extraction |
| if (web_app.lastModified() > extractedWebAppDir.lastModified() || extractionLock.exists()) |
| { |
| extractionLock.createNewFile(); |
| IO.delete(extractedWebAppDir); |
| extractedWebAppDir.mkdir(); |
| LOG.debug("Extract " + web_app + " to " + extractedWebAppDir); |
| Resource jar_web_app = JarResource.newJarResource(web_app); |
| jar_web_app.copyTo(extractedWebAppDir); |
| extractionLock.delete(); |
| } |
| } |
| } |
| web_app = Resource.newResource(extractedWebAppDir.getCanonicalPath()); |
| } |
| |
| // Now do we have something usable? |
| if (!web_app.exists() || !web_app.isDirectory()) |
| { |
| LOG.warn("Web application not found " + war); |
| throw new java.io.FileNotFoundException(war); |
| } |
| |
| context.setBaseResource(web_app); |
| |
| if (LOG.isDebugEnabled()) |
| LOG.debug("webapp=" + web_app); |
| } |
| |
| |
| // Do we need to extract WEB-INF/lib? |
| if (context.isCopyWebInf() && !context.isCopyWebDir()) |
| { |
| Resource web_inf= web_app.addPath("WEB-INF/"); |
| |
| File extractedWebInfDir= new File(context.getTempDirectory(), "webinf"); |
| if (extractedWebInfDir.exists()) |
| IO.delete(extractedWebInfDir); |
| extractedWebInfDir.mkdir(); |
| Resource web_inf_lib = web_inf.addPath("lib/"); |
| File webInfDir=new File(extractedWebInfDir,"WEB-INF"); |
| webInfDir.mkdir(); |
| |
| if (web_inf_lib.exists()) |
| { |
| File webInfLibDir = new File(webInfDir, "lib"); |
| if (webInfLibDir.exists()) |
| IO.delete(webInfLibDir); |
| webInfLibDir.mkdir(); |
| |
| LOG.debug("Copying WEB-INF/lib " + web_inf_lib + " to " + webInfLibDir); |
| web_inf_lib.copyTo(webInfLibDir); |
| } |
| |
| Resource web_inf_classes = web_inf.addPath("classes/"); |
| if (web_inf_classes.exists()) |
| { |
| File webInfClassesDir = new File(webInfDir, "classes"); |
| if (webInfClassesDir.exists()) |
| IO.delete(webInfClassesDir); |
| webInfClassesDir.mkdir(); |
| LOG.debug("Copying WEB-INF/classes from "+web_inf_classes+" to "+webInfClassesDir.getAbsolutePath()); |
| web_inf_classes.copyTo(webInfClassesDir); |
| } |
| |
| web_inf=Resource.newResource(extractedWebInfDir.getCanonicalPath()); |
| |
| ResourceCollection rc = new ResourceCollection(web_inf,web_app); |
| |
| if (LOG.isDebugEnabled()) |
| LOG.debug("context.resourcebase = "+rc); |
| |
| context.setBaseResource(rc); |
| } |
| } |
| |
| |
| |
| |
| /** |
| * Create a canonical name for a webapp temp directory. |
| * The form of the name is: |
| * <code>"jetty-"+host+"-"+port+"-"+resourceBase+"-_"+context+"-"+virtualhost+"-"+randomdigits+".dir"</code> |
| * |
| * host and port uniquely identify the server |
| * context and virtual host uniquely identify the webapp |
| * randomdigits ensure every tmp directory is unique |
| * |
| * @return the canonical name for the webapp temp directory |
| */ |
| public static String getCanonicalNameForWebAppTmpDir (WebAppContext context) |
| { |
| StringBuffer canonicalName = new StringBuffer(); |
| canonicalName.append("jetty-"); |
| |
| //get the host and the port from the first connector |
| Server server=context.getServer(); |
| if (server!=null) |
| { |
| Connector[] connectors = context.getServer().getConnectors(); |
| |
| if (connectors.length>0) |
| { |
| //Get the host |
| String host=null; |
| int port=0; |
| if (connectors!=null && (connectors[0] instanceof NetworkConnector)) |
| { |
| NetworkConnector connector = (NetworkConnector)connectors[0]; |
| host=connector.getHost(); |
| port=connector.getLocalPort(); |
| if (port < 0) |
| port = connector.getPort(); |
| } |
| if (host == null) |
| host = "0.0.0.0"; |
| canonicalName.append(host); |
| |
| //Get the port |
| canonicalName.append("-"); |
| |
| //if not available (eg no connectors or connector not started), |
| //try getting one that was configured. |
| canonicalName.append(port); |
| canonicalName.append("-"); |
| } |
| } |
| |
| |
| //Resource base |
| try |
| { |
| Resource resource = context.getBaseResource(); |
| if (resource == null) |
| { |
| if (context.getWar()==null || context.getWar().length()==0) |
| throw new IllegalStateException("No resourceBase or war set for context"); |
| |
| // Set dir or WAR |
| resource = context.newResource(context.getWar()); |
| } |
| |
| String tmp = URIUtil.decodePath(resource.getURL().getPath()); |
| if (tmp.endsWith("/")) |
| tmp = tmp.substring(0, tmp.length()-1); |
| if (tmp.endsWith("!")) |
| tmp = tmp.substring(0, tmp.length() -1); |
| //get just the last part which is the filename |
| int i = tmp.lastIndexOf("/"); |
| canonicalName.append(tmp.substring(i+1, tmp.length())); |
| canonicalName.append("-"); |
| } |
| catch (Exception e) |
| { |
| LOG.warn("Can't generate resourceBase as part of webapp tmp dir name: " + e); |
| LOG.debug(e); |
| } |
| |
| //Context name |
| String contextPath = context.getContextPath(); |
| contextPath=contextPath.replace('/','_'); |
| contextPath=contextPath.replace('\\','_'); |
| canonicalName.append(contextPath); |
| |
| //Virtual host (if there is one) |
| canonicalName.append("-"); |
| String[] vhosts = context.getVirtualHosts(); |
| if (vhosts == null || vhosts.length <= 0) |
| canonicalName.append("any"); |
| else |
| canonicalName.append(vhosts[0]); |
| |
| // sanitize |
| for (int i=0;i<canonicalName.length();i++) |
| { |
| char c=canonicalName.charAt(i); |
| if (!Character.isJavaIdentifierPart(c) && "-.".indexOf(c)<0) |
| canonicalName.setCharAt(i,'.'); |
| } |
| |
| canonicalName.append("-"); |
| |
| return canonicalName.toString(); |
| } |
| |
| |
| protected List<Resource> findClassDirs (WebAppContext context) |
| throws Exception |
| { |
| if (context == null) |
| return null; |
| |
| List<Resource> classDirs = new ArrayList<Resource>(); |
| |
| Resource webInfClasses = findWebInfClassesDir(context); |
| if (webInfClasses != null) |
| classDirs.add(webInfClasses); |
| List<Resource> extraClassDirs = findExtraClasspathDirs(context); |
| if (extraClassDirs != null) |
| classDirs.addAll(extraClassDirs); |
| |
| return classDirs; |
| } |
| |
| |
| /** |
| * Look for jars that should be treated as if they are in WEB-INF/lib |
| * |
| * @param context |
| * @return the list of jar resources found within context |
| * @throws Exception |
| */ |
| protected List<Resource> findJars (WebAppContext context) |
| throws Exception |
| { |
| List<Resource> jarResources = new ArrayList<Resource>(); |
| List<Resource> webInfLibJars = findWebInfLibJars(context); |
| if (webInfLibJars != null) |
| jarResources.addAll(webInfLibJars); |
| List<Resource> extraClasspathJars = findExtraClasspathJars(context); |
| if (extraClasspathJars != null) |
| jarResources.addAll(extraClasspathJars); |
| return jarResources; |
| } |
| |
| /** |
| * Look for jars in WEB-INF/lib |
| * |
| * @param context |
| * @return |
| * @throws Exception |
| */ |
| protected List<Resource> findWebInfLibJars(WebAppContext context) |
| throws Exception |
| { |
| Resource web_inf = context.getWebInf(); |
| if (web_inf==null || !web_inf.exists()) |
| return null; |
| |
| List<Resource> jarResources = new ArrayList<Resource>(); |
| Resource web_inf_lib = web_inf.addPath("/lib"); |
| if (web_inf_lib.exists() && web_inf_lib.isDirectory()) |
| { |
| String[] files=web_inf_lib.list(); |
| for (int f=0;files!=null && f<files.length;f++) |
| { |
| try |
| { |
| Resource file = web_inf_lib.addPath(files[f]); |
| String fnlc = file.getName().toLowerCase(Locale.ENGLISH); |
| int dot = fnlc.lastIndexOf('.'); |
| String extension = (dot < 0 ? null : fnlc.substring(dot)); |
| if (extension != null && (extension.equals(".jar") || extension.equals(".zip"))) |
| { |
| jarResources.add(file); |
| } |
| } |
| catch (Exception ex) |
| { |
| LOG.warn(Log.EXCEPTION,ex); |
| } |
| } |
| } |
| return jarResources; |
| } |
| |
| |
| |
| /** |
| * Get jars from WebAppContext.getExtraClasspath as resources |
| * |
| * @param context |
| * @return |
| * @throws Exception |
| */ |
| protected List<Resource> findExtraClasspathJars(WebAppContext context) |
| throws Exception |
| { |
| if (context == null || context.getExtraClasspath() == null) |
| return null; |
| |
| List<Resource> jarResources = new ArrayList<Resource>(); |
| StringTokenizer tokenizer = new StringTokenizer(context.getExtraClasspath(), ",;"); |
| while (tokenizer.hasMoreTokens()) |
| { |
| Resource resource = context.newResource(tokenizer.nextToken().trim()); |
| String fnlc = resource.getName().toLowerCase(Locale.ENGLISH); |
| int dot = fnlc.lastIndexOf('.'); |
| String extension = (dot < 0 ? null : fnlc.substring(dot)); |
| if (extension != null && (extension.equals(".jar") || extension.equals(".zip"))) |
| { |
| jarResources.add(resource); |
| } |
| } |
| |
| return jarResources; |
| } |
| |
| /** |
| * Get WEB-INF/classes dir |
| * |
| * @param context |
| * @return |
| * @throws Exception |
| */ |
| protected Resource findWebInfClassesDir (WebAppContext context) |
| throws Exception |
| { |
| if (context == null) |
| return null; |
| |
| Resource web_inf = context.getWebInf(); |
| |
| // Find WEB-INF/classes |
| if (web_inf != null && web_inf.isDirectory()) |
| { |
| // Look for classes directory |
| Resource classes= web_inf.addPath("classes/"); |
| if (classes.exists()) |
| return classes; |
| } |
| return null; |
| } |
| |
| |
| /** |
| * Get class dirs from WebAppContext.getExtraClasspath as resources |
| * |
| * @param context |
| * @return |
| * @throws Exception |
| */ |
| protected List<Resource> findExtraClasspathDirs(WebAppContext context) |
| throws Exception |
| { |
| if (context == null || context.getExtraClasspath() == null) |
| return null; |
| |
| List<Resource> dirResources = new ArrayList<Resource>(); |
| StringTokenizer tokenizer = new StringTokenizer(context.getExtraClasspath(), ",;"); |
| while (tokenizer.hasMoreTokens()) |
| { |
| Resource resource = context.newResource(tokenizer.nextToken().trim()); |
| if (resource.exists() && resource.isDirectory()) |
| dirResources.add(resource); |
| } |
| |
| return dirResources; |
| } |
| |
| |
| } |