KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > ui > wizards > cheatsheet > RegisterCSOperation


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.pde.internal.ui.wizards.cheatsheet;
13
14 import java.lang.reflect.InvocationTargetException JavaDoc;
15
16 import org.eclipse.core.resources.IFile;
17 import org.eclipse.core.runtime.CoreException;
18 import org.eclipse.core.runtime.IProgressMonitor;
19 import org.eclipse.core.runtime.IStatus;
20 import org.eclipse.core.runtime.Status;
21 import org.eclipse.core.runtime.jobs.ISchedulingRule;
22 import org.eclipse.pde.core.IBaseModel;
23 import org.eclipse.pde.core.build.IBuild;
24 import org.eclipse.pde.core.build.IBuildEntry;
25 import org.eclipse.pde.core.build.IBuildModel;
26 import org.eclipse.pde.core.plugin.IPluginAttribute;
27 import org.eclipse.pde.core.plugin.IPluginBase;
28 import org.eclipse.pde.core.plugin.IPluginElement;
29 import org.eclipse.pde.core.plugin.IPluginExtension;
30 import org.eclipse.pde.core.plugin.IPluginModelBase;
31 import org.eclipse.pde.core.plugin.IPluginObject;
32 import org.eclipse.pde.internal.core.ClasspathUtilCore;
33 import org.eclipse.pde.internal.core.ICoreConstants;
34 import org.eclipse.pde.internal.core.TargetPlatformHelper;
35 import org.eclipse.pde.internal.core.build.BuildObject;
36 import org.eclipse.pde.internal.core.build.WorkspaceBuildModel;
37 import org.eclipse.pde.internal.core.ibundle.IBundle;
38 import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
39 import org.eclipse.pde.internal.core.ibundle.IManifestHeader;
40 import org.eclipse.pde.internal.core.icheatsheet.comp.ICompCSConstants;
41 import org.eclipse.pde.internal.core.icheatsheet.simple.ISimpleCSConstants;
42 import org.eclipse.pde.internal.core.plugin.WorkspaceFragmentModel;
43 import org.eclipse.pde.internal.core.plugin.WorkspacePluginModel;
44 import org.eclipse.pde.internal.core.plugin.WorkspacePluginModelBase;
45 import org.eclipse.pde.internal.core.text.bundle.BundleSymbolicNameHeader;
46 import org.eclipse.pde.internal.core.text.bundle.RequireBundleHeader;
47 import org.eclipse.pde.internal.core.util.PDETextHelper;
48 import org.eclipse.pde.internal.ui.IPDEUIConstants;
49 import org.eclipse.pde.internal.ui.PDEPlugin;
50 import org.eclipse.pde.internal.ui.PDEUIMessages;
51 import org.eclipse.pde.internal.ui.util.ModelModification;
52 import org.eclipse.pde.internal.ui.util.PDEModelUtility;
53 import org.eclipse.swt.widgets.Shell;
54 import org.eclipse.ui.actions.WorkspaceModifyOperation;
55 import org.osgi.framework.Constants;
56
57 /**
58  * RegisterCSOperation
59  *
60  */

61 public class RegisterCSOperation extends WorkspaceModifyOperation {
62
63     public static final String JavaDoc F_CS_EXTENSION_ID = "org.eclipse.ui.cheatsheets"; //$NON-NLS-1$
64

65     public static final String JavaDoc F_CS_ATTRIBUTE_CONTENT_FILE = "contentFile"; //$NON-NLS-1$
66

67     public static final String JavaDoc F_CS_ATTRIBUTE_COMPOSITE = "composite"; //$NON-NLS-1$
68

69     private IRegisterCSData fRegisterCSData;
70     
71     private Shell fShell;
72     
73     /**
74      *
75      */

76     public RegisterCSOperation(IRegisterCSData registerCSData, Shell shell) {
77         fRegisterCSData = registerCSData;
78         fShell = shell;
79     }
80
81     /**
82      * @param rule
83      */

84     public RegisterCSOperation(ISchedulingRule rule) {
85         super(rule);
86     }
87
88     /* (non-Javadoc)
89      * @see org.eclipse.ui.actions.WorkspaceModifyOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
90      */

91     protected void execute(IProgressMonitor monitor) throws CoreException,
92             InvocationTargetException JavaDoc, InterruptedException JavaDoc {
93         
94         try {
95             IFile file = fRegisterCSData.getPluginFile();
96             // If the plug-in exists modify it accordingly; otherwise, create
97
// a new plug-in file
98
if (fRegisterCSData.pluginExists()) {
99                 modifyExistingPluginFile(file, monitor);
100             } else {
101                 createNewPluginFile(file, monitor);
102             }
103         } catch (CoreException e) {
104             throw new InvocationTargetException JavaDoc(e);
105         }
106     }
107     
108     /**
109      * FindCSExtensionResult
110      *
111      */

112     private static class FindCSExtensionResult {
113         
114         public IPluginExtension fCSExtension;
115         
116         public IPluginElement fCSElement;
117
118         /**
119          *
120          */

121         public FindCSExtensionResult() {
122             fCSExtension = null;
123             fCSElement = null;
124         }
125         
126         /**
127          * @return
128          */

129         public boolean foundCSExtension() {
130             return (fCSExtension != null);
131         }
132         
133         /**
134          * @return
135          */

136         public boolean foundExactCSElement() {
137             return (fCSElement != null);
138         }
139     }
140     
141     /**
142      * @param file
143      * @param monitor
144      * @throws CoreException
145      */

146     private void modifyExistingPluginFile(IFile file, IProgressMonitor monitor)
147             throws CoreException {
148
149         // Validate the operation
150
// Note: This is not accurate, we are validating the plugin.xml file
151
// but not the manifest.mf file
152
IStatus status =
153             PDEPlugin.getWorkspace().validateEdit(new IFile[] {file}, fShell);
154         if (status.getSeverity() != IStatus.OK) {
155             throw new CoreException(new Status(IStatus.ERROR,
156                     IPDEUIConstants.PLUGIN_ID, IStatus.ERROR,
157                     PDEUIMessages.RegisterCSOperation_errorManifestReadOnly, null));
158         }
159         // Perform the modification of the plugin manifest file
160
ModelModification mod = new ModelModification(fRegisterCSData.getPluginProject()) {
161             protected void modifyModel(IBaseModel model, IProgressMonitor monitor) throws CoreException {
162                 doModifyPluginModel(model, monitor);
163                 doModifyManifestModel(model);
164             }
165         };
166         PDEModelUtility.modifyModel(mod, monitor);
167     }
168
169     /**
170      * @param model
171      * @param monitor
172      * @throws CoreException
173      */

174     private void doModifyPluginModel(IBaseModel model,
175             IProgressMonitor monitor) throws CoreException {
176         if ((model instanceof IPluginModelBase) == false) {
177             return;
178         }
179         IPluginModelBase modelBase = (IPluginModelBase)model;
180         // Find an existing cheat sheet extension
181
FindCSExtensionResult result = findCheatSheetExtension(modelBase);
182         // Check search results and act accordingly
183
if (result.foundCSExtension() &&
184                 result.foundExactCSElement()) {
185             // An exact match to an existing cheat sheet element was
186
// found. Update the elements description and category
187
// fields
188
modifyExistingElement(result.fCSElement, monitor);
189             // Create the category if necessary
190
// Category element
191
IPluginElement categoryElement = createElementCategory(result.fCSExtension);
192             if (categoryElement != null) {
193                 result.fCSExtension.add(categoryElement);
194             }
195         } else if (result.foundCSExtension()) {
196             // No exact match to an existing cheat sheet element found within
197
// the existing cheat sheet extension. Update the
198
// existing extension by adding a new cheat sheet element
199
// to it
200
modifyExistingExtension(result.fCSExtension, monitor);
201         } else {
202             // No existing cheat sheet extension found, create a new
203
// extension
204
insertNewExtension(modelBase, monitor);
205         }
206     }
207     
208     /**
209      * @param modelBase
210      */

211     private void insertNewExtension(IPluginModelBase modelBase,
212             IProgressMonitor monitor) throws CoreException {
213         // Update progress work units
214
monitor.beginTask(PDEUIMessages.RegisterCSOperation_newCSExtensionExistingPlugin, 1);
215         // Create the new extension
216
IPluginExtension extension = createExtensionCheatSheet(modelBase);
217         modelBase.getPluginBase().add(extension);
218         // Update progress work units
219
monitor.done();
220     }
221
222     /**
223      * @param extension
224      */

225     private void modifyExistingExtension(IPluginExtension extension,
226             IProgressMonitor monitor) throws CoreException {
227         // Update progress work units
228
monitor.beginTask(PDEUIMessages.RegisterCSOperation_modCSExtensionExistingPlugin, 1);
229         // Create new children for existing extension
230
createExtensionChildren(extension);
231         // Update progress work units
232
monitor.done();
233     }
234
235     /**
236      * @param csElement
237      * @param monitor
238      */

239     private void modifyExistingElement(IPluginElement csElement,
240             IProgressMonitor monitor) throws CoreException {
241         // Update progress work units
242
monitor.beginTask(PDEUIMessages.RegisterCSOperation_modCSElementExistingPlugin, 1);
243         // Leave id attribute the same
244
// Update the name
245
// Attribute: name
246
csElement.setAttribute(ICompCSConstants.ATTRIBUTE_NAME,
247                 fRegisterCSData.getDataCheatSheetName());
248         // Attribute: category
249
// Update the category.
250
// if "<none>" was selected, clear the entry
251
String JavaDoc categoryID = fRegisterCSData.getDataCategoryID();
252         if (categoryID == null) {
253             categoryID = ""; //$NON-NLS-1$
254
}
255         csElement.setAttribute(RegisterCSWizardPage.F_CS_ELEMENT_CATEGORY,
256             categoryID);
257         // Leave contentFile attribute the same
258
// Leave composite attribute the same
259
// Element: description
260
// Update an existing description if one is found; otherwise,
261
// Create a new description
262
IPluginElement descriptionElement = findExistingDescription(csElement);
263         if (descriptionElement == null) {
264             // Create a new description element
265
descriptionElement = createElementDescription(csElement);
266             if (descriptionElement != null) {
267                 csElement.add(descriptionElement);
268             }
269         } else {
270             // Modify the existing description element
271
boolean modified = modifyExistingDescription(descriptionElement);
272             if (modified == false) {
273                 // New description is not defined, remove the existing
274
// description element
275
csElement.remove(descriptionElement);
276             }
277         }
278         // Update progress work units
279
monitor.done();
280     }
281
282     /**
283      * @param descriptionElement
284      */

285     private boolean modifyExistingDescription(IPluginElement element) throws CoreException {
286         // If the new description is defined set it on the existing description
287
// element; otherwise, delete the existing description element
288
if (PDETextHelper.isDefinedAfterTrim(fRegisterCSData.getDataDescription())) {
289             element.setText(fRegisterCSData.getDataDescription().trim());
290             return true;
291         }
292         return false;
293     }
294
295     /**
296      * @param csElement
297      * @throws CoreException
298      */

299     private IPluginElement findExistingDescription(IPluginElement csElement)
300             throws CoreException {
301         
302         if (csElement.getChildCount() > 0) {
303             IPluginObject pluginObject = csElement.getChildren()[0];
304             if (pluginObject instanceof IPluginElement) {
305                 IPluginElement element = (IPluginElement)pluginObject;
306                 if (element.getName().equals(RegisterCSWizardPage.F_CS_ELEMENT_DESCRIPTION)) {
307                     return element;
308                 }
309             }
310         }
311         return null;
312     }
313
314     /**
315      * @param model
316      * @param extensionResult cheat sheet extension found or null
317      * @param elementResult cheat sheet element found or null
318      * @return
319      */

320     private FindCSExtensionResult findCheatSheetExtension(IPluginModelBase model) {
321         // Container for result
322
FindCSExtensionResult result = new FindCSExtensionResult();
323         // Find all cheat sheet extensions within the host plug-in
324
IPluginExtension[] extensions = fRegisterCSData.findExtensions(model,
325                 RegisterCSWizardPage.F_CS_EXTENSION_POINT_ID);
326         // Process all cheat sheet extensions
327
// Extension search results
328
// (1) An existing extension containing a cheatsheet element with the
329
// exact cheat sheet ID
330
// (2) An existing extension (last one found) containing 0 or more
331
// cheatsheet or category elements
332
// (3) No existing extension
333
for (int i = 0; i < extensions.length; i++) {
334             // Cheat sheet extension match found
335
result.fCSExtension = extensions[i];
336             // Check for children
337
if (extensions[i].getChildCount() == 0) {
338                 // Extension has no children, skip to the next extension
339
continue;
340             }
341             IPluginObject[] pluginObjects = extensions[i].getChildren();
342             // Process all children
343
for (int j = 0; j < pluginObjects.length; j++) {
344                 if (pluginObjects[j] instanceof IPluginElement) {
345                     IPluginElement element = (IPluginElement)pluginObjects[j];
346                     // Find cheat sheet elements
347
if (element.getName().equals(RegisterCSWizardPage.F_CS_ELEMENT_CHEATSHEET)) {
348                         // Cheat sheet element
349
// Get the id attribute
350
IPluginAttribute idAttribute =
351                             element.getAttribute(ICompCSConstants.ATTRIBUTE_ID);
352                         // Check for the generated ID for this cheat sheet
353
// element
354
if ((idAttribute != null) &&
355                                 PDETextHelper.isDefined(idAttribute.getValue()) &&
356                                 fRegisterCSData.getDataCheatSheetID().equals(
357                                         idAttribute.getValue())) {
358                             // Matching cheat sheet element found
359
result.fCSElement = element;
360                             return result;
361                         }
362                     }
363                     
364                 }
365             }
366         }
367         return result;
368     }
369     
370     /**
371      * @param file
372      * @param monitor
373      */

374     private void createNewPluginFile(IFile file, IProgressMonitor monitor)
375             throws CoreException {
376         
377         // Update progress work units
378
monitor.beginTask(PDEUIMessages.RegisterCSOperation_addNewCSExtensionNewPlugin, 4);
379         // Create the plug-in model
380
WorkspacePluginModelBase model =
381             (WorkspacePluginModelBase)createModel(file);
382         // Update progress work units
383
monitor.worked(1);
384         
385         IPluginBase base = model.getPluginBase();
386         // Set schema version
387
double targetVersion = TargetPlatformHelper.getTargetVersion();
388         String JavaDoc version = null;
389         if (targetVersion < 3.2) {
390             version = ICoreConstants.TARGET30;
391         } else {
392             version = ICoreConstants.TARGET32;
393         }
394         base.setSchemaVersion(version);
395         // Create the cheat sheet extension
396
base.add(createExtensionCheatSheet(model));
397         // Update progress work units
398
monitor.worked(1);
399         // Save the model to file
400
model.save();
401         // Update progress work units
402
monitor.worked(1);
403         // Update the MANIFEST.MF file to ensure the singleton directive is set
404
// to true
405
modifyExistingManifestFile(file);
406         // Update progress work units
407
monitor.done();
408     }
409
410     /**
411      * @param model
412      */

413     private void modifyExistingManifestFile(IFile file)
414             throws CoreException {
415         // Validate the operation
416
// Note: This is not accurate, we are validating the plugin.xml file rather
417
// than the manifest file
418
IStatus status =
419             PDEPlugin.getWorkspace().validateEdit(new IFile[] { file }, fShell);
420         if (status.getSeverity() != IStatus.OK) {
421             throw new CoreException(
422                 new Status(IStatus.ERROR, IPDEUIConstants.PLUGIN_ID,
423                         IStatus.ERROR, PDEUIMessages.RegisterCSOperation_errorManifestReadOnly, null));
424         }
425         // Perform the modification of the manifest file
426
ModelModification mod =
427             new ModelModification(fRegisterCSData.getPluginProject()) {
428             protected void modifyModel(IBaseModel model, IProgressMonitor monitor) throws CoreException {
429                 doModifyManifestModel(model);
430                 doModifyBuildModel(model);
431             }
432         };
433         PDEModelUtility.modifyModel(mod, null);
434     }
435
436     /**
437      * @param model
438      */

439     private void doModifyManifestModel(IBaseModel model) {
440         // Make sure we have a base model
441
if ((model instanceof IBundlePluginModelBase) == false) {
442             return;
443         }
444         IBundlePluginModelBase modelBase = (IBundlePluginModelBase)model;
445         IBundle bundle = modelBase.getBundleModel().getBundle();
446         // Get the heading specifying the singleton declaration
447
IManifestHeader header = bundle.getManifestHeader(Constants.BUNDLE_SYMBOLICNAME);
448         if (header instanceof BundleSymbolicNameHeader) {
449             BundleSymbolicNameHeader symbolic = (BundleSymbolicNameHeader)header;
450             // If the singleton declaration is false, change it to true
451
// This is required because plug-ins that specify extensions
452
// must be singletons.
453
if (symbolic.isSingleton() == false) {
454                 symbolic.setSingleton(true);
455             }
456         }
457         // Add the cheat sheets plug-in to the list of required bundles
458
header = bundle.getManifestHeader(Constants.REQUIRE_BUNDLE);
459         if (header instanceof RequireBundleHeader) {
460             RequireBundleHeader require = (RequireBundleHeader)header;
461             if (require.hasElement(F_CS_EXTENSION_ID) == false) {
462                 require.addBundle(F_CS_EXTENSION_ID);
463             }
464         }
465     }
466     
467     /**
468      * @param model
469      */

470     private void doModifyBuildModel(IBaseModel model) throws CoreException {
471         // Make sure we have a base model
472
if ((model instanceof IPluginModelBase) == false) {
473             return;
474         }
475         IPluginModelBase modelBase = (IPluginModelBase)model;
476         IBuild build = ClasspathUtilCore.getBuild(modelBase);
477         // Make sure we have a plugin.properties file
478
if (build == null) {
479             return;
480         }
481         // Get the entry for bin.includes
482
IBuildEntry entry = build.getEntry(IBuildEntry.BIN_INCLUDES);
483         if (entry == null) {
484             // This should never happen since the manifest.mf file exists and
485
// it has to be in the bin.includes
486
return;
487         }
488         // Add the plugin.xml file to the bin.includes build entry if it does
489
// not exist
490
if (entry.contains(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR) == false) {
491             entry.addToken(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR);
492         }
493         // There does not seem to be any support in PDEModelUtility or the
494
// ModelModification framework to save build.properties modifications
495
// As a result, explicitly do that here
496
if (build instanceof BuildObject) {
497             IBuildModel buildModel = ((BuildObject)build).getModel();
498             if (buildModel instanceof WorkspaceBuildModel) {
499                 ((WorkspaceBuildModel)buildModel).save();
500             }
501         }
502     }
503     
504     /**
505      * @param file
506      * @return
507      */

508     private IPluginModelBase createModel(IFile file) {
509         if (fRegisterCSData.isFragment()) {
510             return new WorkspaceFragmentModel(file, false);
511         }
512         return new WorkspacePluginModel(file, false);
513     }
514     
515     /**
516      * @param model
517      * @return
518      * @throws CoreException
519      */

520     private IPluginExtension createExtensionCheatSheet(IPluginModelBase model)
521             throws CoreException {
522         IPluginExtension extension = model.getFactory().createExtension();
523         // Point
524
extension.setPoint(RegisterCSWizardPage.F_CS_EXTENSION_POINT_ID);
525         // NO id
526
// NO name
527

528         createExtensionChildren(extension);
529         
530         return extension;
531     }
532
533     /**
534      * @param extension
535      * @throws CoreException
536      */

537     private void createExtensionChildren(IPluginExtension extension)
538             throws CoreException {
539         // Category element
540
IPluginElement categoryElement = createElementCategory(extension);
541         if (categoryElement != null) {
542             extension.add(categoryElement);
543         }
544         // Cheatsheet element
545
IPluginElement cheatSheetElement = createElementCheatSheet(extension);
546         if (cheatSheetElement != null) {
547             extension.add(cheatSheetElement);
548         }
549     }
550
551     /**
552      * @param extension
553      * @return
554      * @throws CoreException
555      */

556     private IPluginElement createElementCategory(IPluginExtension extension)
557             throws CoreException {
558         // Do not create the category if "<none>" was selected
559
String JavaDoc categoryID = fRegisterCSData.getDataCategoryID();
560         if (categoryID == null) {
561             return null;
562         }
563         // Do not create the category if it is an old category type
564
int type = fRegisterCSData.getDataCategoryType();
565         if (type != CSCategoryTrackerUtil.F_TYPE_NEW_CATEGORY) {
566             return null;
567         }
568         // Create the element
569
IPluginElement element =
570             extension.getModel().getFactory().createElement(extension);
571         // Element: category
572
element.setName(RegisterCSWizardPage.F_CS_ELEMENT_CATEGORY);
573         // Attribute: id
574
element.setAttribute(ICompCSConstants.ATTRIBUTE_ID,
575                 categoryID);
576         // Attribute: name
577
// Already trimmed
578
element.setAttribute(ICompCSConstants.ATTRIBUTE_NAME,
579                 fRegisterCSData.getDataCategoryName());
580         
581         return element;
582     }
583
584     /**
585      * @param extension
586      * @return
587      * @throws CoreException
588      */

589     private IPluginElement createElementCheatSheet(IPluginExtension extension)
590             throws CoreException {
591
592         IPluginElement element =
593             extension.getModel().getFactory().createElement(extension);
594         // Element: cheatsheet
595
element.setName(RegisterCSWizardPage.F_CS_ELEMENT_CHEATSHEET);
596         // Attribute: id
597
element.setAttribute(ICompCSConstants.ATTRIBUTE_ID,
598                 fRegisterCSData.getDataCheatSheetID());
599         // Attribute: name
600
element.setAttribute(ICompCSConstants.ATTRIBUTE_NAME,
601                 fRegisterCSData.getDataCheatSheetName());
602         // Attribute: category
603
// Create the category only if "<none>" was not selected
604
String JavaDoc categoryID = fRegisterCSData.getDataCategoryID();
605         if (categoryID != null) {
606             element.setAttribute(RegisterCSWizardPage.F_CS_ELEMENT_CATEGORY,
607                     categoryID);
608         }
609         // Attribute: contentFile
610
element.setAttribute(F_CS_ATTRIBUTE_CONTENT_FILE,
611                 fRegisterCSData.getDataContentFile());
612         // Attribute: composite
613
element.setAttribute(F_CS_ATTRIBUTE_COMPOSITE,
614                 Boolean.toString(fRegisterCSData.isCompositeCheatSheet()));
615         // Element: description
616
IPluginElement descriptionElement = createElementDescription(element);
617         if (descriptionElement != null) {
618             element.add(descriptionElement);
619         }
620         
621         return element;
622     }
623
624     /**
625      * @param parentElement
626      * @return
627      * @throws CoreException
628      */

629     private IPluginElement createElementDescription(IPluginElement parentElement)
630             throws CoreException {
631         // Define the description element only if description text was
632
// specified
633
String JavaDoc descriptionText = fRegisterCSData.getDataDescription();
634         if (PDETextHelper.isDefinedAfterTrim(descriptionText) == false) {
635             return null;
636         }
637         // Create the element
638
IPluginElement element =
639             parentElement.getModel().getFactory().createElement(parentElement);
640         // Element: description
641
element.setName(ISimpleCSConstants.ELEMENT_DESCRIPTION);
642         // Content
643
element.setText(descriptionText.trim());
644         
645         return element;
646     }
647     
648
649 }
650
Popular Tags