| /******************************************************************************* |
| * Copyright (c) 2005, 2017 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 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.core; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.Platform; |
| |
| /** |
| * Extension point must contain nature entry and priority entry. Other entries |
| * aren't required. |
| * |
| * @author Haiodo |
| */ |
| public class PriorityDLTKExtensionManager { |
| public static final String PRIORITY_ATTR = "priority"; //$NON-NLS-1$ |
| |
| /** |
| * guarded by this |
| */ |
| private Map<String, ElementInfo> extensions; |
| |
| private final String extensionPoint; |
| private final String identifier; |
| /** |
| * The preferred Id is not null, guarded by this. |
| */ |
| private Map<String, Integer> prefferedLevels; |
| /** |
| * guarded by itself |
| */ |
| private final Map<String, ElementInfo> prefferedExtensionCache = new HashMap<>(); |
| |
| public static class ElementInfo { |
| int level; |
| public final IConfigurationElement config; |
| public Object object; |
| public ElementInfo oldInfo; |
| |
| protected ElementInfo(IConfigurationElement config) { |
| this.config = config; |
| } |
| |
| public IConfigurationElement getConfig() { |
| return config; |
| } |
| } |
| |
| public PriorityDLTKExtensionManager(String extensionPoint, |
| String identifier) { |
| Assert.isNotNull(extensionPoint); |
| Assert.isNotNull(identifier); |
| this.extensionPoint = extensionPoint; |
| this.identifier = identifier; |
| } |
| |
| protected synchronized Map<String, ElementInfo> initialize() { |
| if (extensions != null) { |
| return extensions; |
| } |
| |
| extensions = new HashMap<>(5); |
| IConfigurationElement[] cfg = Platform.getExtensionRegistry() |
| .getConfigurationElementsFor(extensionPoint); |
| |
| for (int i = 0; i < cfg.length; i++) { |
| final IConfigurationElement element = cfg[i]; |
| if (!isValidConfigurationElement(element)) |
| continue; |
| String nature = element.getAttribute(identifier); |
| ElementInfo oldInfo = extensions.get(nature); |
| if (oldInfo != null) { |
| int lev = getLevel(element); |
| if (lev <= oldInfo.level) { |
| ElementInfo e = oldInfo; |
| ElementInfo nInfo = createNewInfo(element, null); |
| while (e != null) { |
| if (e.oldInfo == null) { |
| e.oldInfo = nInfo; |
| break; |
| } else { |
| if (nInfo.level < e.oldInfo.level) { |
| e = e.oldInfo; |
| } else { |
| nInfo.oldInfo = e.oldInfo; |
| e.oldInfo = nInfo; |
| break; |
| } |
| } |
| } |
| continue; |
| } |
| } |
| ElementInfo info = createNewInfo(element, oldInfo); |
| extensions.put(nature, info); |
| } |
| return extensions; |
| } |
| |
| /** |
| * @param element |
| * @return |
| */ |
| protected boolean isValidConfigurationElement( |
| IConfigurationElement element) { |
| return true; |
| } |
| |
| private ElementInfo createNewInfo(IConfigurationElement cfg, |
| ElementInfo oldInfo) { |
| ElementInfo info = createInfo(cfg); |
| info.level = getLevel(info.config); |
| info.oldInfo = oldInfo; |
| return info; |
| } |
| |
| protected ElementInfo internalGetElementInfo(String id) { |
| ElementInfo info; |
| synchronized (prefferedExtensionCache) { |
| info = prefferedExtensionCache.get(id); |
| } |
| if (info != null) { |
| return info; |
| } |
| info = initialize().get(id); |
| if (info != null) { |
| final Integer level; |
| synchronized (this) { |
| level = prefferedLevels != null ? prefferedLevels.get(id) |
| : null; |
| } |
| if (level != null) { |
| // Search for preferred id. |
| final int prefferedLevel = level.intValue(); |
| for (ElementInfo o = info;;) { |
| if (o.level == prefferedLevel) { |
| info = o; |
| break; |
| } |
| o = o.oldInfo; |
| if (o == null) { |
| break; |
| } |
| } |
| } |
| synchronized (prefferedExtensionCache) { |
| prefferedExtensionCache.put(id, info); |
| } |
| } |
| return info; |
| } |
| |
| protected ElementInfo getElementInfo(String id) { |
| return internalGetElementInfo(id); |
| } |
| |
| protected int getLevel(IConfigurationElement config) { |
| String priority = config.getAttribute(PRIORITY_ATTR); |
| if (priority == null) { |
| return 0; |
| } |
| try { |
| int parseInt = Integer.parseInt(priority); |
| return parseInt; |
| } catch (NumberFormatException ex) { |
| return 0; |
| } |
| } |
| |
| public ElementInfo[] getElementInfos() { |
| final Map<String, ElementInfo> exts = initialize(); |
| final String[] keys = exts.keySet().toArray(new String[exts.size()]); |
| final ElementInfo[] values = new ElementInfo[keys.length]; |
| for (int i = 0; i < keys.length; i++) { |
| values[i] = getElementInfo(keys[i]); |
| } |
| return values; |
| } |
| |
| /** |
| * Values config, nature, level are setted in current class. |
| * |
| * @param config |
| * @return |
| */ |
| protected ElementInfo createInfo(IConfigurationElement config) { |
| return new ElementInfo(config); |
| } |
| |
| public String findScriptNature(IProject project) { |
| try { |
| if (!project.isAccessible()) { |
| return null; |
| } |
| String[] natureIds = project.getDescription().getNatureIds(); |
| for (int i = 0; i < natureIds.length; i++) { |
| String natureId = natureIds[i]; |
| |
| if (getElementInfo(natureId) != null) { |
| return natureId; |
| } |
| } |
| } catch (CoreException e) { |
| return null; |
| } |
| |
| return null; |
| } |
| |
| public synchronized void setPreffetedLevel(String id, int level) { |
| synchronized (prefferedExtensionCache) { |
| prefferedExtensionCache.clear(); |
| } |
| if (level != -1) { |
| if (prefferedLevels == null) { |
| prefferedLevels = new HashMap<>(); |
| } |
| prefferedLevels.put(id, Integer.valueOf(level)); |
| } else { |
| if (prefferedLevels != null) { |
| prefferedLevels.remove(id); |
| } |
| } |
| } |
| } |