📄 shadingpathresolver.java
字号:
/*****************************************************************************
* 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 + -