1 /******************************************************************************* 2 * Copyright (c) 2007, 2015 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 15 package org.eclipse.pde.internal.ui.wizards.product; 16 17 import org.eclipse.core.runtime.CoreException; 18 import org.eclipse.core.runtime.IProgressMonitor; 19 import org.eclipse.jface.action.Action; 20 import org.eclipse.osgi.util.NLS; 21 import org.eclipse.pde.core.plugin.*; 22 import org.eclipse.pde.internal.core.util.PDETextHelper; 23 import org.eclipse.pde.internal.ui.PDEUIMessages; 24 25 public class UpdateSplashHandlerAction extends Action implements ISplashHandlerConstants { 26 27 private IPluginModelBase fModel; 28 29 private IProgressMonitor fMonitor; 30 31 private CoreException fException; 32 33 private String fFieldID; 34 35 private String fFieldSplashID; 36 37 private String fFieldProductID; 38 39 private String fFieldClass; 40 41 private String fFieldTemplate; 42 43 private String fFieldPluginID; 44 UpdateSplashHandlerAction()45 public UpdateSplashHandlerAction() { 46 reset(); 47 } 48 49 /** 50 * @param fieldID the fFieldID to set 51 */ setFieldID(String fieldID)52 public void setFieldID(String fieldID) { 53 fFieldID = fieldID; 54 } 55 56 /** 57 * @param fieldSplashID the fFieldSplashID to set 58 */ setFieldSplashID(String fieldSplashID)59 public void setFieldSplashID(String fieldSplashID) { 60 fFieldSplashID = fieldSplashID; 61 } 62 63 /** 64 * @param fieldProductID the fFieldProductID to set 65 */ setFieldProductID(String fieldProductID)66 public void setFieldProductID(String fieldProductID) { 67 fFieldProductID = fieldProductID; 68 } 69 70 /** 71 * @param fieldClass the fFieldClass to set 72 */ setFieldClass(String fieldClass)73 public void setFieldClass(String fieldClass) { 74 fFieldClass = fieldClass; 75 } 76 77 /** 78 * @param fieldTemplate the fFieldTemplate to set 79 */ setFieldTemplate(String fieldTemplate)80 public void setFieldTemplate(String fieldTemplate) { 81 fFieldTemplate = fieldTemplate; 82 } 83 84 /** 85 * @param fieldPluginID 86 */ setFieldPluginID(String fieldPluginID)87 public void setFieldPluginID(String fieldPluginID) { 88 fFieldPluginID = fieldPluginID; 89 } 90 91 /** 92 * 93 */ reset()94 public void reset() { 95 fModel = null; 96 fMonitor = null; 97 fException = null; 98 99 fFieldID = null; 100 fFieldClass = null; 101 fFieldSplashID = null; 102 fFieldProductID = null; 103 fFieldTemplate = null; 104 fFieldPluginID = null; 105 } 106 setModel(IPluginModelBase model)107 public void setModel(IPluginModelBase model) { 108 fModel = model; 109 } 110 setMonitor(IProgressMonitor monitor)111 public void setMonitor(IProgressMonitor monitor) { 112 fMonitor = monitor; 113 } 114 115 @Override run()116 public void run() { 117 try { 118 updateModel(); 119 } catch (CoreException e) { 120 fException = e; 121 } 122 } 123 hasException()124 public void hasException() throws CoreException { 125 // Release any caught exceptions 126 if (fException != null) { 127 throw fException; 128 } 129 } 130 updateModel()131 private void updateModel() throws CoreException { 132 // Find the first splash handler extension 133 IPluginExtension extension = findFirstExtension(F_SPLASH_HANDLERS_EXTENSION); 134 // Check to see if one was found 135 if (extension == null) { 136 // None found, add a new splash handler extension 137 addExtensionSplashHandlers(); 138 } else { 139 // Found one, modify the existing splash handler extension 140 modifyExtensionSplashHandlers(extension); 141 } 142 // Determine whether the extensible template was selected 143 if (isExtensibleTemplateSelected(fFieldTemplate)) { 144 // Extensible template was selected 145 // Extra model modifications required for this template 146 // Find the first spash extension point declaration (should only 147 // ever be one) 148 IPluginExtensionPoint extensionPoint = findFirstExtensionPoint(F_SPLASH_EXTENSION_POINT); 149 // Check to see if one was found 150 // If one is found, just assume all its values are correct (no sync) 151 if (extensionPoint == null) { 152 // No splash extension point definition found, add one 153 addExtensionPointSplashExtension(); 154 } 155 // Find the first splash extension contribution 156 String fullExtensionPointID = fFieldPluginID + '.' + F_SPLASH_EXTENSION_POINT; 157 IPluginExtension extensionSplash = findFirstExtension(fullExtensionPointID); 158 // Check to see if one was found 159 // If one is found, just assume all its values are correct (no sync) 160 if (extensionSplash == null) { 161 // No splash extension contribution found, add one 162 addExtensionSplash(); 163 } 164 } 165 } 166 addExtensionSplash()167 private void addExtensionSplash() throws CoreException { 168 // Update progress work units 169 String fullExtensionPointID = fFieldPluginID + '.' + F_SPLASH_EXTENSION_POINT; 170 fMonitor.beginTask(NLS.bind(PDEUIMessages.UpdateSplashHandlerInModelAction_msgAddingExtension, fullExtensionPointID), 1); 171 // Create the new extension 172 IPluginExtension extension = createExtensionSplash(); 173 // Add extension to the model 174 fModel.getPluginBase().add(extension); 175 // Update progress work units 176 fMonitor.done(); 177 } 178 addExtensionPointSplashExtension()179 private void addExtensionPointSplashExtension() throws CoreException { 180 // Update progress work units 181 fMonitor.beginTask(NLS.bind(PDEUIMessages.UpdateSplashHandlerInModelAction_msgAddingExtensionPoint, F_SPLASH_EXTENSION_POINT), 1); 182 // Create the new extension point 183 IPluginExtensionPoint extensionPoint = createExtensionPointSplash(); 184 // Add extension point to the model 185 fModel.getPluginBase().add(extensionPoint); 186 // Update progress work units 187 fMonitor.done(); 188 } 189 createExtensionPointSplash()190 private IPluginExtensionPoint createExtensionPointSplash() throws CoreException { 191 // Create the extension point 192 IPluginExtensionPoint extensionPoint = fModel.getFactory().createExtensionPoint(); 193 // ID 194 extensionPoint.setId(F_SPLASH_EXTENSION_POINT); 195 // Name 196 extensionPoint.setName(PDEUIMessages.UpdateSplashHandlerInModelAction_splashExtensionPointName); 197 // Schema 198 extensionPoint.setSchema("schema/splashExtension.exsd"); //$NON-NLS-1$ 199 200 return extensionPoint; 201 } 202 findFirstExtension(String extensionPointID)203 private IPluginExtension findFirstExtension(String extensionPointID) { 204 // Get all the extensions 205 IPluginExtension[] extensions = fModel.getPluginBase().getExtensions(); 206 // Get the first extension matching the specified extension point ID 207 for (IPluginExtension extension : extensions) { 208 String point = extension.getPoint(); 209 if (extensionPointID.equals(point)) { 210 return extension; 211 } 212 } 213 return null; 214 } 215 findFirstExtensionPoint(String extensionPointID)216 private IPluginExtensionPoint findFirstExtensionPoint(String extensionPointID) { 217 // Get all the extension points 218 IPluginExtensionPoint[] extensionPoints = fModel.getPluginBase().getExtensionPoints(); 219 // Get the first extension point (should only be one) matching the 220 // specified extension point ID 221 for (IPluginExtensionPoint extensionPoint : extensionPoints) { 222 // Not full ID 223 String point = extensionPoint.getId(); 224 if (extensionPointID.equals(point)) { 225 return extensionPoint; 226 } 227 } 228 return null; 229 } 230 addExtensionSplashHandlers()231 private void addExtensionSplashHandlers() throws CoreException { 232 // Update progress work units 233 fMonitor.beginTask(NLS.bind(PDEUIMessages.UpdateSplashHandlerInModelAction_msgAddingExtension, F_SPLASH_HANDLERS_EXTENSION), 1); 234 // Create the new extension 235 IPluginExtension extension = createExtensionSplashHandlers(); 236 fModel.getPluginBase().add(extension); 237 // Update progress work units 238 fMonitor.done(); 239 } 240 createExtensionSplashHandlers()241 private IPluginExtension createExtensionSplashHandlers() throws CoreException { 242 // Create the extension 243 IPluginExtension extension = fModel.getFactory().createExtension(); 244 // Point 245 extension.setPoint(F_SPLASH_HANDLERS_EXTENSION); 246 // NO id 247 // NO name 248 // Create the extension's children 249 createExtensionChildrenSplashHandlers(extension); 250 251 return extension; 252 } 253 createExtensionChildrenSplashHandlers(IPluginExtension extension)254 private void createExtensionChildrenSplashHandlers(IPluginExtension extension) throws CoreException { 255 // Add a splash handler element 256 addElementSplashHandler(extension); 257 // Add a product handler element 258 addElementProductBinding(extension); 259 } 260 addElementSplashHandler(IPluginExtension extension)261 private void addElementSplashHandler(IPluginExtension extension) throws CoreException { 262 // Create the element 263 IPluginElement splashHandlerElement = createElementSplashHandler(extension); 264 // Ensure element was defined and add it to the extension 265 if (splashHandlerElement != null) { 266 // Extension uses the first element only when choosing a splash 267 // handler. Always set as the first extension element to 268 // override any previous elements 269 extension.add(0, splashHandlerElement); 270 } 271 } 272 addElementProductBinding(IPluginExtension extension)273 private void addElementProductBinding(IPluginExtension extension) throws CoreException { 274 // Create the element 275 IPluginElement productBindingElement = createElementProductBinding(extension); 276 // Ensure element was defined and add it to the extension 277 if (productBindingElement != null) { 278 // Extension uses the first element only when choosing a splash 279 // handler. Always set as the first extension element to 280 // override any previous elements 281 extension.add(1, productBindingElement); 282 } 283 } 284 createElementSplashHandler(IPluginExtension extension)285 private IPluginElement createElementSplashHandler(IPluginExtension extension) throws CoreException { 286 // Create the element 287 IPluginElement element = extension.getModel().getFactory().createElement(extension); 288 // Element: Splash handler 289 element.setName(F_ELEMENT_SPLASH_HANDLER); 290 // Attribute: ID 291 element.setAttribute(F_ATTRIBUTE_ID, fFieldID); 292 // Attribute: Class 293 element.setAttribute(F_ATTRIBUTE_CLASS, fFieldClass); 294 295 return element; 296 } 297 createElementProductBinding(IPluginExtension extension)298 private IPluginElement createElementProductBinding(IPluginExtension extension) throws CoreException { 299 // Create the element 300 IPluginElement element = extension.getModel().getFactory().createElement(extension); 301 // Element: Product binding 302 element.setName(F_ELEMENT_PRODUCT_BINDING); 303 // Attribute: Product ID 304 element.setAttribute(F_ATTRIBUTE_PRODUCT_ID, fFieldProductID); 305 // Attribute: Splash ID 306 element.setAttribute(F_ATTRIBUTE_SPLASH_ID, fFieldSplashID); 307 308 return element; 309 } 310 modifyExtensionSplashHandlers(IPluginExtension extension)311 private void modifyExtensionSplashHandlers(IPluginExtension extension) throws CoreException { 312 // Update progress work units 313 fMonitor.beginTask(NLS.bind(PDEUIMessages.UpdateSplashHandlerInModelAction_msgModifyingExtension, F_SPLASH_HANDLERS_EXTENSION), 1); 314 // modify the existing extension children 315 modifyExtensionChildrenSplashHandlers(extension); 316 // Update progress work units 317 fMonitor.done(); 318 } 319 modifyExtensionChildrenSplashHandlers(IPluginExtension extension)320 private void modifyExtensionChildrenSplashHandlers(IPluginExtension extension) throws CoreException { 321 // Find a matching pre-generated splash handler element 322 IPluginElement splashHandlerElement = findSplashHandlerElement(extension); 323 // Check to see if one was found 324 if (splashHandlerElement == null) { 325 // No element found, add one 326 addElementSplashHandler(extension); 327 } else { 328 // One element found, synchronize it 329 syncSplashHandlerElement(splashHandlerElement); 330 } 331 // Find a matching pre-generated product binding element 332 IPluginElement productBindingElement = findProductBindingElement(extension); 333 // Remove any product binding elements bound to the target product but 334 // NOT bound to the target splash ID (if any elements are found) 335 // The splash handler extension provider uses the first product 336 // binding it finds in the extension. 337 // By removing all product bindings bound to a single product, we can 338 // override an existing splash handler with another existing 339 // splash handler. 340 removeMatchingProductBindingElements(extension); 341 // Check to see if one was found 342 if (productBindingElement == null) { 343 // No element found, add one 344 addElementProductBinding(extension); 345 } else { 346 // One element found, synchronize it 347 syncProductBindingElement(productBindingElement); 348 } 349 } 350 removeMatchingProductBindingElements(IPluginExtension extension)351 private void removeMatchingProductBindingElements(IPluginExtension extension) throws CoreException { 352 // Check to see if the extension has any children 353 if (extension.getChildCount() == 0) { 354 // Extension has no children 355 return; 356 } 357 IPluginObject[] pluginObjects = extension.getChildren(); 358 // Process all children 359 for (IPluginObject pluginObject : pluginObjects) { 360 if (pluginObject instanceof IPluginElement) { 361 IPluginElement element = (IPluginElement) pluginObject; 362 // Find splash handler elements 363 if (element.getName().equals(F_ELEMENT_PRODUCT_BINDING)) { 364 // Get the splash ID attribute 365 IPluginAttribute splashIDAttribute = element.getAttribute(F_ATTRIBUTE_SPLASH_ID); 366 // Get the product ID attribute 367 IPluginAttribute productIDAttribute = element.getAttribute(F_ATTRIBUTE_PRODUCT_ID); 368 // (1) Remove any product binding that has an undefined 369 // product ID or splash ID 370 // (2) Remove any product binding bound to the target 371 // product ID but NOT bound to the target splash ID 372 if ((productIDAttribute == null) || (PDETextHelper.isDefined(productIDAttribute.getValue()) == false) || (splashIDAttribute == null) || (PDETextHelper.isDefined(splashIDAttribute.getValue()) == false)) { 373 // Remove product binding element 374 extension.remove(element); 375 } else if (productIDAttribute.getValue().equals(fFieldProductID) && (splashIDAttribute.getValue().equals(fFieldSplashID) == false)) { 376 // Remove product binding element 377 extension.remove(element); 378 } 379 } 380 } 381 } 382 } 383 findSplashHandlerElement(IPluginExtension extension)384 private IPluginElement findSplashHandlerElement(IPluginExtension extension) { 385 // Check to see if the extension has any children 386 if (extension.getChildCount() == 0) { 387 // Extension has no children 388 return null; 389 } 390 IPluginObject[] pluginObjects = extension.getChildren(); 391 // Process all children 392 for (IPluginObject pluginObject : pluginObjects) { 393 if (pluginObject instanceof IPluginElement) { 394 IPluginElement element = (IPluginElement) pluginObject; 395 // Find splash handler elements 396 if (element.getName().equals(F_ELEMENT_SPLASH_HANDLER)) { 397 // Get the id attribute 398 IPluginAttribute idAttribute = element.getAttribute(F_ATTRIBUTE_ID); 399 // Check for the generated ID 400 if ((idAttribute != null) && PDETextHelper.isDefined(idAttribute.getValue()) && idAttribute.getValue().equals(fFieldID)) { 401 // Matching element found 402 return element; 403 } 404 } 405 } 406 } 407 return null; 408 } 409 syncSplashHandlerElement(IPluginElement element)410 private void syncSplashHandlerElement(IPluginElement element) throws CoreException { 411 // Get the class attribute 412 IPluginAttribute classAttribute = element.getAttribute(F_ATTRIBUTE_CLASS); 413 // Check to see if an update is necessary 414 if ((classAttribute != null) && PDETextHelper.isDefined(classAttribute.getValue()) && classAttribute.getValue().equals(fFieldClass)) { 415 // Exact match, no update necessary 416 return; 417 } 418 // No match, override 419 element.setAttribute(F_ATTRIBUTE_CLASS, fFieldClass); 420 } 421 syncProductBindingElement(IPluginElement element)422 private void syncProductBindingElement(IPluginElement element) throws CoreException { 423 // Get the product ID attribute 424 IPluginAttribute productIDAttribute = element.getAttribute(F_ATTRIBUTE_PRODUCT_ID); 425 // Check to see if an update is necessary 426 if ((productIDAttribute != null) && PDETextHelper.isDefined(productIDAttribute.getValue()) && productIDAttribute.getValue().equals(fFieldProductID)) { 427 // Exact match, no update necessary 428 return; 429 } 430 // No match, override 431 element.setAttribute(F_ATTRIBUTE_PRODUCT_ID, fFieldProductID); 432 } 433 findProductBindingElement(IPluginExtension extension)434 private IPluginElement findProductBindingElement(IPluginExtension extension) { 435 // Check to see if the extension has any children 436 if (extension.getChildCount() == 0) { 437 // Extension has no children 438 return null; 439 } 440 IPluginObject[] pluginObjects = extension.getChildren(); 441 // Process all children 442 for (IPluginObject pluginObject : pluginObjects) { 443 if (pluginObject instanceof IPluginElement) { 444 IPluginElement element = (IPluginElement) pluginObject; 445 // Find product binding elements 446 if (element.getName().equals(F_ELEMENT_PRODUCT_BINDING)) { 447 // Get the id attribute 448 IPluginAttribute splashIDAttribute = element.getAttribute(F_ATTRIBUTE_SPLASH_ID); 449 // Check for the generated ID 450 if ((splashIDAttribute != null) && PDETextHelper.isDefined(splashIDAttribute.getValue()) && splashIDAttribute.getValue().equals(fFieldSplashID)) { 451 // Matching element found 452 return element; 453 } 454 } 455 } 456 } 457 return null; 458 } 459 createExtensionSplash()460 private IPluginExtension createExtensionSplash() throws CoreException { 461 462 String fullExtensionPointID = fFieldPluginID + '.' + F_SPLASH_EXTENSION_POINT; 463 // Create the extension 464 IPluginExtension extension = fModel.getFactory().createExtension(); 465 // Point 466 extension.setPoint(fullExtensionPointID); 467 // NO id 468 // NO name 469 // Create the extension's children 470 createExtensionChildrenSplash(extension); 471 472 return extension; 473 } 474 createExtensionChildrenSplash(IPluginExtension extension)475 private void createExtensionChildrenSplash(IPluginExtension extension) throws CoreException { 476 477 String iconsDir = "icons" + '/'; //$NON-NLS-1$ 478 479 // Splash element: Application Framework 480 IPluginElement splashElementAf = createElementSplash(extension, "af", iconsDir + "af.png", PDEUIMessages.UpdateSplashHandlerInModelAction_nameApplicationFramework); //$NON-NLS-1$ //$NON-NLS-2$ 481 if (splashElementAf != null) { 482 extension.add(splashElementAf); 483 } 484 // Splash element: Embedded 485 IPluginElement splashElementEmbedded = createElementSplash(extension, "embedded", iconsDir + "embedded.png", PDEUIMessages.UpdateSplashHandlerInModelAction_nameEmbedded); //$NON-NLS-1$ //$NON-NLS-2$ 486 if (splashElementEmbedded != null) { 487 extension.add(splashElementEmbedded); 488 } 489 // Splash element: Enterprise 490 IPluginElement splashElementEnterprise = createElementSplash(extension, "enterprise", iconsDir + "enterprise.png", PDEUIMessages.UpdateSplashHandlerInModelAction_nameEnterprise); //$NON-NLS-1$ //$NON-NLS-2$ 491 if (splashElementEnterprise != null) { 492 extension.add(splashElementEnterprise); 493 } 494 // Splash element: Languages 495 IPluginElement splashElementLanguages = createElementSplash(extension, "languages", iconsDir + "languages.png", PDEUIMessages.UpdateSplashHandlerInModelAction_nameLanguages); //$NON-NLS-1$ //$NON-NLS-2$ 496 if (splashElementLanguages != null) { 497 extension.add(splashElementLanguages); 498 } 499 // Splash element: RCP 500 IPluginElement splashElementRCP = createElementSplash(extension, "rcp", iconsDir + "rcp.png", PDEUIMessages.UpdateSplashHandlerInModelAction_nameRCP); //$NON-NLS-1$ //$NON-NLS-2$ 501 if (splashElementRCP != null) { 502 extension.add(splashElementRCP); 503 } 504 } 505 createElementSplash(IPluginExtension extension, String id, String icon, String tooltip)506 private IPluginElement createElementSplash(IPluginExtension extension, String id, String icon, String tooltip) throws CoreException { 507 // Create the element 508 IPluginElement element = extension.getModel().getFactory().createElement(extension); 509 // Element: Splash handler 510 element.setName(F_ELEMENT_SPLASH); 511 // Attribute: ID 512 element.setAttribute(F_ATTRIBUTE_ID, id); 513 // Attribute: Icon 514 element.setAttribute(F_ATTRIBUTE_ICON, icon); 515 // Attribute: Tooltip 516 element.setAttribute(F_ATTRIBUTE_TOOLTIP, tooltip); 517 518 return element; 519 } 520 isExtensibleTemplateSelected(String template)521 public static boolean isExtensibleTemplateSelected(String template) { 522 if (template.equals(F_SPLASH_SCREEN_TYPE_CHOICES[2][0])) { 523 return true; 524 } 525 return false; 526 } 527 528 } 529