Package org.jdesktop.wonderland.utils

Source Code of org.jdesktop.wonderland.utils.ArchiveManifest

/**
* Project Wonderland
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., All Rights Reserved
*
* Redistributions in source code form must reproduce the above
* copyright and this condition.
*
* The contents of this file are subject to the GNU General Public
* License, Version 2 (the "License"); you may not use this file
* except in compliance with the License. A copy of the License is
* available at http://www.opensource.org/licenses/gpl-license.php.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the License file that accompanied
* this code.
*/
package org.jdesktop.wonderland.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;

/**
* The ArchiveManifest class represents a tree of entries found in the JAR
* file, so that its entries may be tranversed hierarchically.
* <p>
* This class also serves as the 'front-end' to a JAR file and returns the
* input stream for individual entries.
*
* @author Jordan Slott <jslott@dev.java.net>
*/
public class ArchiveManifest {
    /* The error logger for this class */
    Logger logger = Logger.getLogger(ArchiveManifest.class.getName());
   
    /* The URL used to open the archive */
    private URL url = null;
   
    /*
     * A map that contains a series of file entries parsed into path components.
     * Each of the entries contains a String key of a directory path component,
     * and a linked-list of entries (files or directories) in that path.
     */
    private HashMap<String, LinkedList<String>> fileMap = null;
   
    /* An ordered linked list of all entries in the archive. */
    private LinkedList<String> entryList = null;
  
    /* The JAR file object association with this JAR file */
    private JarFile jarfile;
   
    /**
     * Creates a new instance of ArchiveManifest, takes the JAR file as an
     * argument, parses the manifest into a tree structure.
     *
     * @param file The File of the JAR file
     * @throw IOException Upon failure to open the JAR file
     */
    public ArchiveManifest(File file) throws IOException {
        this.url = file.toURI().toURL();
        this.jarfile = new JarFile(file);
        this.createArchiveMap(jarfile);
    }
   
    /**
     * Creates a new instance of ArchiveManifest, takes the JAR URL as an
     * argument, parses the manifest into a tree structure.
     *
     * @param url The URL of the JAR file
     * @throw IOException Upon failure to open the JAR file URL
     */
    public ArchiveManifest(URL url) throws IOException {
        /* Open a connection to the JAR file and parse out its entries */
        JarURLConnection urlconn = (JarURLConnection) url.openConnection();
        this.url = url;
        this.jarfile = urlconn.getJarFile();
        this.createArchiveMap(this.jarfile);
    }
   
    /**
     * Returns the URL used to open the archive.
     *
     * @return The archive URL
     */
    public URL getURL() {
        return this.url;
    }
   
    /**
     * Returns an input stream given the full pathame of the entry.
     *
     * @path The full pathname of the entry
     * @return The input stream of the entry
     * @throw IOException Upon an invalid entry name
     */
    public InputStream getEntryInputStream(String path) throws IOException {
        ZipEntry entry = this.jarfile.getEntry(path);
        if (entry == null) {
            return null;
        }
        InputStream is = jarfile.getInputStream(entry);
        return is;
    }
   
    /**
     * Returns a JarEntry class given the full pathame of the entry or null
     * if not found
     *
     * @param path The full pathame of the entry
     * @return The jar file entry, or null if not found
     */
    public JarEntry getJarEntry(String path) {
        return this.jarfile.getJarEntry(path);
    }
   
    /**
     * Closes any files associated with the manifest
     */
    public void close() {
        try {
            this.jarfile.close();
        } catch (IOException excp) {
            logger.info("Failed to close JAR file: " + excp.toString());
        }
    }
   
    /**
     * Returns a copy of all of the entries given the full path name of a
     * directory. For the entries at the root, use "" for path.
     *
     * @param path The path name to look for entries
     * @return A linked list of entries in the given path
     */
    public LinkedList<String> getEntries(String path) {
        if (this.fileMap.containsKey(path) == true) {
            return this.fileMap.get(path);
        }
        return new LinkedList<String>();
    }
   
    /**
     * Returns a linked list of all entries in the archive. Note that entries
     * that represent directories have a final "/".
     *
     * @return A linked list of all entries in the archive
     */
    public LinkedList<String> getEntries() {
        return new LinkedList<String>(this.entryList);
    }
   
