/*
 * 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.cache;

import org.apache.felix.framework.Logger;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.WeakZipFileFactory;
import org.osgi.framework.Constants;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;

public class DirectoryContent implements Content
{
    private static final int BUFSIZE = 4096;
    private static final transient String EMBEDDED_DIRECTORY = "-embedded";
    private static final transient String LIBRARY_DIRECTORY = "-lib";

    private final Logger m_logger;
    private final Map m_configMap;
    private final WeakZipFileFactory m_zipFactory;
    private final Object m_revisionLock;
    private final File m_rootDir;
    private final File m_dir;
    private Map m_nativeLibMap;

    public DirectoryContent(Logger logger, Map configMap,
        WeakZipFileFactory zipFactory, Object revisionLock, File rootDir, File dir)
    {
        m_logger = logger;
        m_configMap = configMap;
        m_zipFactory = zipFactory;
        m_revisionLock = revisionLock;
        m_rootDir = rootDir;
        m_dir = dir;
    }

    public File getFile()
    {
        return m_dir;
    }

    public void close()
    {
        // Nothing to clean up.
    }

    public boolean hasEntry(String name) throws IllegalStateException
    {
        if ((name.length() > 0) && (name.charAt(0) == '/'))
        {
            name = name.substring(1);
        }

        // Return true if the file associated with the entry exists,
        // unless the entry name ends with "/", in which case only
        // return true if the file is really a directory.
        File file = new File(m_dir, name);
        return BundleCache.getSecureAction().fileExists(file)
            && (name.endsWith("/")
                ? BundleCache.getSecureAction().isFileDirectory(file) : true);
    }

    public Enumeration<String> getEntries()
    {
        // Wrap entries enumeration to filter non-matching entries.
        Enumeration<String> e = new EntriesEnumeration(m_dir);

        // Spec says to return null if there are no entries.
        return (e.hasMoreElements()) ? e : null;
    }

    public byte[] getEntryAsBytes(String name) throws IllegalStateException
    {
        if ((name.length() > 0) && (name.charAt(0) == '/'))
        {
            name = name.substring(1);
        }

        // Get the embedded resource.

        File file = new File(m_dir, name);
        try
        {

            return BundleCache.getSecureAction().fileExists(file) ? BundleCache.read(BundleCache.getSecureAction().getFileInputStream(file), file.length()) : null;
        }
        catch (Exception ex)
        {
            m_logger.log(
                Logger.LOG_ERROR,
                "DirectoryContent: Unable to read bytes for file " + name + " from file " + file.getAbsolutePath(), ex);
            return null;
        }
    }

    public InputStream getEntryAsStream(String name)
        throws IllegalStateException, IOException
    {
        if ((name.length() > 0) && (name.charAt(0) == '/'))
        {
            name = name.substring(1);
        }

        File file = new File(m_dir, name);
        try
        {
            return BundleCache.getSecureAction().fileExists(file) ? BundleCache.getSecureAction().getFileInputStream(file) : null;
        }
        catch (Exception ex)
        {
            m_logger.log(
                Logger.LOG_ERROR,
                "DirectoryContent: Unable to create inputstream for file " + name + " from file " + file.getAbsolutePath(), ex);
            return null;
        }
    }

    public URL getEntryAsURL(String name)
    {
        if ((name.length() > 0) && (name.charAt(0) == '/'))
        {
            name = name.substring(1);
        }

        if (hasEntry(name))
        {
            try
            {
                return BundleCache.getSecureAction().toURI(new File(m_dir, name)).toURL();
            }
            catch (MalformedURLException e)
            {
                return null;
            }
        }
        else
        {
            return null;
        }
    }

    public Content getEntryAsContent(String entryName)
    {
        // If the entry name refers to the content itself, then
        // just return it immediately.
        if (entryName.equals(FelixConstants.CLASS_PATH_DOT))
        {
            return new DirectoryContent(
                m_logger, m_configMap, m_zipFactory, m_revisionLock, m_rootDir, m_dir);
        }

        // Remove any leading slash, since all bundle class path
        // entries are relative to the root of the bundle.
        entryName = (entryName.startsWith("/")) ? entryName.substring(1) : entryName;

        if (entryName.trim().startsWith(".." + File.separatorChar) ||
            entryName.contains(File.separator + ".." + File.separatorChar) ||
            entryName.trim().endsWith(File.separator + "..") ||
            entryName.trim().equals(".."))
        {
            return null;
        }

        // Any embedded JAR files will be extracted to the embedded directory.
        File embedDir = new File(m_rootDir, m_dir.getName() + EMBEDDED_DIRECTORY);

        // Determine if the entry is an emdedded JAR file or
        // directory in the bundle JAR file. Ignore any entries
        // that do not exist per the spec.
        File file = new File(m_dir, entryName);
        if (BundleCache.getSecureAction().isFileDirectory(file))
        {
            return new DirectoryContent(
                m_logger, m_configMap, m_zipFactory, m_revisionLock, m_rootDir, file);
        }
        else if (BundleCache.getSecureAction().fileExists(file)
            && entryName.endsWith(".jar"))
        {
            File extractDir = new File(embedDir,
                (entryName.lastIndexOf('/') >= 0)
                    ? entryName.substring(0, entryName.lastIndexOf('/'))
                    : entryName);

            return new JarContent(
                m_logger, m_configMap, m_zipFactory, m_revisionLock,
                extractDir, file, null);
        }

        // The entry could not be found, so return null.
        return null;
    }

// TODO: SECURITY - This will need to consider security.
    public String getEntryAsNativeLibrary(String entryName)
    {
        // Return result.
        String result = null;

        // Remove any leading slash, since all bundle class path
        // entries are relative to the root of the bundle.
        entryName = (entryName.startsWith("/")) ? entryName.substring(1) : entryName;

        if (entryName.trim().startsWith(".." + File.separatorChar) ||
            entryName.contains(File.separator + ".." + File.separatorChar) ||
            entryName.trim().endsWith(File.separator + "..") ||
            entryName.trim().equals(".."))
        {
            return null;
        }

        // Any embedded native library files will be extracted to the lib directory.
        File libDir = new File(m_rootDir, m_dir.getName() + LIBRARY_DIRECTORY);

        // The entry must exist and refer to a file, not a directory,
        // since we are expecting it to be a native library.
        File entryFile = new File(m_dir, entryName);
        if (BundleCache.getSecureAction().fileExists(entryFile)
            && !BundleCache.getSecureAction().isFileDirectory(entryFile))
        {
            // Extracting the embedded native library file impacts all other
            // existing contents for this revision, so we have to grab the
            // revision lock first before trying to extract the embedded JAR
            // file to avoid a race condition.
            synchronized (m_revisionLock)
            {
                // Since native libraries cannot be shared, we must extract a
                // separate copy per request, so use the request library counter
                // as part of the extracted path.
                if (m_nativeLibMap == null)
                {
                    m_nativeLibMap = new HashMap();
                }
                Integer libCount = (Integer) m_nativeLibMap.get(entryName);
                // Either set or increment the library count.
                libCount = (libCount == null) ? new Integer(0) : new Integer(libCount.intValue() + 1);
                m_nativeLibMap.put(entryName, libCount);
                File libFile = new File(
                    libDir, libCount.toString() + File.separatorChar + entryName);

                if (!BundleCache.getSecureAction().fileExists(libFile))
                {
                    if (!BundleCache.getSecureAction().fileExists(libFile.getParentFile())
                        && !BundleCache.getSecureAction().mkdirs(libFile.getParentFile()))
                    {
                        m_logger.log(
                            Logger.LOG_ERROR,
                            "Unable to create library directory.");
                    }
                    else
                    {
                        InputStream is = null;

                        try
                        {
                            is = BundleCache.getSecureAction().getFileInputStream(entryFile);

                            // Create the file.
                            BundleCache.copyStreamToFile(is, libFile);

                            // Perform exec permission command on extracted library
                            // if one is configured.
                            String command = (String) m_configMap.get(
                                Constants.FRAMEWORK_EXECPERMISSION);
                            if (command != null)
                            {
                                Properties props = new Properties();
                                props.setProperty("abspath", libFile.toString());
                                command = Util.substVars(command, "command", null, props);
                                Process p = BundleCache.getSecureAction().exec(command);
                                p.waitFor();
                            }

                            // Return the path to the extracted native library.
                            result = BundleCache.getSecureAction().getAbsolutePath(libFile);
                        }
                        catch (Exception ex)
                        {
                            m_logger.log(
                                Logger.LOG_ERROR,
                                "Extracting native library.", ex);
                        }
                    }
                }
                else
                {
                    // Return the path to the extracted native library.
                    result = BundleCache.getSecureAction().getAbsolutePath(libFile);
                }
            }
        }

        return result;
    }

    public String toString()
    {
        return "DIRECTORY " + m_dir;
    }

    private static class EntriesEnumeration implements Enumeration
    {
        private final File m_dir;
        private final File[] m_children;
        private int m_counter = 0;

        public EntriesEnumeration(File dir)
        {
            m_dir = dir;
            m_children = listFilesRecursive(m_dir);
        }

        public synchronized boolean hasMoreElements()
        {
            return (m_children != null) && (m_counter < m_children.length);
        }

        public synchronized Object nextElement()
        {
            if ((m_children == null) || (m_counter >= m_children.length))
            {
                throw new NoSuchElementException("No more entry paths.");
            }

            // Convert the file separator character to slashes.
            String abs = BundleCache.getSecureAction()
                .getAbsolutePath(m_children[m_counter]).replace(File.separatorChar, '/');

            // Remove the leading path of the reference directory, since the
            // entry paths are supposed to be relative to the root.
            StringBuilder sb = new StringBuilder(abs);
            sb.delete(0, BundleCache.getSecureAction().getAbsolutePath(m_dir).length() + 1);
            // Add a '/' to the end of directory entries.
            if (BundleCache.getSecureAction().isFileDirectory(m_children[m_counter]))
            {
                sb.append('/');
            }
            m_counter++;
            return sb.toString();
        }

        private File[] listFilesRecursive(File dir)
        {
            File[] children = BundleCache.getSecureAction().listDirectory(dir);
            File[] combined = children;
            if (children != null)
            {
                for (int i = 0; i < children.length; i++)
                {
                    if (BundleCache.getSecureAction().isFileDirectory(children[i]))
                    {
                        File[] grandchildren = listFilesRecursive(children[i]);
                        if (grandchildren != null && grandchildren.length > 0)
                        {
                            File[] tmp = new File[combined.length + grandchildren.length];
                            System.arraycopy(combined, 0, tmp, 0, combined.length);
                            System.arraycopy(
                                grandchildren, 0, tmp, combined.length, grandchildren.length);
                            combined = tmp;
                        }
                    }
                }
            }
            return combined;
        }
    }
}