KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > ui > util > PDEModelUtility


1 /*******************************************************************************
2  * Copyright (c) 2005, 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 package org.eclipse.pde.internal.ui.util;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Hashtable JavaDoc;
15 import java.util.Iterator JavaDoc;
16
17 import org.eclipse.core.filebuffers.FileBuffers;
18 import org.eclipse.core.filebuffers.ITextFileBuffer;
19 import org.eclipse.core.filebuffers.ITextFileBufferManager;
20 import org.eclipse.core.resources.IFile;
21 import org.eclipse.core.resources.IProject;
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.jface.text.BadLocationException;
25 import org.eclipse.jface.text.IDocument;
26 import org.eclipse.pde.core.IBaseModel;
27 import org.eclipse.pde.core.plugin.IPluginModelBase;
28 import org.eclipse.pde.core.plugin.ISharedExtensionsModel;
29 import org.eclipse.pde.internal.core.bundle.BundleFragmentModel;
30 import org.eclipse.pde.internal.core.bundle.BundlePluginModel;
31 import org.eclipse.pde.internal.core.ibundle.IBundleModel;
32 import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
33 import org.eclipse.pde.internal.core.text.AbstractEditingModel;
34 import org.eclipse.pde.internal.core.text.IEditingModel;
35 import org.eclipse.pde.internal.core.text.IModelTextChangeListener;
36 import org.eclipse.pde.internal.core.text.build.BuildModel;
37 import org.eclipse.pde.internal.core.text.build.PropertiesTextChangeListener;
38 import org.eclipse.pde.internal.core.text.bundle.BundleModel;
39 import org.eclipse.pde.internal.core.text.bundle.BundleTextChangeListener;
40 import org.eclipse.pde.internal.core.text.plugin.FragmentModel;
41 import org.eclipse.pde.internal.core.text.plugin.PluginModel;
42 import org.eclipse.pde.internal.core.text.plugin.XMLTextChangeListener;
43 import org.eclipse.pde.internal.ui.IPDEUIConstants;
44 import org.eclipse.pde.internal.ui.PDEPlugin;
45 import org.eclipse.pde.internal.ui.editor.PDEFormEditor;
46 import org.eclipse.pde.internal.ui.editor.build.BuildEditor;
47 import org.eclipse.pde.internal.ui.editor.build.BuildInputContext;
48 import org.eclipse.pde.internal.ui.editor.build.BuildSourcePage;
49 import org.eclipse.pde.internal.ui.editor.context.InputContext;
50 import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor;
51 import org.eclipse.pde.internal.ui.editor.schema.SchemaEditor;
52 import org.eclipse.pde.internal.ui.editor.schema.SchemaInputContext;
53 import org.eclipse.pde.internal.ui.editor.site.SiteEditor;
54 import org.eclipse.swt.widgets.Display;
55 import org.eclipse.text.edits.MalformedTreeException;
56 import org.eclipse.text.edits.MultiTextEdit;
57 import org.eclipse.text.edits.TextEdit;
58 import org.eclipse.ui.IEditorInput;
59 import org.eclipse.ui.IEditorPart;
60 import org.eclipse.ui.IFileEditorInput;
61 import org.eclipse.ui.forms.editor.IFormPage;
62 import org.osgi.framework.Constants;
63
64 /**
65  * Your one stop shop for preforming changes to your plug-in models.
66  *
67  */

68 public class PDEModelUtility {
69     
70     public static final String JavaDoc F_MANIFEST = "MANIFEST.MF"; //$NON-NLS-1$
71
public static final String JavaDoc F_MANIFEST_FP = "META-INF/" + F_MANIFEST; //$NON-NLS-1$
72
public static final String JavaDoc F_PLUGIN = "plugin.xml"; //$NON-NLS-1$
73
public static final String JavaDoc F_FRAGMENT = "fragment.xml"; //$NON-NLS-1$
74
public static final String JavaDoc F_PROPERTIES = ".properties"; //$NON-NLS-1$
75
public static final String JavaDoc F_BUILD = "build" + F_PROPERTIES; //$NON-NLS-1$
76

77     // bundle / xml various Object[] indices
78
private static final int F_Bi = 0; // the manifest.mf-related object will always be 1st
79
private static final int F_Xi = 1; // the xml-related object will always be 2nd
80

81     private static Hashtable JavaDoc fOpenPDEEditors = new Hashtable JavaDoc();
82     
83     /**
84      * PDE editors should call this during their creation.
85      *
86      * Currently the pde editor superclass (PDEFormEditor)
87      * connects during its createPages method and so this
88      * method does not need to be invoked anywhere else.
89      * @param editor the editor to connect to
90      */

91     public static void connect(PDEFormEditor editor) {
92         IProject project = editor.getCommonProject();
93         if (project == null)
94             return;
95         if (fOpenPDEEditors.containsKey(project)) {
96             ArrayList JavaDoc list = (ArrayList JavaDoc)fOpenPDEEditors.get(project);
97             if (!list.contains(editor))
98                 list.add(editor);
99         } else {
100             ArrayList JavaDoc list = new ArrayList JavaDoc();
101             list.add(editor);
102             fOpenPDEEditors.put(project, list);
103         }
104     }
105     
106     /**
107      * PDE editors should call this when they are closing down.
108      * @param editor the pde editor to disconnect from
109      */

110     public static void disconnect(PDEFormEditor editor) {
111         IProject project = editor.getCommonProject();
112         if (project == null)
113             return;
114         if (!fOpenPDEEditors.containsKey(project))
115             return;
116         ArrayList JavaDoc list = (ArrayList JavaDoc)fOpenPDEEditors.get(project);
117         list.remove(editor);
118         if (list.size() == 0)
119             fOpenPDEEditors.remove(project);
120     }
121     
122     /**
123      * Returns an open ManifestEditor that is associated with this project.
124      * @param project
125      * @return null if no ManifestEditor is open for this project
126      */

127     public static ManifestEditor getOpenManifestEditor(IProject project) {
128         return (ManifestEditor)getOpenEditor(project, IPDEUIConstants.MANIFEST_EDITOR_ID);
129     }
130     
131     /**
132      * Returns an open BuildEditor that is associated with this project.
133      * @param project
134      * @return null if no BuildEditor is open for this project
135      */

136     public static BuildEditor getOpenBuildPropertiesEditor(IProject project) {
137         return (BuildEditor) getOpenEditor(project, IPDEUIConstants.BUILD_EDITOR_ID);
138     }
139     
140     /**
141      * Returns an open SiteEditor that is associated with this project.
142      * @param project
143      * @return null if no SiteEditor is open for this project
144      */

145     public static SiteEditor getOpenUpdateSiteEditor(IProject project) {
146         return (SiteEditor) getOpenEditor(project, IPDEUIConstants.SITE_EDITOR_ID);
147     }
148     
149     private static PDEFormEditor getOpenEditor(IProject project, String JavaDoc editorId) {
150         ArrayList JavaDoc list = (ArrayList JavaDoc)fOpenPDEEditors.get(project);
151         if (list == null)
152             return null;
153         for (int i = 0; i < list.size(); i++) {
154             PDEFormEditor editor = (PDEFormEditor)list.get(i);
155             if (editor.getEditorSite().getId().equals(editorId))
156                 return editor;
157         }
158         return null;
159     }
160     
161     /**
162      * Get the open schema editor rooted at the specified underlying file
163      * @param file
164      * @return editor if found or null
165      */

166     public static SchemaEditor getOpenSchemaEditor(IFile file) {
167         return (SchemaEditor)getOpenEditor(
168                 IPDEUIConstants.SCHEMA_EDITOR_ID,
169                 SchemaInputContext.CONTEXT_ID,
170                 file);
171     }
172
173     /**
174      * @param editorID
175      * @param inputContextID
176      * @param file
177      * @return
178      */

179     private static PDEFormEditor getOpenEditor(String JavaDoc editorID,
180             String JavaDoc inputContextID, IFile file) {
181         // Get the file's project
182
IProject project = file.getProject();
183         // Check for open editors housed in the specified project
184
ArrayList JavaDoc list = (ArrayList JavaDoc)fOpenPDEEditors.get(project);
185         // No open editors found
186
if (list == null) {
187             return null;
188         }
189         // Get the open editor whose
190
// (1) Editor ID matches the specified editor ID
191
// (2) Underlying file matches the specified file
192
// Check all open editors
193
for (int i = 0; i < list.size(); i++) {
194             // Get the editor
195
PDEFormEditor editor = (PDEFormEditor)list.get(i);
196             // Check for the specified type
197
// Get the editor ID
198
String JavaDoc currentEditorID = editor.getEditorSite().getId();
199             if (currentEditorID.equals(editorID) == false) {
200                 continue;
201             }
202             // Check for the specified file
203
// Find the editor's input context
204
InputContext context =
205                 editor.getContextManager().findContext(inputContextID);
206             // Ensure we have an input context
207
if (context == null) {
208                 continue;
209             }
210             // Get the editor input
211
IEditorInput input = context.getInput();
212             // Ensure we have a file editor input
213
if ((input instanceof IFileEditorInput) == false) {
214                 continue;
215             }
216             // Get the editor's underlying file
217
IFile currentFile = ((IFileEditorInput)input).getFile();
218             // If the file matches the specified file, we have found the
219
// specified editor
220
if (currentFile.equals(file)) {
221                 return editor;
222             }
223         }
224         return null;
225     }
226     
227     /**
228      * Returns an IPluginModelBase from the active ManifestEditor or null
229      * if no manifest editor is open.
230      * @return the active IPluginModelBase
231      */

232     public static IPluginModelBase getActivePluginModel() {
233         IEditorPart editor = PDEPlugin.getActivePage().getActiveEditor();
234         if (editor instanceof ManifestEditor) {
235             IBaseModel model = ((ManifestEditor)editor).getAggregateModel();
236             if (model instanceof IPluginModelBase)
237                 return (IPluginModelBase)model;
238         }
239         return null;
240     }
241     
242     /**
243      *
244      * @param doc
245      * @return
246      */

247     public static IEditingModel getOpenModel(IDocument doc) {
248         Iterator JavaDoc it = fOpenPDEEditors.values().iterator();
249         while (it.hasNext()) {
250             ArrayList JavaDoc list = (ArrayList JavaDoc)it.next();
251             for (int i = 0; i < list.size(); i++) {
252                 PDEFormEditor e = (PDEFormEditor)list.get(i);
253                 IPluginModelBase model = (IPluginModelBase)e.getAggregateModel();
254                 if (model instanceof IBundlePluginModelBase) {
255                     IBundleModel bModel = ((IBundlePluginModelBase)model).getBundleModel();
256                     if (bModel instanceof IEditingModel &&
257                             doc == ((IEditingModel)bModel).getDocument())
258                         return (IEditingModel)bModel;
259                     ISharedExtensionsModel eModel = ((IBundlePluginModelBase)model).getExtensionsModel();
260                     if (eModel instanceof IEditingModel &&
261                             doc == ((IEditingModel)eModel).getDocument())
262                         return (IEditingModel)eModel;
263                 }
264                 
265 // IBuildModel bModel = model.getBuildModel();
266
// if (bModel instanceof IEditingModel &&
267
// doc == ((IEditingModel)bModel).getDocument())
268
// return (IEditingModel)bModel;
269

270                 if (model instanceof IEditingModel &&
271                         doc == ((IEditingModel)model).getDocument())
272                     return (IEditingModel)model;
273             }
274         }
275         return null;
276     }
277     
278     /**
279      * Modify a model based on the specifications provided by the ModelModification parameter.
280      *
281      * A model will be searched for in the open editors, if it is found changes will be applied
282      * and the editor will be saved.
283      * If no model is found one will be created and text edit operations will be generated / applied.
284      *
285      * NOTE: If a MANIFEST.MF file is specified in the ModelModification a BundlePluginModel will be
286      * searched for / created and passed to ModelModification#modifyModel(IBaseModel).
287      * (not a BundleModel - which can be retreived from the BundlePluginModel)
288      * @param modification
289      * @param monitor
290      * @throws CoreException
291      */

292     public static void modifyModel(final ModelModification modification, final IProgressMonitor monitor) {
293         // ModelModification was not supplied with the right files
294
// TODO should we just fail silently?
295
if (modification.getFile() == null)
296             return;
297         
298         PDEFormEditor editor = getOpenEditor(modification);
299         IBaseModel model = getModelFromEditor(editor, modification);
300         
301         if (model != null) {
302             // open editor found, should have underlying text listeners -> apply modification
303
modifyEditorModel(modification, editor, model, monitor);
304         } else {
305             // create own model, attach listeners and grab text edits
306
ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
307             IFile[] files;
308             if (modification.isFullBundleModification()) {
309                 files = new IFile[2];
310                 files[F_Bi] = modification.getManifestFile();
311                 files[F_Xi] = modification.getXMLFile();
312             } else {
313                 files = new IFile[] { modification.getFile() };
314             }
315             // need to monitor number of successfull buffer connections for disconnection purposes
316
// @see } finally { statement
317
int sc = 0;
318             try {
319                 ITextFileBuffer[] buffers = new ITextFileBuffer[files.length];
320                 IDocument[] documents = new IDocument[files.length];
321                 for (int i = 0; i < files.length; i++) {
322                     if (files[i] == null || !files[i].exists())
323                         continue;
324                     manager.connect(files[i].getFullPath(), monitor);
325                     sc++;
326                     buffers[i] = manager.getTextFileBuffer(files[i].getFullPath());
327                     if (buffers[i].isDirty())
328                         buffers[i].commit(monitor, true);
329                     documents[i] = buffers[i].getDocument();
330                 }
331                 
332                 IBaseModel editModel;
333                 if (modification.isFullBundleModification())
334                     editModel = prepareBundlePluginModel(files, documents);
335                 else
336                     editModel = prepareAbstractEditingModel(files[0], documents[0]);
337                 
338                 modification.modifyModel(editModel, monitor);
339                 
340                 IModelTextChangeListener[] listeners = gatherListeners(editModel);
341                 for (int i = 0; i < listeners.length; i++) {
342                     if (listeners[i] == null)
343                         continue;
344                     TextEdit[] edits = listeners[i].getTextOperations();
345                     if (edits.length > 0) {
346                         MultiTextEdit multi = new MultiTextEdit();
347                         multi.addChildren(edits);
348                         multi.apply(documents[i]);
349                         buffers[i].commit(monitor, true);
350                     }
351                 }
352             } catch (CoreException e) {
353                 PDEPlugin.log(e);
354             } catch (MalformedTreeException e) {
355                 PDEPlugin.log(e);
356             } catch (BadLocationException e) {
357                 PDEPlugin.log(e);
358             } finally {
359                 // don't want to over-disconnect in case we ran into an exception during connections
360
// dc <= sc stops this from happening
361
int dc = 0;
362                 for (int i = 0; i < files.length && dc <= sc; i++) {
363                     if (files[i] == null || !files[i].exists())
364                         continue;
365                     try {
366                         manager.disconnect(files[i].getFullPath(), monitor);
367                         dc++;
368                     } catch (CoreException e) {
369                         PDEPlugin.log(e);
370                     }
371                 }
372             }
373         }
374     }
375     
376     private static void modifyEditorModel(
377             final ModelModification mod,
378             final PDEFormEditor editor,
379             final IBaseModel model,
380             final IProgressMonitor monitor) {
381         getDisplay().syncExec(new Runnable JavaDoc() {
382             public void run() {
383                 try {
384                     mod.modifyModel(model, monitor);
385                     IFile[] files = new IFile[] {
386                             mod.getManifestFile(),
387                             mod.getXMLFile(),
388                             mod.getPropertiesFile()
389                     };
390                     for (int i = 0; i < files.length; i++) {
391                         if (files[i] == null)
392                             continue;
393                         InputContext con = editor.getContextManager().findContext(files[i]);
394                         if (con != null)
395                             con.flushEditorInput();
396                     }
397                     if (mod.saveOpenEditor())
398                         editor.doSave(monitor);
399                 } catch (CoreException e) {
400                     PDEPlugin.log(e);
401                 }
402             }
403         });
404     }
405     
406     private static PDEFormEditor getOpenEditor(ModelModification modification) {
407         IProject project = modification.getFile().getProject();
408         String JavaDoc name = modification.getFile().getName();
409         if (name.equals(F_PLUGIN) || name.equals(F_FRAGMENT) || name.equals(F_MANIFEST)) {
410             return getOpenManifestEditor(project);
411         } else if (name.equals(F_BUILD)) {
412             PDEFormEditor openEditor = getOpenBuildPropertiesEditor(project);
413             if (openEditor == null)
414                 openEditor = getOpenManifestEditor(project);
415             return openEditor;
416         }
417         return null;
418     }
419     
420     private static IBaseModel getModelFromEditor(PDEFormEditor openEditor, ModelModification modification) {
421         if (openEditor == null)
422             return null;
423         String JavaDoc name = modification.getFile().getName();
424         IBaseModel model = null;
425         if (name.equals(F_PLUGIN) || name.equals(F_FRAGMENT)) {
426             model = openEditor.getAggregateModel();
427             if (model instanceof IBundlePluginModelBase)
428                 model = ((IBundlePluginModelBase)model).getExtensionsModel();
429         } else if (name.equals(F_BUILD)) {
430             if (openEditor instanceof BuildEditor) {
431                 model = openEditor.getAggregateModel();
432             } else if (openEditor instanceof ManifestEditor) {
433                 IFormPage page = openEditor.findPage(BuildInputContext.CONTEXT_ID);
434                 if (page instanceof BuildSourcePage)
435                     model = ((BuildSourcePage)page).getInputContext().getModel();
436             }
437         } else if (name.equals(F_MANIFEST)) {
438             model = openEditor.getAggregateModel();
439             if (model instanceof IBundlePluginModelBase)
440                 return model;
441         }
442         if (model instanceof AbstractEditingModel)
443             return model;
444         return null;
445     }
446     
447     private static IModelTextChangeListener createListener(String JavaDoc filename, IDocument doc) {
448         if (filename.equals(F_PLUGIN) || filename.equals(F_FRAGMENT))
449             return new XMLTextChangeListener(doc);
450         else if (filename.equals(F_MANIFEST))
451             return new BundleTextChangeListener(doc);
452         else if (filename.endsWith(F_PROPERTIES))
453             return new PropertiesTextChangeListener(doc);
454         return null;
455     }
456     
457     private static AbstractEditingModel prepareAbstractEditingModel(IFile file, IDocument doc) {
458         AbstractEditingModel model;
459         String JavaDoc filename = file.getName();
460         if (filename.equals(F_MANIFEST))
461             model = new BundleModel(doc, true);
462         else if (filename.equals(F_FRAGMENT))
463             model = new FragmentModel(doc, true);
464         else if (filename.equals(F_PLUGIN))
465             model = new PluginModel(doc, true);
466         else if (filename.endsWith(F_PROPERTIES))
467             model = new BuildModel(doc, true);
468         else
469             return null;
470         model.setUnderlyingResource(file);
471         try {
472             model.load();
473             IModelTextChangeListener listener = createListener(filename, doc);
474             model.addModelChangedListener(listener);
475         } catch (CoreException e) {
476             PDEPlugin.log(e);
477         }
478         return model;
479     }
480     
481     private static IBaseModel prepareBundlePluginModel(IFile[] files, IDocument[] docs) throws CoreException {
482         AbstractEditingModel[] models = new AbstractEditingModel[docs.length];
483         
484         boolean isFragment = false;
485         models[F_Bi] = prepareAbstractEditingModel(files[F_Bi], docs[F_Bi]);
486         if (models[F_Bi] instanceof IBundleModel)
487             isFragment = ((IBundleModel)models[F_Bi]).getBundle().getHeader(Constants.FRAGMENT_HOST) != null;
488         
489         IBundlePluginModelBase pluginModel;
490         if (isFragment)
491             pluginModel = new BundleFragmentModel();
492         else
493             pluginModel = new BundlePluginModel();
494         
495         pluginModel.setBundleModel((IBundleModel)models[F_Bi]);
496         if (files.length > F_Xi && files[F_Xi] != null) {
497             models[F_Xi] = prepareAbstractEditingModel(files[F_Xi], docs[F_Xi]);
498             pluginModel.setExtensionsModel((ISharedExtensionsModel)models[F_Xi]);
499         }
500         return pluginModel;
501     }
502     
503     private static IModelTextChangeListener[] gatherListeners(IBaseModel editModel) {
504         IModelTextChangeListener[] listeners = new IModelTextChangeListener[0];
505         if (editModel instanceof AbstractEditingModel)
506             listeners = new IModelTextChangeListener[] {
507                     ((AbstractEditingModel)editModel).getLastTextChangeListener()};
508         if (editModel instanceof IBundlePluginModelBase) {
509             IBundlePluginModelBase modelBase = (IBundlePluginModelBase)editModel;
510             listeners = new IModelTextChangeListener[2];
511             listeners[F_Bi] = gatherListener(modelBase.getBundleModel());
512             listeners[F_Xi] = gatherListener(modelBase.getExtensionsModel());
513             return listeners;
514         }
515         return listeners;
516     }
517     
518     private static IModelTextChangeListener gatherListener(IBaseModel model) {
519         if (model instanceof AbstractEditingModel)
520             return((AbstractEditingModel)model).getLastTextChangeListener();
521         return null;
522     }
523     
524     private static Display getDisplay() {
525         Display display = Display.getCurrent();
526         if (display == null)
527             display = Display.getDefault();
528         return display;
529     }
530 }
531
Popular Tags