package org.eclipse.core.internal.plugins; | |
/* | |
* Licensed Materials - Property of IBM, | |
* WebSphere Studio Workbench | |
* (c) Copyright IBM Corp 2000 | |
*/ | |
import org.eclipse.core.boot.BootLoader; | |
import org.eclipse.core.runtime.*; | |
import org.eclipse.core.runtime.model.*; | |
import org.eclipse.core.internal.boot.*; | |
import org.eclipse.core.internal.runtime.*; | |
import java.io.*; | |
import java.lang.reflect.Constructor; | |
import java.lang.reflect.InvocationTargetException; | |
import java.net.*; | |
import java.util.*; | |
public class PluginDescriptor extends PluginDescriptorModel implements IPluginDescriptor { | |
private DelegatingURLClassLoader loader = null; // plugin loader | |
private boolean active = false; // plugin is active | |
private boolean activePending = false; // being activated | |
private boolean deactivated = false; // plugin deactivated due to startup errors | |
protected Plugin pluginObject = null; // plugin object | |
private ResourceBundle bundle = null; // plugin.properties | |
private Locale locale = null; // bundle locale | |
private boolean bundleNotFound = false; // marker to prevent unnecessary lookups | |
// constants | |
private static final String PLUGIN_URL = PlatformURLHandler.PROTOCOL + PlatformURLHandler.PROTOCOL_SEPARATOR + "/" + PlatformURLPluginConnection.PLUGIN + "/"; | |
private static final String DEFAULT_BUNDLE_NAME = "plugin"; | |
private static final String KEY_PREFIX = "%"; | |
private static final String KEY_DOUBLE_PREFIX = "%%"; | |
private static final String URL_PROTOCOL_FILE = "file"; | |
private static final String VERSION_SEPARATOR = "_"; | |
// Development mode constants | |
private static final String PLUGIN_JARS = "plugin.jars"; | |
private static final String VA_PROPERTIES = ".va.properties"; | |
private static final String KEY_PROJECT = "projects"; | |
public PluginDescriptor() { | |
super(); | |
} | |
/** | |
* concatenates start and end. If end has a '.' construct at the beginning | |
* trim off any leading '.' constructs. Since the libSpec was a path, we | |
* know that it was canonicalized and will only have at most one set | |
* of '.' constructs at the beginning. | |
*/ | |
private String concat(String start, String end) { | |
if (end.startsWith("..")) | |
// ISSUE: should log an error here | |
// error case. Can't '..' out of the scope of a plugin. Signal that this | |
// should be ignored (return null). | |
return null; | |
if (end.startsWith("./")) | |
return start + (end.substring(2)); | |
if (end.startsWith(".")) | |
return start + end.substring(1); | |
return start + end; | |
} | |
public Object createExecutableExtension(String className, Object initData, IConfigurationElement cfig, String propertyName) throws CoreException { | |
// load the requested class from this plugin | |
Class classInstance = null; | |
try { | |
classInstance = getPluginClassLoader(true).loadClass(className); | |
} catch (ClassNotFoundException e1) { | |
throwException("Unable to load class " + className, e1); | |
} | |
// create a new instance | |
Object result = null; | |
try { | |
result = classInstance.newInstance(); | |
} catch (InstantiationException e2) { | |
throwException(Policy.bind("noInstanceCreate", new String[] { className }), e2); | |
} catch (IllegalAccessException e3) { | |
throwException(Policy.bind("noInstanceCreate", new String[] { className }), e3); | |
} catch (Exception e4) { | |
// default constructor caused exception | |
throwException(Policy.bind("constructorError", new String[] { className }), e4); | |
} | |
// check if we have extension adapter and initialize | |
if (result instanceof IExecutableExtension) { | |
try { | |
// make the call even if the initialization string is null | |
((IExecutableExtension) result).setInitializationData(cfig, propertyName, initData); | |
} catch (CoreException ce) { | |
// user code threw exception | |
logError(ce.getStatus()); | |
throw new CoreException(ce.getStatus()); | |
} catch (Exception te) { | |
// user code caused exception | |
throwException(Policy.bind("setError", new String[] { className }), te); | |
} | |
} | |
return result; | |
} | |
Object createExecutableExtension(String pluginName, String className, Object initData, IConfigurationElement cfig, String propertyName) throws CoreException { | |
String id = getUniqueIdentifier(); // this plugin id | |
// check if we need to delegate to some other plugin | |
if (pluginName != null && !pluginName.equals("") && !pluginName.equals(id)) { | |
PluginDescriptor plugin = null; | |
plugin = (PluginDescriptor) getPluginRegistry().getPluginDescriptor(pluginName); | |
return plugin.createExecutableExtension(className, initData, cfig, propertyName); | |
} | |
return createExecutableExtension(className, initData, cfig, propertyName); | |
} | |
synchronized void doPluginActivation() throws CoreException { | |
// this method is called by the class loader just prior | |
// to getting a class. It needs to handle the | |
// case where it is called multiple times during the activation | |
// processing itself (as a result of other classes from this | |
// plugin being directly referenced by the plugin class) | |
// NOTE: there is a remote scenario where the plugin class can | |
// deadlock, if it starts separate thread(s) within its | |
// constructor or startup() method, and waits on those | |
// threads before returning (ie. calls join()). | |
boolean errorExit = true; | |
// check if already activated or pending | |
if (pluginActivationEnter()) { | |
try { | |
internalDoPluginActivation(); | |
errorExit = false; | |
} finally { | |
pluginActivationExit(errorExit); | |
} | |
} | |
} | |
synchronized void doPluginDeactivation() { | |
loader = null; | |
pluginObject = null; | |
active = false; | |
activePending = false; | |
deactivated = false; | |
} | |
/** | |
* convert a list of comma-separated tokens into an array | |
*/ | |
private static String[] getArrayFromList(String prop) { | |
if (prop == null || prop.trim().equals("")) | |
return new String[0]; | |
Vector list = new Vector(); | |
StringTokenizer tokens = new StringTokenizer(prop, ","); | |
while (tokens.hasMoreTokens()) { | |
String token = tokens.nextToken().trim(); | |
if (!token.equals("")) | |
list.addElement(token); | |
} | |
return list.isEmpty() ? new String[0] : (String[]) list.toArray(new String[0]); | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public IExtension getExtension(String id) { | |
if (id == null) | |
return null; | |
ExtensionModel[] list = getDeclaredExtensions(); | |
if (list == null) | |
return null; | |
for (int i = 0; i < list.length; i++) { | |
if (id.equals(list[i].getId())) | |
return (IExtension) list[i]; | |
} | |
return null; | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public IExtensionPoint getExtensionPoint(String extensionPointId) { | |
if (extensionPointId == null) | |
return null; | |
ExtensionPointModel[] list = getDeclaredExtensionPoints(); | |
if (list == null) | |
return null; | |
for (int i = 0; i < list.length; i++) { | |
if (extensionPointId.equals(list[i].getId())) | |
return (IExtensionPoint) list[i]; | |
} | |
return null; | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public IExtensionPoint[] getExtensionPoints() { | |
ExtensionPointModel[] list = getDeclaredExtensionPoints(); | |
if (list == null) | |
return new IExtensionPoint[0]; | |
IExtensionPoint[] newValues = new IExtensionPoint[list.length]; | |
System.arraycopy(list, 0, newValues, 0, list.length); | |
return newValues; | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public IExtension[] getExtensions() { | |
ExtensionModel[] list = getDeclaredExtensions(); | |
if (list == null) | |
return new IExtension[0]; | |
IExtension[] newValues = new IExtension[list.length]; | |
System.arraycopy(list, 0, newValues, 0, list.length); | |
return newValues; | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public URL getInstallURL() { | |
try { | |
return new URL(PLUGIN_URL + toString() + "/"); | |
} catch (MalformedURLException e) { | |
throw new IllegalStateException(); // unchecked | |
} | |
} | |
public URL getInstallURLInternal() { | |
String url = getLocation(); | |
try { | |
return new URL(url); | |
} catch (MalformedURLException e) { | |
throw new IllegalStateException(); // unchecked | |
} | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public String getLabel() { | |
String s = getName(); | |
return s == null ? "" : getResourceString(s); | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public Plugin getPlugin() throws CoreException { | |
if (pluginObject == null) | |
doPluginActivation(); | |
return pluginObject; | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public ClassLoader getPluginClassLoader() { | |
return getPluginClassLoader(true); | |
} | |
public ClassLoader getPluginClassLoader(boolean eclipseURLs) { | |
if (loader != null) | |
return loader; | |
Object[] path = getPluginClassLoaderPath(eclipseURLs); | |
URL[] codePath = (URL[]) path[0]; | |
URLContentFilter[] codeFilters = (URLContentFilter[]) path[1]; | |
URL[] resourcePath = (URL[]) path[2]; | |
URLContentFilter[] resourceFilters = (URLContentFilter[]) path[3]; | |
loader = new PluginClassLoader(codePath, codeFilters, resourcePath, resourceFilters, PlatformClassLoader.getDefault(), this); | |
loader.initializeImportedLoaders(); | |
// Note: need to be able to give out a loader reference before | |
// its prereqs are initialized. Otherwise loops in prereq | |
// definition will cause endless loop in initializePrereqs() | |
return loader; | |
} | |
private Object[] getPluginClassLoaderPath(boolean eclipseURLs) { | |
// If running in development mode, check for a plugin.jars file. | |
// The file has entries corresponding to each of the <library> | |
// elements in the plugin.xml. Each defined property is of form | |
// libname=source1,source2,source3,... | |
// For example | |
// plugin.xml | |
// <runtime> | |
// <library name=baseapi.jar> | |
// <export name="*"/> | |
// </library> | |
// <library name=another.jar/> | |
// <library name=base.jar/> | |
// </runtime> | |
// | |
// plugin.jars | |
// baseapi.jar=Base API Project | |
// base.jar=Base Project 1, Base Project 2 | |
// another.jar=More Code | |
// | |
// The above results in a loader search path consisting of | |
// Base API Project | |
// another.jar | |
// Base Project 1, Base Project 2 | |
// | |
// Any library access filters specified in the plugin.xml are | |
// applied to the corresponding loader search path entries | |
Properties jarDefinitions = loadJarDefinitions(); | |
ArrayList resourcePath = new ArrayList(5); | |
ArrayList resourceFilters = new ArrayList(5); | |
ArrayList codePath = new ArrayList(5); | |
ArrayList codeFilters = new ArrayList(5); | |
// compute the base of the classpath urls. If <code>eclipseURLs</code> is | |
// true, we should use eclipse: URLs. Otherwise the native URLs are used. | |
URL install = eclipseURLs ? getInstallURL() : getInstallURLInternal(); | |
String execBase = install.toExternalForm(); | |
String devBase = null; | |
if (InternalPlatform.inVAJ() || InternalPlatform.inVAME()) | |
devBase = PlatformURLBaseConnection.PLATFORM_URL_STRING; | |
else | |
devBase = execBase; | |
// build a list alternating lib spec and export spec | |
ArrayList libSpecs = new ArrayList(5); | |
String[] exportAll = new String[] { "*" }; | |
// add in any development mode class paths and the export all filter | |
if (DelegatingURLClassLoader.devClassPath != null) { | |
String[] specs = getArrayFromList(DelegatingURLClassLoader.devClassPath); | |
// convert dev class path into url strings | |
for (int j = 0; j < specs.length; j++) { | |
String spec = devBase + specs[j]; | |
char lastChar = spec.charAt(spec.length() - 1); | |
if ((spec.endsWith(".jar") || (lastChar == '/' || lastChar == '\\'))) | |
libSpecs.add(spec); | |
else | |
libSpecs.add(spec + "/"); | |
libSpecs.add(exportAll); | |
} | |
} | |
// add in the class path entries spec'd in the plugin.xml. If in development mode, | |
// add the entries from the plugin.jars first. | |
ILibrary[] list = getRuntimeLibraries(); | |
for (int i = 0; i < list.length; i++) { | |
ILibrary library = list[i]; | |
// if the library path is empty or the library is source lib, skip it. | |
if (library.getPath().isEmpty() || library.getType().equals(ILibrary.SOURCE)) | |
continue; | |
String[] filters = library.isFullyExported() ? exportAll : library.getContentFilters(); | |
// add in the plugin.jars entries | |
String libSpec = library.getPath().toString(); | |
libSpec = resolveLibraryPath(libSpec); | |
String jarDefinition = null; | |
if (jarDefinitions != null && libSpec != null) { | |
jarDefinition = jarDefinitions.getProperty(libSpec); | |
String[] specs = getArrayFromList(jarDefinition); | |
// convert jar spec into url strings | |
for (int j = 0; j < specs.length; j++) { | |
libSpecs.add(devBase + specs[j] + "/"); | |
libSpecs.add(filters); | |
} | |
} | |
libSpec = concat(execBase, libSpec); | |
if (libSpec != null) { | |
// if the libspec is NOT considered a directory, treat as a jar | |
if (!libSpec.endsWith("/")) { | |
// if running in VAJ or VAME and there was a plugin.jars definition, ignore the plugin.xml | |
// library entry (assume the plugin.jars entries covered all the bases. Otherwise, | |
// convert the plugin.xml entry into a URL. | |
if ((InternalPlatform.inVAJ() || InternalPlatform.inVAME()) && jarDefinition != null) { | |
libSpec = null; | |
} else { | |
if (libSpec.startsWith(PlatformURLHandler.PROTOCOL + PlatformURLHandler.PROTOCOL_SEPARATOR)) | |
libSpec += PlatformURLHandler.JAR_SEPARATOR; | |
else | |
libSpec = PlatformURLHandler.JAR + PlatformURLHandler.PROTOCOL_SEPARATOR + libSpec + PlatformURLHandler.JAR_SEPARATOR; | |
} | |
} | |
// if we still have a libspec, add it to the list of classpath entries | |
if (libSpec != null) { | |
if (library.getType().equals(ILibrary.CODE)) { | |
libSpecs.add(libSpec); | |
libSpecs.add(filters); | |
} else | |
if (library.getType().equals(ILibrary.RESOURCE)) { | |
resourcePath.add(libSpec); | |
resourceFilters.add(filters); | |
} | |
} | |
} | |
} | |
// create path entries for all libraries except those which are files | |
// and do not exist. | |
for (Iterator it = libSpecs.iterator(); it.hasNext();) { | |
String spec = (String) it.next(); | |
String[] filter = (String[]) it.next(); | |
try { | |
URL entry = new URL(spec); | |
URL resolved = Platform.resolve(entry); | |
boolean add = true; | |
if (resolved.getProtocol().equals(PlatformURLHandler.FILE)) | |
add = new File(resolved.getFile()).exists(); | |
if (add) { | |
codePath.add(resolved); | |
codeFilters.add(new URLContentFilter(filter)); | |
} | |
} catch (IOException e) { | |
// skip bad URLs | |
} | |
} | |
Object[] result = new Object[4]; | |
result[0] = codePath.toArray(new URL[codePath.size()]); | |
result[1] = codeFilters.toArray(new URLContentFilter[codeFilters.size()]); | |
result[2] = resourcePath.toArray(new URL[resourcePath.size()]); | |
result[3] = resourceFilters.toArray(new URLContentFilter[resourceFilters.size()]); | |
return result; | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public IPluginPrerequisite[] getPluginPrerequisites() { | |
PluginPrerequisiteModel[] list = getRequires(); | |
if (list == null) | |
return new IPluginPrerequisite[0]; | |
IPluginPrerequisite[] newValues = new IPluginPrerequisite[list.length]; | |
System.arraycopy(list, 0, newValues, 0, list.length); | |
return newValues; | |
} | |
public PluginRegistry getPluginRegistry() { | |
return (PluginRegistry) getRegistry(); | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public String getProviderName() { | |
String s = super.getProviderName(); | |
return s == null ? "" : getResourceString(s); | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public ResourceBundle getResourceBundle() throws MissingResourceException { | |
return getResourceBundle(Locale.getDefault()); | |
} | |
public ResourceBundle getResourceBundle(Locale locale) throws MissingResourceException { | |
// we cache the bundle for a single locale | |
if (bundle != null && locale.equals(locale)) | |
return bundle; | |
// check if we already tried and failed | |
if (bundleNotFound) | |
throw new MissingResourceException(Policy.bind("resourceNotFound", new String[] { DEFAULT_BUNDLE_NAME + "_" + locale }), DEFAULT_BUNDLE_NAME + "_" + locale, ""); | |
// try to load bundle from this plugin install directory | |
ClassLoader resourceLoader = new URLClassLoader(new URL[] { getInstallURL()}, null); | |
ResourceBundle newBundle = null; | |
try { | |
newBundle = ResourceBundle.getBundle(DEFAULT_BUNDLE_NAME, locale, resourceLoader); | |
} catch (MissingResourceException e) { | |
bundleNotFound = true; | |
throw e; | |
} | |
return newBundle; | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public String getResourceString(String value) { | |
return getResourceString(value, null); | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public String getResourceString(String value, ResourceBundle b) { | |
String s = value.trim(); | |
if (!s.startsWith(KEY_PREFIX)) return s; | |
if (s.startsWith(KEY_DOUBLE_PREFIX)) return s.substring(1); | |
int ix = s.indexOf(" "); | |
String key = ix == -1 ? s : s.substring(0,ix); | |
String dflt = ix == -1 ? s : s.substring(ix+1); | |
if (b==null) { | |
try { b = getResourceBundle(); } | |
catch (MissingResourceException e) {}; | |
} | |
if (b==null) return dflt; | |
try { return b.getString(key.substring(1)); } | |
catch(MissingResourceException e) { return dflt; } | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public ILibrary[] getRuntimeLibraries() { | |
LibraryModel[] list = getRuntime(); | |
if (list == null) | |
return new ILibrary[0]; | |
ILibrary[] newValues = new ILibrary[list.length]; | |
System.arraycopy(list, 0, newValues, 0, list.length); | |
return newValues; | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public String getUniqueIdentifier() { | |
return getId(); | |
} | |
/** | |
* @see #toString | |
*/ | |
public static String getUniqueIdentifierFromString(String pluginString) { | |
int ix = pluginString.indexOf(VERSION_SEPARATOR); | |
return ix==-1 ? pluginString : pluginString.substring(0,ix); | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public PluginVersionIdentifier getVersionIdentifier() { | |
String version = getVersion(); | |
if (version == null) | |
return new PluginVersionIdentifier("1.0.0"); | |
try { | |
return new PluginVersionIdentifier(version); | |
} catch (Exception e) { | |
return new PluginVersionIdentifier("1.0.0"); | |
} | |
} | |
/** | |
* @see #toString | |
*/ | |
public static PluginVersionIdentifier getVersionIdentifierFromString(String pluginString) { | |
int ix = pluginString.indexOf("_"); | |
if (ix==-1) return null; | |
String vid = pluginString.substring(ix+1); | |
try { | |
return new PluginVersionIdentifier(vid); | |
} catch (Exception e) { | |
return null; | |
} | |
} | |
private void internalDoPluginActivation() throws CoreException { | |
String errorMsg; | |
// load the runtime class | |
String pluginClassName = getPluginClass(); | |
Class runtimeClass = null; | |
try { | |
if (pluginClassName == null || pluginClassName.equals("")) | |
runtimeClass = DefaultPlugin.class; | |
else | |
runtimeClass = getPluginClassLoader(true).loadClass(pluginClassName); | |
} catch (ClassNotFoundException e) { | |
errorMsg = Policy.bind("noLoadClass", new String[] { pluginClassName }); | |
throwException(errorMsg, e); | |
} | |
// find the correct constructor | |
Constructor construct = null; | |
try { | |
construct = runtimeClass.getConstructor(new Class[] { IPluginDescriptor.class }); | |
} catch (NoSuchMethodException eNoConstructor) { | |
errorMsg = Policy.bind("constructorError", new String[] { pluginClassName }); | |
throwException(errorMsg, eNoConstructor); | |
} | |
// create a new instance | |
Plugin result = null; | |
try { | |
pluginObject = (Plugin) construct.newInstance(new Object[] { this }); | |
} catch (ClassCastException e) { | |
errorMsg = Policy.bind("notPluginChild", new String[] { pluginClassName }); | |
throwException(errorMsg, null); | |
} catch (InstantiationException e) { | |
errorMsg = Policy.bind("noInstanceCreate", new String[] { pluginClassName }); | |
throwException(errorMsg, e); | |
} catch (IllegalAccessException e) { | |
errorMsg = Policy.bind("noInstanceCreate", new String[] { pluginClassName }); | |
throwException(errorMsg, e); | |
} catch (InvocationTargetException e) { | |
// user code caused exception | |
errorMsg = Policy.bind("constructorError", new String[] { pluginClassName }); | |
throwException(errorMsg, e); | |
} catch (Exception e) { | |
// user code caused exception | |
errorMsg = Policy.bind("constructorError", new String[] { pluginClassName }); | |
throwException(errorMsg, e); | |
} | |
// run startup() | |
final String message = Policy.bind("startupProblems", new String[] { | |
}); | |
final MultiStatus multiStatus = new MultiStatus(Platform.PI_RUNTIME, Platform.PLUGIN_ERROR, message, null); | |
ISafeRunnable code = new ISafeRunnable() { | |
public void run() throws Exception { | |
pluginObject.startup(); | |
} | |
public void handleException(Throwable e) { | |
multiStatus.add(new Status(Status.WARNING, Platform.PI_RUNTIME, Platform.PLUGIN_ERROR, message, e)); | |
try { | |
pluginObject.shutdown(); | |
} catch (Exception ex) { | |
// Ignore exceptions during shutdown. Since startup failed we are probably | |
// in a weird state anyway. | |
} | |
} | |
}; | |
InternalPlatform.run(code); | |
if (!multiStatus.isOK()) | |
throw new CoreException(multiStatus); | |
} | |
/** | |
* @see IPluginDescriptor | |
*/ | |
public synchronized boolean isPluginActivated() { | |
return active; | |
} | |
public synchronized boolean isPluginDeactivated() { | |
return deactivated; | |
} | |
private Properties loadJarDefinitions() { | |
// XXX this should be changed to just be !(inVAJ || inVAME). Eclipse | |
// can now copy the resources etc into the right spot so we don't have to | |
// add the source folders any more. | |
if (!InternalPlatform.inDevelopmentMode()) | |
return null; | |
Properties result = null; | |
InputStream is; | |
try { | |
result = new Properties(); | |
URL props = new URL(getInstallURLInternal(), PLUGIN_JARS); | |
is = props.openStream(); | |
try { | |
result.load(is); | |
return result; | |
} finally { | |
is.close(); | |
} | |
} catch (IOException e) { | |
result = null; | |
} | |
return result; | |
} | |
private void logError(IStatus status) { | |
InternalPlatform.getRuntimePlugin().getLog().log(status); | |
if (InternalPlatform.DEBUG) | |
System.out.println(status.getMessage()); | |
} | |
/** | |
* Returns <code>true</code> if we should continue with the plugin activation. | |
*/ | |
private boolean pluginActivationEnter() throws CoreException { | |
if (deactivated) { | |
// had permanent error on startup | |
String errorMsg = Policy.bind("pluginDisabled", new String[] { getUniqueIdentifier()}); | |
throwException(errorMsg, null); | |
} | |
if (active || activePending) { | |
// already up and running | |
return false; | |
} | |
activePending = true; | |
// go ahead and try to activate | |
return true; | |
} | |
private void pluginActivationExit(boolean errorExit) { | |
// we are done with with activation | |
activePending = false; | |
if (errorExit) { | |
active = false; | |
deactivated = true; | |
} else | |
active = true; | |
} | |
private String resolveLibraryPath(String spec) { | |
if (spec.charAt(0) != '$') | |
return spec; | |
IPath path = new Path(spec); | |
String first = path.segment(0); | |
if (first.equalsIgnoreCase("$ws$")) | |
return new Path("ws/" + BootLoader.getWS()).append(path.removeFirstSegments(1)).toString(); | |
if (first.equalsIgnoreCase("$os$")) | |
return new Path("os/" + BootLoader.getOS()).append(path.removeFirstSegments(1)).toString(); | |
if (first.equalsIgnoreCase("$nl$")) | |
return new Path("nl/" + BootLoader.getNL()).append(path.removeFirstSegments(1)).toString(); | |
return spec; | |
} | |
public void setPluginClassLoader(DelegatingURLClassLoader value) { | |
loader = value; | |
} | |
public void setPluginClassLoader(PluginClassLoader value) { | |
loader = value; | |
} | |
private void throwException(String message, Throwable exception) throws CoreException { | |
IStatus status = new Status(IStatus.ERROR, Platform.PI_RUNTIME, Platform.PLUGIN_ERROR, message, exception); | |
logError(status); | |
throw new CoreException(status); | |
} | |
/** | |
* @see #getUniqueIdentifierFromString | |
* @see #getVersionIdentifierFromString | |
*/ | |
public String toString() { | |
return getUniqueIdentifier()+VERSION_SEPARATOR+getVersionIdentifier().toString(); | |
} | |
} |