/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.felix.framework.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * This class implements a factory for creating weak zip files, which behave
 * mostly like a ZipFile, but can be weakly closed to limit the number of
 * open files.
 */
public class WeakZipFileFactory
{
    private static final int WEAKLY_CLOSED = 0;
    private static final int OPEN = 1;
    private static final int CLOSED = 2;

    private static final SecureAction m_secureAction = new SecureAction();

    private final List<WeakZipFile> m_zipFiles = new ArrayList<WeakZipFile>();
    private final List<WeakZipFile> m_openFiles = new ArrayList<WeakZipFile>();
    private final Lock m_globalMutex = new ReentrantLock();
    private final int m_limit;

    /**
     * Constructs a weak zip file factory with the specified file limit. A limit
     * of zero signifies no limit.
     * @param limit maximum number of open zip files at any given time.
     */
    public WeakZipFileFactory(int limit)
    {
        if (limit < 0)
        {
            throw new IllegalArgumentException("Limit must be non-negative.");
        }
        m_limit = limit;
    }

    /**
     * Factory method used to create weak zip files.
     * @param file the target zip file.
     * @return the created weak zip file.
     * @throws IOException if the zip file could not be opened.
     */
    public WeakZipFile create(File file) throws IOException
    {
        WeakZipFile wzf = new WeakZipFile(file);

        if (m_limit > 0)
        {
            m_globalMutex.lock();

            try
            {
                m_zipFiles.add(wzf);
                m_openFiles.add(wzf);
                if (m_openFiles.size() > m_limit)
                {
                    WeakZipFile candidate = m_openFiles.get(0);
                    for (WeakZipFile tmp : m_openFiles)
                    {
                        if (candidate.m_timestamp > tmp.m_timestamp)
                        {
                            candidate = tmp;
                        }
                    }
                    candidate._closeWeakly();
                }
            }
            finally
            {
                m_globalMutex.unlock();
            }
        }

        return wzf;
    }

    /**
     * Only used for testing.
     * @return unclosed weak zip files.
     **/
    List<WeakZipFile> getZipZiles()
    {
        m_globalMutex.lock();

        try
        {
            return m_zipFiles;
        }
        finally
        {
            m_globalMutex.unlock();
        }
    }

    /**
     * Only used for testing.
     * @return open weak zip files.
     **/
    List<WeakZipFile> getOpenZipZiles()
    {
        m_globalMutex.lock();

        try
        {
            return m_openFiles;
        }
        finally
        {
            m_globalMutex.unlock();
        }
    }

    /**
     * This class wraps a ZipFile to making it possible to weakly close it;
     * this means the underlying zip file will be automatically reopened on demand
     * if anyone tries to use it.
     */
    public class WeakZipFile
    {
        private final File m_file;
        private final Lock m_localMutex = new ReentrantLock(false);
        private volatile ZipFile m_zipFile;
        private volatile int m_status = OPEN;
        private volatile long m_timestamp;
        private volatile SoftReference<LinkedHashMap<String, ZipEntry>> m_entries;

        /**
         * Constructor is private since instances need to be centrally
         * managed.
         * @param file the target zip file.
         * @throws IOException if the zip file could not be opened.
         */
        private WeakZipFile(File file) throws IOException
        {
            m_file = file;
            m_zipFile = m_secureAction.openZipFile(m_file);
            m_timestamp = System.currentTimeMillis();
        }

        /**
         * Returns the specified entry from the zip file.
         * @param name the name of the entry to return.
         * @return the zip entry associated with the specified name or null
         *         if it does not exist.
         */
        public ZipEntry getEntry(String name)
        {
            ensureZipFileIsOpen();

            try
            {
                LinkedHashMap<String, ZipEntry> entries = getEntries(false);
                ZipEntry ze;
                if (entries != null)
                {
                    ze = entries.get(name);
                    if (ze == null)
                    {
                        ze = entries.get(name + "/");
                    }
                }
                else
                {
                    ze = m_zipFile.getEntry(name);
                }

                if ((ze != null) && (ze.getSize() == 0) && !ze.isDirectory())
                {
                    //The attempts to fix an apparent bug in the JVM in versions
                    // 1.4.2 and lower where directory entries in ZIP/JAR files are
                    // not correctly identified.
                    ZipEntry dirEntry = m_zipFile.getEntry(name + '/');
                    if (dirEntry != null)
                    {
                        ze = dirEntry;
                    }
                }
                return ze;
            }
            finally
            {
                if (m_limit > 0)
                {
                    m_localMutex.unlock();
                }
            }
        }

