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

import org.apache.openejb.classloader.ClassLoaderConfigurer;
import org.apache.openejb.classloader.CompositeClassLoaderConfigurer;
import org.apache.openejb.core.TempClassLoader;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.UrlCache;
import org.apache.openejb.util.classloader.URLClassLoaderFirst;
import org.apache.xbean.recipe.ObjectRecipe;

import java.beans.Introspector;
import java.io.File;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.zip.ZipFile;

/**
 * @version $Revision: 1423017 $ $Date: 2012-12-17 16:52:12 +0000 (Mon, 17 Dec 2012) $
 */
public class ClassLoaderUtil {

    private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB, ClassLoaderUtil.class);
    private static final Map<String, List<ClassLoader>> classLoadersByApp = new HashMap<String, List<ClassLoader>>();
    private static final Map<ClassLoader, Set<String>> appsByClassLoader = new HashMap<ClassLoader, Set<String>>();
    private static final UrlCache localUrlCache = new UrlCache();

    public static ClassLoader getContextClassLoader() {
        return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {

            @Override
            public ClassLoader run() {
                return Thread.currentThread().getContextClassLoader();
            }
        });
    }

    public static File getUrlCachedName(final String appId, final URL url) {
        return localUrlCache.getUrlCachedName(appId, url);
    }

    public static boolean isUrlCached(final String appId, final URL url) {
        return localUrlCache.isUrlCached(appId, url);
    }

    public static URL getUrlKeyCached(final String appId, final File file) {
        return localUrlCache.getUrlKeyCached(appId, file);
    }

    public static URLClassLoader createClassLoaderFirst(final String appId, final URL[] urls, final ClassLoader parent) {
        return cacheClassLoader(appId, new URLClassLoaderFirst(localUrlCache.cacheUrls(appId, urls), parent));
    }

    public static URLClassLoader createClassLoader(final String appId, final URL[] urls, final ClassLoader parent) {
        return cacheClassLoader(appId, new URLClassLoader(localUrlCache.cacheUrls(appId, urls), parent));
    }

    private static URLClassLoader cacheClassLoader(final String appId, final URLClassLoader classLoader) {
        List<ClassLoader> classLoaders = classLoadersByApp.get(appId);
        if (classLoaders == null) {
            classLoaders = new ArrayList<ClassLoader>(2);
            classLoadersByApp.put(appId, classLoaders);
        }
        classLoaders.add(classLoader);

        Set<String> apps = appsByClassLoader.get(classLoader);
        if (apps == null) {
            apps = new LinkedHashSet<String>(1);
            appsByClassLoader.put(classLoader, apps);
        }
        apps.add(appId);

        return classLoader;
    }

    /**
     * Destroy a classloader as forcefully as possible.
     *
     * @param classLoader ClassLoader to destroy.
     */
    public static void destroyClassLoader(final ClassLoader classLoader) {
        logger.debug("Destroying classLoader " + toString(classLoader));

        // remove from the indexes
        final Set<String> apps = appsByClassLoader.remove(classLoader);

        if (apps != null) {

            List<ClassLoader> classLoaders;

            for (final String appId : apps) {

                classLoaders = classLoadersByApp.get(appId);

                if (classLoaders != null) {
                    classLoaders.remove(classLoader);
                }

                //If this is the last class loader in the app, clean up the app
                if (null == classLoaders || classLoaders.isEmpty()) {
                    destroyClassLoader(appId);
                }
            }
        }

        // Clear OpenJPA caches
        cleanOpenJPACache(classLoader);

        //Clear open jar files belonging to this ClassLoader
        for (final String jar : getClosedJarFiles(classLoader)) {
            clearSunJarFileFactoryCache(jar);
        }
    }

    /**
     * Dirty hack to force closure of file handles in the Oracle VM URLClassLoader
     * Any URLClassLoader passed into this method will be unusable after the method completes.
     *
     * @param cl ClassLoader of expected type URLClassLoader (Silent failure)
     */
    private static List<String> getClosedJarFiles(final ClassLoader cl) {

        final List<String> files = new ArrayList<String>();

        if (null != cl && cl instanceof URLClassLoader) {

            final URLClassLoader ucl = (URLClassLoader) cl;
            final Class clazz = java.net.URLClassLoader.class;

            try {

                final java.lang.reflect.Field ucp = clazz.getDeclaredField("ucp");
                ucp.setAccessible(true);
                final Object cp = ucp.get(ucl);
                final java.lang.reflect.Field loaders = cp.getClass().getDeclaredField("loaders");
                loaders.setAccessible(true);
                final java.util.Collection c = (java.util.Collection) loaders.get(cp);
                java.lang.reflect.Field loader;
                java.util.jar.JarFile jf;

                for (final Object jl : c.toArray()) {
                    try {
                        loader = jl.getClass().getDeclaredField("jar");
                        loader.setAccessible(true);
                        jf = (java.util.jar.JarFile) loader.get(jl);
                        files.add(jf.getName());
                        jf.close();
                    } catch (Throwable t) {
                        //If we got this far, this is probably not a JAR loader so skip it
                    }
                }
            } catch (Throwable t) {
                //Not an Oracle VM
            }
        }

        return files;
    }

    public boolean finalizeNativeLibs(final ClassLoader cl) {

        boolean res = false;
        final Class classClassLoader = ClassLoader.class;
        java.lang.reflect.Field nativeLibraries = null;

        try {
            nativeLibraries = classClassLoader.getDeclaredField("nativeLibraries");
        } catch (NoSuchFieldException e1) {
            //Ignore
        }

        if (nativeLibraries == null) {
            return res;
        }

        nativeLibraries.setAccessible(true);
        Object obj = null;

        try {
            obj = nativeLibraries.get(cl);
        } catch (IllegalAccessException e1) {
            //Ignore
        }

        if (!(obj instanceof Vector)) {
            return res;
        }

        res = true;
        final Vector java_lang_ClassLoader_NativeLibrary = (Vector) obj;
        java.lang.reflect.Method finalize;

        for (final Object lib : java_lang_ClassLoader_NativeLibrary) {

            try {
                finalize = lib.getClass().getDeclaredMethod("finalize", new Class[0]);

                if (finalize != null) {

                    finalize.setAccessible(true);

                    try {
                        finalize.invoke(lib, new Object[0]);
                    } catch (Throwable e) {
                        //Ignore
                    }
                }
            } catch (Throwable e) {
                //Ignore
            }
        }
        return res;
    }

    public static void destroyClassLoader(final String appId) {

        logger.debug("Destroying classLoaders for application " + appId);
        final List<ClassLoader> classLoaders = classLoadersByApp.remove(appId);

        if (classLoaders != null) {

            final Iterator<ClassLoader> it = classLoaders.iterator();
            Set<String> apps;
            ClassLoader cl;

            while (it.hasNext()) {

                cl = it.next();
                apps = appsByClassLoader.get(cl);

                if (null != apps) {
                    //This app is no longer using the class loader
                    apps.remove(appId);
                }

                //If no apps are using the class loader, destroy it
                if (null == apps || apps.isEmpty()) {
                    it.remove();
                    appsByClassLoader.remove(cl);
                    destroyClassLoader(cl);
                    System.gc();
                } else {
                    logger.debug("ClassLoader " + toString(cl) + " held open by the applications: " + apps);
                }
            }
        }

        localUrlCache.releaseUrls(appId);
        clearSunJarFileFactoryCache(appId);
    }

    public static URLClassLoader createTempClassLoader(final ClassLoader parent) {
        return new TempClassLoader(parent);
    }

    public static URLClassLoader createTempClassLoader(final String appId, final URL[] rawUrls, final ClassLoader parent) {
        String updatedAppId = appId;
        if (appId != null) { // here we often get the full path of the app as id where later it is simply the name of the file/dir
            final File file = new File(appId);
            if (file.exists()) {
                updatedAppId = file.getName();
                if (updatedAppId.endsWith(".war") || updatedAppId.endsWith(".ear")) {
                    updatedAppId = updatedAppId.substring(0, updatedAppId.length() - ".war".length());
                }
            }
        }

        final URL[] urls;
        ClassLoaderConfigurer configurer = ClassLoaderUtil.configurer(updatedAppId);
        if (configurer == null) { // try the complete path
            configurer = ClassLoaderUtil.configurer(appId);
        }
        if (configurer != null) {
            final Collection<URL> urlList = new ArrayList<URL>();
            for (final URL rawUrl : rawUrls) {
                if (configurer.accept(rawUrl)) {
                    urlList.add(rawUrl);
                }
            }
            urlList.addAll(Arrays.asList(configurer.additionalURLs()));
            urls = urlList.toArray(new URL[urlList.size()]);
        } else {
            urls = rawUrls;
        }

        return new TempClassLoader(createClassLoader(appId, urls, parent));
    }

    /**
     * Cleans well known class loader leaks in VMs and libraries.  There is a lot of bad code out there and this method
     * will clear up the know problems.  This method should only be called when the class loader will no longer be used.
     * It this method is called two often it can have a serious impact on preformance.
     */
    public static void clearClassLoaderCaches() {
        clearSunSoftCache(ObjectInputStream.class, "subclassAudits");
        clearSunSoftCache(ObjectOutputStream.class, "subclassAudits");
        clearSunSoftCache(ObjectStreamClass.class, "localDescs");
        clearSunSoftCache(ObjectStreamClass.class, "reflectors");
        Introspector.flushCaches();
    }

    public static void clearSunJarFileFactoryCache(final String jarLocation) {
        clearSunJarFileFactoryCacheImpl(jarLocation, 5);
    }

    /**
     * Due to several different implementation changes in various JDK releases the code here is not as
     * straight forward as reflecting debug items in your current runtime. There have even been breaking changes
     * between 1.6 runtime builds, let alone 1.5.
     * <p/>
     * If you discover a new issue here please be careful to ensure the existing functionality is 'extended' and not
     * just replaced to match your runtime observations.
     * <p/>
     * If you want to look at the mess that leads up to this then follow the source code changes made to
     * the class sun.net.www.protocol.jar.JarFileFactory over several years.
     *
     * @param jarLocation String
     * @param attempt     int
     */
    @SuppressWarnings({"unchecked"})
    private static synchronized void clearSunJarFileFactoryCacheImpl(final String jarLocation, final int attempt) {
        logger.debug("Clearing Sun JarFileFactory cache for directory " + jarLocation);

        try {
            final Class jarFileFactory = Class.forName("sun.net.www.protocol.jar.JarFileFactory");

            //Do not generify these maps as their contents are NOT stable across runtimes.
            final Field fileCacheField = jarFileFactory.getDeclaredField("fileCache");
            fileCacheField.setAccessible(true);
            final Map fileCache = (Map) fileCacheField.get(null);
            final Map fileCacheCopy = new HashMap(fileCache);

            final Field urlCacheField = jarFileFactory.getDeclaredField("urlCache");
            urlCacheField.setAccessible(true);
            final Map urlCache = (Map) urlCacheField.get(null);
            final Map urlCacheCopy = new HashMap(urlCache);

            //The only stable item we have here is the JarFile/ZipFile in this map
            Iterator iterator = urlCacheCopy.entrySet().iterator();
            final List urlCacheRemoveKeys = new ArrayList();

            while (iterator.hasNext()) {
                final Map.Entry entry = (Map.Entry) iterator.next();
                final Object key = entry.getKey();

                if (key instanceof ZipFile) {
                    final ZipFile zf = (ZipFile) key;
                    final File file = new File(zf.getName());  //getName returns File.getPath()
                    if (isParent(jarLocation, file)) {
                        //Flag for removal
                        urlCacheRemoveKeys.add(key);
                    }
                } else {
                    logger.warning("Unexpected key type: " + key);
                }
            }

            iterator = fileCacheCopy.entrySet().iterator();
            final List fileCacheRemoveKeys = new ArrayList();

            while (iterator.hasNext()) {
                final Map.Entry entry = (Map.Entry) iterator.next();
                final Object value = entry.getValue();

                if (urlCacheRemoveKeys.contains(value)) {
                    fileCacheRemoveKeys.add(entry.getKey());
                }
            }

            //Use these unstable values as the keys for the fileCache values.
            iterator = fileCacheRemoveKeys.iterator();
            while (iterator.hasNext()) {

                final Object next = iterator.next();

                try {
                    final Object remove = fileCache.remove(next);
                    if (null != remove) {
                        logger.debug("Removed item from fileCache: " + remove);
                    }
                } catch (Throwable e) {
                    logger.warning("Failed to remove item from fileCache: " + next);
                }
            }

            iterator = urlCacheRemoveKeys.iterator();
            while (iterator.hasNext()) {

                final Object next = iterator.next();

                try {
                    final Object remove = urlCache.remove(next);

                    try {
                        ((ZipFile) next).close();
                    } catch (Throwable e) {
                        //Ignore
                    }

                    if (null != remove) {
                        logger.debug("Removed item from urlCache: " + remove);
                    }
                } catch (Throwable e) {
                    logger.warning("Failed to remove item from urlCache: " + next);
                }

            }

        } catch (ConcurrentModificationException e) {
            if (attempt > 0) {
                clearSunJarFileFactoryCacheImpl(jarLocation, (attempt - 1));
            } else {
                logger.error("Unable to clear Sun JarFileFactory cache after 5 attempts", e);
            }
        } catch (ClassNotFoundException e) {
            // not a sun vm
        } catch (NoSuchFieldException e) {
            // different version of sun vm?
        } catch (Throwable e) {
            logger.error("Unable to clear Sun JarFileFactory cache", e);
        }
    }

    private static boolean isParent(final String jarLocation, File file) {
        final File dir = new File(jarLocation);
        while (file != null) {
            if (file.equals(dir)) {
                return true;
            }
            file = file.getParentFile();
        }
        return false;
    }

    /**
     * Clears the caches maintained by the SunVM object stream implementation.
     * This method uses reflection and setAccessable to obtain access to the Sun cache.
     * The cache Class synchronizes upon itself for access to the cache Map.
     * This method completely clears the class loader cache which will impact preformance of object serialization.
     *
     * @param clazz     the name of the class containing the cache field
     * @param fieldName the name of the cache field
     */
    public static void clearSunSoftCache(final Class clazz, final String fieldName) {
        synchronized (clazz) {
            try {
                final Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                final Map cache = (Map) field.get(null);
                cache.clear();
            } catch (Throwable ignored) {
                // there is nothing a user could do about this anyway
            }
        }
    }

    public static void cleanOpenJPACache(final ClassLoader classLoader) {
        try {
            final Class<?> pcRegistryClass = ClassLoaderUtil.class.getClassLoader().loadClass("org.apache.openjpa.enhance.PCRegistry");
            final Method deRegisterMethod = pcRegistryClass.getMethod("deRegister", ClassLoader.class);
            deRegisterMethod.invoke(null, classLoader);
        } catch (Throwable ignored) {
            // there is nothing a user could do about this anyway
        }
    }

    private static String toString(final ClassLoader classLoader) {
        if (classLoader == null) {
            return "null";
        } else {
            return classLoader.getClass().getSimpleName() + "@" + System.identityHashCode(classLoader);
        }
    }

    public static String resourceName(final String s) {
        return s.replace(".", "/") + ".class";
    }

    public static ClassLoaderConfigurer configurer(final String rawId) {
        String id = rawId;
        if (id != null && (id.startsWith("/") || id.startsWith("\\")) && !new File(id).exists() && id.length() > 1) {
            id = id.substring(1);
        }

        // TODO: see how to manage tomee/openejb prefix
        String key = "tomee.classloader.configurer." + id + ".clazz";
        String impl = SystemInstance.get().getProperty(key);
        if (impl == null) {
            key = "tomee.classloader.configurer.clazz";
            impl = SystemInstance.get().getProperty(key);
            if (impl == null) {
                key = "openejb.classloader.configurer." + id + ".clazz";
                impl = SystemInstance.get().getProperty(key);
                if (impl == null) {
                    key = "openejb.classloader.configurer.clazz";
                    impl = SystemInstance.get().getProperty(key);
                }

            }
        }

        if (impl != null) {
            key = key.substring(0, key.length() - "clazz".length());

            boolean list = false;
            try {
                ClassLoaderUtil.class.getClassLoader().loadClass(impl);
            } catch (ClassNotFoundException e) {
                list = true;
            }

            if (!list) {
                return createConfigurer(key, impl);
            } else {
                final String[] names = impl.split(",");
                final ClassLoaderConfigurer[] configurers = new ClassLoaderConfigurer[names.length];
                for (int i = 0; i < names.length; i++) {
                    configurers[i] = createConfigurer(names[i], SystemInstance.get().getProperty(names[i] + ".clazz"));
                }
                return new CompositeClassLoaderConfigurer(configurers);
            }
        }
        return null;
    }

    private static ClassLoaderConfigurer createConfigurer(final String key, final String impl) {
        try {
            final ObjectRecipe recipe = new ObjectRecipe(impl);
            for (final Map.Entry<Object, Object> entry : SystemInstance.get().getProperties().entrySet()) {
                final String entryKey = entry.getKey().toString();
                if (entryKey.startsWith(key)) {
                    final String newKey = entryKey.substring(key.length());
                    if (!"clazz".equals(newKey)) {
                        recipe.setProperty(newKey, entry.getValue());
                    }
                }
            }

            final Object instance = recipe.create();
            if (instance instanceof ClassLoaderConfigurer) {
                return (ClassLoaderConfigurer) instance;
            } else {
                logger.error(impl + " is not a classlaoder configurer, using default behavior");
            }
        } catch (Exception e) {
            logger.error("Can't create classloader configurer " + impl + ", using default behavior");
        }
        return null;
    }
}