    /**
     * Returns true if the given entry name represents a directory (that is,
     * is has a final "/".
     *
     * @param entry The name of the entry
     * @return True if the entry is a directory, false if not
     */
    public boolean isDirectory(String entry) {
        return entry.endsWith("/");
    }
   
    /**
     * Returns true if the given complete path name exists within the JAR file,
     * false if not.
     *
     * @param path The full pathname of the entry
     * @return True if the entry exists, false if not
     */
    public boolean isValidEntry(String path) {
        return this.fileMap.containsKey(path);
    }
   
    /**
     * Takes a string of a pathname and splits it into a file name part and
     * a path part. The file name part is the part of the path following the
     * final forward slash. The path part is the part preceeding the final
     * forward slash. If there is no forward slash, the path part in "" and
     * the file name part is the contents of the string. Returns an array of
     * length two: the first element is the path part, and the second part is
     * the file name part.
     *
     * @param entry The pathname entry in the JAR file
     * @return An array of strings representing each file component
     */
    private String[] splitEntry(String entry) {
        /* Strip off the last '/' if one exists */
        if (entry.endsWith("/") == true) {
            entry = entry.substring(0, entry.length() - 1);
        }
       
        /*
         * Create an array of length two, and initialize for the case where
         * there is no forward slash present in the string.
         */
        String[] result = new String[2];
        int index = entry.lastIndexOf("/");
        result[0] = "";
        result[1] = entry;

        /* In the case where there are no more characters after the '/' */
        if (index == entry.length() - 1) {
            result[0] = entry.substring(0, index);
            result[1] = "";
        }
        else if (index != -1) {
            /* In the case where index != -1, set the path and file name parts */
            result[0] = entry.substring(0, index);
            result[1] = entry.substring(index + 1);
        }
       
        /* Else when there is no '/' in the string */
        return result;
    }
   
    /**
     * Takes a JAR file and creates a map, where each key in the map is a path
     * component, and its value is are either cell names or directories of
     * children of cells. The directory is structure is stored as follows:
     * <p>
     * 1. All directory entries do not have any trailing '/'.
     * 2. The top-level directories are stored under an empty string entry.
     * <p>
     * For example, if the following hierarchy exists in the JAR file:
     * world-wfs/
     * world-wfs/cell-wlc.xml
     * world-wfs/cell-wld/
     * world-wfs/cell-wld/a-wlc.xml
     * world-wfs/cell-wld/b-wlc.xml
     * <p>
     * then the map will contain the following entries:
     * "" : world-wfs
     * world-wfs : cell-wlc.xml, cell-wld
     * world-wfs/cell-wld : a-wlc.xml, b-wlc.xml
     * <p>
     * @param jarfile The JAR file
     */
    private void createArchiveMap(JarFile jarfile) {
        /* Initialize the tree map */
        this.fileMap = new HashMap<String, LinkedList<String>>();
        this.entryList = new LinkedList<String>();
       
        /*
         * Fetch the entries from the manifest file. Iterate over each of the
         * entries and parse the name into the path and file name components.
         * Add an entry into the map structure.
         */
        Enumeration<JarEntry> entries = jarfile.entries();
        while (entries.hasMoreElements() == true) {
            /* Fetch the next entry */
            JarEntry entry = entries.nextElement();
           
            /* Split the path name into a path and file name part */
            String entryName = entry.getName();
            String paths[] = this.splitEntry(entryName);
           
            /* Add the entry to the map, if it does not already exist */
            LinkedList<String> fnames = this.fileMap.get(paths[0]);
            if (fnames == null) {
                fnames = new LinkedList<String>();
                this.fileMap.put(paths[0], fnames);
            }
           
            /* Add the entry in the map so long as it is not empty */
            if (paths[1].equals("") == false) {
                fnames.add(paths[1]);
            }
           
            /* Always add the entry to the ordered list of entries */
            this.entryList.addLast(entryName);
        }
    }
}
TOP

Related Classes of org.jdesktop.wonderland.utils.ArchiveManifest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.