/*
 *   Copyright 2005 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */
package org.apache.osgi.framework.cache;

import java.io.*;
import java.security.*;
import java.util.*;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

import org.apache.osgi.framework.LogWrapper;
import org.apache.osgi.framework.util.*;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;

/**
 * <p>
 * This class, combined with <tt>DefaultBundleCache</tt>, implements the
 * default file system-based bundle cache for Felix.
 * </p>
 * @see org.apache.osgi.framework.util.DefaultBundleCache
**/
public class DefaultBundleArchive implements BundleArchive
{
    private static final transient String BUNDLE_JAR_FILE = "bundle.jar";
    private static final transient String BUNDLE_LOCATION_FILE = "bundle.location";
    private static final transient String BUNDLE_STATE_FILE = "bundle.state";
    private static final transient String BUNDLE_START_LEVEL_FILE = "bundle.startlevel";
    private static final transient String REFRESH_COUNTER_FILE = "refresh.counter";
    private static final transient String BUNDLE_ACTIVATOR_FILE = "bundle.activator";

    private static final transient String REVISION_DIRECTORY = "version";
    private static final transient String EMBEDDED_DIRECTORY = "embedded";
    private static final transient String LIBRARY_DIRECTORY = "lib";
    private static final transient String DATA_DIRECTORY = "data";

    private static final transient String ACTIVE_STATE = "active";
    private static final transient String INSTALLED_STATE = "installed";
    private static final transient String UNINSTALLED_STATE = "uninstalled";

    private LogWrapper m_logger = null;
    private long m_id = -1;
    private File m_dir = null;
    private String m_location = null;
    private int m_persistentState = -1;
    private int m_startLevel = -1;
    private Map m_currentHeader = null;

    private long m_refreshCount = -1;
    private int m_revisionCount = -1;

    public DefaultBundleArchive(LogWrapper logger, File dir, long id, String location, InputStream is)    
        throws Exception
    {
        this(logger, dir, id);
        m_location = location;

        // Try to save and pre-process the bundle JAR.
        try
        {
            initialize(is);
        }
        catch (Exception ex)
        {
            if (!deleteDirectoryTree(dir))
            {
                m_logger.log(
                    LogWrapper.LOG_ERROR,
                    "Unable to delete the archive directory: " + id);
            }
            throw ex;
        }
    }

    public DefaultBundleArchive(LogWrapper logger, File dir, long id)
    {
        m_logger = logger;
        m_dir = dir;
        m_id = id;
        if (m_id <= 0)
        {
            throw new IllegalArgumentException(
                "Bundle ID cannot be less than or equal to zero.");
        }
    }

