/******************************************************************************* * Copyright (c) 2014 OPCoach. * 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: * OPCoach - initial API and implementation *******************************************************************************/ package com.opcoach.e34tools.views; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.eclipse.pde.core.plugin.IPluginExtension; import org.eclipse.pde.core.plugin.IPluginModelBase; import org.eclipse.pde.core.plugin.IPluginObject; import org.eclipse.pde.internal.core.PDECore; import org.eclipse.pde.internal.core.PDEExtensionRegistry; import org.eclipse.pde.internal.core.bundle.WorkspaceBundleFragmentModel; import org.eclipse.pde.internal.core.bundle.WorkspaceBundlePluginModel; import org.eclipse.pde.internal.core.ischema.ISchema; import org.eclipse.pde.internal.core.ischema.ISchemaElement; import org.eclipse.pde.internal.core.plugin.PluginElement; import org.eclipse.pde.internal.core.plugin.WorkspacePluginModelBase; import org.eclipse.pde.internal.core.project.PDEProject; import org.eclipse.pde.internal.core.schema.Schema; import com.opcoach.e34tools.helpers.SchemaUtil; import com.opcoach.e34tools.model.CustomExtensionPoint; import com.opcoach.e34tools.model.CustomSchema; /** * This class computes all information displayed in E4 Migration Stat view, and * provides helper methods to get tooltip texts It could be listener to * workspace and plugin object to recompute data */ @SuppressWarnings("restriction") public class E4MigrationRegistry implements IResourceChangeListener { private Map<String, Integer> migrationData = null; private Set<CustomExtensionPoint> customExtensionPoint = null; private boolean reparseExtensions = true; private static E4MigrationRegistry INSTANCE; private static boolean computed = false; private E4MigrationRegistry() { migrationData = new HashMap<String, Integer>(); customExtensionPoint = new HashSet<CustomExtensionPoint>(); // Listen to workspace to reparse extensions in case of change try { IWorkspace ws = ResourcesPlugin.getWorkspace(); if (ws != null) ws.addResourceChangeListener(this); } catch (IllegalStateException ex) { // There is no workspace to listen.. we don't care (may be in test // running) } } public static E4MigrationRegistry getDefault() { if (INSTANCE == null) INSTANCE = new E4MigrationRegistry(); return INSTANCE; } public int getInstanceNumber(IExtensionPoint ep, IPluginModelBase plugin) { Integer result = migrationData.get(getKey(ep, plugin)); if (result == null) { computeDataForPlugin(plugin); result = migrationData.get(getKey(ep, plugin)); } return result; } public int getInstanceNumber(ISchemaElement se, IPluginModelBase plugin) { Integer result = migrationData.get(getKey(se, plugin)); if (result == null) { computeDataForPlugin(plugin); result = migrationData.get(getKey(se, plugin)); } return result; } public int getInstanceNumber(CustomExtensionPoint cep, IPluginModelBase plugin) { Integer result = migrationData.get(getKey(cep, plugin)); if (result == null) { computeDataForPlugin(plugin); result = migrationData.get(getKey(cep, plugin)); } return result; } public int getInstanceNumber(CustomSchema cs, IPluginModelBase plugin) { Integer result = migrationData.get(getKey(cs, plugin)); if (result == null) { computeDataForPlugin(plugin); result = migrationData.get(getKey(cs, plugin)); } if (result == null) return 0; return result; } private Collection<IExtensionPoint> extensionsToParse = new ArrayList<IExtensionPoint>(); public Collection<IExtensionPoint> getExtensionsToParse() { if (!reparseExtensions) return extensionsToParse; IExtensionRegistry wsExtRegistry = null; // Read the workspace extensions. Must introspect to get the workspace // extension registry (hidden) try { PDEExtensionRegistry reg = PDECore.getDefault().getExtensionsRegistry(); Field f = reg.getClass().getDeclaredField("fRegistry"); f.setAccessible(true); // @SuppressWarnings("unchecked") wsExtRegistry = (IExtensionRegistry) f.get(reg); } catch (Throwable e) { e.printStackTrace(); } if (wsExtRegistry != null) { IWorkspace ws = PDECore.getWorkspace(); for (IProject project : ws.getRoot().getProjects()) { WorkspacePluginModelBase fModel = null; // This code comes from NewProjectCreationOPeration... IFile fragmentXml = PDEProject.getFragmentXml(project); IFile pluginXml = PDEProject.getPluginXml(project); IFile manifest = PDEProject.getManifest(project); if (fragmentXml.exists()) { fModel = new WorkspaceBundleFragmentModel(manifest, fragmentXml); } else // if (pluginXml.exists()) { fModel = new WorkspaceBundlePluginModel(manifest, pluginXml); } if (fModel == null) break; for (IExtensionPoint ep : wsExtRegistry.getExtensionPoints(project.getName())) { String epId = ep.getNamespaceIdentifier(); extensionsToParse.add(ep); } } } // Read the extensions in the current eclipse configuration (if luna -> // read luna extensions) IExtensionRegistry extReg = Platform.getExtensionRegistry(); for (IExtensionPoint ep : extReg.getExtensionPoints()) { String epId = ep.getNamespaceIdentifier(); if (epId.equals("org.eclipse.ui")) { // Check if extension already exists boolean mustAdd = true; for (IExtensionPoint iep : extensionsToParse) if (iep.getUniqueIdentifier().equals(ep.getUniqueIdentifier())) { mustAdd = false; break; } if (mustAdd) { extensionsToParse.add(ep); System.out.println("Found this extensions to parse : " + ep.getUniqueIdentifier()); } } } reparseExtensions = false; return extensionsToParse; } public Collection<CustomExtensionPoint> getCustomExtensionToParse() { return new ArrayList<CustomExtensionPoint>(customExtensionPoint); } public ISchemaElement[] getElementToParse(IExtensionPoint ep) { ISchema schema = SchemaUtil.getSchema(ep.getUniqueIdentifier()); // PDECore.getDefault().getSchemaRegistry().getSchema(ep.getUniqueIdentifier()); if (schema == null) { System.out.println("---> UNABLE TO LOAD SCHEMA FOR " + ep.getUniqueIdentifier()); return new ISchemaElement[0]; } // Search for extension element ISchemaElement extensionElement = null; for (ISchemaElement e : schema.getElements()) { if ("extension".equals(e.getName())) { extensionElement = e; break; } } return schema.getCandidateChildren(extensionElement); } private String getKey(IExtensionPoint ep, IPluginModelBase plugin) { return plugin.getBundleDescription().getName() + "/" + getXPath(ep); } private String getKey(ISchemaElement e, IPluginModelBase plugin) { return plugin.getBundleDescription().getName() + "/" + getXPath(e); } private String getKey(CustomExtensionPoint cep, IPluginModelBase plugin) { return plugin.getBundleDescription().getName() + "/" + getXPath(cep); } private String getKey(CustomSchema cs, IPluginModelBase plugin) { return plugin.getBundleDescription().getName() + "/" + getXPath(cs); } private String getKey(IPluginModelBase plugin, String xpath) { return plugin.getBundleDescription().getName() + "/" + xpath; } public String getXPath(IExtensionPoint ep) { return ep.getUniqueIdentifier(); } public String getXPath(ISchemaElement e) { Schema o = (Schema) e.getParent(); return o.getQualifiedPointId() + "/" + e.getName(); } public String getXPath(CustomExtensionPoint cep) { return cep.getUniqueId(); } public String getXPath(CustomSchema cs) { return cs.getCustomExtentionPointId() + "/" + cs.getId(); } public static boolean isComputed() { return computed; } /** * * @param xpath * the xpath to element for an extension point. For instance : * "views/view" it must not be prefixed by org.eclipse.ui * @param plugins * the list of plugins to compute * @return */ public int countNumberOfExtensions(String xpath, Collection<IPluginModelBase> plugins) { int result = 0; for (IPluginModelBase p : plugins) { String key = getKey(p, xpath); Integer i = migrationData.get(key); if (i != null) result += i; } return result; } private void computeDataForPlugin(IPluginModelBase plugin) { // Compute information for each extension for this plugin for (IExtensionPoint ep : getExtensionsToParse()) { // First compute number of extension of this point in the // plugin. int nbExtensions = 0; String epID = ep.getUniqueIdentifier(); for (IPluginExtension e : plugin.getExtensions(true).getExtensions()) { if (e.getPoint().equals(epID)) nbExtensions++; } migrationData.put(getKey(ep, plugin), nbExtensions); // System.out.println("Put : " + getKey(ep, plugin) + // " -> value =" + nbExtensions); // Then compute number of element usage for this extension. for (ISchemaElement se : getElementToParse(ep)) { int nbElt = 0; for (IPluginExtension ext : plugin.getExtensions(true).getExtensions()) { if (ext.getPoint().equals(epID)) { // We are in the extension, must find nb of elements // inside. for (IPluginObject po : ext.getChildren()) { // System.out.println("Instance of po is " + // po.getClass().getName()) ; if (po instanceof PluginElement) { PluginElement pen = (PluginElement) po; if (pen.getName().equals(se.getName())) nbElt++; } } } } migrationData.put(getKey(se, plugin), nbElt); } } if (customExtensionPoint.size() != 0) { for (IPluginExtension ext : plugin.getExtensions(true).getExtensions()) { String epId = ext.getPoint(); for (CustomExtensionPoint cep : customExtensionPoint) { String id = cep.getUniqueId(); Integer r = migrationData.get(getKey(cep, plugin)); int nbElt = 0; if (r != null) { nbElt = r; } if (accept(id, epId)) { nbElt++; for (IPluginObject po : ext.getChildren()) { if (po instanceof PluginElement) { PluginElement pen = (PluginElement) po; CustomSchema cs = cep.getSchema(pen.getName()); Integer rcs = migrationData.get(getKey(cs, plugin)); int nbSchElt = 0; if (rcs != null) { nbSchElt = rcs; } nbSchElt++; migrationData.put(getKey(cs, plugin), nbSchElt); } } } migrationData.put(getKey(cep, plugin), nbElt); } } } } private boolean accept(String candidateId, String epId) { return epId.equals(candidateId); } public void addCustomExtensionPointIdentifier(String id) { CustomExtensionPoint cep = new CustomExtensionPoint(id); customExtensionPoint.add(cep); } @Override public void resourceChanged(IResourceChangeEvent event) { reparseExtensions = true; extensionsToParse.clear(); } }