⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 standardpluginclassloader.java

📁 java插件系统源码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
 * Java Plug-in Framework (JPF)
 * Copyright (C) 2004-2007 Dmitry Olshansky
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *****************************************************************************/
package org.java.plugin.standard;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.java.plugin.PathResolver;
import org.java.plugin.PluginClassLoader;
import org.java.plugin.PluginManager;
import org.java.plugin.registry.Library;
import org.java.plugin.registry.PluginDescriptor;
import org.java.plugin.registry.PluginPrerequisite;
import org.java.plugin.registry.PluginRegistry;
import org.java.plugin.util.IoUtil;

/**
 * Standard implementation of plug-in class loader.
 * @version $Id: StandardPluginClassLoader.java,v 1.22 2007/01/05 13:32:09 ddimon Exp $
 */
public class StandardPluginClassLoader extends PluginClassLoader {
    static Log log = LogFactory.getLog(StandardPluginClassLoader.class);
    
    private static File libCacheFolder;
    private static boolean libCacheFolderInitialized = false;
    
    private static URL getClassBaseUrl(final Class cls) {
        ProtectionDomain pd = cls.getProtectionDomain();
        if (pd != null) {
            CodeSource cs = pd.getCodeSource();
            if (cs != null) {
                return cs.getLocation();
            }
        }
        return null;
    }

    private static URL[] getUrls(final PluginManager manager,
            final PluginDescriptor descr) {
        List result = new LinkedList();
        for (Iterator it = descr.getLibraries().iterator(); it.hasNext();) {
            Library lib = (Library) it.next();
            if (!lib.isCodeLibrary()) {
                continue;
            }
            result.add(manager.getPathResolver().resolvePath(lib,
                    lib.getPath()));
        }
        if (log.isDebugEnabled()) {
            StringBuffer buf = new StringBuffer();
            buf.append("Code URL's populated for plug-in " //$NON-NLS-1$
                    + descr + ":\r\n"); //$NON-NLS-1$
            for (Iterator it = result.iterator(); it.hasNext();) {
                buf.append("\t"); //$NON-NLS-1$
                buf.append(it.next());
                buf.append("\r\n"); //$NON-NLS-1$
            }
            log.debug(buf.toString());
        }
        return (URL[]) result.toArray(new URL[result.size()]);
    }
    
    private static URL[] getUrls(final PluginManager manager,
            final PluginDescriptor descr, final URL[] existingUrls) {
        List urls = Arrays.asList(existingUrls);
        List result = new LinkedList();
        for (Iterator it = descr.getLibraries().iterator(); it.hasNext();) {
            Library lib = (Library) it.next();
            if (!lib.isCodeLibrary()) {
                continue;
            }
            URL url = manager.getPathResolver().resolvePath(lib, lib.getPath());
            if (!urls.contains(url)) {
                result.add(url);
            }
        }
        return (URL[]) result.toArray(new URL[result.size()]);
    }
    
    private static File getLibCacheFolder() {
        if (libCacheFolder != null) {
            return libCacheFolderInitialized ? libCacheFolder : null;
        }
        synchronized (StandardPluginClassLoader.class) {
            libCacheFolder = new File(System.getProperty("java.io.tmpdir"), //$NON-NLS-1$
                    System.currentTimeMillis() + ".jpf-lib-cache"); //$NON-NLS-1$
            log.debug("libraries cache folder is " + libCacheFolder); //$NON-NLS-1$
            File lockFile = new File(libCacheFolder, "lock"); //$NON-NLS-1$
            if (lockFile.exists()) {
                log.error("can't initialize libraries cache folder " //$NON-NLS-1$
                        + libCacheFolder + " as lock file indicates that it" //$NON-NLS-1$
                        + " is owned by another JPF instance"); //$NON-NLS-1$
                return null;
            }
            if (libCacheFolder.exists()) {
                // clean up folder
                IoUtil.emptyFolder(libCacheFolder);
            } else {
                libCacheFolder.mkdirs();
            }
            try {
                if (!lockFile.createNewFile()) {
                    log.error("can\'t create lock file in JPF libraries cache" //$NON-NLS-1$
                            + " folder " + libCacheFolder); //$NON-NLS-1$
                    return null;
                }
            } catch (IOException ioe) {
                log.error("can\'t create lock file in JPF libraries cache" //$NON-NLS-1$
                        + " folder " + libCacheFolder, ioe); //$NON-NLS-1$
                return null;
            }
            lockFile.deleteOnExit();
            libCacheFolder.deleteOnExit();
            libCacheFolderInitialized = true;
        }
        return libCacheFolder;
    }
    
    private PluginDescriptor[] publicImports;
    private PluginDescriptor[] privateImports;
    private PluginDescriptor[] reverseLookups;
    private PluginResourceLoader resourceLoader;
    private Map resourceFilters; // <lib URL, ResourceFilter>
    private Map libraryCache; // <lib URL, File>
    private boolean probeParentLoaderLast;

    /**
     * Creates class instance configured to load classes and resources for
     * given plug-in.
     * @param aManager plug-in manager instance
     * @param descr plug-in descriptor
     * @param parent parent class loader, usually this is JPF "host"
     *        application class loader
     */
    public StandardPluginClassLoader(final PluginManager aManager,
            final PluginDescriptor descr, final ClassLoader parent) {
        super(aManager, descr, getUrls(aManager, descr), parent);
        collectImports();
        resourceLoader = PluginResourceLoader.get(aManager, descr);
        collectFilters();
        libraryCache = new HashMap();
    }
    
    protected void collectImports() {
        // collect imported plug-ins (exclude duplicates)
        Map publicImportsMap = new HashMap(); //<plug-in ID, PluginDescriptor>
        Map privateImportsMap = new HashMap(); //<plug-in ID, PluginDescriptor>
        PluginRegistry registry = getPluginDescriptor().getRegistry();
        for (Iterator it = getPluginDescriptor().getPrerequisites().iterator();
                it.hasNext();) {
            PluginPrerequisite pre = (PluginPrerequisite) it.next();
            if (!pre.matches()) {
                continue;
            }
            PluginDescriptor preDescr =
                registry.getPluginDescriptor(pre.getPluginId());
            if (pre.isExported()) {
                publicImportsMap.put(preDescr.getId(), preDescr);
            } else {
                privateImportsMap.put(preDescr.getId(), preDescr);
            }
        }
        publicImports = (PluginDescriptor[]) publicImportsMap.values().toArray(
                new PluginDescriptor[publicImportsMap.size()]);
        privateImports =
            (PluginDescriptor[]) privateImportsMap.values().toArray(
                new PluginDescriptor[privateImportsMap.size()]);
        // collect reverse look up plug-ins (exclude duplicates)
        Map reverseLookupsMap = new HashMap(); //<plug-in ID, PluginDescriptor>
        for (Iterator it = registry.getPluginDescriptors().iterator();
                it.hasNext();) {
            PluginDescriptor descr = (PluginDescriptor) it.next();
            if (descr.equals(getPluginDescriptor())
                    || publicImportsMap.containsKey(descr.getId())
                    || privateImportsMap.containsKey(descr.getId())) {
                continue;
            }
            for (Iterator it2 = descr.getPrerequisites().iterator();
                    it2.hasNext();) {
                PluginPrerequisite pre = (PluginPrerequisite) it2.next();
                if (!pre.getPluginId().equals(getPluginDescriptor().getId())
                        || !pre.isReverseLookup()) {
                    continue;
                }
                if (!pre.matches()) {
                    continue;
                }
                reverseLookupsMap.put(descr.getId(), descr);
                break;
            }
        }
        reverseLookups =
            (PluginDescriptor[]) reverseLookupsMap.values().toArray(
                new PluginDescriptor[reverseLookupsMap.size()]);
    }
    
    protected void collectFilters() {
        if (resourceFilters == null) {
            resourceFilters = new HashMap();
        } else {
            resourceFilters.clear();
        }
        for (Iterator it = getPluginDescriptor().getLibraries().iterator();
                it.hasNext();) {
            Library lib = (Library) it.next();
            resourceFilters.put(
                    getPluginManager().getPathResolver().resolvePath(lib,
                            lib.getPath()).toExternalForm(),
                            new ResourceFilter(lib));
        }
    }
    
    /**
     * @see org.java.plugin.PluginClassLoader#pluginsSetChanged()
     */
    protected void pluginsSetChanged() {
        URL[] newUrls = getUrls(getPluginManager(), getPluginDescriptor(),
                getURLs());
        for (int i = 0; i < newUrls.length; i++) {
            addURL(newUrls[i]);
        }
        if (log.isDebugEnabled()) {
            StringBuffer buf = new StringBuffer();
            buf.append("New code URL's populated for plug-in " //$NON-NLS-1$
                    + getPluginDescriptor() + ":\r\n"); //$NON-NLS-1$
            for (int i = 0; i < newUrls.length; i++) {
                buf.append("\t"); //$NON-NLS-1$
                buf.append(newUrls[i]);
                buf.append("\r\n"); //$NON-NLS-1$
            }
            log.debug(buf.toString());
        }
        collectImports();
        // repopulate resource URLs
        resourceLoader =
            PluginResourceLoader.get(getPluginManager(), getPluginDescriptor());
        collectFilters();
        for (Iterator it = libraryCache.entrySet().iterator(); it.hasNext();) {
            if (((Map.Entry) it.next()).getValue() == null) {
                it.remove();
            }
        }
    }
    
    /**
     * @see org.java.plugin.PluginClassLoader#dispose()
     */
    protected void dispose() {
        for (Iterator it = libraryCache.values().iterator(); it.hasNext();) {
            ((File) it.next()).delete();
        }
        libraryCache.clear();
        resourceFilters.clear();
        privateImports = null;
        publicImports = null;
        resourceLoader = null;
    }
    
    protected void setProbeParentLoaderLast(final boolean value) {
        probeParentLoaderLast = value;
    }
    
    /**
     * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
     */
    protected Class loadClass(final String name, final boolean resolve)
            throws ClassNotFoundException {
        /*log.debug("loadClass(String, boolean): name=" + name + ", this="
                + this);*/
        Class result;
        if (probeParentLoaderLast) {
            try {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -