/*
 * 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.commons.vfs2.impl;

import java.io.IOException;
import java.net.URL;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.SecureClassLoader;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.NameScope;
import org.apache.commons.vfs2.util.FileObjectUtils;

/**
 * A class loader that can load classes and resources from a search path.
 * <p>
 * The search path can consist of VFS FileObjects referring both to folders and JAR files. Any FileObject of type
 * FileType.FILE is assumed to be a JAR and is opened by creating a layered file system with the "jar" scheme.
 * </p>
 * <p>
 * TODO - Test this with signed Jars and a SecurityManager.
 * </p>
 *
 * @see FileSystemManager#createFileSystem
 */
public class VFSClassLoader extends SecureClassLoader {
    private final ArrayList<FileObject> resources = new ArrayList<>();

    /**
     * Constructors a new VFSClassLoader for the given file.
     *
     * @param file the file to load the classes and resources from.
     * @param manager the FileManager to use when trying to create a layered Jar file system.
     * @throws FileSystemException if an error occurs.
     */
    public VFSClassLoader(final FileObject file, final FileSystemManager manager) throws FileSystemException {
        this(new FileObject[] {file}, manager, null);
    }

    /**
     * Constructors a new VFSClassLoader for the given file.
     *
     * @param file the file to load the classes and resources from.
     * @param manager the FileManager to use when trying to create a layered Jar file system.
     * @param parent the parent class loader for delegation.
     * @throws FileSystemException if an error occurs.
     */
    public VFSClassLoader(final FileObject file, final FileSystemManager manager, final ClassLoader parent)
            throws FileSystemException {
        this(new FileObject[] {file}, manager, parent);
    }

    /**
     * Constructors a new VFSClassLoader for the given files. The files will be searched in the order specified.
     *
     * @param files the files to load the classes and resources from.
     * @param manager the FileManager to use when trying to create a layered Jar file system.
     * @throws FileSystemException if an error occurs.
     */
    public VFSClassLoader(final FileObject[] files, final FileSystemManager manager) throws FileSystemException {
        this(files, manager, null);
    }

    /**
     * Constructors a new VFSClassLoader for the given FileObjects. The FileObjects will be searched in the order
     * specified.
     *
     * @param files the FileObjects to load the classes and resources from.
     * @param manager the FileManager to use when trying to create a layered Jar file system.
     * @param parent the parent class loader for delegation.
     * @throws FileSystemException if an error occurs.
     */
    public VFSClassLoader(final FileObject[] files, final FileSystemManager manager, final ClassLoader parent)
            throws FileSystemException {
        super(parent);
        addFileObjects(manager, files);
    }

    /**
     * Appends the specified FileObjects to the list of FileObjects to search for classes and resources.
     *
     * @param manager The FileSystemManager.
     * @param files the FileObjects to append to the search path.
     * @throws FileSystemException if an error occurs.
     */
    private void addFileObjects(final FileSystemManager manager, final FileObject[] files) throws FileSystemException {
        for (FileObject file : files) {
            if (!FileObjectUtils.exists(file)) {
                // Does not exist - skip
                continue;
            }

            // TODO - use federation instead
            if (manager.canCreateFileSystem(file)) {
                // Use contents of the file
                file = manager.createFileSystem(file);
            }

            resources.add(file);
        }
    }

    /**
     * Copies the permissions from src to dest.
     *
     * @param src The source PermissionCollection.
     * @param dest The destination PermissionCollection.
     */
    protected void copyPermissions(final PermissionCollection src, final PermissionCollection dest) {
        for (final Enumeration<Permission> elem = src.elements(); elem.hasMoreElements();) {
            dest.add(elem.nextElement());
        }
    }

    /**
     * Loads and verifies the class with name and located with res.
     */
    private Class<?> defineClass(final String name, final Resource res) throws IOException {
        final URL url = res.getCodeSourceURL();
        final String pkgName = res.getPackageName();
        if (pkgName != null) {
            final Package pkg = getPackage(pkgName);
            if (pkg != null) {
                if (pkg.isSealed()) {
                    if (!pkg.isSealed(url)) {
                        throw new FileSystemException("vfs.impl/pkg-sealed-other-url", pkgName);
                    }
                } else if (isSealed(res)) {
                    throw new FileSystemException("vfs.impl/pkg-sealing-unsealed", pkgName);
                }
            } else {
                definePackage(pkgName, res);
            }
        }

        final byte[] bytes = res.getBytes();
        final Certificate[] certs = res.getFileObject().getContent().getCertificates();
        final CodeSource cs = new CodeSource(url, certs);
        return defineClass(name, bytes, 0, bytes.length, cs);
    }

