| /******************************************************************************* |
| * 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; |
| } |
| } |