/******************************************************************************* * Copyright (c) 2014-2016 Red Hat Inc., 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: * Mickael Istria (Red Hat Inc.) - initial API and implementation ******************************************************************************/ package org.eclipse.ui.internal.wizards.datatransfer; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.expressions.ElementHandler; import org.eclipse.core.expressions.EvaluationContext; import org.eclipse.core.expressions.EvaluationResult; import org.eclipse.core.expressions.Expression; import org.eclipse.core.expressions.ExpressionConverter; import org.eclipse.core.expressions.IEvaluationContext; import org.eclipse.core.resources.IContainer; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Platform; import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; import org.eclipse.ui.internal.wizards.datatransfer.expressions.FileExpressionHandler; import org.eclipse.ui.wizards.datatransfer.ProjectConfigurator; import org.osgi.framework.Bundle; /** * Manages and requests the active {@link ProjectConfigurator} extensions for an * {@link SmartImportJob} execution. * * @since 3.12 * */ public class ProjectConfiguratorExtensionManager { private static final String EXTENSION_POINT_ID = IDEWorkbenchPlugin.IDE_WORKBENCH + ".projectConfigurators"; //$NON-NLS-1$ private IConfigurationElement[] extensions; private ExpressionConverter expressionConverter; private Map<IConfigurationElement, ProjectConfigurator> configuratorsByExtension = new HashMap<>(); /** * Each instance of this class will have it's own internal registry, that will load (maximum) once each extension class, * depending on whether the extension has been active for one case handled by this Manager. */ public ProjectConfiguratorExtensionManager() { this.extensions = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_POINT_ID); // Force Eclipse configurator to be 1st int eclipseConfiguratorIndex = 0; while (eclipseConfiguratorIndex < this.extensions.length && !this.extensions[eclipseConfiguratorIndex] .getAttribute("class").equals(EclipseProjectConfigurator.class.getName())) { //$NON-NLS-1$ eclipseConfiguratorIndex++; } if (eclipseConfiguratorIndex != 0 && eclipseConfiguratorIndex < this.extensions.length) { // swap IConfigurationElement tmp = this.extensions[eclipseConfiguratorIndex]; this.extensions[eclipseConfiguratorIndex] = this.extensions[0]; this.extensions[0] = tmp; } this.expressionConverter = new ExpressionConverter(new ElementHandler[] { ElementHandler.getDefault(), new FileExpressionHandler() }); } /** * * @param container * @return The active connectors for given container, order is important: top-priority are 1st */ private List<ProjectConfigurator> getAllActiveProjectConfiguratorsUntyped(Object container) { List<ProjectConfigurator> res = new ArrayList<>(); for (IConfigurationElement extension : this.extensions) { boolean addIt = false; String bundleOrFragmentId = extension.getContributor().getName(); Bundle contributingBundle = Platform.getBundle(bundleOrFragmentId); if (contributingBundle.getState() == Bundle.ACTIVE) { addIt = true; } else { // Else, only load class and activate bundle if necessary (checked by activeWhen) IConfigurationElement[] activeWhenElements = extension.getChildren("activeWhen"); //$NON-NLS-1$ if (activeWhenElements.length == 0) { // by default, if no activeWhen, enable extension addIt = true; } else if (activeWhenElements.length == 1) { IConfigurationElement activeWhen = activeWhenElements[0]; IConfigurationElement[] activeWhenChildren = activeWhen.getChildren(); if (activeWhenChildren.length == 1) { try { Expression expression = this.expressionConverter.perform(activeWhen.getChildren()[0]); IEvaluationContext context = new EvaluationContext(null, container); addIt = expression.evaluate(context).equals(EvaluationResult.TRUE); } catch (CoreException ex) { IDEWorkbenchPlugin.log( "Could not evaluate expression for " + extension.getContributor().getName(), ex); //$NON-NLS-1$ } } else { IDEWorkbenchPlugin .log("Could not evaluate xpression for " + extension.getContributor().getName() //$NON-NLS-1$ + ": there must be exactly one child of 'activeWhen'"); //$NON-NLS-1$ } } else { IDEWorkbenchPlugin.log("Only one 'activeWhen' is authorized on extension point " //$NON-NLS-1$ + EXTENSION_POINT_ID + ", for extension contributed by " + //$NON-NLS-1$ extension.getContributor().getName()); } } if (addIt) { ProjectConfigurator configurator = getConfigurator(extension); if (configurator instanceof EclipseProjectConfigurator) { // give priority res.add(0, configurator); } else { res.add(configurator); } } } return res; } /** * * @param container * @return The active connectors for given container, order is important: top-priority are 1st */ public List<ProjectConfigurator> getAllActiveProjectConfigurators(IContainer container) { return this.getAllActiveProjectConfiguratorsUntyped(container); } /** * * @param folder * @return The active connectors for given folder, order is important: top-priority are 1st */ public List<ProjectConfigurator> getAllActiveProjectConfigurators(File folder) { Assert.isTrue(folder.isDirectory(), folder.getAbsolutePath()); return this.getAllActiveProjectConfiguratorsUntyped(folder); } private ProjectConfigurator getConfigurator(IConfigurationElement extension) { if (!this.configuratorsByExtension.containsKey(extension)) { try { ProjectConfigurator configurator = (ProjectConfigurator) extension.createExecutableExtension("class"); //$NON-NLS-1$ this.configuratorsByExtension.put(extension, configurator); return configurator; } catch (CoreException ex) { IDEWorkbenchPlugin.log(ex.getMessage(), ex); return null; } } return this.configuratorsByExtension.get(extension); } /** * * @return the label of all known {@link ProjectConfigurator}s */ public static List<String> getAllExtensionLabels() { IConfigurationElement[] extensions = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_POINT_ID); List<String> res = new ArrayList<>(extensions.length); for (IConfigurationElement extension : extensions) { res.add(extension.getAttribute("label")); //$NON-NLS-1$ } return res; } /** * * @param configurator * @return the internationalized label for the provided configurator */ public static String getLabel(ProjectConfigurator configurator) { IConfigurationElement[] extensions = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_POINT_ID); for (IConfigurationElement extension : extensions) { if (configurator.getClass().getName().equals(extension.getAttribute("class"))) { //$NON-NLS-1$ return extension.getAttribute("label"); //$NON-NLS-1$ } } return "Missing label for " + configurator.getClass().getName(); //$NON-NLS-1$ } }