    private void initialize(InputStream is)
        throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.INITIALIZE_ACTION, this, is));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            initializeUnchecked(is);
        }
    }

    private void initializeUnchecked(InputStream is)
        throws Exception
    {
        FileWriter fw = null;
        BufferedWriter bw = null;

        try
        {
            // Create archive directory.
            if (!m_dir.mkdir())
            {
                m_logger.log(
                    LogWrapper.LOG_ERROR,
                    "DefaultBundleArchive: Unable to create archive directory.");
                throw new IOException("Unable to create archive directory.");
            }

            // Save location string.
            File file = new File(m_dir, BUNDLE_LOCATION_FILE);
            fw = new FileWriter(file);
            bw = new BufferedWriter(fw);
            bw.write(m_location, 0, m_location.length());

            // Create version/revision directory for bundle JAR.
            // Since this is only called when the bundle JAR is
            // first saved, the update and revision will always
            // be "0.0" for the directory name.
            File revisionDir = new File(m_dir, REVISION_DIRECTORY + "0.0");
            if (!revisionDir.mkdir())
            {
                m_logger.log(
                    LogWrapper.LOG_ERROR,
                    "DefaultBundleArchive: Unable to create revision directory.");
                throw new IOException("Unable to create revision directory.");
            }

            // Save the bundle jar file.
            file = new File(revisionDir, BUNDLE_JAR_FILE);
            copy(is, file);

            // This will always be revision zero.
            preprocessBundleJar(0, revisionDir);

        }
        finally
        {
            if (is != null) is.close();
            if (bw != null) bw.close();
            if (fw != null) fw.close();
        }
    }

    public File getDirectory()
    {
        return m_dir;
    }

    public long getId()
    {
        return m_id;
    }

    public String getLocation()
        throws Exception
    {
        if (m_location != null)
        {
            return m_location;
        }
        else if (System.getSecurityManager() != null)
        {
            try
            {
                return (String) AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.GET_LOCATION_ACTION, this));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            return getLocationUnchecked();
        }
    }

    private String getLocationUnchecked()
        throws Exception
    {
        // Get bundle location file.
        File locFile = new File(m_dir, BUNDLE_LOCATION_FILE);

        // Read bundle location.
        FileReader fr = null;
        BufferedReader br = null;
        try
        {
            fr = new FileReader(locFile);
            br = new BufferedReader(fr);
            m_location = br.readLine();
            return m_location;
        }
        finally
        {
            if (br != null) br.close();
            if (fr != null) fr.close();
        }
    }

    public int getPersistentState()
        throws Exception
    {
        if (m_persistentState >= 0)
        {
            return m_persistentState;
        }
        else if (System.getSecurityManager() != null)
        {
            try
            {
                return ((Integer) AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.GET_PERSISTENT_STATE_ACTION, this))).intValue();
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            return getPersistentStateUnchecked();
        }
    }

    private int getPersistentStateUnchecked()
        throws Exception
    {
        // Get bundle state file.
        File stateFile = new File(m_dir, BUNDLE_STATE_FILE);

        // If the state file doesn't exist, then
        // assume the bundle was installed.
        if (!stateFile.exists())
        {
            return Bundle.INSTALLED;
        }

        // Read the bundle state.
        FileReader fr = null;
        BufferedReader br= null;
        try
        {
            fr = new FileReader(stateFile);
            br = new BufferedReader(fr);
            String s = br.readLine();
            if (s.equals(ACTIVE_STATE))
            {
                m_persistentState = Bundle.ACTIVE;
            }
            else if (s.equals(UNINSTALLED_STATE))
            {
                m_persistentState = Bundle.UNINSTALLED;
            }
            else
            {
                m_persistentState = Bundle.INSTALLED;
            }
            return m_persistentState;
        }
        finally
        {
            if (br != null) br.close();
            if (fr != null) fr.close();
        }
    }

    public void setPersistentState(int state)
        throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.SET_PERSISTENT_STATE_ACTION, this, state));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            setPersistentStateUnchecked(state);
        }
    }

    private void setPersistentStateUnchecked(int state)
        throws Exception
    {
        // Get bundle state file.
        File stateFile = new File(m_dir, BUNDLE_STATE_FILE);

        // Write the bundle state.
        FileWriter fw = null;
        BufferedWriter bw= null;
        try
        {
            fw = new FileWriter(stateFile);
            bw = new BufferedWriter(fw);
            String s = null;
            switch (state)
            {
                case Bundle.ACTIVE:
                    s = ACTIVE_STATE;
                    break;
                case Bundle.UNINSTALLED:
                    s = UNINSTALLED_STATE;
                    break;
                default:
                    s = INSTALLED_STATE;
                    break;
            }
            bw.write(s, 0, s.length());
            m_persistentState = state;
        }
        catch (IOException ex)
        {
            m_logger.log(
                LogWrapper.LOG_ERROR,
                "DefaultBundleArchive: Unable to record state: " + ex);
            throw ex;
        }
        finally
        {
            if (bw != null) bw.close();
            if (fw != null) fw.close();
        }
    }

    public int getStartLevel()
        throws Exception
    {
        if (m_startLevel >= 0)
        {
            return m_startLevel;
        }
        else if (System.getSecurityManager() != null)
        {
            try
            {
                return ((Integer) AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.GET_START_LEVEL_ACTION, this))).intValue();
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            return getStartLevelUnchecked();
        }
    }

    private int getStartLevelUnchecked()
        throws Exception
    {
        // Get bundle start level file.
        File levelFile = new File(m_dir, BUNDLE_START_LEVEL_FILE);

        // If the start level file doesn't exist, then
        // return an error.
        if (!levelFile.exists())
        {
            return -1;
        }

        // Read the bundle start level.
        FileReader fr = null;
        BufferedReader br= null;
        try
        {
            fr = new FileReader(levelFile);
            br = new BufferedReader(fr);
            m_startLevel = Integer.parseInt(br.readLine());
            return m_startLevel;
        }
        finally
        {
            if (br != null) br.close();
            if (fr != null) fr.close();
        }
    }

    public void setStartLevel(int level)
        throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.SET_START_LEVEL_ACTION, this, level));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            setStartLevelUnchecked(level);
        }
    }

    private void setStartLevelUnchecked(int level)
        throws Exception
    {
        // Get bundle start level file.
        File levelFile = new File(m_dir, BUNDLE_START_LEVEL_FILE);

        // Write the bundle start level.
        FileWriter fw = null;
        BufferedWriter bw = null;
        try
        {
            fw = new FileWriter(levelFile);
            bw = new BufferedWriter(fw);
            String s = Integer.toString(level);
            bw.write(s, 0, s.length());
            m_startLevel = level;
        }
        catch (IOException ex)
        {
            m_logger.log(
                LogWrapper.LOG_ERROR,
                "DefaultBundleArchive: Unable to record start leel: " + ex);
            throw ex;
        }
        finally
        {
            if (bw != null) bw.close();
            if (fw != null) fw.close();
        }
    }

    public File getDataFile(String fileName)
        throws Exception
    {
        // Do some sanity checking.
        if ((fileName.length() > 0) && (fileName.charAt(0) == File.separatorChar))
            throw new IllegalArgumentException("The data file path must be relative, not absolute.");
        else if (fileName.indexOf("..") >= 0)
            throw new IllegalArgumentException("The data file path cannot contain a reference to the \"..\" directory.");

        // Get bundle data directory.
        File dataDir = new File(m_dir, DATA_DIRECTORY);

        if (System.getSecurityManager() != null)
        {
            try
            {
                AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.CREATE_DATA_DIR_ACTION, this, dataDir));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            createDataDirectoryUnchecked(dataDir);
        }

        // Return the data file.
        return new File(dataDir, fileName);
    }

    private void createDataDirectoryUnchecked(File dir)
        throws Exception
    {
        // Create data directory if necessary.
        if (!dir.exists())
        {
            if (!dir.mkdir())
            {
                throw new IOException("Unable to create bundle data directory.");
            }
        }
    }

    public BundleActivator getActivator(ClassLoader loader)
        throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                return (BundleActivator) AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.GET_ACTIVATOR_ACTION, this, loader));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            return getActivatorUnchecked(loader);
        }
    }

    private BundleActivator getActivatorUnchecked(ClassLoader loader)
        throws Exception
    {
        // Get bundle activator file.
        File activatorFile = new File(m_dir, BUNDLE_ACTIVATOR_FILE);
        // If the activator file doesn't exist, then
        // assume there isn't one.
        if (!activatorFile.exists())
            return null;

        // Deserialize the activator object.
        InputStream is = null;
        ObjectInputStreamX ois = null;
        try
        {
            is = new FileInputStream(activatorFile);
            ois = new ObjectInputStreamX(is, loader);
            Object o = ois.readObject();
            return (BundleActivator) o;
        }
        catch (Exception ex)
        {
            m_logger.log(
                LogWrapper.LOG_ERROR,
                "DefaultBundleArchive: Trying to deserialize - " + ex);
        }
        finally
        {
            if (ois != null) ois.close();
            if (is != null) is.close();
        }

        return null;
    }

    public void setActivator(Object obj)
        throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.SET_ACTIVATOR_ACTION, this, obj));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            setActivatorUnchecked(obj);
        }
    }

    private void setActivatorUnchecked(Object obj)
        throws Exception
    {
        if (!(obj instanceof Serializable))
        {
            return;
        }

        // Get bundle activator file.
        File activatorFile = new File(m_dir, BUNDLE_ACTIVATOR_FILE);

        // Serialize the activator object.
        OutputStream os = null;
        ObjectOutputStream oos = null;
        try
        {
            os = new FileOutputStream(activatorFile);
            oos = new ObjectOutputStream(os);
            oos.writeObject(obj);
        }
        catch (IOException ex)
        {
            m_logger.log(
                LogWrapper.LOG_ERROR,
                "DefaultBundleArchive: Unable to serialize activator - " + ex);
            throw ex;
        }
        finally
        {
            if (oos != null) oos.close();
            if (os != null) os.close();
        }
    }

    public int getRevisionCount()
        throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                return ((Integer) AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.GET_REVISION_COUNT_ACTION, this))).intValue();
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            return getRevisionCountUnchecked();
        }
    }

    public int getRevisionCountUnchecked()
    {
        // We should always have at least one revision
        // directory, so try to count them if the value
        // has not been initialized yet.
        if (m_revisionCount <= 0)
        {
            m_revisionCount = 0;
            File[] children = m_dir.listFiles();
            for (int i = 0; (children != null) && (i < children.length); i++)
            {
                if (children[i].getName().startsWith(REVISION_DIRECTORY))
                {
                    m_revisionCount++;
                }
            }
        }
        return m_revisionCount;
    }

    public Map getManifestHeader(int revision)
        throws Exception
    {
        // If the request is for the current revision header,
        // then return the cached copy if it is present.
        if ((revision == (getRevisionCount() - 1)) && (m_currentHeader != null))
        {
            return m_currentHeader;
        }

        // Get the revision directory.
        File revisionDir = new File(
            m_dir, REVISION_DIRECTORY + getRefreshCount() + "." + revision);

        // Get the embedded resource.
        JarFile jarFile = null;

        try
        {
            // Create JarFile object using privileged block.
            if (System.getSecurityManager() != null)
            {
                jarFile = (JarFile) AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.OPEN_BUNDLE_JAR_ACTION, this, revisionDir));
            }
            else
            {
                jarFile = openBundleJarUnchecked(revisionDir);
            }

            // Error if no jar file.
            if (jarFile == null)
            {
                throw new IOException("No JAR file found.");
            }

            // Get manifest.
            Manifest mf = jarFile.getManifest();
            // Create a case insensitive map of manifest attributes.
            Map map = new CaseInsensitiveMap(mf.getMainAttributes());
            // If the request is for the current revision's header,
            // then cache it.
            if (revision == (getRevisionCount() - 1))
            {
                m_currentHeader = map;
            }
            return map;

        } catch (PrivilegedActionException ex) {
            throw ((PrivilegedActionException) ex).getException();
        } finally {
            if (jarFile != null) jarFile.close();
        }
    }

    private JarFile openBundleJarUnchecked(File revisionDir)
        throws Exception
    {
        // Get bundle jar file.
        File bundleJar = new File(revisionDir, BUNDLE_JAR_FILE);
        // Get bundle jar file.
        return new JarFile(bundleJar);
    }

    public String[] getClassPath(int revision)
        throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                return (String []) AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.GET_CLASS_PATH_ACTION, this, revision));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            return getClassPathUnchecked(revision);
        }
    }

    private String[] getClassPathUnchecked(int revision)
        throws Exception
    {
        // Get the revision directory.
        File revisionDir = new File(
            m_dir, REVISION_DIRECTORY + getRefreshCount() + "." + revision);

        // Get the bundle's manifest header.
        Map map = getManifestHeader(revision);
        if (map == null)
        {
            map = new HashMap();
        }

        // Find class path meta-data.
        String classPath = null;
        Iterator iter = map.entrySet().iterator();
        while ((classPath == null) && iter.hasNext())
        {
            Map.Entry entry = (Map.Entry) iter.next();
            if (entry.getKey().toString().toLowerCase().equals(
                FelixConstants.BUNDLE_CLASSPATH.toLowerCase()))
            {
                classPath = entry.getValue().toString();
            }
        }

        // Parse the class path into strings.
        String[] classPathStrings = Util.parseDelimitedString(
            classPath, FelixConstants.CLASS_PATH_SEPARATOR);

        if (classPathStrings == null)
        {
            classPathStrings = new String[0];
        }

        // Now, check for "." in the class path.
        boolean includeDot = false;
        for (int i = 0; !includeDot && (i < classPathStrings.length); i++)
        {
            if (classPathStrings[i].equals(FelixConstants.CLASS_PATH_DOT))
            {
                includeDot = true;
            }
        }

        // Include all JARs in the embedded jar directory, since they
        // were extracted when the bundle was initially saved.
        File embedDir = new File(revisionDir, EMBEDDED_DIRECTORY);
        String[] paths = null;
        if (embedDir.exists())
        {
            // The size of the paths array is the number of
            // embedded JAR files plus one, if we need to include
            // ".", otherwise it is just the number of JAR files.
            // If "." is included, then it will be added to the
            // first place in the path array below.
            File[] children = embedDir.listFiles();
            int size = (children == null) ? 0 : children.length;
            size = (includeDot) ? size + 1 : size;
            paths = new String[size];
            for (int i = 0; i < children.length; i++)
            {
                // If we are including "." then skip the first slot,
                // because this is where we will put the bundle JAR file.
                paths[(includeDot) ? i + 1 : i] = children[i].getPath();
            }
        }

        // If there is nothing on the class path, then include
        // "." by default, as per the spec.
        if ((paths == null) || (paths.length == 0))
        {
            includeDot = true;
            paths = new String[1];
        }

        // Put the bundle jar file first, if included.
        if (includeDot)
        {
            paths[0] = revisionDir + File.separator + BUNDLE_JAR_FILE;
        }

        return paths;
    }

