1 /******************************************************************************* 2 * Copyright (c) 2013, 2018 Remain BV, Industrial-TSI BV and others. 3 * 4 * 5 * This program and the accompanying materials 6 * are made available under the terms of the Eclipse Public License 2.0 7 * which accompanies this distribution, and is available at 8 * https://www.eclipse.org/legal/epl-2.0/ 9 * 10 * SPDX-License-Identifier: EPL-2.0 11 * 12 * Contributors: 13 * Wim Jongmam <wim.jongman@remainsoftware.com> - initial API and implementation 14 * Steven Spungin <steven@spungin.tv> - Ongoing Maintenance 15 ******************************************************************************/ 16 package org.eclipse.e4.tools.emf.ui.internal.imp; 17 18 import java.util.ArrayList; 19 import java.util.Arrays; 20 import java.util.Collection; 21 import java.util.List; 22 23 import org.eclipse.core.runtime.Assert; 24 import org.eclipse.core.runtime.IConfigurationElement; 25 import org.eclipse.core.runtime.IExtension; 26 import org.eclipse.core.runtime.IExtensionRegistry; 27 import org.eclipse.e4.tools.emf.ui.common.IExtensionLookup; 28 import org.eclipse.e4.ui.model.application.MApplication; 29 import org.eclipse.e4.ui.model.application.MApplicationElement; 30 import org.eclipse.e4.ui.model.application.commands.MCategory; 31 import org.eclipse.e4.ui.model.application.commands.MCommand; 32 import org.eclipse.e4.ui.model.application.commands.MCommandsFactory; 33 import org.eclipse.e4.ui.model.application.commands.MHandler; 34 import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor; 35 import org.eclipse.e4.ui.model.application.ui.advanced.MAdvancedFactory; 36 import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective; 37 import org.eclipse.e4.ui.model.application.ui.basic.MPart; 38 import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl; 39 import org.eclipse.e4.ui.model.application.ui.menu.MMenu; 40 import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory; 41 import org.eclipse.e4.ui.model.application.ui.menu.MToolBar; 42 import org.eclipse.e4.ui.workbench.UIEvents.ApplicationElement; 43 import org.eclipse.emf.ecore.util.EcoreUtil; 44 import org.osgi.framework.BundleContext; 45 import org.osgi.framework.FrameworkUtil; 46 import org.osgi.framework.InvalidSyntaxException; 47 import org.osgi.framework.ServiceReference; 48 49 @SuppressWarnings("deprecation") 50 public class RegistryUtil { 51 52 private static final String PLATFORM = "platform:"; //$NON-NLS-1$ 53 private static final String EMPTY_STRING = ""; //$NON-NLS-1$ 54 private static final String COMMAND_ID = "commandId"; //$NON-NLS-1$ 55 private static final String CATEGORY_ID = "categoryId"; //$NON-NLS-1$ 56 private static final String COMPATIBILITY_VIEW = "bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.e4.compatibility.CompatibilityView"; //$NON-NLS-1$ 57 private static final String VIEW_MENU = "ViewMenu"; //$NON-NLS-1$ 58 private static final String LAUNCHER = "launcher"; //$NON-NLS-1$ 59 private static final String EDITOR = "editor"; //$NON-NLS-1$ 60 private static final String VIEW = "View"; //$NON-NLS-1$ 61 private static final String CATEGORY_TAG = "categoryTag:"; //$NON-NLS-1$ 62 private static final String CATEGORY = "category"; //$NON-NLS-1$ 63 private static final String CLASS = "class"; //$NON-NLS-1$ 64 private static final String DESCRIPTION = "description"; //$NON-NLS-1$ 65 private static final String ICON = "icon"; //$NON-NLS-1$ 66 private static final String NAME = "name"; //$NON-NLS-1$ 67 private static final String ID = "id"; //$NON-NLS-1$ 68 public final static String HINT_VIEW = "view"; //$NON-NLS-1$ 69 public final static String HINT_EDITOR = EDITOR; 70 public final static String HINT_COMPAT_VIEW = "compatibilityView"; //$NON-NLS-1$ 71 72 /** 73 * 74 * @param t 75 * @param application 76 * @param elements 77 */ getModelElements(Class<? extends MApplicationElement> t, String hint, MApplication application, IConfigurationElement... elements)78 public static MApplicationElement[] getModelElements(Class<? extends MApplicationElement> t, String hint, 79 MApplication application, IConfigurationElement... elements) { 80 81 Assert.isNotNull(t); 82 Assert.isNotNull(elements); 83 Assert.isTrue(elements.length > 0); 84 85 if (t.equals(MCommand.class)) { 86 return getCommands(elements, application); 87 } else if (t.equals(MCategory.class)) { 88 return getCategories(elements); 89 } else if (t.equals(MPerspective.class)) { 90 return getPerspectives(elements); 91 } else if (t.equals(MPart.class) && HINT_COMPAT_VIEW.equals(hint)) { 92 return getViewsAsCompatibilityViews(elements); 93 } else if (t.equals(MPart.class)) { 94 return getViews(elements); 95 } else if (t.equals(MHandler.class)) { 96 return getHandlers(elements, application); 97 } else if (t.equals(MPartDescriptor.class) && HINT_EDITOR.equals(hint)) { 98 return getEditorPartDescriptors(elements); 99 } else if (t.equals(MPartDescriptor.class) && HINT_VIEW.equals(hint)) { 100 return getViewPartDescriptors(elements); 101 } else if (t.equals(MPartDescriptor.class) && HINT_COMPAT_VIEW.equals(hint)) { 102 return getPartDescriptorsAsCompatibilyViews(elements); 103 } 104 return new MApplicationElement[0]; 105 } 106 getCommands(IConfigurationElement[] elements, MApplication application)107 private static MCommand[] getCommands(IConfigurationElement[] elements, MApplication application) { 108 109 final ArrayList<MCommand> result = new ArrayList<>(); 110 111 final MCommandsFactory commandsFactory = MCommandsFactory.INSTANCE; 112 113 for (final IConfigurationElement element : elements) { 114 115 final MCommand command = commandsFactory.createCommand(); 116 command.setCommandName(element.getAttribute(NAME)); 117 command.setDescription(element.getAttribute(DESCRIPTION)); 118 command.setElementId(element.getAttribute(ID)); 119 final String catId = element.getAttribute(CATEGORY_ID); 120 121 if (catId != null && catId.trim().length() > 0) { 122 final List<MCategory> categories = application.getCategories(); 123 for (final MCategory category : categories) { 124 if (category.getElementId().equals(catId)) { 125 command.setCategory(category); 126 break; 127 } 128 } 129 } 130 131 result.add(command); 132 } 133 134 return result.toArray(new MCommand[0]); 135 } 136 getPerspectives(IConfigurationElement[] elements)137 private static MPerspective[] getPerspectives(IConfigurationElement[] elements) { 138 139 final ArrayList<MPerspective> result = new ArrayList<>(); 140 141 final MAdvancedFactory factory = MAdvancedFactory.INSTANCE; 142 143 for (final IConfigurationElement element : elements) { 144 final MPerspective perspective = factory.createPerspective(); 145 perspective.setLabel(element.getAttribute(NAME)); 146 perspective.setIconURI(getIconURI(element, ICON)); 147 perspective.setElementId(element.getAttribute(ID)); 148 perspective.setToBeRendered(true); 149 perspective.setVisible(true); 150 result.add(perspective); 151 } 152 153 return result.toArray(new MPerspective[0]); 154 } 155 getCategories(IConfigurationElement[] elements)156 private static MCategory[] getCategories(IConfigurationElement[] elements) { 157 158 final ArrayList<MCategory> result = new ArrayList<>(); 159 160 final MCommandsFactory commandsFactory = MCommandsFactory.INSTANCE; 161 162 for (final IConfigurationElement element : elements) { 163 164 final MCategory category = commandsFactory.createCategory(); 165 category.setDescription(element.getAttribute(DESCRIPTION)); 166 category.setElementId(element.getAttribute(ID)); 167 category.setName(element.getAttribute(NAME)); 168 169 result.add(category); 170 } 171 172 return result.toArray(new MCategory[0]); 173 } 174 getViews(IConfigurationElement[] elements)175 private static MPart[] getViews(IConfigurationElement[] elements) { 176 177 final ArrayList<MPart> result = new ArrayList<>(); 178 for (final IConfigurationElement element : elements) { 179 final MPart part = (MPart) EcoreUtil.create(BasicPackageImpl.Literals.PART); 180 part.setElementId(element.getAttribute(ID)); 181 part.setLabel(element.getAttribute(NAME)); 182 part.setIconURI(getIconURI(element, ICON)); 183 part.setContributionURI(getContributionURI(element, CLASS)); 184 part.setToBeRendered(true); 185 part.setVisible(true); 186 part.setToolbar(createToolBar(part)); 187 part.getMenus().add(createViewMenu(part)); 188 part.setCloseable(true); 189 part.getTags().add(VIEW); 190 if (element.getAttribute(CATEGORY) != null) { 191 part.getTags().add(CATEGORY_TAG + element.getAttribute(CATEGORY)); 192 } 193 194 result.add(part); 195 } 196 return result.toArray(new MPart[0]); 197 } 198 createToolBar(MPart part)199 private static MToolBar createToolBar(MPart part) { 200 final MToolBar toolBar = MMenuFactory.INSTANCE.createToolBar(); 201 toolBar.setElementId(part.getElementId()); 202 return toolBar; 203 } 204 createViewMenu(MPart part)205 private static MMenu createViewMenu(MPart part) { 206 final MMenu menu = MMenuFactory.INSTANCE.createMenu(); 207 menu.setElementId(part.getElementId()); 208 menu.getTags().add(VIEW_MENU); 209 return menu; 210 } 211 getViewsAsCompatibilityViews(IConfigurationElement[] elements)212 private static MPart[] getViewsAsCompatibilityViews(IConfigurationElement[] elements) { 213 final ArrayList<MPart> result = new ArrayList<>(); 214 final MPart[] parts = getViews(elements); 215 for (final MPart part : parts) { 216 part.setContributionURI(COMPATIBILITY_VIEW); 217 result.add(part); 218 } 219 return result.toArray(new MPart[0]); 220 } 221 getPartDescriptorsAsCompatibilyViews(IConfigurationElement[] elements)222 private static MPartDescriptor[] getPartDescriptorsAsCompatibilyViews(IConfigurationElement[] elements) { 223 final ArrayList<MPartDescriptor> result = new ArrayList<>(); 224 final MPartDescriptor[] parts = getViewPartDescriptors(elements); 225 for (final MPartDescriptor part : parts) { 226 part.setContributionURI(COMPATIBILITY_VIEW); 227 result.add(part); 228 } 229 return result.toArray(new MPartDescriptor[0]); 230 } 231 getEditorPartDescriptors(IConfigurationElement[] elements)232 private static MPartDescriptor[] getEditorPartDescriptors(IConfigurationElement[] elements) { 233 234 final ArrayList<MPartDescriptor> result = new ArrayList<>(); 235 for (final IConfigurationElement element : elements) { 236 final MPartDescriptor part = (MPartDescriptor) EcoreUtil 237 .create(org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.Literals.PART_DESCRIPTOR); 238 part.setElementId(element.getAttribute(ID)); 239 part.setLabel(element.getAttribute(NAME)); 240 part.setIconURI(getIconURI(element, ICON)); 241 if (element.getAttribute(CLASS) != null) { 242 part.setContributionURI(getContributionURI(element, CLASS)); 243 } else { 244 part.setContributionURI(getContributionURI(element, LAUNCHER)); 245 } 246 part.setDirtyable(true); 247 part.setAllowMultiple(true); 248 249 final MToolBar toolBar = MMenuFactory.INSTANCE.createToolBar(); 250 toolBar.setElementId(part.getElementId()); 251 part.setToolbar(toolBar); 252 253 final MMenu menu = MMenuFactory.INSTANCE.createMenu(); 254 menu.setElementId(part.getElementId()); 255 menu.getTags().add(VIEW_MENU); 256 part.getMenus().add(menu); 257 258 part.setCloseable(true); 259 result.add(part); 260 } 261 262 return result.toArray(new MPartDescriptor[0]); 263 } 264 getViewPartDescriptors(IConfigurationElement[] elements)265 private static MPartDescriptor[] getViewPartDescriptors(IConfigurationElement[] elements) { 266 267 final ArrayList<MPartDescriptor> result = new ArrayList<>(); 268 for (final IConfigurationElement element : elements) { 269 final MPartDescriptor part = (MPartDescriptor) EcoreUtil 270 .create(org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.Literals.PART_DESCRIPTOR); 271 part.setElementId(element.getAttribute(ID)); 272 part.setLabel(element.getAttribute(NAME)); 273 part.setIconURI(getIconURI(element, ICON)); 274 275 final MToolBar toolBar = MMenuFactory.INSTANCE.createToolBar(); 276 toolBar.setElementId(part.getElementId()); 277 part.setToolbar(toolBar); 278 279 final MMenu menu = MMenuFactory.INSTANCE.createMenu(); 280 menu.setElementId(part.getElementId()); 281 menu.getTags().add(VIEW_MENU); 282 part.getMenus().add(menu); 283 284 part.setCloseable(true); 285 result.add(part); 286 } 287 288 return result.toArray(new MPartDescriptor[0]); 289 } 290 getHandlers(IConfigurationElement[] elements, MApplication application)291 private static MHandler[] getHandlers(IConfigurationElement[] elements, MApplication application) { 292 293 final ArrayList<MHandler> result = new ArrayList<>(); 294 for (final IConfigurationElement element : elements) { 295 final MHandler hand = MCommandsFactory.INSTANCE.createHandler(); 296 hand.setElementId(element.getAttribute(ID)); 297 hand.setContributionURI(getContributionURI(element, CLASS)); 298 299 final String cmdId = element.getAttribute(COMMAND_ID); 300 301 if (cmdId != null && cmdId.trim().length() > 0) { 302 final List<MCommand> categories = application.getCommands(); 303 for (final MCommand command : categories) { 304 if (command.getElementId().equals(cmdId)) { 305 hand.setCommand(command); 306 break; 307 } 308 } 309 } 310 result.add(hand); 311 } 312 return result.toArray(new MHandler[0]); 313 } 314 getIconURI(IConfigurationElement element, String attribute)315 private static String getIconURI(IConfigurationElement element, String attribute) { 316 if (element.getAttribute(attribute) == null) { 317 return EMPTY_STRING; 318 } 319 // FIXME any other cases? 320 if (element.getAttribute(attribute).startsWith(PLATFORM)) { 321 return element.getAttribute(attribute); 322 } 323 return "platform:/plugin/" + element.getContributor().getName() + "/" + element.getAttribute(attribute); //$NON-NLS-1$ //$NON-NLS-2$ 324 } 325 getContributionURI(IConfigurationElement element, String attribute)326 private static String getContributionURI(IConfigurationElement element, String attribute) { 327 return "bundleclass://" + element.getContributor().getName() + "/" + element.getAttribute(attribute); //$NON-NLS-1$ //$NON-NLS-2$ 328 } 329 330 /** 331 * Returns a list of bundle id's that have extension to the passed extension 332 * point. 333 * 334 * @param registry 335 * @param extensionPoint 336 * @return the bundle ids as an array of Strings 337 */ getProvidingBundles(IExtensionRegistry registry, String extensionPoint, boolean isLive)338 public static String[] getProvidingBundles(IExtensionRegistry registry, String extensionPoint, boolean isLive) { 339 340 final IExtensionLookup service = getService(IExtensionLookup.class, null); 341 342 if (service == null) { 343 return new String[] { "No " + IExtensionLookup.class.getName() + " service found." }; //$NON-NLS-1$ //$NON-NLS-2$ 344 } 345 346 final ArrayList<String> result = new ArrayList<>(); 347 348 final IExtension[] extensions = service.findExtensions(extensionPoint, isLive); 349 for (final IExtension extension : extensions) { 350 final IConfigurationElement[] elements = extension.getConfigurationElements(); 351 for (final IConfigurationElement element : elements) { 352 if (!result.contains(element.getContributor().getName())) { 353 result.add(element.getContributor().getName()); 354 } 355 } 356 } 357 358 final String[] resultArray = result.toArray(new String[0]); 359 Arrays.sort(resultArray); 360 return resultArray; 361 } 362 363 /** 364 * 365 * @param registry 366 * @param struct 367 * @return the array of {@link IConfigurationElement} objects that meets the 368 * passed criteria. 369 */ getExtensions(IExtensionRegistry registry, RegistryStruct struct, boolean isLive)370 public static IConfigurationElement[] getExtensions(IExtensionRegistry registry, RegistryStruct struct, 371 boolean isLive) { 372 373 final IExtensionLookup service = getService(IExtensionLookup.class, null); 374 if (struct == null || service == null) { 375 return new IConfigurationElement[0]; 376 } 377 378 final ArrayList<IConfigurationElement> result = new ArrayList<>(); 379 380 final IExtension[] extensions = service.findExtensions(struct.getExtensionPoint(), isLive); 381 for (final IExtension extension : extensions) { 382 final IConfigurationElement[] elements = extension.getConfigurationElements(); 383 for (final IConfigurationElement element : elements) { 384 if (element.getContributor().getName().equals(struct.getBundle())) { 385 if (element.getName().equals(struct.getExtensionPointName())) { 386 result.add(element); 387 } 388 } 389 } 390 } 391 392 return result.toArray(new IConfigurationElement[0]); 393 } 394 395 /** 396 * This will return a structure that contains the registry information we 397 * are looking for. 398 * 399 * @param applicationElement 400 * @return the structure that matches the extension registry to the passed {@link ApplicationElement} 401 */ getStruct(Class<? extends MApplicationElement> applicationElement, String hint)402 public static RegistryStruct getStruct(Class<? extends MApplicationElement> applicationElement, String hint) { 403 404 if (applicationElement == MCommand.class) { 405 return new RegistryStruct(EMPTY_STRING, "org.eclipse.ui.commands", "command", NAME); //$NON-NLS-1$ //$NON-NLS-2$ 406 } else if (applicationElement == MCategory.class) { 407 return new RegistryStruct(EMPTY_STRING, "org.eclipse.ui.commands", CATEGORY, NAME); //$NON-NLS-1$ 408 } else if (applicationElement == MPerspective.class) { 409 return new RegistryStruct(EMPTY_STRING, "org.eclipse.ui.perspectives", "perspective", NAME); //$NON-NLS-1$ //$NON-NLS-2$ 410 } else if (applicationElement == MPart.class) { 411 return new RegistryStruct(EMPTY_STRING, "org.eclipse.ui.views", "view", NAME); //$NON-NLS-1$ //$NON-NLS-2$ 412 } else if (applicationElement == MHandler.class) { 413 return new RegistryStruct(EMPTY_STRING, "org.eclipse.ui.handlers", "handler", COMMAND_ID); //$NON-NLS-1$ //$NON-NLS-2$ 414 } else if (applicationElement == MPart.class) { 415 return new RegistryStruct(EMPTY_STRING, "org.eclipse.ui.views", "view", NAME); //$NON-NLS-1$ //$NON-NLS-2$ 416 } 417 418 else if (applicationElement == MPartDescriptor.class) { 419 if (hint == HINT_EDITOR) 420 { 421 return new RegistryStruct(EMPTY_STRING, "org.eclipse.ui.editors", EDITOR, NAME); //$NON-NLS-1$ 422 } 423 if (hint == HINT_VIEW || hint == HINT_COMPAT_VIEW) 424 { 425 return new RegistryStruct(EMPTY_STRING, "org.eclipse.ui.views", "view", NAME); //$NON-NLS-1$ //$NON-NLS-2$ 426 } 427 } 428 429 return null; 430 } 431 getService(Class<T> clazz, String filter)432 private static <T> T getService(Class<T> clazz, String filter) { 433 434 try { 435 final BundleContext context = FrameworkUtil.getBundle(RegistryUtil.class).getBundleContext(); 436 Collection<ServiceReference<T>> references; 437 references = context.getServiceReferences(clazz, filter); 438 for (final ServiceReference<T> reference : references) { 439 return context.getService(reference); 440 } 441 } catch (final InvalidSyntaxException e) { 442 // FIXME log 443 } 444 return null; 445 } 446 } 447