📄 pluginregistryimpl.java
字号:
/*****************************************************************************
* 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.registry.xml;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
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 java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.java.plugin.PathResolver;
import org.java.plugin.registry.Extension;
import org.java.plugin.registry.ExtensionPoint;
import org.java.plugin.registry.IntegrityCheckReport;
import org.java.plugin.registry.ManifestProcessingException;
import org.java.plugin.registry.PluginDescriptor;
import org.java.plugin.registry.PluginFragment;
import org.java.plugin.registry.PluginPrerequisite;
import org.java.plugin.registry.PluginRegistry;
import org.java.plugin.registry.Version;
import org.java.plugin.registry.IntegrityCheckReport.ReportItem;
import org.java.plugin.registry.xml.IntegrityChecker.ReportItemImpl;
import org.java.plugin.util.ExtendedProperties;
/**
* This is an implementation of plug-in registry of XML syntax plug-in
* manifests. Manifests should be prepared according to
* <a href="{@docRoot}/../plugin_1_0.dtd">plug-in DTD</a>.
* <p>
* <b>Configuration parameters</b>
* <p>
* This registry implementation supports following configuration parameters:
* <dl>
* <dt>isValidating</dt>
* <dd>Regulates is registry should use validating parser when loading
* plug-in manifests. The default parameter value is <code>true</code>.</dd>
* <dt>stopOnError</dt>
* <dd>Regulates is registry should stop and throw RuntimeException if an
* error occurred while {@link PluginRegistry#register(URL[]) registering}
* or {@link PluginRegistry#unregister(String[]) un-registering} plug-ins.
* If this is <code>false</code>, the registration errors will be stored
* in the internal report that is available with
* {@link PluginRegistry#checkIntegrity(PathResolver)} method.
* The default parameter value is <code>false</code>.</dd>
* </dl>
*
* @see org.java.plugin.ObjectFactory#createRegistry()
*
* @version $Id: PluginRegistryImpl.java,v 1.17 2007/01/05 14:05:23 ddimon Exp $
*/
public final class PluginRegistryImpl implements PluginRegistry {
static final String PACKAGE_NAME = "org.java.plugin.registry.xml"; //$NON-NLS-1$
private static final char UNIQUE_SEPARATOR = '@';
private static final Log log = LogFactory.getLog(PluginRegistryImpl.class);
private final List registrationReport = new LinkedList(); // <ReportItemImpl>
private final Map registeredPlugins = new HashMap(); // <pluginId, PluginDescriptorImpl>
private final Map registeredFragments = new HashMap(); // <fragmentId, PluginFragmentImpl>
private final List listeners = Collections.synchronizedList(new LinkedList()); // <EventListener>
private ManifestParser manifestParser;
private boolean stopOnError = false;
/**
* Creates plug-in registry object.
*/
public PluginRegistryImpl() {
registrationReport.add(new ReportItemImpl(ReportItem.SEVERITY_INFO,
null, ReportItem.ERROR_NO_ERROR, "registryStart", null)); //$NON-NLS-1$
}
/**
* @see org.java.plugin.registry.PluginRegistry#configure(
* ExtendedProperties)
*/
public void configure(final ExtendedProperties config) {
stopOnError = "true".equalsIgnoreCase( //$NON-NLS-1$
config.getProperty("stopOnError", "false")); //$NON-NLS-1$ //$NON-NLS-2$
boolean isValidating = !"false".equalsIgnoreCase( //$NON-NLS-1$
config.getProperty("isValidating", "true")); //$NON-NLS-1$ //$NON-NLS-2$
manifestParser = new ManifestParser(isValidating);
log.info("configured, stopOnError=" + stopOnError //$NON-NLS-1$
+ ", isValidating=" + isValidating); //$NON-NLS-1$
}
/**
* @see org.java.plugin.registry.PluginRegistry#readManifestInfo(
* java.net.URL)
*/
public ManifestInfo readManifestInfo(final URL url)
throws ManifestProcessingException {
try {
return new ManifestInfoImpl(manifestParser.parseManifestInfo(url));
} catch (Exception e) {
throw new ManifestProcessingException(PACKAGE_NAME,
"manifestParsingError", url, e); //$NON-NLS-1$
}
}
/**
* General algorithm:
* <ol>
* <li>Collect all currently registered extension points.</li>
* <li>Parse given URL's as XML content files and separate them on plug-in
* and plug-in fragment descriptors.</li>
* <li>Process new plug-in descriptors first:
* <ol>
* <li>Instantiate new PluginDescriptorImpl object.</li>
* <li>Handle versions correctly - register new descriptor as most
* recent version or as an old version.</li>
* <li>If other versions of the same plug-in already registered, take
* their fragments and register them with this version.</li>
* </ol>
* </li>
* <li>Process new plug-in fragments next:
* <ol>
* <li>Instantiate new PluginFragmentImpl object.</li>
* <li>Check if older version of the same fragment already registered.
* If yes, un-register it and move to old plug-in fragments
* collection.</li>
* <li>Register new fragment with all matches plug-in descriptors (if
* this fragment is of most recent version).</li>
* </ol>
* </li>
* <li>Notify collected extension points about potential changes in
* extensions set.</li>
* <li>Propagate events about registry changes.</li>
* </ol>
* @see org.java.plugin.registry.PluginRegistry#register(java.net.URL[])
*/
public Map register(final URL[] manifests)
throws ManifestProcessingException {
// collecting registered extension points and extensions
List registeredPoints = new LinkedList(); //<ExtensionPointImpl>
Map registeredExtensions = new HashMap(); //<extensionUid, ExtensionImpl>
for (Iterator it = registeredPlugins.values().iterator();
it.hasNext();) {
for (Iterator it2 = ((PluginDescriptor) it.next())
.getExtensionPoints().iterator();
it2.hasNext();) {
ExtensionPoint point = (ExtensionPoint) it2.next();
registeredPoints.add(point);
for (Iterator it3 = point.getConnectedExtensions().iterator();
it3.hasNext();) {
Extension ext = (Extension) it3.next();
registeredExtensions.put(ext.getUniqueId(), ext);
}
}
}
Map result = new HashMap(manifests.length); //<URL, PluginDescriptor or PluginFragment>
Map plugins = new HashMap(); //<URL, ModelPluginDescriptor>
Map fragments = new HashMap(); //<URL, ModelPluginFrafment>
// parsing given manifests
registrationReport.add(new ReportItemImpl(ReportItem.SEVERITY_INFO,
null, ReportItem.ERROR_NO_ERROR, "manifestsParsingStart", null)); //$NON-NLS-1$
for (int i = 0; i < manifests.length; i++) {
URL url = manifests[i];
ModelPluginManifest model;
try {
model = manifestParser.parseManifest(url);
} catch (Exception e) {
log.error("can't parse manifest file " + url, e); //$NON-NLS-1$
if (stopOnError) {
throw new ManifestProcessingException(PACKAGE_NAME,
"manifestParsingError", url, e); //$NON-NLS-1$
}
registrationReport.add(new ReportItemImpl(
ReportItem.SEVERITY_ERROR, null,
ReportItem.ERROR_MANIFEST_PROCESSING_FAILED,
"manifestParsingError", new Object[] {url, e})); //$NON-NLS-1$
continue;
}
if (model instanceof ModelPluginFragment) {
fragments.put(url, model);
continue;
}
if (!(model instanceof ModelPluginDescriptor)) {
log.warn("URL " + url //$NON-NLS-1$
+ " points to XML document of unknown type"); //$NON-NLS-1$
continue;
}
plugins.put(url, model);
}
if (log.isDebugEnabled()) {
log.debug("manifest files parsed, plugins.size=" + plugins.size() //$NON-NLS-1$
+ ", fragments.size=" + fragments.size()); //$NON-NLS-1$
}
registrationReport.add(new ReportItemImpl(ReportItem.SEVERITY_INFO,
null, ReportItem.ERROR_NO_ERROR, "manifestsParsingFinish", //$NON-NLS-1$
new Object[] {new Integer(plugins.size()),
new Integer(fragments.size())}));
checkVersions(plugins);
if (log.isDebugEnabled()) {
log.debug("plug-ins versions checked, plugins.size=" //$NON-NLS-1$
+ plugins.size());
}
checkVersions(fragments);
if (log.isDebugEnabled()) {
log.debug("plug-in fragments versions checked, fragments.size=" //$NON-NLS-1$
+ fragments.size());
}
RegistryChangeDataImpl registryChangeData =
new RegistryChangeDataImpl();
// registering new plug-ins
registrationReport.add(new ReportItemImpl(ReportItem.SEVERITY_INFO,
null, ReportItem.ERROR_NO_ERROR,
"registeringPluginsStart", null)); //$NON-NLS-1$
for (Iterator it = plugins.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Entry) it.next();
URL url = (URL) entry.getKey();
PluginDescriptor descr = registerPlugin(url,
(ModelPluginDescriptor) entry.getValue(),
registryChangeData);
if (descr != null) {
result.put(url, descr);
}
}
plugins.clear();
// registering new plug-in fragments
registrationReport.add(new ReportItemImpl(ReportItem.SEVERITY_INFO,
null, ReportItem.ERROR_NO_ERROR,
"registeringFragmentsStart", null)); //$NON-NLS-1$
for (Iterator it = fragments.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Entry) it.next();
URL url = (URL) entry.getKey();
PluginFragment fragment =
registerFragment(url, (ModelPluginFragment) entry.getValue(),
registryChangeData);
if (fragment != null) {
result.put(url, fragment);
}
}
fragments.clear();
registrationReport.add(new ReportItemImpl(ReportItem.SEVERITY_INFO,
null, ReportItem.ERROR_NO_ERROR,
"registeringPluginsFinish", //$NON-NLS-1$
new Integer(registeredPlugins.size())));
registrationReport.add(new ReportItemImpl(ReportItem.SEVERITY_INFO,
null, ReportItem.ERROR_NO_ERROR,
"registeringFragmentsFinish", //$NON-NLS-1$
new Integer(registeredFragments.size())));
log.info("plug-in and fragment descriptors registered - " //$NON-NLS-1$
+ result.size());
dump();
if (result.isEmpty()) {
return result;
}
// notify all interested members that plug-ins set has been changed
for (Iterator it = registeredPoints.iterator(); it.hasNext();) {
((ExtensionPointImpl) it.next()).registryChanged();
}
for (Iterator it = registeredExtensions.values().iterator();
it.hasNext();) {
((ExtensionImpl) it.next()).registryChanged();
}
if (!listeners.isEmpty() || log.isDebugEnabled()) {
// analyze changes in extensions set
for (Iterator it = registeredPlugins.values().iterator();
it.hasNext();) {
for (Iterator it2 = ((PluginDescriptor) it.next())
.getExtensionPoints().iterator();
it2.hasNext();) {
for (Iterator it3 = ((ExtensionPoint) it2.next())
.getConnectedExtensions().iterator();
it3.hasNext();) {
Extension ext = (Extension) it3.next();
if (!registeredExtensions.containsKey(
ext.getUniqueId())) {
registryChangeData.putAddedExtension(
ext.getUniqueId(),
makeUniqueId(ext.getExtendedPluginId(),
ext.getExtendedPointId()));
} else {
registeredExtensions.remove(ext.getUniqueId());
if (registryChangeData.modifiedPlugins().contains(
ext.getDeclaringPluginDescriptor().getId())
|| registryChangeData.modifiedPlugins()
.contains(ext.getExtendedPluginId())) {
registryChangeData.putModifiedExtension(
ext.getUniqueId(),
makeUniqueId(ext.getExtendedPluginId(),
ext.getExtendedPointId()));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -