All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.webapp.MetaInfConfiguration Maven / Gradle / Ivy

There is a newer version: 11.0.24
Show newest version
//
//  ========================================================================
//  Copyright (c) 1995-2015 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.JarURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.EmptyResource;
import org.eclipse.jetty.util.resource.Resource;

/**
 * MetaInfConfiguration
 * 

* * Scan META-INF of jars to find: *

    *
  • tlds
  • *
  • web-fragment.xml
  • *
  • resources
  • *
* * The jars which are scanned are: *
    *
  1. those from the container classpath whose pattern matched the WebInfConfiguration.CONTAINER_JAR_PATTERN
  2. *
  3. those from WEB-INF/lib
  4. *
*/ public class MetaInfConfiguration extends AbstractConfiguration { private static final Logger LOG = Log.getLogger(MetaInfConfiguration.class); public static final String USE_CONTAINER_METAINF_CACHE = "org.eclipse.jetty.metainf.useCache"; public static final boolean DEFAULT_USE_CONTAINER_METAINF_CACHE = true; public static final String CACHED_CONTAINER_TLDS = "org.eclipse.jetty.tlds.cache"; public static final String CACHED_CONTAINER_FRAGMENTS = FragmentConfiguration.FRAGMENT_RESOURCES+".cache"; public static final String CACHED_CONTAINER_RESOURCES = WebInfConfiguration.RESOURCE_DIRS+".cache"; public static final String METAINF_TLDS = "org.eclipse.jetty.tlds"; public static final String METAINF_FRAGMENTS = FragmentConfiguration.FRAGMENT_RESOURCES; public static final String METAINF_RESOURCES = WebInfConfiguration.RESOURCE_DIRS; @Override public void preConfigure(final WebAppContext context) throws Exception { boolean useContainerCache = DEFAULT_USE_CONTAINER_METAINF_CACHE; Boolean attr = (Boolean)context.getServer().getAttribute(USE_CONTAINER_METAINF_CACHE); if (attr != null) useContainerCache = attr.booleanValue(); if (LOG.isDebugEnabled()) LOG.debug("{} = {}", USE_CONTAINER_METAINF_CACHE, useContainerCache); //pre-emptively create empty lists for tlds, fragments and resources as context attributes //this signals that this class has been called. This differentiates the case where this class //has been called but finds no META-INF data from the case where this class was never called if (context.getAttribute(METAINF_TLDS) == null) context.setAttribute(METAINF_TLDS, new HashSet()); if (context.getAttribute(METAINF_RESOURCES) == null) context.setAttribute(METAINF_RESOURCES, new HashSet()); if (context.getAttribute(METAINF_FRAGMENTS) == null) context.setAttribute(METAINF_FRAGMENTS, new HashMap()); scanJars(context, context.getMetaData().getContainerResources(), useContainerCache); scanJars(context, context.getMetaData().getWebInfJars(), false); } /** * Look into the jars to discover info in META-INF. If useCaches == true, then we will * cache the info discovered indexed by the jar in which it was discovered: this speeds * up subsequent context deployments. * * @param context the context for the scan * @param jars the jars resources to scan * @param useCaches if true, cache the info discovered * @throws Exception if unable to scan the jars */ public void scanJars (final WebAppContext context, Collection jars, boolean useCaches) throws Exception { ConcurrentHashMap metaInfResourceCache = null; ConcurrentHashMap metaInfFragmentCache = null; ConcurrentHashMap> metaInfTldCache = null; if (useCaches) { metaInfResourceCache = (ConcurrentHashMap)context.getServer().getAttribute(CACHED_CONTAINER_RESOURCES); if (metaInfResourceCache == null) { metaInfResourceCache = new ConcurrentHashMap(); context.getServer().setAttribute(CACHED_CONTAINER_RESOURCES, metaInfResourceCache); } metaInfFragmentCache = (ConcurrentHashMap)context.getServer().getAttribute(CACHED_CONTAINER_FRAGMENTS); if (metaInfFragmentCache == null) { metaInfFragmentCache = new ConcurrentHashMap(); context.getServer().setAttribute(CACHED_CONTAINER_FRAGMENTS, metaInfFragmentCache); } metaInfTldCache = (ConcurrentHashMap>)context.getServer().getAttribute(CACHED_CONTAINER_TLDS); if (metaInfTldCache == null) { metaInfTldCache = new ConcurrentHashMap>(); context.getServer().setAttribute(CACHED_CONTAINER_TLDS, metaInfTldCache); } } //Scan jars for META-INF information if (jars != null) { for (Resource r : jars) { scanForResources(context, r, metaInfResourceCache); scanForFragment(context, r, metaInfFragmentCache); scanForTlds(context, r, metaInfTldCache); } } } /** * Scan for META-INF/resources dir in the given jar. * * @param context the context for the scan * @param target the target resource to scan for * @param cache the resource cache * @throws Exception if unable to scan for resources */ public void scanForResources (WebAppContext context, Resource target, ConcurrentHashMap cache) throws Exception { Resource resourcesDir = null; if (cache != null && cache.containsKey(target)) { resourcesDir = cache.get(target); if (resourcesDir == EmptyResource.INSTANCE) { if (LOG.isDebugEnabled()) LOG.debug(target+" cached as containing no META-INF/resources"); return; } else if (LOG.isDebugEnabled()) LOG.debug(target+" META-INF/resources found in cache "); } else { //not using caches or not in the cache so check for the resources dir if (LOG.isDebugEnabled()) LOG.debug(target+" META-INF/resources checked"); if (target.isDirectory()) { //TODO think how to handle an unpacked jar file (eg for osgi) resourcesDir = target.addPath("/META-INF/resources"); } else { //Resource represents a packed jar URI uri = target.getURI(); resourcesDir = Resource.newResource("jar:"+uri+"!/META-INF/resources", false); } if (!resourcesDir.exists() || !resourcesDir.isDirectory()) { resourcesDir.close(); resourcesDir = EmptyResource.INSTANCE; } if (cache != null) { Resource old = cache.putIfAbsent(target, resourcesDir); if (old != null) resourcesDir = old; else if (LOG.isDebugEnabled()) LOG.debug(target+" META-INF/resources cache updated"); } if (resourcesDir == EmptyResource.INSTANCE) { return; } } //add it to the meta inf resources for this context Set dirs = (Set)context.getAttribute(METAINF_RESOURCES); if (dirs == null) { dirs = new HashSet(); context.setAttribute(METAINF_RESOURCES, dirs); } if (LOG.isDebugEnabled()) LOG.debug(resourcesDir+" added to context"); dirs.add(resourcesDir); } /** * Scan for META-INF/web-fragment.xml file in the given jar. * * @param context the context for the scan * @param jar the jar resource to scan for fragements in * @param cache the resource cache * @throws Exception if unable to scan for fragments */ public void scanForFragment (WebAppContext context, Resource jar, ConcurrentHashMap cache) throws Exception { Resource webFrag = null; if (cache != null && cache.containsKey(jar)) { webFrag = cache.get(jar); if (webFrag == EmptyResource.INSTANCE) { if (LOG.isDebugEnabled()) LOG.debug(jar+" cached as containing no META-INF/web-fragment.xml"); return; } else if (LOG.isDebugEnabled()) LOG.debug(jar+" META-INF/web-fragment.xml found in cache "); } else { //not using caches or not in the cache so check for the web-fragment.xml if (LOG.isDebugEnabled()) LOG.debug(jar+" META-INF/web-fragment.xml checked"); if (jar.isDirectory()) { //TODO ???? webFrag = jar.addPath("/META-INF/web-fragment.xml"); } else { URI uri = jar.getURI(); webFrag = Resource.newResource("jar:"+uri+"!/META-INF/web-fragment.xml", false); } if (!webFrag.exists() || webFrag.isDirectory()) { webFrag.close(); webFrag = EmptyResource.INSTANCE; } if (cache != null) { //web-fragment.xml doesn't exist: put token in cache to signal we've seen the jar Resource old = cache.putIfAbsent(jar, webFrag); if (old != null) webFrag = old; else if (LOG.isDebugEnabled()) LOG.debug(jar+" META-INF/web-fragment.xml cache updated"); } if (webFrag == EmptyResource.INSTANCE) return; } Map fragments = (Map)context.getAttribute(METAINF_FRAGMENTS); if (fragments == null) { fragments = new HashMap(); context.setAttribute(METAINF_FRAGMENTS, fragments); } fragments.put(jar, webFrag); if (LOG.isDebugEnabled()) LOG.debug(webFrag+" added to context"); } /** * Discover META-INF/*.tld files in the given jar * * @param context the context for the scan * @param jar the jar resources to scan tlds for * @param cache the resource cache * @throws Exception if unable to scan for tlds */ public void scanForTlds (WebAppContext context, Resource jar, ConcurrentHashMap> cache) throws Exception { Collection tlds = null; if (cache != null && cache.containsKey(jar)) { Collection tmp = cache.get(jar); if (tmp.isEmpty()) { if (LOG.isDebugEnabled()) LOG.debug(jar+" cached as containing no tlds"); return; } else { tlds = tmp; if (LOG.isDebugEnabled()) LOG.debug(jar+" tlds found in cache "); } } else { //not using caches or not in the cache so find all tlds tlds = new HashSet(); if (jar.isDirectory()) { tlds.addAll(getTlds(jar.getFile())); } else { URI uri = jar.getURI(); tlds.addAll(getTlds(uri)); } if (cache != null) { if (LOG.isDebugEnabled()) LOG.debug(jar+" tld cache updated"); Collection old = (Collection)cache.putIfAbsent(jar, tlds); if (old != null) tlds = old; } if (tlds.isEmpty()) return; } Collection metaInfTlds = (Collection)context.getAttribute(METAINF_TLDS); if (metaInfTlds == null) { metaInfTlds = new HashSet(); context.setAttribute(METAINF_TLDS, metaInfTlds); } metaInfTlds.addAll(tlds); if (LOG.isDebugEnabled()) LOG.debug("tlds added to context"); } @Override public void postConfigure(WebAppContext context) throws Exception { context.setAttribute(METAINF_RESOURCES, null); context.setAttribute(METAINF_FRAGMENTS, null); context.setAttribute(METAINF_TLDS, null); } /** * Find all .tld files in all subdirs of the given dir. * * @param dir the directory to scan * @return the list of tlds found * @throws IOException if unable to scan the directory */ public Collection getTlds (File dir) throws IOException { if (dir == null || !dir.isDirectory()) return Collections.emptySet(); HashSet tlds = new HashSet(); File[] files = dir.listFiles(); if (files != null) { for (File f:files) { if (f.isDirectory()) tlds.addAll(getTlds(f)); else { String name = f.getCanonicalPath(); if (name.contains("META-INF") && name.endsWith(".tld")) tlds.add(f.toURI().toURL()); } } } return tlds; } /** * Find all .tld files in the given jar. * * @param uri the uri to jar file * @return the collection of tlds as url references * @throws IOException if unable to scan the jar file */ public Collection getTlds (URI uri) throws IOException { HashSet tlds = new HashSet(); URL url = new URL("jar:"+uri+"!/"); JarURLConnection jarConn = (JarURLConnection) url.openConnection(); jarConn.setUseCaches(false); JarFile jarFile = jarConn.getJarFile(); Enumeration entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry e = entries.nextElement(); String name = e.getName(); if (name.startsWith("META-INF") && name.endsWith(".tld")) { tlds.add(new URL("jar:"+uri+"!/"+name)); } } if (!Resource.getDefaultUseCaches()) jarFile.close(); return tlds; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy