FileDocCategorySizeDatePackage
ExtensionValidator.javaAPI DocApache Tomcat 6.0.1416482Fri Jul 20 04:20:34 BST 2007org.apache.catalina.util

ExtensionValidator

public final class ExtensionValidator extends Object
Ensures that all extension dependies are resolved for a WEB application are met. This class builds a master list of extensions available to an applicaiton and then validates those extensions. See http://java.sun.com/j2se/1.4/docs/guide/extensions/spec.html for a detailed explanation of the extension mechanism in Java.
author
Greg Murray
author
Justyna Horwat
version
$Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $

Fields Summary
private static org.apache.juli.logging.Log
log
private static StringManager
sm
The string resources for this package.
private static ArrayList
containerAvailableExtensions
private static ArrayList
containerManifestResources
Constructors Summary
Methods Summary
private static voidaddFolderList(java.lang.String property)
Add the JARs specified to the extension list.


        // get the files in the extensions directory
        String extensionsDir = System.getProperty(property);
        if (extensionsDir != null) {
            StringTokenizer extensionsTok
                = new StringTokenizer(extensionsDir, File.pathSeparator);
            while (extensionsTok.hasMoreTokens()) {
                File targetDir = new File(extensionsTok.nextToken());
                if (!targetDir.exists() || !targetDir.isDirectory()) {
                    continue;
                }
                File[] files = targetDir.listFiles();
                for (int i = 0; i < files.length; i++) {
                    if (files[i].getName().toLowerCase().endsWith(".jar")) {
                        try {
                            addSystemResource(files[i]);
                        } catch (IOException e) {
                            log.error
                                (sm.getString
                                 ("extensionValidator.failload", files[i]), e);
                        }
                    }
                }
            }
        }

    
public static voidaddSystemResource(java.io.File jarFile)
Checks to see if the given system JAR file contains a MANIFEST, and adds it to the container's manifest resources.

param
jarFile The system JAR whose manifest to add

        Manifest manifest = getManifest(new FileInputStream(jarFile));
        if (manifest != null)  {
            ManifestResource mre
                = new ManifestResource(jarFile.getAbsolutePath(),
                                       manifest,
                                       ManifestResource.SYSTEM);
            containerManifestResources.add(mre);
        }
    
private static java.util.ArrayListbuildAvailableExtensionsList(java.util.ArrayList resources)


        ArrayList availableList = null;

        Iterator it = resources.iterator();
        while (it.hasNext()) {
            ManifestResource mre = (ManifestResource)it.next();
            ArrayList list = mre.getAvailableExtensions();
            if (list != null) {
                Iterator values = list.iterator();
                while (values.hasNext()) {
                    Extension ext = (Extension) values.next();
                    if (availableList == null) {
                        availableList = new ArrayList();
                        availableList.add(ext);
                    } else {
                        availableList.add(ext);
                    }
                }
            }
        }

        return availableList;
    
private static java.util.jar.ManifestgetManifest(java.io.InputStream inStream)
Return the Manifest from a jar file or war file

param
inStream Input stream to a WAR or JAR file
return
The WAR's or JAR's manifest


        Manifest manifest = null;
        JarInputStream jin = null;

        try {
            jin = new JarInputStream(inStream);
            manifest = jin.getManifest();
            jin.close();
            jin = null;
        } finally {
            if (jin != null) {
                try {
                    jin.close();
                } catch (Throwable t) {
                    // Ignore
                }
            }
        }

        return manifest;
    
public static synchronized booleanvalidateApplication(javax.naming.directory.DirContext dirContext, org.apache.catalina.core.StandardContext context)
Runtime validation of a Web Applicaiton. This method uses JNDI to look up the resources located under a DirContext. It locates Web Application MANIFEST.MF file in the /META-INF/ directory of the application and all MANIFEST.MF files in each JAR file located in the WEB-INF/lib directory and creates an ArrayList of ManifestResorce objects. These objects are then passed to the validateManifestResources method for validation.

