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

📄 shadingpathresolver.java

📁 java插件系统源码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
 * Java Plug-in Framework (JPF)
 * Copyright (C) 2004-2006 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.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.java.plugin.registry.Identity;
import org.java.plugin.registry.Library;
import org.java.plugin.registry.PluginAttribute;
import org.java.plugin.registry.PluginDescriptor;
import org.java.plugin.registry.PluginElement;
import org.java.plugin.registry.PluginFragment;
import org.java.plugin.registry.UniqueIdentity;
import org.java.plugin.util.ExtendedProperties;
import org.java.plugin.util.IoUtil;

/**
 * This implementation of path resolver makes "shadow copy" of plug-in resources
 * before resolving paths to them, this helps avoid locking of local resources
 * and run native code from remote locations.
 * <p>
 * <b>Configuration parameters</b>
 * </p>
 * <p>
 * This path resolver implementation supports following configuration
 * parameters:
 * <dl>
 *   <dt>shadowFolder</dt>
 *   <dd>Path to the folder where to copy resources to prevent their locking. By
 *     default this will be
 *     <code>System.getProperty("java.io.tmpdir") + "/.jpf-shadow"</code>.
 *     Please note that this folder will be maintained automatically by the
 *     Framework and might be cleared without any confirmation or notification.
 *     So it is strongly not recommended to use plug-ins folder (or other
 *     sensitive application directory) as shadow folder, this may lead to
 *     losing your data.</dd>
 *   <dt>unpackMode</dt>
 *   <dd>If <code>always</code>, "JAR'ed" or "ZIP'ed" plug-ins will be
 *     un-compressed to the shadow folder, if <code>never</code>, they will be
 *     just copied, if <code>smart</code>, the processing depends on plug-in
 *     content - if plug-in contains JAR libraries, it will be un-packed,
 *     otherwise just copied to shadow folder. It is also possible to add
 *     boolean "unpack" attribute to plug-in manifest, in this case, it's value
 *     will be taken into account. The default parameter value is
 *     <code>smart</code>.</dd>
 *   <dt>excludes</dt>
 *   <dd>Pipe <code>'|'</code> separated list of regular expression patterns
 *     to be used to exclude files to be shadowed. By default no files excluded.
 *     </dd>
 *   <dt>includes</dt>
 *   <dd>Pipe <code>'|'</code> separated list of regular expression patterns
 *     to be used to include files to be shadowed. By default all files
 *     included.</dd>
 * </dl>
 * </p>
 *
 * @version $Id: ShadingPathResolver.java,v 1.16 2006/10/19 18:41:19 ddimon Exp $
 */
public class ShadingPathResolver extends StandardPathResolver {
    private static final String UNPACK_MODE_ALWAIS = "always"; //$NON-NLS-1$
    private static final String UNPACK_MODE_NEVER = "never"; //$NON-NLS-1$
    private static final String UNPACK_MODE_SMART = "smart"; //$NON-NLS-1$
    
    private File shadowFolder;
    private String unpackMode;
    private Map shadowUrlMap = new HashMap(); // <pluginId or fragmentId, shadow URL>
    private Map unpackModeMap = new HashMap(); // <pluginId or fragmentId, Boolean>
    private ShadowDataController controller;

    /**
     * @see org.java.plugin.PathResolver#configure(ExtendedProperties)
     */
    public synchronized void configure(final ExtendedProperties config)
            throws Exception {
        super.configure(config);
        String folder = config.getProperty("shadowFolder"); //$NON-NLS-1$
        if ((folder != null) && (folder.length() > 0)) {
            try {
                shadowFolder = new File(folder).getCanonicalFile();
            } catch (IOException ioe) {
                log.warn("failed initializing shadow folder " + folder //$NON-NLS-1$
                        + ", falling back to the default folder", ioe); //$NON-NLS-1$
            }
        }
        if (shadowFolder == null) {
            shadowFolder = new File(System.getProperty("java.io.tmpdir"), //$NON-NLS-1$
                    ".jpf-shadow"); //$NON-NLS-1$
        }
        log.debug("shadow folder is " + shadowFolder); //$NON-NLS-1$
        if (!shadowFolder.exists()) {
            shadowFolder.mkdirs();
        }
        unpackMode = config.getProperty("unpackMode", UNPACK_MODE_SMART); //$NON-NLS-1$
        log.debug("unpack mode parameter value is " + unpackMode); //$NON-NLS-1$
        controller = ShadowDataController.init(shadowFolder,
                buildFileFilter(config));
        log.info("configured, shadow folder is " + shadowFolder); //$NON-NLS-1$
    }
    
    private FileFilter buildFileFilter(final ExtendedProperties config) {
        final FileFilter includesFilter;
        String patterns = config.getProperty("includes"); //$NON-NLS-1$
        if ((patterns != null) && (patterns.trim().length() > 0)) {
            includesFilter = new RegexpFileFilter(patterns);
        } else {
            includesFilter = null;
        }
        final FileFilter excludesFilter;
        patterns = config.getProperty("excludes"); //$NON-NLS-1$
        if ((patterns != null) && (patterns.trim().length() > 0)) {
            excludesFilter = new RegexpFileFilter(patterns);
        } else {
            excludesFilter = null;
        }
        if ((excludesFilter == null) && (includesFilter == null)) {
            return null;
        }
        return new CombinedFileFilter(includesFilter, excludesFilter);
    }