        /**
         * Returns an enumeration of zip entries from the zip file.
         * @return an enumeration of zip entries.
         */
        public Enumeration<ZipEntry> entries()
        {
            ensureZipFileIsOpen();

            try
            {
                LinkedHashMap<String, ZipEntry> entries = getEntries(true);
                return Collections.enumeration(entries.values());
            }
            finally
            {
                if (m_limit > 0)
                {
                    m_localMutex.unlock();
                }
            }
        }

        public Enumeration<String> names()
        {
            ensureZipFileIsOpen();

            try
            {
                LinkedHashMap<String, ZipEntry> entries = getEntries(true);
                return Collections.enumeration(entries.keySet());
            }
            finally
            {
                if (m_limit > 0)
                {
                    m_localMutex.unlock();
                }
            }
        }

        private LinkedHashMap<String, ZipEntry> getEntries(boolean create)
        {
            LinkedHashMap<String, ZipEntry> entries = null;
            if (m_entries != null)
            {
                entries = m_entries.get();
            }
            if (entries == null && create)
            {
                synchronized (m_zipFile)
                {
                    if (m_entries != null)
                    {
                        entries = m_entries.get();
                    }
                    if (entries == null)
                    {
                        // We need to suck in all of the entries since the zip
                        // file may get weakly closed during iteration. Technically,
                        // this may not be 100% correct either since if the zip file
                        // gets weakly closed and reopened, then the zip entries
                        // will be from a different zip file. It is not clear if this
                        // will cause any issues.
                        Enumeration<? extends ZipEntry> e = m_zipFile.entries();
                        entries = new LinkedHashMap<String, ZipEntry>();
                        while (e.hasMoreElements())
                        {
                            ZipEntry entry = e.nextElement();
                            entries.put(entry.getName(), entry);
                        }
                        m_entries = new SoftReference<LinkedHashMap<String, ZipEntry>>(entries);
                    }
                }
            }
            return entries;
        }

        /**
         * Returns an input stream for the specified zip entry.
         * @param ze the zip entry whose input stream is to be retrieved.
         * @return an input stream to the zip entry.
         * @throws IOException if the input stream cannot be opened.
         */
        public InputStream getInputStream(ZipEntry ze) throws IOException
        {
            ensureZipFileIsOpen();

            try
            {
                InputStream is = m_zipFile.getInputStream(ze);
                return m_limit == 0 ? is : new WeakZipInputStream(ze.getName(), is);
            }
            finally
            {
                if (m_limit > 0)
                {
                    m_localMutex.unlock();
                }
            }
        }

        /**
         * Weakly closes the zip file, which means that it will be reopened
         * if anyone tries to use it again.
         */
        void closeWeakly()
        {
            m_globalMutex.lock();

            try
            {
                _closeWeakly();
            }
            finally
            {
                m_globalMutex.unlock();
            }
        }

        /**
         * This method is used internally to weakly close a zip file. It should
         * only be called when already holding the global lock, otherwise use
         * closeWeakly().
         */
        private void _closeWeakly()
        {
            m_localMutex.lock();

            try
            {
                if (m_status == OPEN)
                {
                    try
                    {
                        m_status = WEAKLY_CLOSED;
                        if (m_zipFile != null)
                        {
                            m_zipFile.close();
                            m_zipFile = null;
                        }
                        m_openFiles.remove(this);
                    }
                    catch (IOException ex)
                    {
                        __close();
                    }
                }
            }
            finally
            {
                m_localMutex.unlock();
            }
        }

        /**
         * This method permanently closes the zip file.
         * @throws IOException if any error occurs while trying to close the
         *         zip file.
         */
        public void close() throws IOException
        {
            if (m_limit > 0)
            {
                m_globalMutex.lock();
                m_localMutex.lock();
            }

            try
            {
                ZipFile tmp = m_zipFile;
                __close();
                if (tmp != null)
                {
                    tmp.close();
                }
            }
            finally
            {
                if (m_limit > 0)
                {
                    m_localMutex.unlock();
                    m_globalMutex.unlock();
                }
            }
        }

        /**
         * This internal method is used to clear the zip file from the data
         * structures and reset its state. It should only be called when
         * holding the global and local mutexes.
         */
        private void __close()
        {
            m_status = CLOSED;
            m_zipFile = null;
            m_zipFiles.remove(this);
            m_openFiles.remove(this);
        }

        /**
         * This method ensures that the zip file associated with this
         * weak zip file instance is actually open and acquires the
         * local weak zip file mutex. If the underlying zip file is closed,
         * then the local mutex is released and an IllegalStateException is
         * thrown. If the zip file is weakly closed, then it is reopened.
         * If the zip file is already opened, then no additional action is
         * necessary. If this method does not throw an exception, then
         * the end result is the zip file member field is non-null and the
         * local mutex has been acquired.
         */
        private void ensureZipFileIsOpen()
        {
            if (m_limit == 0)
            {
                return;
            }

            // Get mutex for zip file.
            m_localMutex.lock();

            // If zip file is closed, then just return null.
            if (m_status == CLOSED)
            {
                m_localMutex.unlock();
                throw new IllegalStateException("Zip file is closed: " + m_file);
            }

            // If zip file is weakly closed, we need to reopen it,
            // but we have to release the zip mutex to acquire the
            // global mutex, then reacquire the zip mutex. This
            // ensures that the global mutex is always acquired
            // before any local mutex to avoid deadlocks.
            IOException cause = null;
            if (m_status == WEAKLY_CLOSED)
            {
                m_localMutex.unlock();

                m_globalMutex.lock();

                m_localMutex.lock();

                // Double check status since it may have changed.
                if (m_status == CLOSED)
                {
                    m_localMutex.unlock();
                    m_globalMutex.unlock();
                    throw new IllegalStateException("Zip file is closed: " + m_file);
                }
                else if (m_status == WEAKLY_CLOSED)
                {
                    try
                    {
                        __reopenZipFile();
                    }
                    catch (IOException ex)
                    {
                        cause = ex;
                    }
                }

                // Release the global mutex, since it should no longer be necessary.
                m_globalMutex.unlock();
            }

            // It is possible that reopening the zip file failed, so we check
            // for that case and throw an exception.
            if (m_zipFile == null)
            {
                m_localMutex.unlock();
                IllegalStateException ise =
                    new IllegalStateException("Zip file is closed: " + m_file);
                if (cause != null)
                {
                    ise.initCause(cause);
                }
                throw ise;
            }
        }

        /**
         * Thie internal method is used to reopen a weakly closed zip file.
         * It makes a best effort, but may fail and leave the zip file member
         * field null. Any failure reopening a zip file results in it being
         * permanently closed. This method should only be invoked when holding
         * the global and local mutexes.
         */
        private void __reopenZipFile() throws IOException
        {
            if (m_status == WEAKLY_CLOSED)
            {
                try
                {
                    m_zipFile = m_secureAction.openZipFile(m_file);
                    m_status = OPEN;
                    m_timestamp = System.currentTimeMillis();
                }
                catch (IOException ex)
                {
                    __close();
                    throw ex;
                }

                if (m_zipFile != null)
                {
                    m_openFiles.add(this);
                    if (m_openFiles.size() > m_limit)
                    {
                        WeakZipFile candidate = m_openFiles.get(0);
                        for (WeakZipFile tmp : m_openFiles)
                        {
                            if (candidate.m_timestamp > tmp.m_timestamp)
                            {
                                candidate = tmp;
                            }
                        }
                        candidate._closeWeakly();
                    }
                }
            }
        }

