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