1) Fixed issue #776.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / PHPeclipsePlugin.java
1 /**********************************************************************
2  Copyright (c) 2000, 2002 IBM Corp. and others.
3  All rights reserved. This program and the accompanying materials
4  are made available under the terms of the Common Public License v1.0
5  which accompanies this distribution, and is available at
6  http://www.eclipse.org/legal/cpl-v10.html
7
8  **********************************************************************/
9 package net.sourceforge.phpeclipse;
10
11 import java.io.File;
12 import java.io.IOException;
13 import java.io.InputStream;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Enumeration;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.PropertyResourceBundle;
22 import java.util.Set;
23
24 import net.sourceforge.phpdt.core.IBuffer;
25 import net.sourceforge.phpdt.core.IBufferFactory;
26 import net.sourceforge.phpdt.core.ICompilationUnit;
27 import net.sourceforge.phpdt.core.IJavaElement;
28 import net.sourceforge.phpdt.core.JavaCore;
29 import net.sourceforge.phpdt.core.WorkingCopyOwner;
30 import net.sourceforge.phpdt.internal.core.BatchOperation;
31 import net.sourceforge.phpdt.internal.core.JavaModelManager;
32 import net.sourceforge.phpdt.internal.core.util.Util;
33 import net.sourceforge.phpdt.internal.corext.template.php.CodeTemplateContextType;
34 import net.sourceforge.phpdt.internal.corext.template.php.HTMLContextType;
35 import net.sourceforge.phpdt.internal.corext.template.php.JavaContextType;
36 import net.sourceforge.phpdt.internal.corext.template.php.JavaDocContextType;
37 import net.sourceforge.phpdt.internal.ui.IJavaStatusConstants;
38 import net.sourceforge.phpdt.internal.ui.JavaElementAdapterFactory;
39 import net.sourceforge.phpdt.internal.ui.ResourceAdapterFactory;
40 import net.sourceforge.phpdt.internal.ui.preferences.MembersOrderPreferenceCache;
41 import net.sourceforge.phpdt.internal.ui.preferences.MockupPreferenceStore;
42 import net.sourceforge.phpdt.internal.ui.text.PreferencesAdapter;
43 import net.sourceforge.phpdt.internal.ui.text.folding.JavaFoldingStructureProviderRegistry;
44 import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaEditorTextHoverDescriptor;
45 import net.sourceforge.phpdt.internal.ui.viewsupport.ImageDescriptorRegistry;
46 import net.sourceforge.phpdt.internal.ui.viewsupport.ProblemMarkerManager;
47 import net.sourceforge.phpdt.ui.IContextMenuConstants;
48 import net.sourceforge.phpdt.ui.IWorkingCopyManager;
49 import net.sourceforge.phpdt.ui.PreferenceConstants;
50 import net.sourceforge.phpdt.ui.text.JavaTextTools;
51 import net.sourceforge.phpeclipse.builder.ExternalEditorInput;
52 import net.sourceforge.phpeclipse.builder.ExternalStorageDocumentProvider;
53 import net.sourceforge.phpeclipse.builder.FileStorage;
54 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
55 import net.sourceforge.phpeclipse.CustomBufferFactory;
56 import net.sourceforge.phpeclipse.DocumentAdapter;
57 import net.sourceforge.phpeclipse.phpeditor.ICompilationUnitDocumentProvider;
58 import net.sourceforge.phpeclipse.phpeditor.PHPDocumentProvider;
59 import net.sourceforge.phpeclipse.phpeditor.PHPSyntaxRdr;
60 import net.sourceforge.phpeclipse.phpeditor.WorkingCopyManager;
61 import net.sourceforge.phpeclipse.phpeditor.util.PHPColorProvider;
62
63 import org.eclipse.core.resources.IFile;
64 import org.eclipse.core.resources.IProject;
65 import org.eclipse.core.resources.IResource;
66 import org.eclipse.core.resources.IResourceChangeEvent;
67 import org.eclipse.core.resources.ISavedState;
68 import org.eclipse.core.resources.IWorkspace;
69 import org.eclipse.core.resources.IWorkspaceRunnable;
70 import org.eclipse.core.resources.ResourcesPlugin;
71 import org.eclipse.core.resources.WorkspaceJob;
72 import org.eclipse.core.runtime.CoreException;
73 import org.eclipse.core.runtime.IAdapterManager;
74 import org.eclipse.core.runtime.IConfigurationElement;
75 import org.eclipse.core.runtime.IPath;
76 import org.eclipse.core.runtime.IProgressMonitor;
77 import org.eclipse.core.runtime.IStatus;
78 import org.eclipse.core.runtime.Path;
79 import org.eclipse.core.runtime.Platform;
80 import org.eclipse.core.runtime.Status;
81 import org.eclipse.core.runtime.jobs.ISchedulingRule;
82 import org.eclipse.core.runtime.jobs.Job;
83 import org.eclipse.jface.action.GroupMarker;
84 import org.eclipse.jface.action.IMenuManager;
85 import org.eclipse.jface.action.Separator;
86 import org.eclipse.jface.preference.IPreferenceStore;
87 import org.eclipse.jface.preference.PreferenceConverter;
88 import org.eclipse.jface.resource.JFaceResources;
89 import org.eclipse.jface.text.BadLocationException;
90 import org.eclipse.jface.text.IDocument;
91 import org.eclipse.jface.text.templates.ContextTypeRegistry;
92 import org.eclipse.jface.text.templates.persistence.TemplateStore;
93 import org.eclipse.jface.util.IPropertyChangeListener;
94 import org.eclipse.jface.util.PropertyChangeEvent;
95 import org.eclipse.swt.graphics.RGB;
96 import org.eclipse.swt.widgets.Display;
97 import org.eclipse.swt.widgets.Shell;
98 import org.eclipse.ui.IEditorDescriptor;
99 import org.eclipse.ui.IEditorInput;
100 import org.eclipse.ui.IEditorPart;
101 import org.eclipse.ui.IEditorRegistry;
102 import org.eclipse.ui.IWorkbench;
103 import org.eclipse.ui.IWorkbenchPage;
104 import org.eclipse.ui.IWorkbenchWindow;
105 import org.eclipse.ui.PlatformUI;
106 import org.eclipse.ui.editors.text.EditorsUI;
107 import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
108 import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
109 import org.eclipse.ui.ide.IDE;
110 import org.eclipse.ui.plugin.AbstractUIPlugin;
111 import org.eclipse.ui.texteditor.ChainedPreferenceStore;
112 import org.eclipse.ui.texteditor.ConfigurationElementSorter;
113 import org.eclipse.ui.texteditor.IDocumentProvider;
114 import org.eclipse.ui.texteditor.ITextEditor;
115 import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
116 import org.osgi.framework.BundleContext;
117
118 /**
119  * The main plugin class to be used in the desktop.
120  */
121 public class PHPeclipsePlugin extends AbstractUIPlugin implements
122                 IPreferenceConstants {
123         /**
124          * The id of the PHP plugin (value <code>"net.sourceforge.phpeclipse"</code>).
125          */
126         public static final String PLUGIN_ID = "net.sourceforge.phpeclipse"; //$NON-NLS-1$
127
128         public static final String EDITOR_ID = PHPeclipsePlugin.PLUGIN_ID
129                         + ".PHPUnitEditor";
130
131         public static final String ID_PERSPECTIVE = "net.sourceforge.phpeclipse.PHPPerspective"; //$NON-NLS-1$
132
133         IWorkspace w;
134
135         /**
136          * id of builder - matches plugin.xml (concatenate pluginid.builderid)
137          */
138         public static final String BUILDER_PARSER_ID = PLUGIN_ID + ".parserbuilder";
139
140         // public static final String BUILDER_INDEX_ID = PLUGIN_ID +
141         // ".indexbuilder";
142         /** General debug flag */
143
144         public static final boolean DEBUG = false;
145
146         /**
147          * The maximum number of allowed proposals by category
148          */
149         public final static int MAX_PROPOSALS = 200;
150
151         /**
152          * The key to store customized templates.
153          * 
154          * @since 3.0
155          */
156         private static final String TEMPLATES_KEY = "net.sourceforge.phpdt.ui.text.custom_templates"; //$NON-NLS-1$
157
158         /**
159          * The key to store customized code templates.
160          * 
161          * @since 3.0
162          */
163         private static final String CODE_TEMPLATES_KEY = "net.sourceforge.phpdt.ui.text.custom_code_templates"; //$NON-NLS-1$
164
165         public static final String PHP_CODING_ACTION_SET_ID = PLUGIN_ID
166                         + ".ui.CodingActionSet"; //$NON-NLS-1$
167
168         public final static String PHP_NATURE_ID = PLUGIN_ID + ".phpnature";
169
170         public static final String PHPPARSER_ORIGINAL = "net.sourceforge.phpdt.internal.compiler.parser.Parser";
171
172         public static final String PHPPARSER_NEW = "test.PHPParser";
173
174         /** Change this if you want to switch PHP Parser. */
175         public static final String PHPPARSER = PHPPARSER_ORIGINAL;
176
177         // The shared instance.
178         private static PHPeclipsePlugin plugin;
179
180         /**
181          * The template context type registry for the java editor.
182          * 
183          * @since 3.0
184          */
185         private ContextTypeRegistry fContextTypeRegistry;
186
187         /**
188          * The code template context type registry for the java editor.
189          * 
190          * @since 3.0
191          */
192         private ContextTypeRegistry fCodeTemplateContextTypeRegistry;
193
194         /**
195          * The template store for the java editor.
196          * 
197          * @since 3.0
198          */
199         private TemplateStore fTemplateStore;
200
201         /**
202          * The coded template store for the java editor.
203          * 
204          * @since 3.0
205          */
206         private TemplateStore fCodeTemplateStore;
207
208         /** Windows 9x */
209         private static final int WINDOWS_9x = 6;
210
211         /** Windows NT */
212         private static final int WINDOWS_NT = 5;
213
214         private ImageDescriptorRegistry fImageDescriptorRegistry;
215
216         private HashMap fIndexManagerMap = new HashMap();
217
218         private IWorkingCopyManager fWorkingCopyManager;
219
220         private IBufferFactory fBufferFactory;
221
222         private ICompilationUnitDocumentProvider fCompilationUnitDocumentProvider;
223
224         private JavaTextTools fJavaTextTools;
225
226         private ProblemMarkerManager fProblemMarkerManager;
227
228         private MembersOrderPreferenceCache fMembersOrderPreferenceCache;
229
230         private IFile fLastEditorFile = null;
231
232         private JavaEditorTextHoverDescriptor[] fJavaEditorTextHoverDescriptors;
233
234         private JavaElementAdapterFactory fJavaElementAdapterFactory;
235
236         // private MarkerAdapterFactory fMarkerAdapterFactory;
237         // private EditorInputAdapterFactory fEditorInputAdapterFactory;
238         private ResourceAdapterFactory fResourceAdapterFactory;
239
240         // private LogicalPackageAdapterFactory fLogicalPackageAdapterFactory;
241         private IPropertyChangeListener fFontPropertyChangeListener;
242
243         /**
244          * Property change listener on this plugin's preference store.
245          * 
246          * @since 3.0
247          */
248         // private IPropertyChangeListener fPropertyChangeListener;
249         /**
250          * The combined preference store.
251          * 
252          * @since 3.0
253          */
254         private IPreferenceStore fCombinedPreferenceStore;
255
256         /**
257          * The extension point registry for the
258          * <code>net.sourceforge.phpdt.ui.javaFoldingStructureProvider</code>
259          * extension point.
260          * 
261          * @since 3.0
262          */
263         private JavaFoldingStructureProviderRegistry fFoldingStructureProviderRegistry;
264
265         /**
266          * Mockup preference store for firing events and registering listeners on
267          * project setting changes. FIXME: Temporary solution.
268          * 
269          * @since 3.0
270          */
271         private MockupPreferenceStore fMockupPreferenceStore;
272
273         /**
274          * The constructor.
275          */
276         public PHPeclipsePlugin() {
277                 super();
278                 plugin = this;
279                 // externalTools = new ExternalToolsPlugin();
280
281                 // try {
282                 // resourceBundle =
283                 // ResourceBundle.getBundle("net.sourceforge.PHPeclipsePluginResources");
284                 // } catch (MissingResourceException x) {
285                 // resourceBundle = null;
286                 // }
287         }
288
289         // /**
290         // * Returns all Java editor text hovers contributed to the workbench.
291         // *
292         // * @return an array of JavaEditorTextHoverDescriptor
293         // * @since 2.1
294         // */
295         // public JavaEditorTextHoverDescriptor[]
296         // getJavaEditorTextHoverDescriptors()
297         // {
298         // if (fJavaEditorTextHoverDescriptors == null)
299         // fJavaEditorTextHoverDescriptors = JavaEditorTextHoverDescriptor
300         // .getContributedHovers();
301         // return fJavaEditorTextHoverDescriptors;
302         // }
303         /**
304          * Returns all Java editor text hovers contributed to the workbench.
305          * 
306          * @return an array of JavaEditorTextHoverDescriptor
307          * @since 2.1
308          */
309         public JavaEditorTextHoverDescriptor[] getJavaEditorTextHoverDescriptors() {
310                 if (fJavaEditorTextHoverDescriptors == null) {
311                         fJavaEditorTextHoverDescriptors = JavaEditorTextHoverDescriptor
312                                         .getContributedHovers();
313                         ConfigurationElementSorter sorter = new ConfigurationElementSorter() {
314                                 /*
315                                  * @see org.eclipse.ui.texteditor.ConfigurationElementSorter#getConfigurationElement(java.lang.Object)
316                                  */
317                                 public IConfigurationElement getConfigurationElement(
318                                                 Object object) {
319                                         return ((JavaEditorTextHoverDescriptor) object)
320                                                         .getConfigurationElement();
321                                 }
322                         };
323                         sorter.sort(fJavaEditorTextHoverDescriptors);
324
325                         // The Problem hover has to be the first and the Annotation hover
326                         // has to
327                         // be the last one in the JDT UI's hover list
328                         int length = fJavaEditorTextHoverDescriptors.length;
329                         int first = -1;
330                         int last = length - 1;
331                         int problemHoverIndex = -1;
332                         int annotationHoverIndex = -1;
333                         for (int i = 0; i < length; i++) {
334                                 if (!fJavaEditorTextHoverDescriptors[i].getId().startsWith(
335                                                 PLUGIN_ID)) {
336                                         if (problemHoverIndex == -1 || annotationHoverIndex == -1)
337                                                 continue;
338                                         else {
339                                                 last = i - 1;
340                                                 break;
341                                         }
342                                 }
343                                 if (first == -1)
344                                         first = i;
345
346                                 if (fJavaEditorTextHoverDescriptors[i].getId().equals(
347                                                 "net.sourceforge.phpdt.ui.AnnotationHover")) { //$NON-NLS-1$
348                                         annotationHoverIndex = i;
349                                         continue;
350                                 }
351                                 if (fJavaEditorTextHoverDescriptors[i].getId().equals(
352                                                 "net.sourceforge.phpdt.ui.ProblemHover")) { //$NON-NLS-1$
353                                         problemHoverIndex = i;
354                                         continue;
355                                 }
356                         }
357
358                         JavaEditorTextHoverDescriptor hoverDescriptor = null;
359
360                         if (first > -1 && problemHoverIndex > -1
361                                         && problemHoverIndex != first) {
362                                 // move problem hover to beginning
363                                 hoverDescriptor = fJavaEditorTextHoverDescriptors[first];
364                                 fJavaEditorTextHoverDescriptors[first] = fJavaEditorTextHoverDescriptors[problemHoverIndex];
365                                 fJavaEditorTextHoverDescriptors[problemHoverIndex] = hoverDescriptor;
366
367                                 // update annotation hover index if needed
368                                 if (annotationHoverIndex == first)
369                                         annotationHoverIndex = problemHoverIndex;
370                         }
371
372                         if (annotationHoverIndex > -1 && annotationHoverIndex != last) {
373                                 // move annotation hover to end
374                                 hoverDescriptor = fJavaEditorTextHoverDescriptors[last];
375                                 fJavaEditorTextHoverDescriptors[last] = fJavaEditorTextHoverDescriptors[annotationHoverIndex];
376                                 fJavaEditorTextHoverDescriptors[annotationHoverIndex] = hoverDescriptor;
377                         }
378
379                         // Move Best Match hover to front
380                         for (int i = 0; i < fJavaEditorTextHoverDescriptors.length - 1; i++) {
381                                 if (PreferenceConstants.ID_BESTMATCH_HOVER
382                                                 .equals(fJavaEditorTextHoverDescriptors[i].getId())) {
383                                         hoverDescriptor = fJavaEditorTextHoverDescriptors[i];
384                                         for (int j = i; j > 0; j--)
385                                                 fJavaEditorTextHoverDescriptors[j] = fJavaEditorTextHoverDescriptors[j - 1];
386                                         fJavaEditorTextHoverDescriptors[0] = hoverDescriptor;
387                                         break;
388                                 }
389
390                         }
391                 }
392
393                 return fJavaEditorTextHoverDescriptors;
394         }
395
396         /**
397          * Resets the Java editor text hovers contributed to the workbench.
398          * <p>
399          * This will force a rebuild of the descriptors the next time a client asks
400          * for them.
401          * </p>
402          * 
403          * @return an array of JavaEditorTextHoverDescriptor
404          * @since 2.1
405          */
406         public void resetJavaEditorTextHoverDescriptors() {
407                 fJavaEditorTextHoverDescriptors = null;
408         }
409
410         /**
411          * Creates the PHP plugin standard groups in a context menu.
412          */
413         public static void createStandardGroups(IMenuManager menu) {
414                 if (!menu.isEmpty())
415                         return;
416                 menu.add(new Separator(IContextMenuConstants.GROUP_NEW));
417                 menu.add(new GroupMarker(IContextMenuConstants.GROUP_GOTO));
418                 menu.add(new Separator(IContextMenuConstants.GROUP_OPEN));
419                 menu.add(new GroupMarker(IContextMenuConstants.GROUP_SHOW));
420                 menu.add(new Separator(IContextMenuConstants.GROUP_REORGANIZE));
421                 menu.add(new Separator(IContextMenuConstants.GROUP_GENERATE));
422                 menu.add(new Separator(IContextMenuConstants.GROUP_SEARCH));
423                 menu.add(new Separator(IContextMenuConstants.GROUP_BUILD));
424                 menu.add(new Separator(IContextMenuConstants.GROUP_ADDITIONS));
425                 menu.add(new Separator(IContextMenuConstants.GROUP_VIEWER_SETUP));
426                 menu.add(new Separator(IContextMenuConstants.GROUP_PROPERTIES));
427         }
428
429         public static IWorkbenchPage getActivePage() {
430                 return getDefault().internalGetActivePage();
431         }
432
433         public static Shell getActiveWorkbenchShell() {
434                 return getActiveWorkbenchWindow().getShell();
435         }
436
437         /**
438          * Returns an array of all editors that have an unsaved content. If the
439          * identical content is presented in more than one editor, only one of those
440          * editor parts is part of the result.
441          * 
442          * @return an array of all dirty editor parts.
443          */
444         public static IEditorPart[] getDirtyEditors() {
445                 Set inputs = new HashSet();
446                 List result = new ArrayList(0);
447                 IWorkbench workbench = getDefault().getWorkbench();
448                 IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
449                 for (int i = 0; i < windows.length; i++) {
450                         IWorkbenchPage[] pages = windows[i].getPages();
451                         for (int x = 0; x < pages.length; x++) {
452                                 IEditorPart[] editors = pages[x].getDirtyEditors();
453                                 for (int z = 0; z < editors.length; z++) {
454                                         IEditorPart ep = editors[z];
455                                         IEditorInput input = ep.getEditorInput();
456                                         if (!inputs.contains(input)) {
457                                                 inputs.add(input);
458                                                 result.add(ep);
459                                         }
460                                 }
461                         }
462                 }
463                 return (IEditorPart[]) result.toArray(new IEditorPart[result.size()]);
464         }
465
466         public static IWorkbenchWindow getActiveWorkbenchWindow() {
467                 return getDefault().getWorkbench().getActiveWorkbenchWindow();
468         }
469
470         /**
471          * Returns the shared instance.
472          */
473         public static PHPeclipsePlugin getDefault() {
474                 return plugin;
475         }
476
477         public static ImageDescriptorRegistry getImageDescriptorRegistry() {
478                 return getDefault().internalGetImageDescriptorRegistry();
479         }
480
481         static IPath getInstallLocation() {
482                 return new Path(getDefault().getBundle().getEntry("/").getFile());
483         }
484
485         // public static int getJVM() {
486         // return jvm;
487         // }
488
489         public static String getPluginId() {
490                 return getDefault().getBundle().getSymbolicName();
491         }
492
493         /**
494          * Returns the standard display to be used. The method first checks, if the
495          * thread calling this method has an associated display. If so, this display
496          * is returned. Otherwise the method returns the default display.
497          */
498         public static Display getStandardDisplay() {
499                 Display display = Display.getCurrent();
500                 if (display == null) {
501                         display = Display.getDefault();
502                 }
503                 return display;
504         }
505
506         // public static ExternalToolsPlugin getExternalTools() {
507         // return externalTools;
508         // }
509         /**
510          * Returns the workspace instance.
511          */
512         public static IWorkspace getWorkspace() {
513                 return ResourcesPlugin.getWorkspace();
514         }
515
516         public static boolean isDebug() {
517                 return getDefault().isDebugging();
518         }
519
520         // public static void logErrorMessage(String message) {
521         // log(new Status(IStatus.ERROR, getPluginId(),
522         // JavaStatusConstants.INTERNAL_ERROR, message, null));
523         // }
524         //
525         // public static void logErrorStatus(String message, IStatus status) {
526         // if (status == null) {
527         // logErrorMessage(message);
528         // return;
529         // }
530         // MultiStatus multi= new MultiStatus(getPluginId(),
531         // JavaStatusConstants.INTERNAL_ERROR, message, null);
532         // multi.add(status);
533         // log(multi);
534         // }
535         //
536         // public static void log(Throwable e) {
537         // log(new Status(IStatus.ERROR, getPluginId(),
538         // JavaStatusConstants.INTERNAL_ERROR,
539         // JavaUIMessages.getString("JavaPlugin.internal_error"), e)); //$NON-NLS-1$
540         // }
541         public static void log(int severity, String message) {
542                 Status status = new Status(severity, PLUGIN_ID, IStatus.OK, message,
543                                 null);
544                 log(status);
545         }
546
547         public static void log(IStatus status) {
548                 getDefault().getLog().log(status);
549         }
550
551         public static void log(Throwable t) {
552                 log(error(t));
553         }
554
555         public static void log(String message, Throwable t) {
556                 log(error(message, t));
557         }
558
559         public static void logErrorMessage(String message) {
560                 log(new Status(IStatus.ERROR, getPluginId(),
561                                 IJavaStatusConstants.INTERNAL_ERROR, message, null));
562         }
563
564         public static IStatus error(Throwable t) {
565                 return error("PHPeclipsePlugin.internalErrorOccurred", t); //$NON-NLS-1$
566         }
567
568         public static IStatus error(String message, Throwable t) {
569                 return new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, message, t);
570         }
571
572         // private static void setJVM() {
573         // String osName = System.getProperty("os.name");
574         // if (osName.startsWith("Mac OS")) {
575         // String mrjVersion = System.getProperty("mrj.version");
576         // String majorMRJVersion = mrjVersion.substring(0, 3);
577         // jvm = OTHER;
578         // try {
579         // double version = Double.valueOf(majorMRJVersion).doubleValue();
580         // if (version == 2) {
581         // jvm = MRJ_2_0;
582         // } else if (version >= 2.1 && version < 3) {
583         // jvm = MRJ_2_1;
584         // } else if (version == 3.0) {
585         // jvm = MRJ_3_0;
586         // } else if (version >= 3.1) {
587         // jvm = MRJ_3_1;
588         // }
589         // } catch (NumberFormatException nfe) {
590         // }
591         // } else if (osName.startsWith("Windows")) {
592         // if (osName.indexOf("9") != -1) {
593         // jvm = WINDOWS_9x;
594         // } else {
595         // jvm = WINDOWS_NT;
596         // }
597         // }
598         // }
599
600         // TODO: refactor this into a better method name !
601         public synchronized ICompilationUnitDocumentProvider getCompilationUnitDocumentProvider() {
602                 if (fCompilationUnitDocumentProvider == null)
603                         fCompilationUnitDocumentProvider = new PHPDocumentProvider();
604                 return fCompilationUnitDocumentProvider;
605         }
606
607         /**
608          * Get the identifier index manager for the given project
609          * 
610          * @param iProject
611          *            the current project
612          * @return
613          */
614         public IdentifierIndexManager getIndexManager(IProject iProject) {
615                 IPath path = iProject.getWorkingLocation(PHPeclipsePlugin.PLUGIN_ID);
616                 path = path.append("project.index");
617                 String indexFilename = path.toString();
618                 // try {
619                 // IdentDB db = IdentDB.getInstance();
620                 // } catch (ClassNotFoundException e) {
621                 // e.printStackTrace();
622                 // } catch (SQLException e) {
623                 // e.printStackTrace();
624                 // }
625                 IdentifierIndexManager indexManager = (IdentifierIndexManager) fIndexManagerMap
626                                 .get(indexFilename);
627                 if (indexManager == null) {
628                         indexManager = new IdentifierIndexManager(indexFilename);
629                         fIndexManagerMap.put(indexFilename, indexManager);
630                 }
631                 return indexManager;
632         }
633
634         public synchronized IWorkingCopyManager getWorkingCopyManager() {
635                 if (fWorkingCopyManager == null) {
636                         ICompilationUnitDocumentProvider provider = getCompilationUnitDocumentProvider();
637                         fWorkingCopyManager = new WorkingCopyManager(provider);
638                 }
639                 return fWorkingCopyManager;
640         }
641
642         public synchronized MembersOrderPreferenceCache getMemberOrderPreferenceCache() {
643                 if (fMembersOrderPreferenceCache == null)
644                         fMembersOrderPreferenceCache = new MembersOrderPreferenceCache();
645                 return fMembersOrderPreferenceCache;
646         }
647
648         /**
649          * Returns the mockup preference store for firing events and registering
650          * listeners on project setting changes. Temporary solution.
651          */
652         public MockupPreferenceStore getMockupPreferenceStore() {
653                 if (fMockupPreferenceStore == null)
654                         fMockupPreferenceStore = new MockupPreferenceStore();
655
656                 return fMockupPreferenceStore;
657         }
658
659         public synchronized ProblemMarkerManager getProblemMarkerManager() {
660                 if (fProblemMarkerManager == null)
661                         fProblemMarkerManager = new ProblemMarkerManager();
662                 return fProblemMarkerManager;
663         }
664
665         // public synchronized JavaTextTools getJavaTextTools() {
666         // if (fJavaTextTools == null)
667         // fJavaTextTools = new JavaTextTools(getPreferenceStore());
668         // return fJavaTextTools;
669         // }
670         public synchronized JavaTextTools getJavaTextTools() {
671                 if (fJavaTextTools == null)
672                         fJavaTextTools = new JavaTextTools(getPreferenceStore(), JavaCore
673                                         .getPlugin().getPluginPreferences());
674                 return fJavaTextTools;
675         }
676
677         public IFile getLastEditorFile() {
678                 return fLastEditorFile;
679         }
680
681         /**
682          * Returns the string from the plugin's resource bundle, or 'key' if not
683          * found.
684          */
685         // public static String getResourceString(String key) {
686         // ResourceBundle bundle =
687         // PHPeclipsePlugin.getDefault().getResourceBundle();
688         // try {
689         // return bundle.getString(key);
690         // } catch (MissingResourceException e) {
691         // return key;
692         // }
693         // }
694         /**
695          * Returns the plugin's resource bundle,
696          */
697         // public ResourceBundle getResourceBundle() {
698         // return resourceBundle;
699         // }
700         protected void initializeDefaultPreferences(IPreferenceStore store) {
701                 String operatingSystem = Platform.getOS();
702                 // maxosx, linux, solaris, win32,...
703                 try {
704                         InputStream is = getDefault()
705                                         .openStream(
706                                                         new Path("prefs/default_" + operatingSystem
707                                                                         + ".properties"));
708                         PropertyResourceBundle resourceBundle = new PropertyResourceBundle(
709                                         is);
710                         Enumeration e = resourceBundle.getKeys();
711                         String key;
712                         while (e.hasMoreElements()) {
713                                 key = (String) e.nextElement();
714                                 store.setDefault(key, resourceBundle.getString(key));
715                         }
716                 } catch (Exception e) {
717                         // no default properties found
718                         if (operatingSystem.equals(Platform.OS_WIN32)) {
719                                 // store.setDefault(PHP_RUN_PREF, "c:\\apache\\php\\php.exe");
720                                 // store.setDefault(EXTERNAL_PARSER_PREF, "c:\\apache\\php\\php
721                                 // -l -f {0}");
722                                 // store.setDefault(MYSQL_RUN_PREF,
723                                 // "c:\\apache\\mysql\\bin\\mysqld-nt.exe");
724                                 // store.setDefault(APACHE_RUN_PREF, "c:\\apache\\apache.exe");
725                                 // store.setDefault(XAMPP_START_PREF,
726                                 // "c:\\xampp\\xampp_start.exe");
727                                 // store.setDefault(XAMPP_STOP_PREF,
728                                 // "c:\\xampp\\xampp_stop.exe");
729                                 // store.setDefault(
730                                 // ETC_HOSTS_PATH_PREF,
731                                 // "c:\\windows\\system32\\drivers\\etc\\hosts");
732                         } else {
733                                 // store.setDefault(PHP_RUN_PREF, "/apache/php/php");
734                                 // store.setDefault(EXTERNAL_PARSER_PREF, "/apache/php/php -l -f
735                                 // {0}");
736                                 // store.setDefault(MYSQL_RUN_PREF, "/apache/mysql/bin/mysqld");
737                                 // store.setDefault(APACHE_RUN_PREF, "/apache/apache");
738                                 // store.setDefault(XAMPP_START_PREF, "xamp/xampp_start");
739                                 // store.setDefault(XAMPP_STOP_PREF, "xampp/xampp_stop");
740                         }
741                         // store.setDefault(MYSQL_PREF, "--standalone");
742                         // store.setDefault(APACHE_START_PREF, "-c \"DocumentRoot
743                         // \"{0}\"\"");
744                         // store.setDefault(APACHE_STOP_PREF, "-k shutdown");
745                         // store.setDefault(APACHE_RESTART_PREF, "-k restart");
746                         // store.setDefault(MYSQL_START_BACKGROUND, "true");
747                         // store.setDefault(APACHE_START_BACKGROUND, "true");
748                         // store.setDefault(APACHE_STOP_BACKGROUND, "true");
749                         // store.setDefault(APACHE_RESTART_BACKGROUND, "true");
750                 }
751
752                 // php syntax highlighting
753                 store.setDefault(PHP_USERDEF_XMLFILE, "");
754                 PreferenceConverter.setDefault(store, PHP_TAG, PHPColorProvider.TAG);
755                 PreferenceConverter.setDefault(store, PHP_KEYWORD,
756                                 PHPColorProvider.KEYWORD);
757                 PreferenceConverter.setDefault(store, PHP_VARIABLE,
758                                 PHPColorProvider.VARIABLE);
759                 PreferenceConverter.setDefault(store, PHP_VARIABLE_DOLLAR,
760                                 PHPColorProvider.VARIABLE);
761                 PreferenceConverter.setDefault(store, PHP_FUNCTIONNAME,
762                                 PHPColorProvider.FUNCTION_NAME);
763                 PreferenceConverter.setDefault(store, PHP_CONSTANT,
764                                 PHPColorProvider.CONSTANT);
765                 PreferenceConverter.setDefault(store, PHP_TYPE, PHPColorProvider.TYPE);
766                 PreferenceConverter.setDefault(store, PHP_DEFAULT,
767                                 PHPColorProvider.DEFAULT);
768                 PreferenceConverter.setDefault(store, PHPDOC_KEYWORD,
769                                 PHPColorProvider.PHPDOC_KEYWORD);
770                 PreferenceConverter.setDefault(store, PHPDOC_TAG,
771                                 PHPColorProvider.PHPDOC_TAG);
772                 PreferenceConverter.setDefault(store, PHPDOC_LINK,
773                                 PHPColorProvider.PHPDOC_LINK);
774                 PreferenceConverter.setDefault(store, PHPDOC_DEFAULT,
775                                 PHPColorProvider.PHPDOC_DEFAULT);
776
777                 PreferenceConverter.setDefault(store, EDITOR_PHP_KEYWORD_RETURN_COLOR,
778                                 new RGB(127, 0, 85));
779                 store.setDefault(EDITOR_PHP_KEYWORD_RETURN_BOLD, true);
780                 store.setDefault(EDITOR_PHP_KEYWORD_RETURN_ITALIC, false);
781
782                 PreferenceConverter.setDefault(store, EDITOR_PHP_OPERATOR_COLOR,
783                                 new RGB(0, 0, 0));
784                 store.setDefault(EDITOR_PHP_OPERATOR_BOLD, false);
785                 store.setDefault(EDITOR_PHP_OPERATOR_ITALIC, false);
786
787                 PreferenceConverter.setDefault(store, EDITOR_PHP_BRACE_OPERATOR_COLOR,
788                                 new RGB(0, 0, 0));
789                 store.setDefault(EDITOR_PHP_BRACE_OPERATOR_BOLD, false);
790                 store.setDefault(EDITOR_PHP_BRACE_OPERATOR_ITALIC, false);
791
792                 // this will initialize the static fields in the syntaxrdr class
793                 new PHPSyntaxRdr();
794                 JavaCore.initializeDefaultPluginPreferences();
795                 PreferenceConstants.initializeDefaultValues(store);
796                 // externalTools.initializeDefaultPreferences(store);
797                 // MarkerAnnotationPreferences.initializeDefaultValues(store);
798         }
799
800         private IWorkbenchPage internalGetActivePage() {
801                 IWorkbenchWindow window = getWorkbench().getActiveWorkbenchWindow();
802                 if (window != null)
803                         return window.getActivePage();
804                 return null;
805         }
806
807         private ImageDescriptorRegistry internalGetImageDescriptorRegistry() {
808                 if (fImageDescriptorRegistry == null)
809                         fImageDescriptorRegistry = new ImageDescriptorRegistry();
810                 return fImageDescriptorRegistry;
811         }
812
813         /**
814          * Open a file in the Workbench that may or may not exist in the workspace.
815          * Must be run on the UI thread.
816          * 
817          * @param filename
818          * @throws CoreException
819          */
820         public ITextEditor openFileInTextEditor(String filename)
821                         throws CoreException {
822                 // reject directories
823                 if (new File(filename).isDirectory())
824                         return null;
825                 IWorkbench workbench = PlatformUI.getWorkbench();
826                 IWorkbenchWindow window = workbench.getWorkbenchWindows()[0];
827                 IWorkbenchPage page = window.getActivePage();
828                 IPath path = new Path(filename);
829                 // If the file exists in the workspace, open it
830                 IFile file = getWorkspace().getRoot().getFile(path);
831                 IEditorPart editor;
832                 ITextEditor textEditor;
833                 if (file != null && file.exists()) {
834                         editor = IDE.openEditor(page, file, true);
835                         textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
836                 } else {
837                         // Otherwise open the stream directly
838                         if (page == null)
839                                 return null;
840                         FileStorage storage = new FileStorage(path);
841                         IEditorRegistry registry = getWorkbench().getEditorRegistry();
842                         IEditorDescriptor desc = registry.getDefaultEditor(filename);
843                         if (desc == null) {
844                                 desc = registry
845                                                 .findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID);
846                                 // desc = registry.getDefaultEditor();
847                         }
848                         IEditorInput input = new ExternalEditorInput(storage);
849                         editor = page.openEditor(input, desc.getId());
850                         textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
851                         // If the storage provider is not ours, we can't guarantee
852                         // read/write.
853                         if (textEditor != null) {
854                                 IDocumentProvider documentProvider = textEditor
855                                                 .getDocumentProvider();
856                                 if (!(documentProvider instanceof ExternalStorageDocumentProvider)) {
857                                         storage.setReadOnly();
858                                 }
859                         }
860                 }
861                 return textEditor;
862         }
863
864         /**
865          * Open a file in the Workbench that may or may not exist in the workspace.
866          * Must be run on the UI thread.
867          * 
868          * @param filename
869          * @param line
870          * @throws CoreException
871          */
872         public void openFileAndGotoLine(String filename, int line)
873                         throws CoreException {
874                 ITextEditor textEditor = openFileInTextEditor(filename);
875                 if (textEditor != null) {
876                         // If a line number was given, go to it
877                         if (line > 0) {
878                                 try {
879                                         line--; // document is 0 based
880                                         IDocument document = textEditor.getDocumentProvider()
881                                                         .getDocument(textEditor.getEditorInput());
882                                         textEditor.selectAndReveal(document.getLineOffset(line),
883                                                         document.getLineLength(line));
884                                 } catch (BadLocationException e) {
885                                         // invalid text position -> do nothing
886                                 }
887                         }
888                 }
889         }
890
891         /**
892          * Open a file in the Workbench that may or may not exist in the workspace.
893          * Must be run on the UI thread.
894          * 
895          * @param filename
896          * @param offset
897          * @throws CoreException
898          */
899         public void openFileAndGotoOffset(String filename, int offset, int length)
900                         throws CoreException {
901                 ITextEditor textEditor = openFileInTextEditor(filename);
902                 if (textEditor != null) {
903                         // If a line number was given, go to it
904                         if (offset >= 0) {
905                                 IDocument document = textEditor.getDocumentProvider()
906                                                 .getDocument(textEditor.getEditorInput());
907                                 textEditor.selectAndReveal(offset, length);
908                         }
909                 }
910         }
911
912         public void openFileAndFindString(String filename, String findString)
913                         throws CoreException {
914                 ITextEditor textEditor = openFileInTextEditor(filename);
915                 if (textEditor != null) {
916                         // If a string was given, go to it
917                         if (findString != null) {
918                                 try {
919                                         IDocument document = textEditor.getDocumentProvider()
920                                                         .getDocument(textEditor.getEditorInput());
921                                         int offset = document.search(0, findString, true, false,
922                                                         true);
923                                         textEditor.selectAndReveal(offset, findString.length());
924                                 } catch (BadLocationException e) {
925                                         // invalid text position -> do nothing
926                                 }
927                         }
928                 }
929         }
930
931         public void setLastEditorFile(IFile textEditor) {
932                 this.fLastEditorFile = textEditor;
933         }
934
935         /*
936          * @see org.eclipse.core.runtime.Plugin#stop
937          */
938         public void stop(BundleContext context) throws Exception {
939                 try {
940                         // JavaCore.stop(this, context);
941                         plugin.savePluginPreferences();
942                         IWorkspace workspace = ResourcesPlugin.getWorkspace();
943                         workspace.removeResourceChangeListener(JavaModelManager
944                                         .getJavaModelManager().deltaState);
945                         workspace.removeSaveParticipant(plugin);
946
947                         JavaModelManager.getJavaModelManager().shutdown();
948
949                         // save the information from the php index files if necessary
950                         Collection collection = fIndexManagerMap.values();
951                         Iterator iterator = collection.iterator();
952                         IdentifierIndexManager indexManager = null;
953                         while (iterator.hasNext()) {
954                                 indexManager = (IdentifierIndexManager) iterator.next();
955                                 indexManager.writeFile();
956                         }
957                         if (fImageDescriptorRegistry != null)
958                                 fImageDescriptorRegistry.dispose();
959
960                         // AllTypesCache.terminate();
961
962                         if (fImageDescriptorRegistry != null)
963                                 fImageDescriptorRegistry.dispose();
964
965                         unregisterAdapters();
966
967                         // if (fASTProvider != null) {
968                         // fASTProvider.dispose();
969                         // fASTProvider= null;
970                         // }
971
972                         if (fWorkingCopyManager != null) {
973                                 fWorkingCopyManager.shutdown();
974                                 fWorkingCopyManager = null;
975                         }
976
977                         if (fCompilationUnitDocumentProvider != null) {
978                                 fCompilationUnitDocumentProvider.shutdown();
979                                 fCompilationUnitDocumentProvider = null;
980                         }
981
982                         if (fJavaTextTools != null) {
983                                 fJavaTextTools.dispose();
984                                 fJavaTextTools = null;
985                         }
986                         // JavaDocLocations.shutdownJavadocLocations();
987
988                         uninstallPreferenceStoreBackwardsCompatibility();
989
990                         // RefactoringCore.getUndoManager().shutdown();
991                 } finally {
992                         super.stop(context);
993                 }
994         }
995
996         /**
997          * Installs backwards compatibility for the preference store.
998          */
999         private void installPreferenceStoreBackwardsCompatibility() {
1000
1001                 /*
1002                  * Installs backwards compatibility: propagate the Java editor font from
1003                  * a pre-2.1 plug-in to the Platform UI's preference store to preserve
1004                  * the Java editor font from a pre-2.1 workspace. This is done only
1005                  * once.
1006                  */
1007                 String fontPropagatedKey = "fontPropagated"; //$NON-NLS-1$
1008                 if (getPreferenceStore().contains(JFaceResources.TEXT_FONT)
1009                                 && !getPreferenceStore().isDefault(JFaceResources.TEXT_FONT)) {
1010                         if (!getPreferenceStore().getBoolean(fontPropagatedKey))
1011                                 PreferenceConverter
1012                                                 .setValue(PlatformUI.getWorkbench()
1013                                                                 .getPreferenceStore(),
1014                                                                 PreferenceConstants.EDITOR_TEXT_FONT,
1015                                                                 PreferenceConverter.getFontDataArray(
1016                                                                                 getPreferenceStore(),
1017                                                                                 JFaceResources.TEXT_FONT));
1018                 }
1019                 getPreferenceStore().setValue(fontPropagatedKey, true);
1020
1021                 /*
1022                  * Backwards compatibility: set the Java editor font in this plug-in's
1023                  * preference store to let older versions access it. Since 2.1 the Java
1024                  * editor font is managed by the workbench font preference page.
1025                  */
1026                 PreferenceConverter.putValue(getPreferenceStore(),
1027                                 JFaceResources.TEXT_FONT, JFaceResources.getFontRegistry()
1028                                                 .getFontData(PreferenceConstants.EDITOR_TEXT_FONT));
1029
1030                 fFontPropertyChangeListener = new IPropertyChangeListener() {
1031                         public void propertyChange(PropertyChangeEvent event) {
1032                                 if (PreferenceConstants.EDITOR_TEXT_FONT.equals(event
1033                                                 .getProperty()))
1034                                         PreferenceConverter.putValue(getPreferenceStore(),
1035                                                         JFaceResources.TEXT_FONT,
1036                                                         JFaceResources.getFontRegistry().getFontData(
1037                                                                         PreferenceConstants.EDITOR_TEXT_FONT));
1038                         }
1039                 };
1040                 JFaceResources.getFontRegistry().addListener(
1041                                 fFontPropertyChangeListener);
1042         }
1043
1044         /**
1045          * Uninstalls backwards compatibility for the preference store.
1046          */
1047         private void uninstallPreferenceStoreBackwardsCompatibility() {
1048                 JFaceResources.getFontRegistry().removeListener(
1049                                 fFontPropertyChangeListener);
1050                 // getPreferenceStore().removePropertyChangeListener(fPropertyChangeListener);
1051         }
1052
1053         /*
1054          * (non - Javadoc) Method declared in Plugin
1055          */
1056         public void start(BundleContext context) throws Exception {
1057                 super.start(context);
1058
1059                 // JavaCore.start(this, context);
1060                 final JavaModelManager modelManager = JavaModelManager
1061                                 .getJavaModelManager();
1062                 try {
1063                         modelManager.configurePluginDebugOptions();
1064
1065                         // request state folder creation (workaround 19885)
1066                         getStateLocation();
1067                         // retrieve variable values
1068                         PHPeclipsePlugin.getDefault().getPluginPreferences()
1069                                         .addPropertyChangeListener(
1070                                                         new JavaModelManager.PluginPreferencesListener());
1071                         // manager.loadVariablesAndContainers();
1072
1073                         final IWorkspace workspace = ResourcesPlugin.getWorkspace();
1074                         workspace.addResourceChangeListener(modelManager.deltaState,
1075                                         IResourceChangeEvent.PRE_BUILD
1076                                                         | IResourceChangeEvent.POST_BUILD
1077                                                         | IResourceChangeEvent.POST_CHANGE
1078                                                         | IResourceChangeEvent.PRE_DELETE
1079                                                         | IResourceChangeEvent.PRE_CLOSE);
1080
1081                         ISavedState savedState = workspace.addSaveParticipant(
1082                                         PHPeclipsePlugin.this, modelManager);
1083
1084                         // process deltas since last activated in indexer thread so that
1085                         // indexes are up-to-date.
1086                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658
1087 // This causes timeout at EclipseLazyStarter
1088 //                      Job processSavedState = new Job(Util.bind("savedState.jobName")) { //$NON-NLS-1$
1089 //                              protected IStatus run(IProgressMonitor monitor) {
1090 //                                      try {
1091 //                                              // add save participant and process delta atomically
1092 //                                              // see
1093 //                                              // https://bugs.eclipse.org/bugs/show_bug.cgi?id=59937
1094 //                                              workspace.run(new IWorkspaceRunnable() {
1095 //                                                      public void run(IProgressMonitor progress)
1096 //                                                                      throws CoreException {
1097 //                                                              ISavedState savedState = workspace
1098 //                                                                              .addSaveParticipant(
1099 //                                                                                              PHPeclipsePlugin.this,
1100 //                                                                                              modelManager);
1101 //                                                              if (savedState != null) {
1102 //                                                                      // the event type coming from the saved
1103 //                                                                      // state is always POST_AUTO_BUILD
1104 //                                                                      // force it to be POST_CHANGE so that the
1105 //                                                                      // delta processor can handle it
1106 //                                                                      modelManager.deltaState.getDeltaProcessor().overridenEventType = IResourceChangeEvent.POST_CHANGE;
1107 //                                                                      savedState
1108 //                                                                                      .processResourceChangeEvents(modelManager.deltaState);
1109 //                                                              }
1110 //                                                      }
1111 //                                              }, monitor);
1112 //                                      } catch (CoreException e) {
1113 //                                              return e.getStatus();
1114 //                                      }
1115 //                                      return Status.OK_STATUS;
1116 //                              }
1117 //                      };
1118 // Replace Job + IWorkspace.run() to WorkspaceJob
1119                         WorkspaceJob processSavedState = new WorkspaceJob(
1120                                         Util.bind("savedState.jobName")) { //$NON-NLS-1$
1121                                 public IStatus runInWorkspace(IProgressMonitor monitor)
1122                                                 throws CoreException {
1123                                         ISavedState savedState = workspace.addSaveParticipant(
1124                                                         PHPeclipsePlugin.this, modelManager);
1125                                         if (savedState != null) {
1126                                                 modelManager.deltaState.getDeltaProcessor().overridenEventType
1127                                                                 = IResourceChangeEvent.POST_CHANGE;
1128                                                 savedState.processResourceChangeEvents(modelManager.deltaState);
1129                                         }
1130                                         return Status.OK_STATUS;
1131                                 }
1132                         };
1133                         processSavedState.setSystem(true);
1134                         processSavedState.setPriority(Job.SHORT); // process asap
1135                         processSavedState.schedule();
1136                 } catch (RuntimeException e) {
1137                         modelManager.shutdown();
1138                         throw e;
1139                 }
1140
1141                 registerAdapters();
1142
1143                 // if (USE_WORKING_COPY_OWNERS) {
1144                 WorkingCopyOwner.setPrimaryBufferProvider(new WorkingCopyOwner() {
1145                         public IBuffer createBuffer(ICompilationUnit workingCopy) {
1146                                 ICompilationUnit original = workingCopy.getPrimary();
1147                                 IResource resource = original.getResource();
1148                                 if (resource instanceof IFile)
1149                                         return new DocumentAdapter(workingCopy, (IFile) resource);
1150                                 return DocumentAdapter.NULL;
1151                         }
1152                 });
1153                 // }
1154
1155                 installPreferenceStoreBackwardsCompatibility();
1156
1157         }
1158
1159         private void registerAdapters() {
1160                 fJavaElementAdapterFactory = new JavaElementAdapterFactory();
1161                 fResourceAdapterFactory = new ResourceAdapterFactory();
1162
1163                 IAdapterManager manager = Platform.getAdapterManager();
1164                 manager
1165                                 .registerAdapters(fJavaElementAdapterFactory,
1166                                                 IJavaElement.class);
1167                 manager.registerAdapters(fResourceAdapterFactory, IResource.class);
1168         }
1169
1170         private void unregisterAdapters() {
1171                 IAdapterManager manager = Platform.getAdapterManager();
1172                 manager.unregisterAdapters(fJavaElementAdapterFactory);
1173                 manager.unregisterAdapters(fResourceAdapterFactory);
1174         }
1175
1176         /**
1177          * Returns a combined preference store, this store is read-only.
1178          * 
1179          * @return the combined preference store
1180          * 
1181          * @since 3.0
1182          */
1183         public IPreferenceStore getCombinedPreferenceStore() {
1184                 if (fCombinedPreferenceStore == null) {
1185                         IPreferenceStore generalTextStore = EditorsUI.getPreferenceStore();
1186                         fCombinedPreferenceStore = new ChainedPreferenceStore(
1187                                         new IPreferenceStore[] {
1188                                                         getPreferenceStore(),
1189                                                         new PreferencesAdapter(PHPeclipsePlugin
1190                                                                         .getDefault().getPluginPreferences()),
1191                                                         generalTextStore });
1192                 }
1193                 return fCombinedPreferenceStore;
1194         }
1195
1196         public synchronized IBufferFactory getBufferFactory() {
1197                 if (fBufferFactory == null)
1198                         fBufferFactory = new CustomBufferFactory();
1199                 return fBufferFactory;
1200         }
1201
1202         /**
1203          * Returns the registry of the extensions to the
1204          * <code>net.sourceforge.phpdt.ui.javaFoldingStructureProvider</code>
1205          * extension point.
1206          * 
1207          * @return the registry of contributed
1208          *         <code>IJavaFoldingStructureProvider</code>
1209          * @since 3.0
1210          */
1211         public synchronized JavaFoldingStructureProviderRegistry getFoldingStructureProviderRegistry() {
1212                 if (fFoldingStructureProviderRegistry == null)
1213                         fFoldingStructureProviderRegistry = new JavaFoldingStructureProviderRegistry();
1214                 return fFoldingStructureProviderRegistry;
1215         }
1216
1217         /**
1218          * Runs the given action as an atomic Java model operation.
1219          * <p>
1220          * After running a method that modifies java elements, registered listeners
1221          * receive after-the-fact notification of what just transpired, in the form
1222          * of a element changed event. This method allows clients to call a number
1223          * of methods that modify java elements and only have element changed event
1224          * notifications reported at the end of the entire batch.
1225          * </p>
1226          * <p>
1227          * If this method is called outside the dynamic scope of another such call,
1228          * this method runs the action and then reports a single element changed
1229          * event describing the net effect of all changes done to java elements by
1230          * the action.
1231          * </p>
1232          * <p>
1233          * If this method is called in the dynamic scope of another such call, this
1234          * method simply runs the action.
1235          * </p>
1236          * 
1237          * @param action
1238          *            the action to perform
1239          * @param monitor
1240          *            a progress monitor, or <code>null</code> if progress
1241          *            reporting and cancellation are not desired
1242          * @exception CoreException
1243          *                if the operation failed.
1244          * @since 2.1
1245          */
1246         public static void run(IWorkspaceRunnable action, IProgressMonitor monitor)
1247                         throws CoreException {
1248                 run(action, ResourcesPlugin.getWorkspace().getRoot(), monitor);
1249         }
1250
1251         /**
1252          * Runs the given action as an atomic Java model operation.
1253          * <p>
1254          * After running a method that modifies java elements, registered listeners
1255          * receive after-the-fact notification of what just transpired, in the form
1256          * of a element changed event. This method allows clients to call a number
1257          * of methods that modify java elements and only have element changed event
1258          * notifications reported at the end of the entire batch.
1259          * </p>
1260          * <p>
1261          * If this method is called outside the dynamic scope of another such call,
1262          * this method runs the action and then reports a single element changed
1263          * event describing the net effect of all changes done to java elements by
1264          * the action.
1265          * </p>
1266          * <p>
1267          * If this method is called in the dynamic scope of another such call, this
1268          * method simply runs the action.
1269          * </p>
1270          * <p>
1271          * The supplied scheduling rule is used to determine whether this operation
1272          * can be run simultaneously with workspace changes in other threads. See
1273          * <code>IWorkspace.run(...)</code> for more details.
1274          * </p>
1275          * 
1276          * @param action
1277          *            the action to perform
1278          * @param rule
1279          *            the scheduling rule to use when running this operation, or
1280          *            <code>null</code> if there are no scheduling restrictions
1281          *            for this operation.
1282          * @param monitor
1283          *            a progress monitor, or <code>null</code> if progress
1284          *            reporting and cancellation are not desired
1285          * @exception CoreException
1286          *                if the operation failed.
1287          * @since 3.0
1288          */
1289         public static void run(IWorkspaceRunnable action, ISchedulingRule rule,
1290                         IProgressMonitor monitor) throws CoreException {
1291                 IWorkspace workspace = ResourcesPlugin.getWorkspace();
1292                 if (workspace.isTreeLocked()) {
1293                         new BatchOperation(action).run(monitor);
1294                 } else {
1295                         // use IWorkspace.run(...) to ensure that a build will be done in
1296                         // autobuild mode
1297                         workspace.run(new BatchOperation(action), rule,
1298                                         IWorkspace.AVOID_UPDATE, monitor);
1299                 }
1300         }
1301
1302         /**
1303          * Returns the template context type registry for the java plugin.
1304          * 
1305          * @return the template context type registry for the java plugin
1306          * @since 3.0
1307          */
1308         public ContextTypeRegistry getTemplateContextRegistry() {
1309                 if (fContextTypeRegistry == null) {
1310                         fContextTypeRegistry = new ContributionContextTypeRegistry();
1311
1312                         fContextTypeRegistry.addContextType(new JavaContextType());
1313                         fContextTypeRegistry.addContextType(new JavaDocContextType());
1314                         fContextTypeRegistry.addContextType(new HTMLContextType());
1315                 }
1316
1317                 return fContextTypeRegistry;
1318         }
1319
1320         /**
1321          * Returns the template store for the java editor templates.
1322          * 
1323          * @return the template store for the java editor templates
1324          * @since 3.0
1325          */
1326         public TemplateStore getTemplateStore() {
1327                 if (fTemplateStore == null) {
1328                         fTemplateStore = new ContributionTemplateStore(
1329                                         getTemplateContextRegistry(), getPreferenceStore(),
1330                                         TEMPLATES_KEY);
1331                         try {
1332                                 fTemplateStore.load();
1333                         } catch (IOException e) {
1334                                 log(e);
1335                         }
1336                 }
1337
1338                 return fTemplateStore;
1339         }
1340
1341         /**
1342          * Returns the template context type registry for the code generation
1343          * templates.
1344          * 
1345          * @return the template context type registry for the code generation
1346          *         templates
1347          * @since 3.0
1348          */
1349         public ContextTypeRegistry getCodeTemplateContextRegistry() {
1350                 if (fCodeTemplateContextTypeRegistry == null) {
1351                         fCodeTemplateContextTypeRegistry = new ContributionContextTypeRegistry();
1352
1353                         CodeTemplateContextType
1354                                         .registerContextTypes(fCodeTemplateContextTypeRegistry);
1355                 }
1356
1357                 return fCodeTemplateContextTypeRegistry;
1358         }
1359
1360         /**
1361          * Returns the template store for the code generation templates.
1362          * 
1363          * @return the template store for the code generation templates
1364          * @since 3.0
1365          */
1366         public TemplateStore getCodeTemplateStore() {
1367                 if (fCodeTemplateStore == null) {
1368                         fCodeTemplateStore = new ContributionTemplateStore(
1369                                         getCodeTemplateContextRegistry(), getPreferenceStore(),
1370                                         CODE_TEMPLATES_KEY);
1371                         try {
1372                                 fCodeTemplateStore.load();
1373                         } catch (IOException e) {
1374                                 log(e);
1375                         }
1376                 }
1377
1378                 return fCodeTemplateStore;
1379         }
1380 }