/*
 *  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.harmony.luni.internal.net.www.protocol.jar;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.net.ContentHandler;
import java.net.ContentHandlerFactory;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipFile;

// BEGIN android-removed
// import org.apache.harmony.kernel.vm.VM;
// END android-removed
import org.apache.harmony.luni.util.Msg;
import org.apache.harmony.luni.util.Util;

/**
 * This subclass extends <code>URLConnection</code>.
 * <p>
 * 
 * This class is responsible for connecting and retrieving resources from a Jar
 * file which can be anywhere that can be refered to by an URL.
 */
public class JarURLConnection extends java.net.JarURLConnection {

    static Hashtable<String, CacheEntry<? extends JarFile>> jarCache = new Hashtable<String, CacheEntry<?>>();

    InputStream jarInput;

    private JarFile jarFile;

    private JarEntry jarEntry;
    
    private boolean closed;

    ReferenceQueue<JarFile> cacheQueue = new ReferenceQueue<JarFile>();

    static TreeSet<LRUKey> lru = new TreeSet<LRUKey>(
            new LRUComparator<LRUKey>());

    static int Limit;

    static {
        Limit = AccessController.doPrivileged(new PrivilegedAction<Integer>() {
            public Integer run() {
                return Integer.getInteger("jar.cacheSize", 500); //$NON-NLS-1$
            }
        });
        // BEGIN android-removed
        // TODO this needs to be implemented once this is available.
        // VM.closeJars();
        // END android-removed
    }

    static final class CacheEntry<T extends JarFile> extends WeakReference<T> {
        Object key;

        CacheEntry(T jar, String key, ReferenceQueue<JarFile> queue) {
            super(jar, queue);
            this.key = key;
        }
    }

    static final class LRUKey {
        JarFile jar;

        long ts;

        LRUKey(JarFile file, long time) {
            jar = file;
            ts = time;
        }

        /**
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals(Object obj) {
            return (obj instanceof LRUKey) &&
                (jar == ((LRUKey) obj).jar);
        }

        @Override
        public int hashCode() {
            return jar.hashCode();
        }
    }

    static final class LRUComparator<T> implements Comparator<LRUKey> {

        LRUComparator() {
        }

        /**
         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
         */
        public int compare(LRUKey o1, LRUKey o2) {
            if ((o1).ts > (o2).ts) {
                return 1;
            }
            return (o1).ts == (o2).ts ? 0 : -1;
        }

        /**
         * @param o1
         *            an object to compare
         * @param o2
         *            an object to compare
         * @return <code>true</code> if the objects are equal,
         *         <code>false</code> otherwise.
         */
        public boolean equals(Object o1, Object o2) {
            return o1.equals(o2);
        }
    }

    /**
     * @param url
     *            the URL of the JAR
     * @throws MalformedURLException
     *             if the URL is malformed
     */
    public JarURLConnection(java.net.URL url) throws MalformedURLException {
        super(url);
    }

    /**
     * @see java.net.URLConnection#connect()
     */
    @Override
    public void connect() throws IOException {
        jarFileURLConnection = getJarFileURL().openConnection();
        findJarFile(); // ensure the file can be found
        findJarEntry(); // ensure the entry, if any, can be found
        connected = true;
    }

    /**
     * Returns the Jar file refered by this <code>URLConnection</code>
     * 
     * @return the JAR file referenced by this connection
     * 
     * @throws IOException
     *             thrown if an IO error occurs while connecting to the
     *             resource.
     */
    @Override
    public JarFile getJarFile() throws IOException {
        if (!connected) {
            connect();
        }
        return jarFile;
    }

    /**
     * Returns the Jar file refered by this <code>URLConnection</code>
     * 
     * @throws IOException
     *             if an IO error occurs while connecting to the resource.
     */
    private void findJarFile() throws IOException {
        URL jarFileURL = getJarFileURL();
        if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$
            String fileName = jarFileURL.getFile();
            if(!new File(Util.decode(fileName,false)).exists()){
                // KA026=JAR entry {0} not found in {1}
                throw new FileNotFoundException(Msg.getString("KA026", //$NON-NLS-1$
                        getEntryName(), fileName));
            }
            String host = jarFileURL.getHost();
            if (host != null && host.length() > 0) {
                fileName = "//" + host + fileName; //$NON-NLS-1$
            }
            jarFile = openJarFile(fileName, fileName, false);
            return;
        }

        final String externalForm = jarFileURLConnection.getURL()
                .toExternalForm();
        jarFile = AccessController
                .doPrivileged(new PrivilegedAction<JarFile>() {
                    public JarFile run() {
                        try {
                            return openJarFile(null, externalForm, false);
                        } catch (IOException e) {
                            return null;
                        }
                    }
                });
        if (jarFile != null) {
            return;
        }

        // Build a temp jar file
        final InputStream is = jarFileURLConnection.getInputStream();
        try {
            jarFile = AccessController
                    .doPrivileged(new PrivilegedAction<JarFile>() {
                        public JarFile run() {
                            try {
                                File tempJar = File.createTempFile("hyjar_", //$NON-NLS-1$
                                        ".tmp", null); //$NON-NLS-1$
                                FileOutputStream fos = new FileOutputStream(
                                        tempJar);
                                byte[] buf = new byte[4096];
                                int nbytes = 0;
                                while ((nbytes = is.read(buf)) > -1) {
                                    fos.write(buf, 0, nbytes);
                                }
                                fos.close();
                                String path = tempJar.getPath();
                                return openJarFile(path, externalForm, true);
                            } catch (IOException e) {
                                return null;
                            }
                        }
                    });
        } finally {
            is.close();
        }
        if (jarFile == null) {
            throw new IOException();
        }
    }

    JarFile openJarFile(String fileString, String key, boolean temp)
            throws IOException {

        JarFile jar = null;
        if (useCaches) {
            CacheEntry<? extends JarFile> entry;
            while ((entry = (CacheEntry<? extends JarFile>) cacheQueue.poll()) != null) {
                jarCache.remove(entry.key);
            }
            entry = jarCache.get(key);
            if (entry != null) {
                jar = entry.get();
            }
            if (jar == null && fileString != null) {
                int flags = ZipFile.OPEN_READ
                        + (temp ? ZipFile.OPEN_DELETE : 0);
                jar = new JarFile(new File(Util.decode(fileString, false)),
                        true, flags);
                jarCache
                        .put(key, new CacheEntry<JarFile>(jar, key, cacheQueue));
            } else {
                SecurityManager security = System.getSecurityManager();
                if (security != null) {
                    security.checkPermission(getPermission());
                }
                if (temp) {
                    lru.remove(new LRUKey(jar, 0));
                }
            }
        } else if (fileString != null) {
            int flags = ZipFile.OPEN_READ + (temp ? ZipFile.OPEN_DELETE : 0);
            jar = new JarFile(new File(Util.decode(fileString, false)), true,
                    flags);
        }

        if (temp) {
            lru.add(new LRUKey(jar, new Date().getTime()));
            if (lru.size() > Limit) {
                lru.remove(lru.first());
            }
        }
        return jar;
    }

    /**
     * Returns the JarEntry of the entry referenced by this
     * <code>URLConnection</code>.
     * 
     * @return java.util.jar.JarEntry the JarEntry referenced
     * 
     * @throws IOException
     *             if an IO error occurs while getting the entry
     */
    @Override
    public JarEntry getJarEntry() throws IOException {
        if (!connected) {
            connect();
        }
        return jarEntry;

    }

    /**
     * Look up the JarEntry of the entry referenced by this
     * <code>URLConnection</code>.
     */
    private void findJarEntry() throws IOException {
        if (getEntryName() == null) {
            return;
        }
        jarEntry = jarFile.getJarEntry(getEntryName());
        if (jarEntry == null) {
            throw new FileNotFoundException(getEntryName());
        }
    }

    /**
     * Creates an input stream for reading from this URL Connection.
     * 
     * @return the input stream
     * 
     * @throws IOException
     *             if an IO error occurs while connecting to the resource.
     */
    @Override
    public InputStream getInputStream() throws IOException {
        if (closed) {
            throw new IllegalStateException(Msg.getString("KA027"));
        }
        if (!connected) {
            connect();
        }
        if (jarInput != null) {
            return jarInput;
        }
        if (jarEntry == null) {
            throw new IOException(Msg.getString("K00fc")); //$NON-NLS-1$
        }
        return jarInput = new JarURLConnectionInputStream(jarFile
                .getInputStream(jarEntry), jarFile);
    }

    /**
     * Returns the content type of the resource. Test cases reveal that only if
     * the URL is refering to a Jar file, that this method returns a non-null
     * value - x-java/jar.
     * 
     * @return the content type
     */
    @Override
    public String getContentType() {
        // it could also return "x-java/jar" which jdk returns but here, we get
        // it from the URLConnection
        try {
            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
                return getJarFileURL().openConnection().getContentType();
            }
        } catch (IOException ioe) {
            // Ignore
        }
        // if there is an Jar Entry, get the content type from the name
        return guessContentTypeFromName(url.getFile());
    }

    /**
     * Returns the content length of the resource. Test cases reveal that if the
     * URL is refering to a Jar file, this method returns a content-length
     * returned by URLConnection. If not, it will return -1.
     * 
     * @return the content length
     */
    @Override
    public int getContentLength() {
        try {
            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
                return getJarFileURL().openConnection().getContentLength();
            }
        } catch (IOException e) {
            //Ignored
        }
        return -1;
    }

    /**
     * Returns the object pointed by this <code>URL</code>. If this
     * URLConnection is pointing to a Jar File (no Jar Entry), this method will
     * return a <code>JarFile</code> If there is a Jar Entry, it will return
     * the object corresponding to the Jar entry content type.
     * 
     * @return a non-null object
     * 
     * @throws IOException
     *             if an IO error occured
     * 
     * @see ContentHandler
     * @see ContentHandlerFactory
     * @see java.io.IOException
     * @see #setContentHandlerFactory(ContentHandlerFactory)
     */
    @Override
    public Object getContent() throws IOException {
        if (!connected) {
            connect();
        }
        // if there is no Jar Entry, return a JarFile
        if (jarEntry == null) {
            return jarFile;
        }
        return super.getContent();
    }

    /**
     * Returns the permission, in this case the subclass, FilePermission object
     * which represents the permission necessary for this URLConnection to
     * establish the connection.
     * 
     * @return the permission required for this URLConnection.
     * 
     * @throws IOException
     *             thrown when an IO exception occurs while creating the
     *             permission.
     */
    @Override
    public Permission getPermission() throws IOException {
        if (jarFileURLConnection != null) {
            return jarFileURLConnection.getPermission();
        }
        return getJarFileURL().openConnection().getPermission();
    }

    /**
     * Closes the cached files.
     */
    public static void closeCachedFiles() {
        Enumeration<CacheEntry<? extends JarFile>> elemEnum = jarCache
                .elements();
        while (elemEnum.hasMoreElements()) {
            try {
                ZipFile zip = elemEnum.nextElement().get();
                if (zip != null) {
                    zip.close();
                }
            } catch (IOException e) {
                // Ignored
            }
        }
    }

    private class JarURLConnectionInputStream extends FilterInputStream {
        InputStream inputStream;

        JarFile jarFile;

        protected JarURLConnectionInputStream(InputStream in, JarFile file) {
            super(in);
            inputStream = in;
            jarFile = file;
        }

        @Override
        public void close() throws IOException {
            super.close();
            if (!useCaches) {
                closed = true;
                jarFile.close();
            }
        }

        @Override
        public int read() throws IOException {
            return inputStream.read();
        }

        @Override
        public int read(byte[] buf, int off, int nbytes) throws IOException {
            return inputStream.read(buf, off, nbytes);
        }

        @Override
        public long skip(long nbytes) throws IOException {
            return inputStream.skip(nbytes);
        }
    }
}