    /**
     * @see org.java.plugin.standard.StandardPathResolver#registerContext(
     *      org.java.plugin.registry.Identity, java.net.URL)
     */
    public void registerContext(Identity idt, URL url) {
        super.registerContext(idt, url);
        Boolean mode;
        if (UNPACK_MODE_ALWAIS.equalsIgnoreCase(unpackMode)) {
            mode = Boolean.TRUE;
        } else if (UNPACK_MODE_NEVER.equalsIgnoreCase(unpackMode)) {
            mode = Boolean.FALSE;
        } else {
            PluginDescriptor descr = null;
            PluginFragment fragment = null;
            if (idt instanceof PluginDescriptor) {
                descr = (PluginDescriptor) idt;
            } else if (idt instanceof PluginFragment) {
                fragment = (PluginFragment) idt;
                descr = fragment.getRegistry().getPluginDescriptor(
                        fragment.getPluginId());
            } else if (idt instanceof PluginElement) {
                PluginElement element = (PluginElement) idt;
                descr = element.getDeclaringPluginDescriptor();
                fragment = element.getDeclaringPluginFragment();
            } else {
                throw new IllegalArgumentException("unknown identity class " //$NON-NLS-1$
                        + idt.getClass().getName());
            }
            mode = getUnpackMode(descr, fragment);
        }
        log.debug("unpack mode for " + idt + " is " + mode); //$NON-NLS-1$ //$NON-NLS-2$
        unpackModeMap.put(idt.getId(), mode);
    }
    
    private Boolean getUnpackMode(final PluginDescriptor descr,
            final PluginFragment fragment) {
        for (Iterator it = filterCollection(descr.getAttributes("unpack"), //$NON-NLS-1$
                fragment).iterator(); it.hasNext();) {
            return Boolean.valueOf("false".equalsIgnoreCase( //$NON-NLS-1$
                    ((PluginAttribute) it.next()).getValue()));
        }
        for (Iterator it = filterCollection(descr.getLibraries(),
                fragment).iterator(); it.hasNext();) {
            Library lib = (Library) it.next();
            if (lib.isCodeLibrary() && (lib.getPath().toLowerCase(
                            Locale.getDefault()).endsWith(".jar") //$NON-NLS-1$
                    || lib.getPath().toLowerCase(
                            Locale.getDefault()).endsWith(".zip"))) { //$NON-NLS-1$
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }
    
    private Collection filterCollection(final Collection coll,
            final PluginFragment fragment) {
        if (fragment == null) {
            return coll;
        }
        LinkedList result = new LinkedList();
        for (Iterator it = coll.iterator(); it.hasNext();) {
            PluginElement element = (PluginElement) it.next();
            if (fragment.equals(element.getDeclaringPluginFragment())) {
                result.add(element);
            }
        }
        return result;
    }
    
    /**
     * @see org.java.plugin.standard.StandardPathResolver#unregisterContext(
     *      java.lang.String)
     */
    public void unregisterContext(String id) {
        shadowUrlMap.remove(id);
        unpackModeMap.remove(id);
        super.unregisterContext(id);
    }

    /**
     * @see org.java.plugin.PathResolver#resolvePath(
     *      org.java.plugin.registry.Identity, java.lang.String)
     */
    public URL resolvePath(final Identity idt, final String path) {
        URL baseUrl;
        if (idt instanceof PluginDescriptor) {
            baseUrl = getBaseUrl((PluginDescriptor) idt);
        } else if (idt instanceof PluginFragment) {
            baseUrl = getBaseUrl((PluginFragment) idt);
        } else if (idt instanceof PluginElement) {
            PluginElement element = (PluginElement) idt;
            if (element.getDeclaringPluginFragment() != null) {
                baseUrl = getBaseUrl(
                        element.getDeclaringPluginFragment());
            } else {
                baseUrl = getBaseUrl(
                        element.getDeclaringPluginDescriptor());
            }
        } else {
            throw new IllegalArgumentException("unknown identity class " //$NON-NLS-1$
                    + idt.getClass().getName());
        }
        return resolvePath(baseUrl, path);
    }
    
    protected synchronized URL getBaseUrl(final UniqueIdentity uid) {
        URL result = (URL) shadowUrlMap.get(uid.getId());
        if (result != null) {
            return result;
        }
        result = controller.shadowResource(getRegisteredContext(uid.getId()),
                uid.getUniqueId(),
                ((Boolean) unpackModeMap.get(uid.getId())).booleanValue());
        shadowUrlMap.put(uid.getId(), result);
        return result;
    }
}

final class ShadingUtil {
    static String getExtension(final String name) {
        if ((name == null) || (name.length() == 0)) {
            return null;
        }
        int p = name.lastIndexOf('.');
        if ((p != -1) && (p > 0) && (p < name.length() - 1)) {
            return name.substring(p + 1);
        }
        return null;
    }
    
    static void unpack(final ZipFile zipFile,
            final File destFolder) throws IOException {
        for (Enumeration en = zipFile.entries(); en.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) en.nextElement();
            String name = entry.getName();
            File entryFile =
                new File(destFolder.getCanonicalPath() + "/" + name); //$NON-NLS-1$
            if (name.endsWith("/")) { //$NON-NLS-1$
                if (!entryFile.exists() && !entryFile.mkdirs()) {
                    throw new IOException("can't create folder " + entryFile); //$NON-NLS-1$
                }
            } else {
                File folder = entryFile.getParentFile();
                if (!folder.exists() && !folder.mkdirs()) {
                    throw new IOException("can't create folder " + folder); //$NON-NLS-1$
                }
                OutputStream out = new BufferedOutputStream(
                        new FileOutputStream(entryFile, false));

⌨️ 快捷键说明

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