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

com.tangosol.dev.component.JarStorage Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

package com.tangosol.dev.component;


import com.tangosol.dev.assembler.ClassFile;

import com.tangosol.util.ErrorList;
import com.tangosol.util.StringTable;
import com.tangosol.util.SimpleEnumerator;

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;

import java.util.Enumeration;
import java.util.StringTokenizer;

import java.util.jar.JarFile;
import java.util.jar.JarEntry;


/**
* JarStorage loads classes from JAR file and turn them into
* Java Class Signatures. Component Definitions are not handled
* by the JarStorage, ArchivedStorage should be used instead.
*
* @version 1.00, 02/01/99
* @author  cp
* @author  gg
*/
public class JarStorage
        extends BaseStorage
    {
    // ----- constructors ---------------------------------------------------

    /**
    * Create a storage object backed by the specified jar.
    *
    * @param sFile  the path of the jar to read entries from
    * @param sRoot  relative path within the jar file that should
    *               be used to retrieve the resources
    *
    * Note: sRoot parameter could point to either directory (and must
    * be terminated by "/") or to an entry representing a contained jar.
    */
    public JarStorage(String sFile, String sRoot)
        {
        this(new File(sFile), sRoot);
        }

    /**
    * Create a storage object backed by the specified jar.
    *
    * @param file   the File object specifying the jar to read entries from
    * @param sRoot  relative path within the jar file that should
    *               be used to retrieve the resources
    *
    * Note: sRoot parameter could point to either directory (and must
    * be terminated by "/") or to an entry representing a contained jar.
    */
    public JarStorage(File file, String sRoot)
        {
        if (!(file.exists() && file.isFile()))
            {
            throw new IllegalArgumentException(CLASS + ":  Invalid file:  "
                    + file.toString());
            }

        if (!file.canRead())
            {
            throw new IllegalArgumentException(CLASS + ":  Read access required:  "
                    + file.toString());
            }

        JarFile jar;
        try
            {
            jar = new JarFile(file.getCanonicalFile());
            }
        catch (IOException e)
            {
            throw new IllegalArgumentException(CLASS + ":  Unable to open jar:  "
                    + file.toString() + " (" + e.getMessage() + ")");
            }

        if (sRoot == null)
            {
            sRoot = "";
            }
        else
            {
            // JarFile entries only allow forward slash
            sRoot = sRoot.replace('\\', '/');
            while (sRoot.startsWith("/"))
                {
                sRoot = sRoot.substring(1);
                }

            if (sRoot.length() > 0)
                {
                StringTokenizer tokens = new StringTokenizer(sRoot, "!");
                while (tokens.hasMoreTokens())
                    {
                    String sPath = tokens.nextToken();
                    if (sPath.endsWith("/"))
                        {
                        sRoot = sPath;
                        while (sRoot.startsWith("/"))
                            {
                            sRoot = sRoot.substring(1);
                            }

                        if (tokens.hasMoreTokens())
                            {
                            try
                                {
                                jar.close();
                                }
                            catch (IOException eIgnore) {}

                            throw new IllegalArgumentException(CLASS +
                                ": Illegal path " + sRoot + '!' + tokens.nextToken());
                            }
                        }
                    else
                        {
                        // the entry must be a contained jar
                        JarFile jarInner;
                        try
                            {
                            jarInner = extractJar(jar, sPath);
                            }
                        catch (IOException e)
                            {
                            throw ensureRuntimeException(e);
                            }
                        finally
                            {
                            try
                                {
                                jar.close();
                                }
                            catch (IOException e) {}
                            }

                        jar   = jarInner;
                        sRoot = "";
                        m_fDeleteOnClose = true;
                        }
                    }
                }
            }

        m_jar   = jar;
        m_sRoot = sRoot;
        }

    // ----- Components -----------------------------------------------------

    /**
    * Load the specified Component.
    *
    * @param sName      fully qualified Component Definition name
    * @param fReadOnly  true if the loaded component will be read-only
    * @param errlist    the ErrorList object to log any derivation/
    *                   modification errors to
    *
    * @return the specified Component Definition or null
    *
    * @exception ComponentException  if an unrecoverable error occurs
    */
    public Component loadComponent(String sName, boolean fReadOnly, ErrorList errlist)
            throws ComponentException
        {
        return Component.isQualifiedNameLegal(sName) ? null : loadSignature(sName);
        }

    /**
    * Store the specified Component.
    *
    * @param cd       the Component Definition
    * @param errlist  the ErrorList object to log any derivation/modification
    *                 errors to
    *
    * @exception ComponentException  if an unrecoverable error occurs
    */
    public void storeComponent(Component cd, ErrorList errlist)
            throws ComponentException
        {
        throw new UnsupportedOperationException("Read-only storage: " + this);
        }


    /**
    * Remove the specified Component.
    *
    * @param sName fully qualified Component Definition name
    *
    * @exception ComponentException  if an unrecoverable error occurs
    */
    public void removeComponent(String sName)
            throws ComponentException
        {
        throw new UnsupportedOperationException("Read-only storage: " + this);
        }


    // ----- Java Class Signatures ------------------------------------------

    /**
    * Load the specified Class Signature.
    *
    * @param sName    qualified Java Class Signature (JCS) name
    *
    * @return the specified Class Signature
    *
    * @exception ComponentException  if an unrecoverable error occurs
    */
    public Component loadSignature(String sName)
            throws ComponentException
        {
        ClassFile clzf = loadOriginalClass(sName);

        if (clzf == null)
            {
            return null;
            }

        // 2002-07-22 cp - support for parsing parameter names
        String sScript = null;
        try
            {
            sScript = loadJava(sName);
            }
        catch (Exception e)
            {
            }

        return new Component(clzf, sScript);
        }

    /**
    * Store the specified Java Class Signature.
    *
    * @param cdJCS  the Java Class Signature
    *
    * @exception ComponentException  if an unrecoverable error occurs
    */
    public void storeSignature(Component cdJCS)
            throws ComponentException
        {
        throw new UnsupportedOperationException("Read-only storage: " + this);
        }


    // ----- Classes --------------------------------------------------------

    /**
    * Load the original (before any customization takes place) Java Class.
    *
    * @param sName  fully qualified Java Class name
    *
    * @return the specified Class structure
    *
    * @exception ComponentException  if an unrecoverable error occurs
    */
    public ClassFile loadOriginalClass(String sName)
            throws ComponentException
        {
        try
            {
            DataInputStream stream = loadFile(sName.replace('.', '/') + ".class");

            return stream == null ? null : new ClassFile(stream);
            }
        catch (IOException e)
            {
            throw new ComponentException(e.toString());
            }
        }

    /**
    * Load the specified generated Java Class.
    *
    * @param sName  fully qualified Java Class name
    *
    * @return the specified Class structure
    *
    * @exception ComponentException  if an unrecoverable error occurs
    */
    public ClassFile loadClass(String sName)
            throws ComponentException
        {
        return null;
        }

    /**
    * Store the specified generated Java Class along with its listing
    *
    * @param clz       the generated Class structure to store
    * @param sListing  (optional) the java listing of the class
    *
    * @exception ComponentException  if an unrecoverable error occurs
    */
    public void storeClass(ClassFile clz, String sListing)
            throws ComponentException
        {
        throw new UnsupportedOperationException("Read-only storage: " + this);
        }


    // ----- Java -------------------------------------------------------------

    /**
    * Load the source code for the specified (original) Java class.
    *
    * @param sName  fully qualified Java Class name
    *
    * @return the specified Java source code as a String
    *
    * @exception IOException  if an unrecoverable error occurs
    */
    public String loadJava(String sName)
            throws IOException
        {
        byte[] ab = loadFileBytes(sName.replace('.', '/') + ".java");

        if (ab == null)
            {
            int of = sName.indexOf('$');
            if (of != -1)
                {
                sName = sName.substring(0, of).replace('.', '/');
                ab    = loadFileBytes(sName + ".java");
                }
            }

        return ab == null ? null : new String(ab);
        }


    // ----- Resources --------------------------------------------------------

    /**
    * Load the original (before any customization takes place) resource.
    *
    * @param sName  fully qualified resource name
    *
    * @return the specified resource as a byte array
    *
    * @exception IOException  if an unrecoverable error occurs
    */
    public byte[] loadOriginalResource(String sName)
            throws IOException
        {
        return loadFileBytes(sName);
        }

    /**
    * Load the Resource Signature.
    *
    * @param sName  fully qualified resource name
    *
    * @return the specified Resource Signature as a byte array
    *
    * @exception IOException  if an unrecoverable error occurs
    */
    public byte[] loadResourceSignature(String sName)
            throws IOException
        {
        return loadOriginalResource(sName);
        }

    /**
    * Store the specified Resource Signature.
    *
    * @param sName  fully qualified resource name
    * @param abData the specified Resource Signature as a byte array
    *
    * @exception IOException  if an unrecoverable error occurs
    */
    public void storeResourceSignature(String sName, byte[] abData)
            throws IOException
        {
        throw new UnsupportedOperationException("Read-only storage: " + this);
        }

    /**
    * Remove the specified Resource Signature
    *
    * @param sName fully qualified resource name
    *
    * @exception IOException  if an unrecoverable error occurs
    */
    public void removeResourceSignature(String sName)
            throws IOException
        {
        throw new UnsupportedOperationException("Read-only storage: " + this);
        }

    /**
    * Load the generated resource.
    *
    * @param sName  fully qualified resource name
    *
    * @return the specified resource as a byte array
    *
    * @exception IOException  if an unrecoverable error occurs
    */
    public byte[] loadResource(String sName)
            throws IOException
        {
        return null;
        }

    /**
    * Store the specified resource.
    *
    * @param sName  fully qualified resource name
    * @param abData the specified resource as a byte array
    *
    * @exception IOException  if an unrecoverable error occurs
    */
    public void storeResource(String sName, byte[] abData)
            throws IOException
        {
        throw new UnsupportedOperationException("Read-only storage: " + this);
        }


    // ---- component management --------------------------------------------

    /**
    * Return a StringTable which contains the names of Component Definitions
    * (CD) that derive from the specified Component Definition
    *
    * @param  sComponent  the qualified CD name
    * @param  fQualify    if set to true, return fully qualified CD names;
    *                     otherwise -- non-qualified names
    *
    * @return StringTable object with Component Definition names as keys
    */
    public StringTable getSubComponents(String sComponent, boolean fQualify)
        {
        return new StringTable();
        }

    /**
    * Return a StringTable which contains the names of Component Definitions
    * (CD) that belong to the specified package
    *
    * @param  sPackage  the qualified package name
    * @param  fQualify  if set to true, return fully qualified CD names;
    *                   otherwise -- non-qualified names
    *
    * @return StringTable object with CD names as keys
    */
    public StringTable getPackageComponents(String sPackage, boolean fQualify)
        {
        return new StringTable();
        }

    /**
    * Return a StringTable which contains the names of sub-packages in
    * the specified component package
    *
    * @param sPackage   the qualified package name; pass null to retrieve
    *                   the top level component packages
    * @param fQualify   if set to true, return fully qualified package names;
    *                   otherwise -- non-qualified names
    * @param fSubs      if set to true, returns the entire tree of sub-packages
    *
    * @return StringTable object with package names as keys
    */
    public StringTable getComponentPackages(String sPackage, boolean fQualify, boolean fSubs)
        {
        return new StringTable();
        }

    /**
    * Return a StringTable which contains the names of Java Class Signature
    * (JCS) names that belong to the specified java class package
    * (i.e. "javax.swing")
    *
    * @param sPackage   the qualified package name
    * @param fQualify   if set to true, return fully qualified JCS names;
    *                   otherwise -- non-qualified names
    *
    * @return StringTable object with JCS names as keys
    */
    public StringTable getPackageSignatures(String sPackage, boolean fQualify)
        {
        ensureContents();
        return getNamesFromPackage(m_tblClasses, sPackage, fQualify, '.');
        }

    /**
    * Return a StringTable which contains the names of sub-packages in
    * the specified java class package
    * (i.e. "javax.swing" is a sub-package of "javax" package)
    *
    * @param sPackage   the qualified package name; pass null to retrieve
    *                   the top level java class packages
    * @param fQualify   if set to true, return fully qualified JCS names;
    *                   otherwise -- non-qualified names
    * @param fSubs      if set to true, returns the entire tree of sub-packages
    *
    * @return StringTable object with package names as keys
    */
    public StringTable getSignaturePackages(String sPackage, boolean fQualify, boolean fSubs)
        {
        StringTable tblAll = m_tblClassPackages;
        if (tblAll == null)
            {
            ensureContents();
            m_tblClassPackages = tblAll = ensurePackages(m_tblClasses);
            }
        return extractPackages(tblAll, sPackage, fQualify, fSubs, '.');
        }

    /**
    * Return a StringTable which contains the names of resource
    * names that belong to the specified package
    * (i.e. "img/tde")
    *
    * @param sPackage   the qualified package name
    * @param fQualify   if set to true, return fully qualified resource names;
    *                   otherwise -- non-qualified names
    *
    * @return StringTable object with resource names as keys
    */
    public StringTable getPackageResources(String sPackage, boolean fQualify)
        {
        ensureContents();
        return getNamesFromPackage(m_tblResources, sPackage, fQualify, '/');
        }

    /**
    * Return a StringTable which contains the names of sub-packages in
    * the specified resource package
    * (i.e. "img/tde" is a sub-package of "img" package)
    *
    * @param sPackage   the qualified package name; pass null to retrieve
    *                   the top level resource packages
    * @param fQualify   if set to true, return fully qualified package names;
    *                   otherwise -- non-qualified names
    * @param fSubs      if set to true, returns the entire tree of sub-packages
    *
    * @return StringTable object with package names as keys
    */
    public StringTable getResourcePackages(String sPackage, boolean fQualify, boolean fSubs)
        {
        StringTable tblAll = m_tblResourcePackages;
        if (tblAll == null)
            {
            ensureContents();
            m_tblResourcePackages = tblAll = ensurePackages(m_tblResources);
            }
        return extractPackages(tblAll, sPackage, fQualify, fSubs, '/');
        }


    /**
    * Close the storage and release all the resources
    */
    public void close()
        {
        // using File.deleteOnExit wouldn't help since without closing the jar
        // the file would not be deleted anyway (see bug id #4171239)
        if (m_jar != null)
            {
            try
                {
                m_jar.close();
                if (m_fDeleteOnClose)
                    {
                    new File(m_jar.getName()).delete();
                    }
                }
            catch (IOException e)
                {
                }
            finally
                {
                m_jar = null;
                }
            }
        }


    // ----- accessors ------------------------------------------------------

    /**
    * @return the jar file that backs up this JarStorage
    */
    public JarFile getJar()
        {
        return m_jar;
        }

    /**
    * @return the path within the jar file that should be used to retrieve
    * the jar entries.
    */
    public String getRoot()
        {
        return m_sRoot;
        }

    // ----- helpers --------------------------------------------------------

    /**
    * Extract an entry representing a jar file out of the specified jar
    * into a temporary file. Caller is supposed to delete this file
    * when the JarFile object is no longer used.
    *
    * @param jar    the enclosing jar file
    * @param sPath  entry name representing an enclosed jar file
    *
    * @return a JarFile object backed up by a temporary file
    */
    public static JarFile extractJar(JarFile jar, String sPath)
            throws IOException
        {
        JarEntry    entry    = jar.getJarEntry(sPath);
        InputStream streamIn = entry == null ? null : jar.getInputStream(entry);
        if (streamIn == null)
            {
            throw new IOException(CLASS +
                ":  Unable to open contained jar:  " + jar.getName() + "!/" + sPath);
            }

        String sName   = sPath.substring(sPath.lastIndexOf('/') + 1);
        int    of      = sName.lastIndexOf('.');
        String sPrefix = of >= 3 ? sName.substring(0, of) : "tmp";
        String sSuffix = of >= 0 && of < sName.length() - 3 ? sName.substring(of) : ".jar";

        File             fileTemp  = File.createTempFile(sPrefix, sSuffix, null);
        FileOutputStream streamOut = new FileOutputStream(fileTemp);

        try
            {
            int    cbBlock = 4096;
            byte[] ab      = new byte[cbBlock];

            while (true)
                {
                int cb = read(streamIn, ab);
                if (cb <= 0)
                    {
                    break;
                    }
                streamOut.write(ab, 0, cb);
                }
            }
        finally
            {
            streamIn .close();
            streamOut.close();
            }

        return new JarFile(fileTemp);
        }

    /**
    * Provide the contents of the specified item as a data input stream.
    *
    * @param sName  the name of the item, potentially dot-delimited
    *
    * @return   the file contents as a data input stream; null if the item
    *           does not exist
    */
    protected DataInputStream loadFile(String sName)
            throws IOException
        {
        String   sEntry = sName.startsWith("/") ? sName.substring(1) : m_sRoot + sName;
        JarEntry entry  = m_jar.getJarEntry(sEntry);

        return entry == null ? null :
            new DataInputStream(m_jar.getInputStream(entry));
        }

    /**
    * Provide the contents of the specified item as a byte array.
    *
    * @param sName  the entry name to be loaded
    *
    * @return  the file contents as a byte array;null if the item
    *           does not exist
    */
    protected byte[] loadFileBytes(String sName)
            throws IOException
        {
        final long MAX_SIZE = 0x500000L; // 0.5Meg

        String   sEntry = sName.startsWith("/") ? sName.substring(1) : m_sRoot + sName;
        JarEntry entry  = m_jar.getJarEntry(sEntry);

        if (entry == null)
            {
            return null;
            }

        long lSize = entry.getSize();
        if (lSize > MAX_SIZE)
            {
            throw new IOException(CLASS + ".loadFileBytes: " +
                "Entry " + sEntry + " exceeds maximum size");
            }

        InputStream     streamRaw  = m_jar.getInputStream(entry);
        DataInputStream streamData = new DataInputStream(streamRaw);

        // bug Id 4295717: JarInputStream.read(byte[] b,int off, int len) not working properly
        // m_jar.getInputStream(entry).read(ab, 0, cb);

        byte[] ab = read(streamData);

        if (ab.length != lSize)
            {
            throw new EOFException(CLASS + ".loadFileBytes: " +
                "Premature EOF: " + sEntry + " expected=" + lSize + " actual=" + ab.length);
            }
        streamRaw.close();

        return ab;
        }

    /**
    * Make sure an index of the JAR has been loaded.
    */
    protected void ensureContents()
        {
        if (m_tblClasses != null)
            {
            return;
            }

        m_tblClasses   = new StringTable();
        m_tblResources = new StringTable();

        String sPrefix = m_sRoot;

        for (Enumeration enmr = m_jar.entries(); enmr.hasMoreElements();)
            {
            JarEntry entry  = (JarEntry) enmr.nextElement();
            String   sEntry = entry.getName();
            int      iType  = getEntryType(sEntry);

            if (iType != -1)
                {
                if (sEntry.startsWith(sPrefix))
                    {
                    sEntry = sEntry.substring(sPrefix.length());
                    }
                addContentEntry(sEntry, iType);
                }
            }
        }

    /**
    * @return a type of the specified entry; -1 if the entry type is not known
    */
    protected int getEntryType(String sEntry)
        {
        String sPrefix = m_sRoot;

        if (sEntry.startsWith(sPrefix))
            {
            // everything but .class and .java is a resource
            // (except the "META-INF/Manifest.mf" entry)
            if (sEntry.endsWith(".class"))
                {
                return T_CLASS;
                }

            if (!sEntry.endsWith("/") && !sEntry.endsWith("java") &&
                !sEntry.equalsIgnoreCase("META-INF/Manifest.mf"))
                {
                return T_RES_BINARY;
                }
            }
        return -1;
        }

    /**
    * Add the specified entry to the content of the specified type
    */
    protected void addContentEntry(String sEntry, int iType)
        {
        switch (iType)
            {
            case T_CLASS:
                {
                // ".class".length() == 6
                String sClz = sEntry.substring(0, sEntry.length() - 6);
                m_tblClasses.put(sClz, getLocator());
                break;
                }

            case T_RES_BINARY:
                {
                m_tblResources.put(sEntry, getLocator());
                break;
                }
            }
        }

    /**
    * Create a StringTable of packages for the specified table of names
    */
    protected StringTable ensurePackages(StringTable tblNames)
        {
        Object      oLocator = getLocator();
        StringTable tblPkg   = new StringTable();
        String      sPrev    = "";
        for (Enumeration enmr = tblNames.keys(); enmr.hasMoreElements();)
            {
            String sName = (String) enmr.nextElement();

            int    of    = sName.lastIndexOf('/');
            if (of > 0)
                {
                // get name of pkg
                sName = sName.substring(0, of);

                // avoid repetitions
                if (!sName.equals(sPrev))
                    {
                    // make sure that all the sub-packages are registered as well
                    while (true)
                        {
                        of = sName.lastIndexOf('/', of - 1);
                        if (of < 0)
                            {
                            break;
                            }
                        tblPkg.put(sName.substring(0, of), oLocator);
                        }
                    tblPkg.put(sName, oLocator);
                    sPrev = sName;
                    }
                }
            }

        return tblPkg;
        }

    protected StringTable getNamesFromPackage(StringTable tblAll,
                                               String sPackage, boolean fQualify, char chDelim)
        {
        StringTable tbl = new StringTable();

        sPackage = (sPackage == null || sPackage.length() == 0) ? "" : sPackage + '/';
        if (chDelim != '/')
            {
            sPackage = sPackage.replace(chDelim, '/');
            }

        boolean fPreserveAbsoluteName = false;
        if (sPackage.startsWith("/"))
            {
            fPreserveAbsoluteName = true;
            sPackage = sPackage.substring(1);
            }

        int      cchPackage = sPackage.length();
        String[] asNames    = tblAll.stringsStartingWith(sPackage);

        if (asNames.length == 0)
            {
            return tbl;
            }

        Object oLocator = getLocator();

        for (Enumeration enmr = new SimpleEnumerator(asNames); enmr.hasMoreElements();)
            {
            String sName = (String) enmr.nextElement();

            if (sName.indexOf('/', cchPackage) < 0)
                {
                if (!fQualify)
                    {
                    sName = sName.substring(cchPackage);
                    }
                else if (chDelim != '/')
                    {
                    sName = sName.replace('/', chDelim);
                    }

                if (fPreserveAbsoluteName)
                    {
                    sName = "/" + sName;
                    }
                tbl.put(sName, oLocator);
                }
            }

        return tbl;
        }

    protected StringTable extractPackages(StringTable tblAll, String sPackage,
                                           boolean fQualify, boolean fSubs, char chDelim)
        {
        if (fSubs)
            {
            fQualify = true;
            }

        StringTable tblSub = new StringTable();

        sPackage = (sPackage == null || sPackage.length() == 0) ? "" : sPackage + '/';
        if (chDelim != '/')
            {
            sPackage = sPackage.replace(chDelim, '/');
            }

        int      cchPackage = sPackage.length();
        String[] asNames    = tblAll.stringsStartingWith(sPackage);

        if (asNames.length == 0)
            {
            return tblSub;
            }

        Object oLocator = getLocator();

        for (Enumeration enmr = new SimpleEnumerator(asNames); enmr.hasMoreElements();)
            {
            String sName = (String) enmr.nextElement();

            int of = sName.indexOf('/', cchPackage);
            if (of < 0)
                {
                if (!fQualify)
                    {
                    sName = sName.substring(cchPackage);
                    }
                else if (chDelim != '/')
                    {
                    sName = sName.replace('/', chDelim);
                    }

                tblSub.put(sName, oLocator);

                if (fSubs)
                    {
                    tblSub.addAll(extractPackages(tblAll, sName, true, true, chDelim));
                    }
                }
            }

        return tblSub;
        }


    // ----- Object methods -------------------------------------------------

    /**
    * Provide a short human-readable description of the trait.
    *
    * @return a human-readable description of this trait
    */
    public String toString()
        {
        return CLASS + '(' + m_jar.getName() + "!/" + m_sRoot + ')';
        }


    // ----- data members ---------------------------------------------------

    /**
    * The name of this class.
    */
    private static final String CLASS = "JarStorage";

    /**
    * The component type of entry
    */
    protected static final int T_COMPONENT   = 0;
    /**
    * The Java Class Signature type of entry.
    */
    protected static final int T_SIGNATURE   = 1;
    /**
    * The Java Classes type of entry.
    */
    protected static final int T_CLASS       = 2;
    /**
    * The Java source type of entry.
    */
    protected static final int T_JAVA        = 3;
    /**
    * The Resource Signature type of entry.
    */
    protected static final int T_RES_SIG     = 4;
    /**
    * The [resolved] Resource type of entry.
    */
    protected static final int T_RES_BINARY  = 5;

    /**
    * The JarFile that backs up this JarStorage
    */
    private JarFile m_jar;

    /**
    * The relative path within the jar file that should
    * be used to retrieve the entries. It could point to either directory
    * or an entry representing a contained jar.
    */
    private String m_sRoot;

    /**
    * Specifies whether the jar file is a temporary one
    * and should be removed when this storage is gc'ed
    */
    private transient boolean m_fDeleteOnClose = false;

    // cache tables (all entries are '/'-delimited)
    protected transient StringTable m_tblClasses;
    protected transient StringTable m_tblClassPackages;

    protected transient StringTable m_tblResources;
    protected transient StringTable m_tblResourcePackages;
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy