blob: 0b47f340551b48be1cb890132999214aaae53484 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.update.internal.core;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.core.ContentReference;
import org.eclipse.update.core.IFeature;
import org.eclipse.update.core.IFeatureContentConsumer;
import org.eclipse.update.core.IInstallHandler;
import org.eclipse.update.core.IInstallHandlerEntry;
import org.eclipse.update.core.IInstallHandlerWithFilter;
import org.eclipse.update.core.INonPluginEntry;
import org.eclipse.update.core.IPluginEntry;
import org.eclipse.update.core.IVerificationListener;
import org.eclipse.update.core.InstallMonitor;
import org.eclipse.update.core.Utilities;
import org.osgi.framework.Bundle;
public class InstallHandlerProxy implements IInstallHandlerWithFilter {
private IFeature feature = null;
private int type;
private IInstallHandler handler = null;
private IStatus savedStatus = null;
private boolean DEBUG = false;
private static final String EXT_PLUGIN = "org.eclipse.update.core"; //$NON-NLS-1$
private static final String UI_PLUGIN = "org.eclipse.ui"; //$NON-NLS-1$
private static final String EXT_POINT = "installHandlers"; //$NON-NLS-1$
private Method nonPluginDataAcceptor = null;
/**
* A class loader that combines a the org.eclipse.update.core plugin class loader with the
* org.eclipse.ui class loader (only when UI is active).
*/
private static class InstallHandlerClassLoader extends URLClassLoader {
private Bundle updateCore;
private Bundle eclipseUI;
public InstallHandlerClassLoader(URL[] classpath) {
super(classpath);
updateCore = Platform.getBundle(EXT_PLUGIN);
eclipseUI = Platform.getBundle(UI_PLUGIN);
if (eclipseUI != null && eclipseUI.getState() != Bundle.ACTIVE)
eclipseUI = null;
}
public Class loadClass(String className) throws ClassNotFoundException {
// First check update core plugin loader, then the eclipse ui plugin loader
Class c = null;
try {
c = updateCore.loadClass(className);
} catch (ClassNotFoundException e) {
try {
if(eclipseUI != null)
c = eclipseUI.loadClass(className);
} catch (ClassNotFoundException e2) {
} finally {
}
} finally {
}
if (c != null)
return c;
else
return super.loadClass(className);
}
public URL getResource(String resName) {
// First check update core plugin loader, then the eclipse ui plugin loader
URL u = updateCore.getResource(resName);
if(u == null && eclipseUI != null)
u = eclipseUI.getResource(resName);
if (u != null)
return u;
else
return super.getResource(resName);
}
}
public InstallHandlerProxy(
int type,
IFeature feature,
IInstallHandlerEntry entry,
InstallMonitor monitor)
throws CoreException {
initialize(type, feature, entry, monitor);
}
/*
* @see IInstallHandler#initialize
*/
public void initialize(
int type,
IFeature feature,
IInstallHandlerEntry entry,
InstallMonitor monitor)
throws CoreException {
DEBUG = UpdateCore.DEBUG_SHOW_IHANDLER;
// validate arguments
if (feature == null)
throw new IllegalArgumentException();
this.feature = feature;
this.type = type;
// check if we have a handler entry specified in the feature.xml
if (entry == null) {
if (DEBUG)
debug("not specified"); //$NON-NLS-1$
return; // no handler entry
}
String library = entry.getLibrary();
String handlerName = entry.getHandlerName();
if (handlerName == null || handlerName.trim().equals("")) { //$NON-NLS-1$
if (DEBUG)
debug("not specified"); //$NON-NLS-1$
return; // no handler class spacified in entry
}
if (DEBUG) {
debug("handler=" + handlerName); //$NON-NLS-1$
debug("path= " + library); //$NON-NLS-1$
}
// get handler instance
try {
if (library == null || library.trim().equals("")) //$NON-NLS-1$
this.handler = getGlobalHandler(handlerName);
else
this.handler = getLocalHandler(library, handlerName);
if (this.handler == null)
return;
handler.initialize(type, feature, entry, monitor);
} catch (ClassNotFoundException e) {
handleExceptionInInit(
NLS.bind(Messages.InstallHandler_notFound, (new String[] { feature.getLabel() })),
e);
} catch (ClassCastException e) {
handleExceptionInInit(
NLS.bind(Messages.InstallHandler_invalidHandler, (new String[] { feature.getLabel() })),
e);
} catch (CoreException e) {
handleExceptionInInit(null, e);
} catch (Exception e) {
handleExceptionInInit(
NLS.bind(Messages.InstallHandler_unableToCreateHandler, (new String[] { feature.getLabel() })),
e);
}
}
/*
* @see IInstallHandler#installInitiated
*/
public void installInitiated() throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling installInitiated()"); //$NON-NLS-1$
handler.installInitiated();
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#allPluginsDownloaded
*/
public void pluginsDownloaded(IPluginEntry[] plugins) throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling pluginsDownloaded()"); //$NON-NLS-1$
handler.pluginsDownloaded(plugins);
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#allPluginsInstalled
*/
public void completeInstall(IFeatureContentConsumer consumer)
throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling completeInstall()"); //$NON-NLS-1$
handler.completeInstall(consumer);
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#allDataDownloaded
*/
public void nonPluginDataDownloaded(
INonPluginEntry[] nonPluginData,
IVerificationListener listener)
throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling nonPluginDataDownloaded()"); //$NON-NLS-1$
handler.nonPluginDataDownloaded(nonPluginData, listener);
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#installCompleted
*/
public void installCompleted(boolean success) throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling installCompleted()"); //$NON-NLS-1$
handler.installCompleted(success);
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#configureInitiated
*/
public void configureInitiated() throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling configureInitiated()"); //$NON-NLS-1$
handler.configureInitiated();
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#completeConfigure
*/
public void completeConfigure() throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling completeConfigure()"); //$NON-NLS-1$
handler.completeConfigure();
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#configureCompleted
*/
public void configureCompleted(boolean success) throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling configureCompleted()"); //$NON-NLS-1$
handler.configureCompleted(success);
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#unconfigureInitiated
*/
public void unconfigureInitiated() throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling unconfigureInitiated()"); //$NON-NLS-1$
handler.unconfigureInitiated();
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#completeUnconfigure
*/
public void completeUnconfigure() throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling completeUnconfigure()"); //$NON-NLS-1$
handler.completeUnconfigure();
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#unconfigureCompleted
*/
public void unconfigureCompleted(boolean success) throws CoreException {
if (handler == null) {
if (savedStatus == null)
return;
else
throw new CoreException(savedStatus); // delayed exception
} else {
try {
if (DEBUG)
debug("calling unconfigureCompleted()"); //$NON-NLS-1$
handler.unconfigureCompleted(success);
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
if (savedStatus != null)
throw new CoreException(savedStatus); // delayed exception
}
}
/*
* @see IInstallHandler#uninstallInitiated
*/
public void uninstallInitiated() throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling uninstallInitiated()"); //$NON-NLS-1$
handler.uninstallInitiated();
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#completeUninstall
*/
public void completeUninstall() throws CoreException {
if (handler == null)
return;
else {
try {
if (DEBUG)
debug("calling completeUninstall()"); //$NON-NLS-1$
handler.completeUninstall();
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
}
}
/*
* @see IInstallHandler#uninstallCompleted
*/
public void uninstallCompleted(boolean success) throws CoreException {
if (handler == null) {
if (savedStatus == null)
return;
else
throw new CoreException(savedStatus); // delayed exception
} else {
try {
if (DEBUG)
debug("calling uninstallCompleted()"); //$NON-NLS-1$
handler.uninstallCompleted(success);
} catch (Throwable e) {
handleExceptionInCall(e, feature);
}
if (savedStatus != null)
throw new CoreException(savedStatus); // delayed exception
}
}
/*
* common exception handling for initialization
*/
private void handleExceptionInInit(String s, Exception e)
throws CoreException {
CoreException ce;
if (e instanceof CoreException)
ce = (CoreException) e;
else
ce = Utilities.newCoreException(s, e);
if (isUndoAction()) {
// for "undo" operations, deactivate handler and log error
String id =
UpdateCore.getPlugin().getBundle().getSymbolicName();
IStatus status =
new Status(IStatus.ERROR, id, 0, "InstallHandler.deactivated", ce); //$NON-NLS-1$
UpdateCore.getPlugin().getLog().log(status);
handler = null; // disable subsequent handler calls
savedStatus = status;
} else
// for "do" operations, hurl ...
throw ce;
}
/*
* common exception handling for calls to install handler
*/
private void handleExceptionInCall(Throwable e, IFeature feature)
throws CoreException {
CoreException ce;
if (e instanceof CoreException)
ce = (CoreException) e;
else
ce =
Utilities.newCoreException(
NLS.bind(Messages.InstallHandler_callException, (new String[] { feature.getLabel() })),
e);
if (isUndoAction()) {
// for "undo" operations, deactivate handler and log error
String id =
UpdateCore.getPlugin().getBundle().getSymbolicName();
IStatus status =
new Status(IStatus.ERROR, id, 0, "InstallHandler.deactivated", ce); //$NON-NLS-1$
UpdateCore.getPlugin().getLog().log(status);
handler = null; // disable subsequent handler calls
savedStatus = status;
} else
// for "do" operations, hurl ...
throw ce;
}
/*
* Indicates whether we are doing (install, configure) or
* undoing (uninstall, unconfigure)
*/
private boolean isUndoAction() {
if (this.type == IInstallHandler.HANDLER_ACTION_INSTALL
|| this.type == IInstallHandler.HANDLER_ACTION_CONFIGURE)
return false; // causes exception to be thrown and action aborted
else
return true; // causes exception to be logged and action continues
}
/*
* get an instance of handler downloaded as part of the feature
*/
private IInstallHandler getLocalHandler(String libs, String name)
throws IOException, CoreException, ClassNotFoundException, InstantiationException, IllegalAccessException {
// Get baseline URL for handler (relative to feature.xml). For
// features being installed from a server (eg. http protocol)
// the URL will most likely be to a local file copy containing the
// unpacked feature jar.
ContentReference baseRef =
feature.getFeatureContentProvider().getFeatureManifestReference(null);
URL base = null;
if (baseRef != null)
base = baseRef.asURL();
if (base == null)
throw Utilities.newCoreException(
NLS.bind(Messages.InstallHandler_unableToCreateHandler, (new String[] { this.feature.getLabel() })),
null);
// determine loader class path
StringTokenizer libraries = new StringTokenizer(libs, ","); //$NON-NLS-1$
URL[] cp = new URL[libraries.countTokens()];
for( int token = 0; token < cp.length; token++) {
cp[token] = new URL(base, libraries.nextToken());
}
if (this.type == IInstallHandler.HANDLER_ACTION_UNINSTALL) {
// check if we are doing uninstall
// ... need to make temp copy of library (being removed)
URL[] jars = new URL[cp.length];
for( int jar = 0; jar < cp.length; jar++) {
File tempLib = File.createTempFile("tmp" + jar, ".jar"); //$NON-NLS-1$ //$NON-NLS-2$
tempLib.deleteOnExit();
FileOutputStream fos = null;
InputStream is = null;
try {
fos = new FileOutputStream(tempLib);
is = new FileInputStream(cp[jar].getPath());
Utilities.copy(is, fos, null);
} finally {
if (fos != null)
try {
fos.close();
} catch (Exception e) {
}
if (is != null)
try {
is.close();
} catch (Exception e) {
}
}
jars[jar] = tempLib.toURL();
}
cp = jars;
}
// create class loader, load and instantiate handler
ClassLoader loader = new InstallHandlerClassLoader(cp);
Class clazz = loader.loadClass(name);
IInstallHandler handler = (IInstallHandler) clazz.newInstance();
return handler;
}
/*
* get instance of global handler registered via extension point
*/
private IInstallHandler getGlobalHandler(String name) throws Exception {
IExtensionRegistry reg = Platform.getExtensionRegistry();
IConfigurationElement[] handlerExtension =
reg.getConfigurationElementsFor(EXT_PLUGIN, EXT_POINT, name);
if (handlerExtension == null || handlerExtension.length <= 0)
throw Utilities.newCoreException(
NLS.bind(Messages.InstallHandler_unableToCreateHandler, (new String[] { this.feature.getLabel() })),
null);
return (IInstallHandler) handlerExtension[0].createExecutableExtension("class"); //$NON-NLS-1$
}
private void debug(String s) {
String pfx = (feature==null) ? "" : feature.getVersionedIdentifier().toString(); //$NON-NLS-1$
System.out.println("InstallHandler["+pfx+"]: " + s); //$NON-NLS-1$ //$NON-NLS-2$
}
public boolean acceptNonPluginData(INonPluginEntry data) {
Boolean result = new Boolean(true);
if (handler != null){
if (DEBUG)
debug("calling acceptNonPluginData()"); //$NON-NLS-1$
if(handler instanceof IInstallHandlerWithFilter)
return ((IInstallHandlerWithFilter)handler).acceptNonPluginData(data);
else{ //support upgrade from legacy versions
if(getNonPluginDataAcceptor() != null){
try{
Object[] param = {data};
result = (Boolean)getNonPluginDataAcceptor().invoke(handler,param);
}catch(Exception e){
//todo
}
}
}
}
return result.booleanValue();
}
private Method getNonPluginDataAcceptor(){
if(nonPluginDataAcceptor == null){
try{
Class[] types = {INonPluginEntry.class};
nonPluginDataAcceptor = handler.getClass().getMethod("acceptNonPluginData",types); //$NON-NLS-1$
}catch(NoSuchMethodException nsme){
}
}
return nonPluginDataAcceptor;
}
}