    /**
     * Reads attributes for the package and defines it.
     */
    private Package definePackage(final String name, final Resource res) throws FileSystemException {
        // TODO - check for MANIFEST_ATTRIBUTES capability first
        final String specTitle = res.getPackageAttribute(Name.SPECIFICATION_TITLE);
        final String specVendor = res.getPackageAttribute(Attributes.Name.SPECIFICATION_VENDOR);
        final String specVersion = res.getPackageAttribute(Name.SPECIFICATION_VERSION);
        final String implTitle = res.getPackageAttribute(Name.IMPLEMENTATION_TITLE);
        final String implVendor = res.getPackageAttribute(Name.IMPLEMENTATION_VENDOR);
        final String implVersion = res.getPackageAttribute(Name.IMPLEMENTATION_VERSION);

        final URL sealBase;
        if (isSealed(res)) {
            sealBase = res.getCodeSourceURL();
        } else {
            sealBase = null;
        }

        return definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
    }

    /**
     * Finds and loads the class with the specified name from the search path.
     *
     * @throws ClassNotFoundException if the class is not found.
     */
    @Override
    protected Class<?> findClass(final String name) throws ClassNotFoundException {
        try {
            final String path = name.replace('.', '/').concat(".class");
            final Resource res = loadResource(path);
            if (res == null) {
                throw new ClassNotFoundException(name);
            }
            return defineClass(name, res);
        } catch (final IOException ioe) {
            throw new ClassNotFoundException(name, ioe);
        }
    }

    /**
     * Finds the resource with the specified name from the search path. This returns null if the resource is not found.
     *
     * @param name The resource name.
     * @return The URL that matches the resource.
     */
    @Override
    protected URL findResource(final String name) {
        try {
            final Resource res = loadResource(name);
            if (res != null) {
                return res.getURL();
            }
            return null;
        } catch (final Exception ignored) {
            return null; // TODO: report?
        }
    }

    /**
     * Returns an Enumeration of all the resources in the search path with the specified name.
     * <p>
     * Gets called from {@link ClassLoader#getResources(String)} after parent class loader was questioned.
     *
     * @param name The resources to find.
     * @return An Enumeration of the resources associated with the name.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    protected Enumeration<URL> findResources(final String name) throws IOException {
        final List<URL> result = new ArrayList<>(2);

        for (final FileObject baseFile : resources) {
            try (FileObject file = baseFile.resolveFile(name, NameScope.DESCENDENT_OR_SELF)) {
                if (FileObjectUtils.exists(file)) {
                    result.add(new Resource(name, baseFile, file).getURL());
                }
            }
        }

        return Collections.enumeration(result);
    }

    /**
     * Provide access to the file objects this class loader represents.
     *
     * @return An array of FileObjects.
     * @since 2.0
     */
    public FileObject[] getFileObjects() {
        return resources.toArray(FileObject.EMPTY_ARRAY);
    }

    /**
     * Calls super.getPermissions both for the code source and also adds the permissions granted to the parent layers.
     *
     * @param cs the CodeSource.
     * @return The PermissionCollections.
     */
    @Override
    protected PermissionCollection getPermissions(final CodeSource cs) {
        try {
            final String url = cs.getLocation().toString();
            final FileObject file = lookupFileObject(url);
            if (file == null) {
                return super.getPermissions(cs);
            }

            final FileObject parentLayer = file.getFileSystem().getParentLayer();
            if (parentLayer == null) {
                return super.getPermissions(cs);
            }

            final Permissions combi = new Permissions();
            PermissionCollection permCollect = super.getPermissions(cs);
            copyPermissions(permCollect, combi);

            for (FileObject parent = parentLayer; parent != null; parent = parent.getFileSystem().getParentLayer()) {
                final CodeSource parentcs = new CodeSource(parent.getURL(), parent.getContent().getCertificates());
                permCollect = super.getPermissions(parentcs);
                copyPermissions(permCollect, combi);
            }

            return combi;
        } catch (final FileSystemException fse) {
            throw new SecurityException(fse.getMessage());
        }
    }

    /**
     * Returns true if we should seal the package where res resides.
     */
    private boolean isSealed(final Resource res) throws FileSystemException {
        final String sealed = res.getPackageAttribute(Attributes.Name.SEALED);
        return "true".equalsIgnoreCase(sealed);
    }

    /**
     * Searches through the search path of for the first class or resource with specified name.
     *
     * @param name The resource to load.
     * @return The Resource.
     * @throws FileSystemException if an error occurs.
     */
    private Resource loadResource(final String name) throws FileSystemException {
        for (final FileObject baseFile : resources) {
            try (FileObject file = baseFile.resolveFile(name, NameScope.DESCENDENT_OR_SELF)) {
                if (FileObjectUtils.exists(file)) {
                    return new Resource(name, baseFile, file);
                }
            }
        }
        return null;
    }

    /**
     * Does a reverse lookup to find the FileObject when we only have the URL.
     */
    private FileObject lookupFileObject(final String name) {
        for (final FileObject object : resources) {
            if (name.equals(object.getName().getURI())) {
                return object;
            }
        }
        return null;
    }
}