        /**
         * This is an InputStream wrapper that will properly reopen the underlying
         * zip file if it is weakly closed and create the underlying input stream.
         */
        class WeakZipInputStream extends InputStream
        {
            private final String m_entryName;
            private volatile InputStream m_is;
            private volatile int m_currentPos = 0;
            private volatile ZipFile m_zipFileSnapshot;

            WeakZipInputStream(String entryName, InputStream is)
            {
                m_entryName = entryName;
                m_is = is;
                m_zipFileSnapshot = m_zipFile;
            }

            /**
             * This internal method ensures that the zip file is open and that
             * the underlying input stream is valid. Upon successful completion,
             * the underlying input stream will be valid and the local mutex
             * will be held.
             * @throws IOException if the was an error handling the input stream.
             */
            private void ensureInputStreamIsValid() throws IOException
            {
                if (m_limit == 0)
                {
                    return;
                }

                ensureZipFileIsOpen();

                // If the underlying zip file changed, then we need
                // to get the input stream again.
                if (m_zipFileSnapshot != m_zipFile)
                {
                    m_zipFileSnapshot = m_zipFile;

                    if (m_is != null)
                    {
                        try
                        {
                            m_is.close();
                        }
                        catch (Exception ex)
                        {
                            // Not much we can do.
                        }
                    }
                    try
                    {
                        m_is = m_zipFile.getInputStream(m_zipFile.getEntry(m_entryName));
                        m_is.skip(m_currentPos);
                    }
                    catch (IOException ex)
                    {
                        if (m_limit > 0)
                        {
                            m_localMutex.unlock();
                        }
                        throw ex;
                    }
                }
            }

            @Override
            public int available() throws IOException
            {
                ensureInputStreamIsValid();
                try
                {
                    return m_is.available();
                }
                finally
                {
                    if (m_limit > 0)
                    {
                        m_localMutex.unlock();
                    }
                }
            }

            @Override
            public void close() throws IOException
            {
                ensureInputStreamIsValid();
                try
                {
                    InputStream is = m_is;
                    m_is = null;
                    if (is != null)
                    {
                        is.close();
                    }
                }
                finally
                {
                    if (m_limit > 0)
                    {
                        m_localMutex.unlock();
                    }
                }
            }

            public int read() throws IOException
            {
                ensureInputStreamIsValid();
                try
                {
                    int len = m_is.read();
                    if (len > 0)
                    {
                        m_currentPos++;
                    }
                    return len;
                }
                finally
                {
                    if (m_limit > 0)
                    {
                        m_localMutex.unlock();
                    }
                }
            }

            @Override
            public int read(byte[] bytes) throws IOException
            {
                ensureInputStreamIsValid();
                try
                {
                    int len = m_is.read(bytes);
                    if (len > 0)
                    {
                        m_currentPos += len;
                    }
                    return len;
                }
                finally
                {
                    if (m_limit > 0)
                    {
                        m_localMutex.unlock();
                    }
                }
            }

            @Override
            public int read(byte[] bytes, int i, int i1) throws IOException
            {
                ensureInputStreamIsValid();
                try
                {
                    int len = m_is.read(bytes, i, i1);
                    if (len > 0)
                    {
                        m_currentPos += len;
                    }
                    return len;
                }
                finally
                {
                    if (m_limit > 0)
                    {
                        m_localMutex.unlock();
                    }
                }
            }

            @Override
            public long skip(long l) throws IOException
            {
                ensureInputStreamIsValid();
                try
                {
                    long len = m_is.skip(l);
                    if (len > 0)
                    {
                        m_currentPos += len;
                    }
                    return len;
                }
                finally
                {
                    if (m_limit > 0)
                    {
                        m_localMutex.unlock();
                    }
                }
            }
        }
    }
}
