/******************************************************************************* * Copyright (c) 2004, 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.ui.internal.intro.impl.model.loader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.eclipse.ui.internal.intro.impl.model.AbstractIntroIdElement; import org.eclipse.ui.internal.intro.impl.model.IntroModelRoot; import org.eclipse.ui.internal.intro.impl.util.Log; import org.eclipse.ui.internal.intro.impl.util.Util; /** * Base class for handling Intro Extensions. */ public class BaseExtensionPointManager { // the config extension id protected static final String CONFIG = "org.eclipse.ui.intro.config"; //$NON-NLS-1$ // the configExtension extension id protected static final String CONFIG_EXTENSION = "org.eclipse.ui.intro.configExtension"; //$NON-NLS-1$ // the attribute in the config element to specify the intro part id. protected static final String ATT_CONFIG_INTRO_ID = "introId"; //$NON-NLS-1$ // the attribute in the config element to specify the intro part id. protected static final String ATT_CONFIG_EXTENSION_CONFIG_ID = "configId"; //$NON-NLS-1$ // the id attribute in any intro element. protected static final String ATT_ID = AbstractIntroIdElement.ATT_ID; protected Map<String, IntroModelRoot> introModels = new HashMap<>(); protected IExtensionRegistry registry; protected SharedConfigExtensionsManager sharedConfigExtensionsManager; private String extensionFilter; /* * Prevent creation. */ protected BaseExtensionPointManager() { registry = Platform.getExtensionRegistry(); } protected IntroModelRoot loadModel(String attributeName, String attributeValue) { long start = 0; if (Log.logPerformance) start = System.currentTimeMillis(); // get all Config extension point contributions. There could be more // than one config contribution, but there should only be one that maps // to the cached intro part id. IConfigurationElement introConfig = getIntroConfig(attributeName, attributeValue); // load model with the config elements of the correct contribution. If // there are no valid contribution, model stays null. if (introConfig != null) { // we found matching config. Get all configExtension contributed to // this config and pass to model. Load generic config extensions as // well. String configId = introConfig.getAttribute(ATT_ID); IConfigurationElement[] introConfigExtensions = null; if (configId == null) // if id of config is null, pass empty array. introConfigExtensions = new IConfigurationElement[0]; else introConfigExtensions = getIntroConfigExtensions( ATT_CONFIG_EXTENSION_CONFIG_ID, configId); if (Log.logPerformance) Util.logPerformanceTime( "BEGIN: quering registry for configs took: ", start); //$NON-NLS-1$ IntroModelRoot model = new IntroModelRoot(introConfig, introConfigExtensions); model.loadModel(); // add the current model to the hash table of models, only if it is // not null. They key is the model id, which is the id of the // config that defined this model. addCachedModel(model.getId(), model); // now load all generic config extension. ie: standbyPart and // command contributions. loadSharedConfigExtensions(); if (Log.logPerformance) Util .logPerformanceTime( "loading Intro Model (quering registry/creating & resolving model) took: ", //$NON-NLS-1$ start); return model; } return null; } /** * Go through all the config elements and only return the correct config * that maps to the correct intro part id. If there is more than one config * thats maps to the same intro part id, log the fact, and return the first * one. If there are non, return null. * * @param configElements * @return */ protected IConfigurationElement getIntroConfig(String attrributeName, String attributeValue) { IConfigurationElement[] configElements = registry .getConfigurationElementsFor(CONFIG); IConfigurationElement config = getConfigurationFromAttribute( configElements, attrributeName, attributeValue); if (config == null) // if there is no valid config, log the fact. Log.warning("No Intro configuration found with " + attrributeName //$NON-NLS-1$ + " of value = " + attributeValue); //$NON-NLS-1$ return config; } /** * Go through all the configExtension elements and return an array of all * extensions that match the attribute and its value. If there are non, * return empty array. This also loads all standby contributions. */ protected IConfigurationElement[] getIntroConfigExtensions( String attrributeName, String attributeValue) { IConfigurationElement[] configExtensionElements = registry .getConfigurationElementsFor(CONFIG_EXTENSION); /* * Extension filter is used for performance testing to only load contributions * from a specific plug-in (fixed data set). */ if (extensionFilter != null) { List<IConfigurationElement> filtered = new ArrayList<>(); for (int i=0;i<configExtensionElements.length;++i) { if (extensionFilter.equals(configExtensionElements[i].getContributor().getName())) { filtered.add(configExtensionElements[i]); } } configExtensionElements = (IConfigurationElement[])filtered.toArray(new IConfigurationElement[filtered.size()]); } IConfigurationElement[] configExtensions = getConfigurationsFromAttribute( configExtensionElements, attrributeName, attributeValue); return configExtensions; } /** * Add a model to the cache. This method is private because only this * manager class knows how to load an intro model. * * @param modelId * @param model */ protected void addCachedModel(String modelId, IntroModelRoot model) { introModels.put(modelId, model); } /** * Gets the given model from the cache. * * @param modelId */ protected IntroModelRoot getCachedModel(String configId) { return (IntroModelRoot) introModels.get(configId); } /** * Go through all the config elements and only return the correct config * with an attribute of the given value. If there is more than one * configuration element that maps to the attribute value log the fact, and * return the first one. If there are non, return null. * * @param configElements * @return */ protected IConfigurationElement getConfigurationFromAttribute( IConfigurationElement[] configElements, String attributeName, String attributeValue) { // find all configs with given attribute and attibute value. IConfigurationElement[] filteredConfigElements = getConfigurationsFromAttribute( configElements, attributeName, attributeValue); // now validate that we got only one. IConfigurationElement config = ModelLoaderUtil .validateSingleContribution(filteredConfigElements, attributeName); return config; } /** * Go through all the config elements and return an array of matching * configs with an attribute of the given value. If there are non, return * empty array. */ protected IConfigurationElement[] getConfigurationsFromAttribute( IConfigurationElement[] configElements, String attributeName, String attributeValue) { // find all configs with given attribute and attibute value. Vector<IConfigurationElement> elements = new Vector<>(); for (int i = 0; i < configElements.length; i++) { String currentAttributeValue = configElements[i] .getAttribute(attributeName); if (currentAttributeValue != null && currentAttributeValue.equals(attributeValue)) elements.add(configElements[i]); } // now return array. IConfigurationElement[] filteredConfigElements = new IConfigurationElement[elements .size()]; elements.copyInto(filteredConfigElements); return filteredConfigElements; } /** * Loads all shared config extennsions (ie: standby parts and commands). */ protected void loadSharedConfigExtensions() { sharedConfigExtensionsManager = new SharedConfigExtensionsManager( registry); sharedConfigExtensionsManager.loadSharedConfigExtensions(); } /** * @return Returns the sharedConfigExtensionsManager. */ public SharedConfigExtensionsManager getSharedConfigExtensionsManager() { return sharedConfigExtensionsManager; } /** * @return Returns the cached introModels. */ public Map<String, IntroModelRoot> getIntroModels() { return introModels; } /* * Internal test hook for restricting which extensions to load. */ public void setExtensionFilter(String pluginId) { extensionFilter = pluginId; } }