//  TODO: This will need to consider security.
    public String findLibrary(int revision, String libName)
        throws Exception
    {
        return findLibraryUnchecked(revision, libName);
    }

    private String findLibraryUnchecked(int revision, String libName)
        throws Exception
    {
        // Get the revision directory.
        File revisionDir = new File(
            m_dir.getAbsoluteFile(),
            REVISION_DIRECTORY + getRefreshCount() + "." + revision);

        // Get bundle lib directory.
        File libDir = new File(revisionDir, LIBRARY_DIRECTORY);
        // Get lib file.
        File libFile = new File(libDir, File.separatorChar + libName);
        // Make sure that the library's parent directory exists;
        // it may be in a sub-directory.
        libDir = libFile.getParentFile();
        if (!libDir.exists())
        {
            if (!libDir.mkdirs())
            {
                throw new IOException("Unable to create library directory.");
            }
        }
        // Extract the library from the JAR file if it does not
        // already exist.
        if (!libFile.exists())
        {
            JarFile jarFile = null;
            InputStream is = null;

            try
            {
                jarFile = openBundleJarUnchecked(revisionDir);
                ZipEntry ze = jarFile.getEntry(libName);
                if (ze == null)
                {
                    throw new IOException("No JAR entry: " + libName);
                }
                is = new BufferedInputStream(
                    jarFile.getInputStream(ze), DefaultBundleCache.BUFSIZE);
                if (is == null)
                {
                    throw new IOException("No input stream: " + libName);
                }

                // Create the file.
                copy(is, libFile);

            }
            finally
            {
                if (jarFile != null) jarFile.close();
                if (is != null) is.close();
            }
        }

        return libFile.toString();
    }

    /**
     * This utility method is used to retrieve the current refresh
     * counter value for the bundle. This value is used when generating
     * the bundle JAR directory name where native libraries are extracted.
     * This is necessary because Sun's JVM requires a one-to-one mapping
     * between native libraries and class loaders where the native library
     * is uniquely identified by its absolute path in the file system. This
     * constraint creates a problem when a bundle is refreshed, because it
     * gets a new class loader. Using the refresh counter to generate the name
     * of the bundle JAR directory resolves this problem because each time
     * bundle is refresh, the native library will have a unique name.
     * As a result of the unique name, the JVM will then reload the
     * native library without a problem.
    **/
    private long getRefreshCount()
        throws Exception
    {
        // If we have already read the update counter file,
        // then just return the result.
        if (m_refreshCount >= 0)
        {
            return m_refreshCount;
        }

        // Get update counter file.
        File counterFile = new File(m_dir, REFRESH_COUNTER_FILE);

        // If the update counter file doesn't exist, then
        // assume the counter is at zero.
        if (!counterFile.exists())
        {
            return 0;
        }

        // Read the bundle update counter.
        FileReader fr = null;
        BufferedReader br = null;
        try
        {
            fr = new FileReader(counterFile);
            br = new BufferedReader(fr);
            long counter = Long.parseLong(br.readLine());
            return counter;
        }
        finally
        {
            if (br != null) br.close();
            if (fr != null) fr.close();
        }
    }

    /**
     * This utility method is used to retrieve the current refresh
     * counter value for the bundle. This value is used when generating
     * the bundle JAR directory name where native libraries are extracted.
     * This is necessary because Sun's JVM requires a one-to-one mapping
     * between native libraries and class loaders where the native library
     * is uniquely identified by its absolute path in the file system. This
     * constraint creates a problem when a bundle is refreshed, because it
     * gets a new class loader. Using the refresh counter to generate the name
     * of the bundle JAR directory resolves this problem because each time
     * bundle is refresh, the native library will have a unique name.
     * As a result of the unique name, the JVM will then reload the
     * native library without a problem.
    **/
    private void setRefreshCount(long counter)
        throws Exception
    {
        // Get update counter file.
        File counterFile = new File(m_dir, REFRESH_COUNTER_FILE);

        // Write the update counter.
        FileWriter fw = null;
        BufferedWriter bw = null;
        try
        {
            fw = new FileWriter(counterFile);
            bw = new BufferedWriter(fw);
            String s = Long.toString(counter);
            bw.write(s, 0, s.length());
            m_refreshCount = counter;
        }
        catch (IOException ex)
        {
            m_logger.log(
                LogWrapper.LOG_ERROR,
                "DefaultBundleArchive: Unable to write counter: " + ex);
            throw ex;
        }
        finally
        {
            if (bw != null) bw.close();
            if (fw != null) fw.close();
        }
    }

    //
    // File-oriented utility methods.
    //

    protected static boolean deleteDirectoryTree(File target)
    {
        if (!target.exists())
        {
            return true;
        }

        if (target.isDirectory())
        {
            File[] files = target.listFiles();
            for (int i = 0; i < files.length; i++)
            {
                deleteDirectoryTree(files[i]);
            }
        }

        return target.delete();
    }

    /**
     * This method copies an input stream to the specified file.
     * <p>
     * Security: This method must be called from within a <tt>doPrivileged()</tt>
     * block since it accesses the disk.
     * @param is the input stream to copy.
     * @param outputFile the file to which the input stream should be copied.
    **/
    private void copy(InputStream is, File outputFile)
        throws IOException
    {
        OutputStream os = null;

        try
        {
            os = new BufferedOutputStream(
                new FileOutputStream(outputFile), DefaultBundleCache.BUFSIZE);
            byte[] b = new byte[DefaultBundleCache.BUFSIZE];
            int len = 0;
            while ((len = is.read(b)) != -1)
                os.write(b, 0, len);
        }
        finally
        {
            if (is != null) is.close();
            if (os != null) os.close();
        }
    }

    /**
     * This method pre-processes a bundle JAR file making it ready
     * for use. This entails extracting all embedded JAR files and
     * all native libraries.
     * @throws java.lang.Exception if any error occurs while processing JAR file.
    **/
    private void preprocessBundleJar(int revision, File revisionDir)
        throws Exception
    {
        //
        // Create special directories so that we can avoid checking
        // for their existence all the time.
        //

        File embedDir = new File(revisionDir, EMBEDDED_DIRECTORY);
        if (!embedDir.exists())
        {
            if (!embedDir.mkdir())
            {
                throw new IOException("Could not create embedded JAR directory.");
            }
        }

        File libDir = new File(revisionDir, LIBRARY_DIRECTORY);
        if (!libDir.exists())
        {
            if (!libDir.mkdir())
            {
                throw new IOException("Unable to create native library directory.");
            }
        }

        //
        // This block extracts all embedded JAR files.
        //

        try
        {
            // Get the bundle's manifest header.
            Map map = getManifestHeader(revision);
            if (map == null)
            {
                map = new HashMap();
            }

            // Find class path meta-data.
            String classPath = null;
            Iterator iter = map.entrySet().iterator();
            while ((classPath == null) && iter.hasNext())
            {
                Map.Entry entry = (Map.Entry) iter.next();
                if (entry.getKey().toString().toLowerCase().equals(
                    FelixConstants.BUNDLE_CLASSPATH.toLowerCase()))
                {
                    classPath = entry.getValue().toString();
                }
            }

            // Parse the class path into strings.
            String[] classPathStrings = Util.parseDelimitedString(
                classPath, FelixConstants.CLASS_PATH_SEPARATOR);

            if (classPathStrings == null)
            {
                classPathStrings = new String[0];
            }

            for (int i = 0; i < classPathStrings.length; i++)
            {
                if (!classPathStrings[i].equals(FelixConstants.CLASS_PATH_DOT))
                {
                    extractEmbeddedJar(revisionDir, classPathStrings[i]);
                }
            }

        }
        catch (PrivilegedActionException ex)
        {
            throw ((PrivilegedActionException) ex).getException();
        }
    }

    /**
     * This method extracts an embedded JAR file from the bundle's
     * JAR file.
     * <p>
     * Security: This method must be called from within a <tt>doPrivileged()</tt>
     * block since it accesses the disk.
     * @param id the identifier of the bundle that owns the embedded JAR file.
     * @param jarPath the path to the embedded JAR file inside the bundle JAR file.
    **/
    private void extractEmbeddedJar(File revisionDir, String jarPath)
        throws Exception
    {
        // Remove leading slash if present.
        jarPath = (jarPath.charAt(0) == '/') ? jarPath.substring(1) : jarPath;
        // Get only the JAR file name.
        String jarName = (jarPath.lastIndexOf('/') >= 0)
            ? jarPath.substring(jarPath.lastIndexOf('/') + 1) : jarPath;

        // If JAR is already extracted, then don't
        // re-extract it...
        File embedFile = new File(
            revisionDir, EMBEDDED_DIRECTORY + File.separatorChar + jarName);
        if (!embedFile.exists())
        {
            JarFile jarFile = null;
            InputStream is = null;

            try
            {
                jarFile = openBundleJarUnchecked(revisionDir);
                ZipEntry ze = jarFile.getEntry(jarPath);
                if (ze == null)
                {
                    throw new IOException("No JAR entry: " + jarPath);
                }
                is = new BufferedInputStream(jarFile.getInputStream(ze), DefaultBundleCache.BUFSIZE);
                if (is == null)
                {
                    throw new IOException("No input stream: " + jarPath);
                }

                // Create the file.
                copy(is, embedFile);

            }
            finally
            {
                if (jarFile != null) jarFile.close();
                if (is != null) is.close();
            }
        }
    }

    // INCREASES THE REVISION COUNT.    
    protected void update(InputStream is) throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.UPDATE_ACTION, this, is));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            updateUnchecked(is);
        }
    }

    // INCREASES THE REVISION COUNT.    
    private void updateUnchecked(InputStream is) throws Exception
    {
        File revisionDir = null;

        try
        {
            // Create the new revision directory.
            int revision = getRevisionCountUnchecked();
            revisionDir = new File(
                m_dir, REVISION_DIRECTORY
                + getRefreshCount() + "." + revision);
            if (!revisionDir.mkdir())
            {
                throw new IOException("Unable to create revision directory.");
            }

            // Save the new revision bundle jar file.
            File file = new File(revisionDir, BUNDLE_JAR_FILE);
            copy(is, file);

            preprocessBundleJar(revision, revisionDir);
        }
        catch (Exception ex)
        {
            if ((revisionDir != null) && revisionDir.exists())
            {
                try
                {
                    deleteDirectoryTree(revisionDir);
                }
                catch (Exception ex2)
                {
                    // There is very little we can do here.
                    m_logger.log(
                        LogWrapper.LOG_ERROR,
                        "Unable to remove partial revision directory.", ex2);
                }
            }
            throw ex;
        }

        // If everything was successful, then update
        // the revision count.
        m_revisionCount++;
        // Clear the cached revision header, since it is
        // no longer the current revision.
        m_currentHeader = null;
    }

    // DECREASES THE REVISION COUNT.    
    protected void purge() throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.PURGE_ACTION, this));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            purgeUnchecked();
        }
    }
    
    // DECREASES THE REVISION COUNT.    
    private void purgeUnchecked() throws Exception
    {
        // Get the current update count.
        long update = getRefreshCount();
        // Get the current revision count.
        int count = getRevisionCountUnchecked();

        File revisionDir = null;
        for (int i = 0; i < count - 1; i++)
        {
            revisionDir = new File(m_dir, REVISION_DIRECTORY + update + "." + i);
            if (revisionDir.exists())
            {
                deleteDirectoryTree(revisionDir);
            }
        }
        // Increment the update count.
        setRefreshCount(update + 1);

        // Rename the current revision to be the current update.
        File currentDir = new File(m_dir, REVISION_DIRECTORY + (update + 1) + ".0");
        revisionDir = new File(m_dir, REVISION_DIRECTORY + update + "." + (count - 1));
        revisionDir.renameTo(currentDir);
        
        // If everything is successful, then set the revision
        // count to one.
        m_revisionCount = 1;
        // Although the cached current header should stay the same
        // here, clear it for consistency.
        m_currentHeader = null;
    }

    protected void remove() throws Exception
    {
        if (System.getSecurityManager() != null)
        {
            try
            {
                AccessController.doPrivileged(
                    new PrivilegedAction(
                        PrivilegedAction.REMOVE_ACTION, this));
            }
            catch (PrivilegedActionException ex)
            {
                throw ((PrivilegedActionException) ex).getException();
            }
        }
        else
        {
            removeUnchecked();
        }
    }
    
    private void removeUnchecked() throws Exception
    {
        deleteDirectoryTree(m_dir);
    }

    //
    // Utility class for performing privileged actions.
    //

    private static class PrivilegedAction implements PrivilegedExceptionAction
    {
        private static final int INITIALIZE_ACTION = 0;
        private static final int UPDATE_ACTION = 1;
        private static final int PURGE_ACTION = 2;
        private static final int REMOVE_ACTION = 3;
        private static final int GET_REVISION_COUNT_ACTION = 4;
        private static final int GET_LOCATION_ACTION = 5;
        private static final int GET_PERSISTENT_STATE_ACTION = 6;
        private static final int SET_PERSISTENT_STATE_ACTION = 7;
        private static final int GET_START_LEVEL_ACTION = 8;
        private static final int SET_START_LEVEL_ACTION = 9;
        private static final int OPEN_BUNDLE_JAR_ACTION = 10;
        private static final int CREATE_DATA_DIR_ACTION = 11;
        private static final int GET_CLASS_PATH_ACTION = 12;
        private static final int GET_ACTIVATOR_ACTION = 13;
        private static final int SET_ACTIVATOR_ACTION = 14;

        private int m_action = 0;
        private DefaultBundleArchive m_archive = null;
        private InputStream m_isArg = null;
        private int m_intArg = 0;
        private File m_fileArg = null;
        private ClassLoader m_loaderArg = null;
        private Object m_objArg = null;

        public PrivilegedAction(int action, DefaultBundleArchive archive)
        {
            m_action = action;
            m_archive = archive;
        }

        public PrivilegedAction(int action, DefaultBundleArchive archive, InputStream isArg)
        {
            m_action = action;
            m_archive = archive;
            m_isArg = isArg;
        }

        public PrivilegedAction(int action, DefaultBundleArchive archive, int intArg)
        {
            m_action = action;
            m_archive = archive;
            m_intArg = intArg;
        }

        public PrivilegedAction(int action, DefaultBundleArchive archive, File fileArg)
        {
            m_action = action;
            m_archive = archive;
            m_fileArg = fileArg;
        }

        public PrivilegedAction(int action, DefaultBundleArchive archive, ClassLoader loaderArg)
        {
            m_action = action;
            m_archive = archive;
            m_loaderArg = loaderArg;
        }

        public PrivilegedAction(int action, DefaultBundleArchive archive, Object objArg)
        {
            m_action = action;
            m_archive = archive;
            m_objArg = objArg;
        }

        public Object run() throws Exception
        {
            switch (m_action)
            {
                case INITIALIZE_ACTION:
                    m_archive.initializeUnchecked(m_isArg);
                    return null;
                case UPDATE_ACTION:
                    m_archive.updateUnchecked(m_isArg);
                    return null;
                case PURGE_ACTION:
                    m_archive.purgeUnchecked();
                    return null;
                case REMOVE_ACTION:
                    m_archive.removeUnchecked();
                    return null;
                case GET_REVISION_COUNT_ACTION:
                    return new Integer(m_archive.getRevisionCountUnchecked());
                case GET_LOCATION_ACTION:
                    return m_archive.getLocationUnchecked();
                case GET_PERSISTENT_STATE_ACTION:
                    return new Integer(m_archive.getPersistentStateUnchecked());
                case SET_PERSISTENT_STATE_ACTION:
                    m_archive.setPersistentStateUnchecked(m_intArg);
                    return null;
                case GET_START_LEVEL_ACTION:
                    return new Integer(m_archive.getStartLevelUnchecked());
                case SET_START_LEVEL_ACTION:
                    m_archive.setStartLevelUnchecked(m_intArg);
                    return null;
                case OPEN_BUNDLE_JAR_ACTION:
                    return m_archive.openBundleJarUnchecked(m_fileArg);
                case CREATE_DATA_DIR_ACTION:
                    m_archive.createDataDirectoryUnchecked(m_fileArg);
                    return null;
                case GET_CLASS_PATH_ACTION:
                    return m_archive.getClassPathUnchecked(m_intArg);
                case GET_ACTIVATOR_ACTION:
                    return m_archive.getActivatorUnchecked(m_loaderArg);
                case SET_ACTIVATOR_ACTION:
                    m_archive.setActivatorUnchecked(m_objArg);
                    return null;
            }

            throw new IllegalArgumentException("Invalid action specified.");
        }
    }
}