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