param
dirContext The JNDI root of the Web Application
param
context The context from which the Logger and path to the application
return
true if all required extensions satisfied



    // ----------------------------------------------------- Static Initializer


                                                          
     

        // check for container level optional packages
        String systemClasspath = System.getProperty("java.class.path");

        StringTokenizer strTok = new StringTokenizer(systemClasspath, 
                                                     File.pathSeparator);

        // build a list of jar files in the classpath
        while (strTok.hasMoreTokens()) {
            String classpathItem = strTok.nextToken();
            if (classpathItem.toLowerCase().endsWith(".jar")) {
                File item = new File(classpathItem);
                if (item.exists()) {
                    try {
                        addSystemResource(item);
                    } catch (IOException e) {
                        log.error(sm.getString
                                  ("extensionValidator.failload", item), e);
                    }
                }
            }
        }

        // add specified folders to the list
        addFolderList("java.ext.dirs");
        addFolderList("catalina.ext.dirs");

    

        String appName = context.getPath();
        ArrayList appManifestResources = new ArrayList();
        // If the application context is null it does not exist and 
        // therefore is not valid
        if (dirContext == null) return false;
        // Find the Manifest for the Web Applicaiton
        InputStream inputStream = null;
        try {
            NamingEnumeration wne = dirContext.listBindings("/META-INF/");
            Binding binding = (Binding) wne.nextElement();
            if (binding.getName().toUpperCase().equals("MANIFEST.MF")) {
                Resource resource = (Resource)dirContext.lookup
                                    ("/META-INF/" + binding.getName());
                inputStream = resource.streamContent();
                Manifest manifest = new Manifest(inputStream);
                inputStream.close();
                inputStream = null;
                ManifestResource mre = new ManifestResource
                    (sm.getString("extensionValidator.web-application-manifest"),
                    manifest, ManifestResource.WAR);
                appManifestResources.add(mre);
            } 
        } catch (NamingException nex) {
            // Application does not contain a MANIFEST.MF file
        } catch (NoSuchElementException nse) {
            // Application does not contain a MANIFEST.MF file
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Throwable t) {
                    // Ignore
                }
            }
        }

        // Locate the Manifests for all bundled JARs
        NamingEnumeration ne = null;
        try {
            if (dirContext != null) {
                ne = dirContext.listBindings("WEB-INF/lib/");
            }
            while ((ne != null) && ne.hasMoreElements()) {
                Binding binding = (Binding)ne.nextElement();
                if (!binding.getName().toLowerCase().endsWith(".jar")) {
                    continue;
                }
                Resource resource = (Resource)dirContext.lookup
                                        ("/WEB-INF/lib/" + binding.getName());
                Manifest jmanifest = getManifest(resource.streamContent());
                if (jmanifest != null) {
                    ManifestResource mre = new ManifestResource(
                                                binding.getName(),
                                                jmanifest, 
                                                ManifestResource.APPLICATION);
                    appManifestResources.add(mre);
                }
            }
        } catch (NamingException nex) {
            // Jump out of the check for this application because it 
            // has no resources
        }

        return validateManifestResources(appName, appManifestResources);
    
private static booleanvalidateManifestResources(java.lang.String appName, java.util.ArrayList resources)
Validates a ArrayList of ManifestResource objects. This method requires an application name (which is the context root of the application at runtime). false is returned if the extension dependencies represented by any given ManifestResource objects is not met. This method should also provide static validation of a Web Applicaiton if provided with the necessary parameters.

param
appName The name of the Application that will appear in the error messages
param
resources A list of ManifestResource objects to be validated.
return
true if manifest resource file requirements are met

        boolean passes = true;
        int failureCount = 0;        
        ArrayList availableExtensions = null;

        Iterator it = resources.iterator();
        while (it.hasNext()) {
            ManifestResource mre = (ManifestResource)it.next();
            ArrayList requiredList = mre.getRequiredExtensions();
            if (requiredList == null) {
                continue;
            }

            // build the list of available extensions if necessary
            if (availableExtensions == null) {
                availableExtensions = buildAvailableExtensionsList(resources);
            }

            // load the container level resource map if it has not been built
            // yet
            if (containerAvailableExtensions == null) {
                containerAvailableExtensions
                    = buildAvailableExtensionsList(containerManifestResources);
            }

            // iterate through the list of required extensions
            Iterator rit = requiredList.iterator();
            while (rit.hasNext()) {
                boolean found = false;
                Extension requiredExt = (Extension)rit.next();
                // check the applicaion itself for the extension
                if (availableExtensions != null) {
                    Iterator ait = availableExtensions.iterator();
                    while (ait.hasNext()) {
                        Extension targetExt = (Extension) ait.next();
                        if (targetExt.isCompatibleWith(requiredExt)) {
                            requiredExt.setFulfilled(true);
                            found = true;
                            break;
                        }
                    }
                }
                // check the container level list for the extension
                if (!found && containerAvailableExtensions != null) {
                    Iterator cit = containerAvailableExtensions.iterator();
                    while (cit.hasNext()) {
                        Extension targetExt = (Extension) cit.next();
                        if (targetExt.isCompatibleWith(requiredExt)) {
                            requiredExt.setFulfilled(true);
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) {
                    // Failure
                    log.info(sm.getString(
                        "extensionValidator.extension-not-found-error",
                        appName, mre.getResourceName(),
                        requiredExt.getExtensionName()));
                    passes = false;
                    failureCount++;
                }
            }
        }

        if (!passes) {
            log.info(sm.getString(
                     "extensionValidator.extension-validation-error", appName,
                     failureCount + ""));
        }

        return passes;