KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > terracotta > dso > TcPlugin


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package org.terracotta.dso;
5
6 import org.apache.commons.io.CopyUtils;
7 import org.apache.commons.io.IOUtils;
8 import org.apache.xmlbeans.XmlError;
9 import org.apache.xmlbeans.XmlException;
10 import org.apache.xmlbeans.XmlOptions;
11 import org.dijon.DictionaryResource;
12 import org.eclipse.core.commands.common.EventManager;
13 import org.eclipse.core.resources.IFile;
14 import org.eclipse.core.resources.IMarker;
15 import org.eclipse.core.resources.IProject;
16 import org.eclipse.core.resources.IProjectDescription;
17 import org.eclipse.core.resources.IResource;
18 import org.eclipse.core.resources.IResourceChangeEvent;
19 import org.eclipse.core.resources.IResourceChangeListener;
20 import org.eclipse.core.resources.ResourcesPlugin;
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.IAdapterFactory;
23 import org.eclipse.core.runtime.IAdapterManager;
24 import org.eclipse.core.runtime.ILog;
25 import org.eclipse.core.runtime.IPath;
26 import org.eclipse.core.runtime.IProgressMonitor;
27 import org.eclipse.core.runtime.IStatus;
28 import org.eclipse.core.runtime.Path;
29 import org.eclipse.core.runtime.Platform;
30 import org.eclipse.core.runtime.QualifiedName;
31 import org.eclipse.core.runtime.Status;
32 import org.eclipse.debug.core.DebugPlugin;
33 import org.eclipse.debug.core.ILaunch;
34 import org.eclipse.debug.core.ILaunchConfigurationType;
35 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
36 import org.eclipse.debug.core.ILaunchManager;
37 import org.eclipse.jdt.core.ElementChangedEvent;
38 import org.eclipse.jdt.core.IClassFile;
39 import org.eclipse.jdt.core.ICompilationUnit;
40 import org.eclipse.jdt.core.IField;
41 import org.eclipse.jdt.core.IJavaElement;
42 import org.eclipse.jdt.core.IJavaProject;
43 import org.eclipse.jdt.core.IMethod;
44 import org.eclipse.jdt.core.IPackageFragment;
45 import org.eclipse.jdt.core.IPackageFragmentRoot;
46 import org.eclipse.jdt.core.IType;
47 import org.eclipse.jdt.core.JavaCore;
48 import org.eclipse.jdt.core.JavaModelException;
49 import org.eclipse.jdt.internal.core.BinaryMember;
50 import org.eclipse.jdt.internal.core.SourceMethod;
51 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
52 import org.eclipse.jdt.ui.JavaElementImageDescriptor;
53 import org.eclipse.jface.dialogs.MessageDialog;
54 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
55 import org.eclipse.jface.operation.IRunnableWithProgress;
56 import org.eclipse.jface.resource.ImageDescriptor;
57 import org.eclipse.jface.text.Document;
58 import org.eclipse.jface.text.FindReplaceDocumentAdapter;
59 import org.eclipse.jface.text.IDocument;
60 import org.eclipse.jface.text.IRegion;
61 import org.eclipse.jface.wizard.WizardDialog;
62 import org.eclipse.swt.graphics.Image;
63 import org.eclipse.swt.graphics.Point;
64 import org.eclipse.swt.widgets.Display;
65 import org.eclipse.swt.widgets.Shell;
66 import org.eclipse.ui.IDecoratorManager;
67 import org.eclipse.ui.IEditorPart;
68 import org.eclipse.ui.IEditorReference;
69 import org.eclipse.ui.IFileEditorInput;
70 import org.eclipse.ui.IWorkbench;
71 import org.eclipse.ui.IWorkbenchPage;
72 import org.eclipse.ui.IWorkbenchWindow;
73 import org.eclipse.ui.PartInitException;
74 import org.eclipse.ui.PlatformUI;
75 import org.eclipse.ui.ide.IDE;
76 import org.eclipse.ui.part.FileEditorInput;
77 import org.eclipse.ui.plugin.AbstractUIPlugin;
78 import org.eclipse.ui.texteditor.MarkerUtilities;
79 import org.osgi.framework.BundleContext;
80 import org.terracotta.dso.actions.ActionUtil;
81 import org.terracotta.dso.actions.IProjectAction;
82 import org.terracotta.dso.decorator.AdaptedModuleDecorator;
83 import org.terracotta.dso.decorator.AdaptedPackageFragmentDecorator;
84 import org.terracotta.dso.decorator.AdaptedTypeDecorator;
85 import org.terracotta.dso.decorator.AutolockedDecorator;
86 import org.terracotta.dso.decorator.ConfigFileDecorator;
87 import org.terracotta.dso.decorator.DistributedMethodDecorator;
88 import org.terracotta.dso.decorator.ExcludedModuleDecorator;
89 import org.terracotta.dso.decorator.ExcludedTypeDecorator;
90 import org.terracotta.dso.decorator.NameLockedDecorator;
91 import org.terracotta.dso.decorator.RootDecorator;
92 import org.terracotta.dso.decorator.ServerRunningDecorator;
93 import org.terracotta.dso.decorator.TransientDecorator;
94 import org.terracotta.dso.editors.ConfigurationEditor;
95 import org.terracotta.dso.wizards.ProjectWizard;
96
97 import com.tc.admin.common.InputStreamDrainer;
98 import com.tc.config.Loader;
99 import com.terracottatech.config.Server;
100 import com.terracottatech.config.Servers;
101 import com.terracottatech.config.TcConfigDocument;
102 import com.terracottatech.config.TcConfigDocument.TcConfig;
103
104 import java.io.ByteArrayInputStream JavaDoc;
105 import java.io.File JavaDoc;
106 import java.io.FileInputStream JavaDoc;
107 import java.io.FileOutputStream JavaDoc;
108 import java.io.FileWriter JavaDoc;
109 import java.io.IOException JavaDoc;
110 import java.io.InputStream JavaDoc;
111 import java.io.ObjectInputStream JavaDoc;
112 import java.io.ObjectOutputStream JavaDoc;
113 import java.io.StringReader JavaDoc;
114 import java.lang.reflect.InvocationTargetException JavaDoc;
115 import java.net.URL JavaDoc;
116 import java.util.ArrayList JavaDoc;
117 import java.util.ConcurrentModificationException JavaDoc;
118 import java.util.HashMap JavaDoc;
119 import java.util.Iterator JavaDoc;
120 import java.util.List JavaDoc;
121
122 import javax.swing.SwingUtilities JavaDoc;
123 import javax.swing.UIManager JavaDoc;
124
125 /**
126  * The Terracotta plugin. The whole enchilada centers around this singleton.
127  *
128  * The primary duties of this class are to manage the configuration information
129  * associated with a Terracotta Eclipse project.
130  *
131  * Configuration information is stored as session properties in the project, which
132  * are not persistent across sessions. The config information is made up of:
133  *
134  * 1) the config file XML document
135  * 2) the parsed form of the XML document, aka the config object
136  * 3) the line length information of the config document
137  * 3) a configuration helper, used by various popup actions
138  *
139  * After successfully parsing the config document, items 1-3 above are
140  * serialized to the plugin's private working area. Subsequent lookups are
141  * first attempted on the serialized form. When the config data changes, the
142  * serialized form is cleared.
143  * @see loadConfiguration(IProject)
144  *
145  * When there are errors instantiating the config document, those XmlErrors are
146  * turned into SAXMarkers on the document, which appear as error indicators in
147  * the config document editor.
148  * @see handleXmlErrors(IFile, LineLengths, Iterator)
149  *
150  * At times, it is necessary to inspect a module to determine where to add
151  * annotations denoting configuration-related Java elements, such as a particular
152  * method being locked.
153  * @see inspect(ICompilationUnit).
154  *
155  * Another responsibility of this class is to launch the server using the config
156  * information, additional boot jar, etc.
157  * @see launchServer(IJavaProject, String, String, String)
158  *
159  * Finally, this class provides methods for updating the annotations used to indicate
160  * various states related to the config information, such as a field being a root.
161  * @see updateDecorators()
162  *
163  * @see org.eclipse.ui.plugin.AbstractUIPlugin
164  * @see com.terracottatech.config.TerracottaDomainConfigurationDocument
165  * @see com.terracottatech.config.TerracottaDomainConfigurationDocument.TerracottaDomainConfiguration
166  */

167
168 public class TcPlugin extends AbstractUIPlugin
169   implements QualifiedNames,
170              IJavaLaunchConfigurationConstants,
171              TcPluginStatusConstants
172 {
173   private static TcPlugin m_plugin;
174   private DictionaryResource m_topRes;
175   private Loader m_configLoader;
176   private CompilationUnitVisitor m_compilationUnitVisitor;
177   private ResourceListener m_resourceListener;
178   private ResourceDeltaVisitor m_resourceDeltaVisitor;
179   private XmlOptions m_xmlOptions;
180   private DecoratorUpdateAction m_decoratorUpdateAction;
181   private ArrayList JavaDoc<IProjectAction> m_projectActionList;
182   private BootClassHelper m_bootClassHelper;
183   
184   public static final String JavaDoc PLUGIN_ID = "org.terracotta.dso";
185   private static final String JavaDoc RESOURCE_FILE = "Resources.xml";
186   
187   public static final String JavaDoc DEFAULT_CONFIG_FILENAME = "tc-config.xml";
188   public static final String JavaDoc DEFAULT_SERVER_OPTIONS = "-Xms256m -Xmx256m";
189   
190   public TcPlugin() {
191     super();
192   }
193
194   public static String JavaDoc getPluginId() {
195     return PLUGIN_ID;
196   }
197
198   public BootClassHelper getBootClassHelper() {
199     return m_bootClassHelper;
200   }
201   
202   public boolean isBootClass(final ICompilationUnit module) {
203     if(m_bootClassHelper != null) {
204       return module != null ? isBootClass(module.findPrimaryType()) : false;
205     }
206     return false;
207   }
208   
209   public boolean isBootClass(final IClassFile classFile) {
210     if(m_bootClassHelper != null && classFile != null) {
211       try {
212         return isBootClass(classFile.getType());
213       } catch(JavaModelException jme) {/**/}
214     }
215     return false;
216   }
217   
218   public boolean isBootClass(final IType type) {
219     if(m_bootClassHelper != null && type != null) {
220       return isBootClass(PatternHelper.getFullyQualifiedName(type));
221     }
222     return false;
223   }
224   
225   public boolean isBootClass(String JavaDoc name) {
226     return m_bootClassHelper != null ? m_bootClassHelper.isAdaptable(name) : false;
227   }
228   
229   public void registerProjectAction(IProjectAction action) {
230     if(action != null) {
231       m_projectActionList.add(action);
232     }
233   }
234   
235   public void notifyProjectActions(IProject project) {
236     Iterator JavaDoc iter = m_projectActionList.iterator();
237     
238     while(iter.hasNext()) {
239       ((IProjectAction)iter.next()).update(project);
240     }
241   }
242   
243   private void addResourceChangeListener() {
244     ResourcesPlugin.getWorkspace().addResourceChangeListener(
245       m_resourceListener,
246       IResourceChangeEvent.POST_BUILD);
247   }
248   
249   private IPath m_location;
250   
251   public IPath getLocation() {
252     return m_location;
253   }
254
255   public IPath getLibDirPath() {
256     return getLocation().append("lib");
257   }
258   
259   public void start(BundleContext context) throws Exception JavaDoc {
260     super.start(context);
261
262     m_plugin = this;
263     m_configLoader = new Loader();
264     
265     // TODO: after we remove 3.1 support, change to FileLocator.resolve
266
URL JavaDoc url = Platform.resolve(context.getBundle().getEntry("/"));
267     m_location = new Path(url.getPath()).removeTrailingSeparator();
268
269     try {
270       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
271     } catch(Exception JavaDoc e) {
272       /**/
273     }
274     
275     InputStream JavaDoc is = null;
276     try {
277       is = getClass().getResourceAsStream(RESOURCE_FILE);
278       m_topRes = DictionaryResource.load(is);
279       is = null;
280     } catch(Exception JavaDoc e) {
281       throw new RuntimeException JavaDoc("Error loading resource file '"+RESOURCE_FILE+"'", e);
282     } finally {
283       if(is != null) {
284         IOUtils.closeQuietly(is);
285       }
286     }
287
288     JavaCore.addElementChangedListener(
289       new ElementChangedListener(),
290       ElementChangedEvent.POST_RECONCILE);
291     
292     m_resourceListener = new ResourceListener();
293     addResourceChangeListener();
294     
295     IPath tcInstallPath = getLocation();
296     if(tcInstallPath != null) {
297       System.setProperty("tc.install", tcInstallPath.toString());
298     }
299     
300     m_xmlOptions = createXmlOptions();
301     m_projectActionList = new ArrayList JavaDoc<IProjectAction>();
302     
303     IAdapterManager manager = Platform.getAdapterManager();
304     IAdapterFactory factory = new JavaElementAdapter();
305     manager.registerAdapters(factory, IField.class);
306     manager.registerAdapters(factory, IType.class);
307     manager.registerAdapters(factory, IMethod.class);
308     manager.registerAdapters(factory, IClassFile.class);
309
310     // TODO: REMOVE the following when 3.1 is no longer supported
311
// SourceMethod and BinaryMember are internal types
312
manager.registerAdapters(factory, SourceMethod.class);
313     manager.registerAdapters(factory, BinaryMember.class);
314     
315     try {
316       m_bootClassHelper = BootClassHelper.initialize();
317     } catch(Exception JavaDoc e) {
318       buildBootJarForThisVM();
319     }
320   }
321
322   private void buildBootJarForThisVM() {
323     new Thread JavaDoc() {
324       public void run() {
325         try {
326           IPath tcJarPath = TcPlugin.getDefault().getLibDirPath().append("tc.jar");
327           File bootJarFile = BootJarHelper.getHelper().getBootJarFileForThisVM();
328     
329           System.setProperty("tc.install-root", getLocation().toOSString());
330           
331           String JavaDoc[] args = {System.getProperty("eclipse.vm"),
332                            "-cp",
333                            tcJarPath.toOSString(),
334                            "com.tc.object.tools.BootJarTool",
335                            "-q",
336                            "-o",
337                            bootJarFile.getAbsolutePath()};
338     
339           Process JavaDoc p = Runtime.getRuntime().exec(args);
340           
341           InputStreamDrainer outReader = new InputStreamDrainer(p.getInputStream());
342           InputStreamDrainer errReader = new InputStreamDrainer(p.getErrorStream());
343           
344           outReader.start();
345           errReader.start();
346           
347           while(true) {
348             try {
349               p.waitFor();
350               break;
351             } catch(InterruptedException JavaDoc ie) {/**/}
352             
353             try {Thread.sleep(1000);} catch(InterruptedException JavaDoc ie) {/**/}
354           }
355     
356           m_bootClassHelper = BootClassHelper.initialize();
357         } catch(Throwable JavaDoc t) {
358           openError("Plugin Initialization Error", t);
359         }
360       }
361     }.start();
362   }
363   
364   public void stop(BundleContext context) throws Exception JavaDoc {
365     ServerTracker.getDefault().shutdownAllServers();
366     super.stop(context);
367     m_plugin = null;
368   }
369
370   public static TcPlugin getDefault() {
371     if(m_plugin == null) {
372       new TcPlugin();
373     }
374     return m_plugin;
375   }
376
377   public DictionaryResource getResources() {
378     return m_topRes;
379   }
380
381   public void setup(IProject project, String JavaDoc configFilePath, String JavaDoc serverOpts) {
382     clearConfigurationSessionProperties(project);
383     setConfigurationFilePath(project, configFilePath);
384     setPersistentProperty(project, SERVER_OPTIONS, serverOpts);
385     reloadConfiguration(project);
386   }
387
388   public void addTerracottaNature(IJavaProject currentProject) {
389     IWorkbench workbench = PlatformUI.getWorkbench();
390     IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
391     Shell shell = window != null ? window.getShell() : null;
392
393     try {
394       ProjectWizard wizard = new ProjectWizard(currentProject);
395       WizardDialog dialog = new WizardDialog(shell, wizard);
396   
397       wizard.setWindowTitle("Terracotta Project Wizard");
398       dialog.open();
399     }
400     catch(Exception JavaDoc e) {
401       MessageDialog.openInformation(
402         shell,
403         "Terracotta",
404         "Cannot add Terracotta nature:\n" +
405         ActionUtil.getStatusMessages(e));
406     }
407     finally {
408       if(shell != null) shell.setCursor(null);
409     }
410   }
411
412   public void removeTerracottaNature(IJavaProject javaProject) {
413     IWorkbench workbench = PlatformUI.getWorkbench();
414     IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
415     Shell shell = window != null ? window.getShell() : null;
416
417     try {
418       IRunnableWithProgress op = new TCNatureRemover(javaProject);
419       new ProgressMonitorDialog(shell).run(false, false, op);
420     } catch(InvocationTargetException JavaDoc e) {
421       openError("Cannot remove Terracotta nature", e.getCause());
422     } catch(InterruptedException JavaDoc e) {/**/}
423   }
424
425   class TCNatureRemover implements IRunnableWithProgress {
426     IJavaProject m_javaProject;
427     
428     TCNatureRemover(IJavaProject javaProject) {
429       m_javaProject = javaProject;
430     }
431     
432     public void run(IProgressMonitor monitor)
433       throws InvocationTargetException JavaDoc
434     {
435       try {
436         monitor.beginTask("Removing project nature", 4);
437         IProject project = m_javaProject.getProject();
438         IProjectDescription description = project.getDescription();
439         String JavaDoc[] natures = description.getNatureIds();
440         ArrayList JavaDoc<String JavaDoc> natureList = new ArrayList JavaDoc<String JavaDoc>();
441         
442         for(int i = 0; i < natures.length; i++) {
443           if(!natures[i].equals(ProjectNature.NATURE_ID)) {
444             natureList.add(natures[i]);
445           }
446         }
447         description.setNatureIds(natureList.toArray(new String JavaDoc[0]));
448         project.setDescription(description, monitor);
449         project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
450         monitor.worked(1);
451         
452         monitor.beginTask("Closing configuration editor", 4);
453         closeConfigurationEditor(project);
454         monitor.worked(2);
455         
456         monitor.beginTask("Stopping server", 4);
457         final ServerTracker tracker = ServerTracker.getDefault();
458         if(tracker.anyRunning(m_javaProject)) {
459           Display.getDefault().syncExec(new Runnable JavaDoc() {
460             public void run() {
461               tracker.shutdownAllServers();
462             }
463           });
464         }
465         monitor.worked(3);
466         
467         monitor.beginTask("Removing markers", 4);
468         IPackageFragment[] fragments = m_javaProject.getPackageFragments();
469         ICompilationUnit[] cus;
470         IResource file;
471         
472         for(int i = 0; i < fragments.length; i++) {
473           if(fragments[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
474             cus = fragments[i].getCompilationUnits();
475             
476             for(int j = 0; j < cus.length; j++) {
477               file = cus[j].getResource();
478               monitor.subTask(file.getLocation().toString());
479               file.deleteMarkers("org.terracotta.dso.baseMarker", true, IResource.DEPTH_ZERO);
480             }
481           }
482         }
483         
484         IFile configFile = getConfigurationFile(m_javaProject.getProject());
485         if(configFile != null && configFile.exists()) {
486           clearSAXMarkers(configFile);
487         }
488         
489         clearConfigProblemMarkers(project);
490         clearConfigurationSessionProperties(project);
491         notifyProjectActions(project);
492         updateDecorators();
493         fireConfigurationChange(project);
494         
495         monitor.worked(4);
496       } catch(CoreException e) {
497         throw new InvocationTargetException JavaDoc(e);
498       }
499     }
500   }
501   
502   public ILaunch launchServer(IJavaProject javaProject, String JavaDoc projectName, String JavaDoc serverName)
503     throws CoreException
504   {
505     IProject project = javaProject.getProject();
506     ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
507     String JavaDoc id = ID_JAVA_APPLICATION;
508     ILaunchConfigurationType type = manager.getLaunchConfigurationType(id);
509     String JavaDoc installPath = getLocation().makeAbsolute().toOSString();
510     
511     ILaunchConfigurationWorkingCopy wc = type.newInstance(null, projectName+"."+serverName);
512         
513     wc.setAttribute(ATTR_PROJECT_NAME, project.getName());
514     wc.setAttribute(ATTR_MAIN_TYPE_NAME, "com.tc.server.TCServerMain");
515       
516     IFile configFile = getConfigurationFile(project);
517     
518     if(configFile != null) {
519       String JavaDoc configPath = configFile.getLocation().toOSString();
520       String JavaDoc vmargs = " -Dtc.install-root=\""+installPath+"\""+
521                           " -Dtc.config=\""+configPath+"\""+
522                           " -Dtc.server.name=\""+serverName+"\""+
523                           " -Dcom.sun.management.jmxremote"+
524                           " -Dcom.sun.management.jmxremote.authenticate=false";
525       String JavaDoc origVMArgs = wc.getAttribute(ATTR_VM_ARGUMENTS, "") + " " + getServerOptions(project) + " ";
526       
527       wc.setAttribute(ATTR_VM_ARGUMENTS, vmargs + origVMArgs);
528       wc.setAttribute(ATTR_CLASSPATH_PROVIDER, "org.terracotta.dso.classpathProvider");
529       wc.setAttribute(ATTR_WORKING_DIRECTORY,
530                       project.getLocation().append("terracotta").makeAbsolute().toOSString());
531       
532       return wc.launch(ILaunchManager.DEBUG_MODE, null);
533     }
534     else {
535       System.out.println("No config file specified. Set in project properties");
536       return null;
537     }
538   }
539   
540   public String JavaDoc getAnyServerName(IProject project) {
541     TcConfig config = getConfiguration(project);
542     
543     if(config != null) {
544       Servers servers = config.getServers();
545       
546       if(servers != null) {
547         Server[] serverArr = servers.getServerArray();
548         
549         for(int i = 0; i < serverArr.length; i++) {
550           String JavaDoc name = serverArr[i].getName();
551           
552           if(name != null && name.length() > 0) {
553             return name;
554           }
555         }
556       }
557     }
558
559     return "default";
560   }
561   
562   public int getJmxPort(IProject project, String JavaDoc name) {
563     TcConfig config = getConfiguration(project);
564     
565     if(config != null) {
566       Servers servers = config.getServers();
567       
568       if(servers != null) {
569         Server[] serverArr = servers.getServerArray();
570         Server server;
571         
572         for(int i = 0; i < serverArr.length; i++) {
573           server = serverArr[i];
574           
575           if(name.equals(server.getName())) {
576             return server.getJmxPort();
577           }
578         }
579       }
580     }
581
582     return -1;
583   }
584
585   private File getSerializedFile(IFile file) {
586     File result = getStateLocation().append(file.getLocation()).toFile();
587     
588     if(!result.exists()) {
589       result.getParentFile().mkdirs();
590     }
591     
592     return result;
593   }
594
595   /**
596    * Returns the file to which the config document, config object, and
597    * line lengths are serialized. This file lives in the plugin's private
598    * working area.
599    */

600   private File getSerializedConfigFile(IProject project) {
601     IFile configFile = getConfigurationFile(project);
602     return configFile != null ? getSerializedFile(configFile) : null;
603   }
604   
605   private void clearSerializedFile(IFile file) {
606     File serialFile = getSerializedFile(file);
607     
608     if(serialFile.exists()) {
609       serialFile.delete();
610     }
611   }
612   
613   /**
614    * Remove the serialized form of the config information.
615    */

616   private void clearSerializedConfigFile(IProject project) {
617     IFile configFile = getConfigurationFile(project);
618     
619     if(configFile != null && configFile.exists()) {
620       clearSerializedFile(configFile);
621     }
622   }
623   
624   private void moveSerializedFile(IFile fromFile, IFile toFile) {
625     getSerializedFile(fromFile).renameTo(getSerializedFile(toFile));
626   }
627   
628   /**
629    * Test for the existance of, and load, the serialized form our the config
630    * information. Both the config and the LineLengths objects are stored under
631    * the name of the config file in the plugin working area, federated by the project
632    * name.
633    */

634   private boolean testLoadSerializedConfigFile(IProject project) {
635     LineLengths lineLengths;
636     TcConfig config;
637     
638     File serialFile = getSerializedConfigFile(project);
639     IFile configFile = getConfigurationFile(project);
640     
641     if(serialFile != null &&
642        configFile != null &&
643        serialFile.exists() &&
644       (serialFile.lastModified() > configFile.getLocalTimeStamp()))
645     {
646       ObjectInputStream JavaDoc ois = null;
647       
648       try {
649         ois = new ObjectInputStream JavaDoc(new FileInputStream JavaDoc(serialFile));
650         lineLengths = (LineLengths)ois.readObject();
651         config = (TcConfig)ois.readObject();
652         
653         ois.close();
654         ois = null;
655         
656         setSessionProperty(project, CONFIGURATION_LINE_LENGTHS, lineLengths);
657         setSessionProperty(project, CONFIGURATION, config);
658         
659         return true;
660       } catch(Exception JavaDoc e) {
661         clearSerializedConfigFile(project);
662       } finally {
663         if(ois != null) {
664           IOUtils.closeQuietly(ois);
665         }
666       }
667     }
668     
669     return false;
670   }
671
672   /**
673    * Serialize out the config information to the plugin's private work area.
674    */

675   private void writeSerializedConfigFile(
676     IProject project,
677     LineLengths lineLengths,
678     TcConfig config)
679   {
680     File file = getSerializedConfigFile(project);
681     ObjectOutputStream JavaDoc oos = null;
682     
683     try {
684       oos = new ObjectOutputStream JavaDoc(new FileOutputStream JavaDoc(file));
685
686       oos.writeObject(lineLengths);
687       oos.writeObject(config);
688       
689       oos.close();
690       oos = null;
691     } catch(Exception JavaDoc e) {
692       clearSerializedConfigFile(project);
693     } finally {
694       if(oos != null) {
695         IOUtils.closeQuietly(oos);
696       }
697     }
698   }
699   
700   /**
701    * Instantiate the config information, either from the serialized form, or
702    * directly from the config document.
703    */

704   private void loadConfiguration(IProject project)
705     throws XmlException,
706            IOException JavaDoc,
707            CoreException,
708            ConcurrentModificationException JavaDoc
709   {
710     if(!project.isOpen()) {
711       return;
712     }
713     
714     IFile configFile = getConfigurationFile(project);
715
716     if(configFile != null) {
717       IPath path = configFile.getLocation();
718       File file = path.toFile();
719       List JavaDoc errors = new ArrayList JavaDoc();
720       boolean refreshed = false;
721       
722       if(!configFile.isSynchronized(IResource.DEPTH_ZERO)) {
723         configFile.refreshLocal(IResource.DEPTH_ZERO, null);
724         refreshed = true;
725       }
726       
727       LineLengths lineLengths = new LineLengths(configFile);
728       setSessionProperty(project, CONFIGURATION_LINE_LENGTHS, lineLengths);
729     
730       if(m_configLoader.testIsOld(file)) {
731         m_configLoader.updateToCurrent(file);
732       }
733       
734       if(!refreshed && testLoadSerializedConfigFile(project)) {
735         return;
736       }
737       
738       clearSAXMarkers(configFile);
739       
740       // The following line may throw XmlException if the doc is not well-formed.
741
// That's why LineLengths are setup earlier, they are used by the catching
742
// block to apply SAXMarkers to the config IFile. Otherwise, it's done
743
// below.
744

745       TcConfigDocument doc;
746       TcConfig config;
747       
748       doc = m_configLoader.parse(file, m_xmlOptions);
749       config = doc.getTcConfig();
750       
751       m_xmlOptions.setErrorListener(errors);
752       if(!doc.validate(m_xmlOptions)) {
753         handleXmlErrors(configFile, lineLengths, errors.iterator());
754       }
755       m_xmlOptions.setErrorListener(null);
756       
757       setSessionProperty(project, CONFIGURATION, config);
758   
759       if(config != null) {
760         getConfigurationHelper(project).validateAll();
761         JavaSetupParticipant.inspectAll();
762         updateDecorators();
763         fireConfigurationChange(project);
764         writeSerializedConfigFile(project, lineLengths, config);
765       }
766     }
767   }
768
769   /**
770    * Instantiate the config information from the passed-in text.
771    */

772   private void loadConfiguration(IProject project, String JavaDoc xmlText)
773     throws XmlException,
774            ConcurrentModificationException JavaDoc,
775            IOException JavaDoc
776   {
777     IFile configFile = getConfigurationFile(project);
778     
779     if(configFile != null) {
780       List JavaDoc errors = new ArrayList JavaDoc();
781   
782       LineLengths lineLengths = new LineLengths(new StringReader JavaDoc(xmlText));
783       setSessionProperty(project, CONFIGURATION_LINE_LENGTHS, lineLengths);
784   
785       clearSAXMarkers(configFile);
786     
787       // The following line may throw XmlException if the doc is not well-formed.
788
// That's why LineLengths are setup earlier, they are used by the catching
789
// block to apply SAXMarkers to the config IFile. Otherwise, it's done
790
// below.
791

792       TcConfigDocument doc;
793       TcConfig config;
794   
795       doc = m_configLoader.parse(xmlText, m_xmlOptions);
796       config = doc.getTcConfig();
797     
798       m_xmlOptions.setErrorListener(errors);
799       if(!doc.validate(m_xmlOptions)) {
800         handleXmlErrors(configFile, lineLengths, errors.iterator());
801       }
802       m_xmlOptions.setErrorListener(null);
803     
804       setSessionProperty(project, CONFIGURATION, config);
805   
806       if(config != null) {
807         getConfigurationHelper(project).validateAll();
808         JavaSetupParticipant.inspectAll();
809         updateDecorators();
810         fireConfigurationChange(project);
811         writeSerializedConfigFile(project, lineLengths, config);
812       }
813     }
814   }
815
816   public void fileMoved(IFile file, IPath movedFromPath) {
817     IProject project = file.getProject();
818     IPath path = file.getProjectRelativePath();
819     String JavaDoc extension = path.getFileExtension();
820     IPath fromPath = movedFromPath.removeFirstSegments(1);
821     
822     if(extension.equals("xml")) {
823       String JavaDoc configPath = getConfigurationFilePath(project);
824       
825       if(fromPath.toString().equals(configPath)) {
826         setConfigurationFilePath(project, path.toString());
827         moveSerializedFile(project.getFile(fromPath), file);
828       }
829     }
830   }
831
832   public void replaceConfigText(IProject project, String JavaDoc oldText, String JavaDoc newText) {
833     ConfigurationEditor editor = getConfigurationEditor(project);
834     IDocument doc;
835     
836     if(editor != null) {
837       doc = editor.getDocument();
838     }
839     else {
840       try {
841         IFile configFile = getConfigurationFile(project);
842         String JavaDoc content = IOUtils.toString(configFile.getContents());
843       
844         doc = new Document(content);
845       } catch(Exception JavaDoc e) {
846         openError("Problem handling refactor", e);
847         return;
848       }
849     }
850     
851     FindReplaceDocumentAdapter finder = new FindReplaceDocumentAdapter(doc);
852     int offset = 0;
853     IRegion region;
854     
855     try {
856       while((region = finder.find(offset, "\\Q"+oldText+"\\E", true, true, true, false)) != null) {
857         region = finder.replace(newText, false);
858         offset = region.getOffset()+region.getLength();
859       }
860       
861       IFile configFile = getConfigurationFile(project);
862       InputStream JavaDoc stream = new ByteArrayInputStream JavaDoc(doc.get().getBytes());
863
864       configFile.setContents(stream, true, true, null);
865       JavaSetupParticipant.inspectAll();
866     } catch(Exception JavaDoc e) {
867       openError("Problem handling refactor", e);
868       return;
869     }
870   }
871   
872   /**
873    * Called when a new project is created and it has a leftover Terracotta
874    * nature. This can happen because it doesn't appear to be possible to
875    * do anything useful with IResourceChangeEvent.PRE_DELETE because the
876    * workspace is locked then... and after, the project doesn't exists
877    * anymore.
878    */

879   public void staleProjectAdded(IProject project) {
880     try {
881       IProjectDescription description = project.getDescription();
882       String JavaDoc[] natures = description.getNatureIds();
883       String JavaDoc[] newNatures = new String JavaDoc[natures.length - 1];
884       
885       for(int i = 0; i < natures.length; i++) {
886         if(!natures[i].equals(ProjectNature.NATURE_ID)) {
887           newNatures[i] = natures[i];
888         }
889       }
890       description.setNatureIds(newNatures);
891       project.setDescription(description, null);
892       updateDecorator("org.terracotta.dso.projectDecorator");
893     } catch(CoreException ce) {
894       ce.printStackTrace();
895     }
896   }
897   
898   public void fileRemoved(IFile file) {
899     IPath path = file.getProjectRelativePath();
900     String JavaDoc extension = path.getFileExtension();
901     
902     if(extension.equals("java")) {
903       clearSerializedFile(file);
904       getConfigurationHelper(file.getProject()).validateAll();
905     }
906     else if(extension.equals("xml")) {
907       final IProject project = file.getProject();
908       IFile configFile = getConfigurationFile(project);
909       
910       if(file.equals(configFile)) {
911         Display.getDefault().asyncExec(new Runnable JavaDoc() {
912           public void run() {
913             removeTerracottaNature(JavaCore.create(project));
914           }
915         });
916       }
917     }
918   }
919   
920   /**
921    * Sets the new config information from the passed-in text. This is invoked
922    * by the ConfigurationEditor after the user modifies its contents manually.
923    */

924   public void setConfigurationFromString(IProject project, String JavaDoc xmlText)
925     throws IOException JavaDoc
926   {
927     TcConfig config = null;
928     
929     try {
930       loadConfiguration(project, xmlText);
931       config = (TcConfig)getSessionProperty(project, CONFIGURATION);
932     } catch(XmlException e) {
933       LineLengths lineLengths = getConfigurationLineLengths(project);
934       handleXmlException(getConfigurationFile(project), lineLengths, e);
935     }
936
937     if(config == null) {
938       config = BAD_CONFIG;
939       setSessionProperty(project, CONFIGURATION, config);
940       JavaSetupParticipant.inspectAll();
941       updateDecorators();
942       fireConfigurationChange(project);
943     }
944   }
945   
946   /**
947    * Return the config document's line length information, which might not exist.
948    */

949   public LineLengths getConfigurationLineLengths(IProject project) {
950     return (LineLengths)
951       getSessionProperty(project, CONFIGURATION_LINE_LENGTHS);
952   }
953
954   public ConfigurationHelper getConfigurationHelper(IProject project) {
955     ConfigurationHelper helper = (ConfigurationHelper)
956       getSessionProperty(project, CONFIGURATION_HELPER);
957     
958     if(helper == null) {
959       helper = new ConfigurationHelper(project);
960     }
961     
962     return helper;
963   }
964
965   public static final TcConfig BAD_CONFIG = ProjectWizard.createTemplateConfigDoc().getTcConfig();
966   
967   public synchronized TcConfig getConfiguration(IProject project) {
968     TcConfig config = (TcConfig)getSessionProperty(project, CONFIGURATION);
969     
970     if(config == null) {
971       try {
972         loadConfiguration(project);
973         config = (TcConfig)getSessionProperty(project, CONFIGURATION);
974       } catch(XmlException e) {
975         LineLengths lineLengths = getConfigurationLineLengths(project);
976         handleXmlException(getConfigurationFile(project), lineLengths, e);
977       } catch(Exception JavaDoc e) {
978         /**/
979       } catch(NoClassDefFoundError JavaDoc noClassDef) {
980         noClassDef.printStackTrace();
981       }
982
983       if(config == null) {
984         config = BAD_CONFIG;
985         setSessionProperty(project, CONFIGURATION, config);
986         JavaSetupParticipant.inspectAll();
987         updateDecorators();
988         fireConfigurationChange(project);
989       }
990     }
991     
992     return config;
993   }
994   
995   public void handleXmlException(
996     IFile configFile,
997     LineLengths lineLengths,
998     XmlException e)
999   {
1000    if(configFile != null) {
1001      handleXmlErrors(configFile, lineLengths, e.getErrors().iterator());
1002    }
1003  }
1004
1005  public void handleXmlErrors(
1006    IFile configFile,
1007    LineLengths lineLengths,
1008    Iterator JavaDoc errors)
1009  {
1010    try {
1011      XmlError error;
1012        
1013      while(errors.hasNext()) {
1014        error = (XmlError)errors.next();
1015
1016        HashMap JavaDoc<String JavaDoc, Object JavaDoc> map = new HashMap JavaDoc<String JavaDoc, Object JavaDoc>();
1017        int line = error.getLine();
1018        int col = error.getColumn();
1019        String JavaDoc msg = error.getMessage();
1020        int severity = XmlError2IMarkerSeverity(error.getSeverity());
1021        int start = lineLengths.offset(line-1);
1022        int end = start + ((col == -1) ? lineLengths.lineSize(line-1) : col);
1023        
1024        MarkerUtilities.setMessage(map, msg);
1025        MarkerUtilities.setLineNumber(map, line);
1026        MarkerUtilities.setCharStart(map, start);
1027        MarkerUtilities.setCharEnd(map, end);
1028          
1029        map.put(IMarker.PRIORITY, new Integer JavaDoc(IMarker.PRIORITY_HIGH));
1030        map.put(IMarker.SEVERITY, new Integer JavaDoc(severity));
1031        map.put(IMarker.LOCATION, "line " + line);
1032            
1033        MarkerUtilities.createMarker(configFile, map, "org.terracotta.dso.SAXMarker");
1034      }
1035    } catch(CoreException ce) {
1036      openError("Error handling XML error", ce);
1037    }
1038  }
1039    
1040  private int XmlError2IMarkerSeverity(int severity) {
1041    switch(severity) {
1042      case XmlError.SEVERITY_ERROR: return IMarker.SEVERITY_ERROR;
1043      case XmlError.SEVERITY_INFO: return IMarker.SEVERITY_INFO;
1044      case XmlError.SEVERITY_WARNING: return IMarker.SEVERITY_WARNING;
1045      default: return IMarker.SEVERITY_INFO;
1046    }
1047  }
1048
1049  ConfigurationEditor[] getConfigurationEditors(IProject project) {
1050    ArrayList JavaDoc<ConfigurationEditor> list = new ArrayList JavaDoc<ConfigurationEditor>();
1051    IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
1052    
1053    for(int i = 0; i < windows.length; i++) {
1054      IWorkbenchPage[] pages = windows[i].getPages();
1055      
1056      for(int j = 0; j < pages.length; j++) {
1057        IEditorReference[] editorRefs = pages[j].getEditorReferences();
1058        
1059        for(int k = 0; k < editorRefs.length; k++) {
1060          IEditorPart editorPart = editorRefs[k].getEditor(false);
1061          
1062          if(editorPart != null) {
1063            if(editorPart instanceof ConfigurationEditor) {
1064              ConfigurationEditor configEditor = (ConfigurationEditor)editorPart;
1065              IFile file = ((IFileEditorInput)editorPart.getEditorInput()).getFile();
1066              
1067              if(file.getProject().equals(project)) {
1068                list.add(configEditor);
1069              }
1070            }
1071          }
1072        }
1073      }
1074    }
1075    return list.toArray(new ConfigurationEditor[0]);
1076  }
1077  
1078  public void reloadConfiguration(IProject project) {
1079    clearConfigurationSessionProperties(project);
1080    getConfiguration(project);
1081    
1082    ConfigurationEditor[] configEditors = getConfigurationEditors(project);
1083    for(int i = 0; i < configEditors.length; i++) {
1084      IFileEditorInput fileEditorInput = (IFileEditorInput)configEditors[i].getEditorInput();
1085      IFile file = fileEditorInput.getFile();
1086      
1087      configEditors[i].newInputFile(file);
1088    }
1089  }
1090  
1091  public synchronized void clearConfigurationSessionProperties(
1092    IProject project)
1093  {
1094    IFile file = getConfigurationFile(project);
1095    if(file != null && file.exists()) {
1096      setSessionProperty(file, ACTIVE_CONFIGURATION_FILE, null);
1097    }
1098    
1099    setSessionProperty(project, CONFIGURATION_LINE_LENGTHS, null);
1100    setSessionProperty(project, CONFIGURATION_FILE, null);
1101    setSessionProperty(project, CONFIGURATION, null);
1102
1103    clearSerializedConfigFile(project);
1104    
1105    setConfigurationFileDirty(project, Boolean.FALSE);
1106  }
1107
1108  public void setConfigurationFileDirty(
1109    IProject project,
1110    Boolean JavaDoc dirty)
1111  {
1112    setSessionProperty(project, IS_DIRTY, dirty);
1113  }
1114
1115  public boolean isConfigurationFileDirty(IProject project) {
1116    if(project.isOpen()) {
1117      Boolean JavaDoc dirty = (Boolean JavaDoc)getSessionProperty(project, IS_DIRTY);
1118      return dirty != null ? dirty.booleanValue() : false;
1119    }
1120    return false;
1121  }
1122
1123  public void saveConfiguration(IProject project) {
1124    IFile configFile;
1125    TcConfig config;
1126    TcConfigDocument configDoc;
1127    XmlOptions opts;
1128    InputStream JavaDoc stream;
1129    
1130    opts = getXmlOptions();
1131    configFile = getConfigurationFile(project);
1132    config = getConfiguration(project);
1133    configDoc = TcConfigDocument.Factory.newInstance();
1134    stream = null;
1135    
1136    try {
1137      if(config != null) {
1138        configDoc.setTcConfig(config);
1139        stream = configDoc.newInputStream(opts);
1140        configFile.setContents(stream, true, true, null);
1141        stream = null;
1142        
1143        getConfigurationHelper(project).validateAll();
1144        JavaSetupParticipant.inspectAll();
1145        updateDecorators();
1146        fireConfigurationChange(project);
1147      }
1148    } catch(Exception JavaDoc e) {
1149      openError("Error saving '" + configFile.getName() + "'", e);
1150    } finally {
1151      if(stream != null) {
1152        IOUtils.closeQuietly(stream);
1153      }
1154    }
1155  }
1156
1157  public void saveConfigurationQuietly(IProject project) {
1158    IFile configFile;
1159    TcConfig config;
1160    TcConfigDocument configDoc;
1161    XmlOptions opts;
1162    InputStream JavaDoc inStream;
1163    FileWriter JavaDoc outWriter;
1164    
1165    opts = getXmlOptions();
1166    configFile = getConfigurationFile(project);
1167    config = getConfiguration(project);
1168    configDoc = TcConfigDocument.Factory.newInstance();
1169    inStream = null;
1170    outWriter = null;
1171    
1172    try {
1173      if(config != null) {
1174        configDoc.setTcConfig(config);
1175        
1176        inStream = configDoc.newInputStream(opts);
1177        outWriter = new FileWriter JavaDoc(configFile.getLocation().toOSString());
1178
1179        CopyUtils.copy(inStream, outWriter);
1180        
1181        getConfigurationHelper(project).validateAll();
1182        JavaSetupParticipant.inspectAll();
1183        updateDecorators();
1184        fireConfigurationChange(project);
1185      }
1186    } catch(Exception JavaDoc e) {
1187      openError("Error saving '" + configFile.getName() + "'", e);
1188    } finally {
1189      IOUtils.closeQuietly(inStream);
1190      IOUtils.closeQuietly(outWriter);
1191    }
1192  }
1193
1194  public void setSessionProperty(
1195    IResource res,
1196    QualifiedName name,
1197    Object JavaDoc value)
1198  {
1199    if(res != null && res.exists()) {
1200      try {
1201        res.setSessionProperty(name, value);
1202      } catch(CoreException ce) {
1203        ce.printStackTrace();
1204      }
1205    }
1206  }
1207
1208  public Object JavaDoc getSessionProperty(
1209    IResource res,
1210    QualifiedName name)
1211  {
1212    if(res != null && res.exists()) {
1213      try {
1214        return res.getSessionProperty(name);
1215      } catch(CoreException ce) {
1216        ce.printStackTrace();
1217      }
1218    }
1219    
1220    return null;
1221  }
1222
1223  public void setPersistentProperty(
1224    IResource resource,
1225    QualifiedName name,
1226    String JavaDoc value)
1227  {
1228    if(resource != null && resource.exists() ) {
1229      try {
1230        resource.setPersistentProperty(name, value);
1231      } catch(CoreException ce) {
1232        ce.printStackTrace();
1233      }
1234    }
1235  }
1236
1237  public String JavaDoc getPersistentProperty(
1238    IResource resource,
1239    QualifiedName name)
1240  {
1241    if(resource != null && resource.exists()) {
1242      try {
1243        return resource.getPersistentProperty(name);
1244      } catch(CoreException ce) {
1245        return null;
1246      }
1247    }
1248    
1249    return null;
1250  }
1251
1252  public ConfigurationEditor getConfigurationEditor(IProject project) {
1253    ConfigurationEditor[] configEditors = getConfigurationEditors(project);
1254    IFile configFile = getConfigurationFile(project);
1255    
1256    for(int i = 0; i < configEditors.length; i++) {
1257      IFileEditorInput fileEditorInput = (IFileEditorInput)configEditors[i].getEditorInput();
1258      IFile file = fileEditorInput.getFile();
1259      
1260      if(file.equals(configFile)) {
1261        return configEditors[i];
1262      }
1263    }
1264
1265    return null;
1266  }
1267
1268  public ConfigurationEditor ensureConfigurationEditor(IProject project) {
1269    ConfigurationEditor editor = getConfigurationEditor(project);
1270    
1271    if(editor == null) {
1272      try {
1273        editor = openConfigurationEditor(project);
1274      } catch(PartInitException pie) {
1275        openError("Unable to open configuration editor", pie);
1276      }
1277    }
1278    
1279    return editor;
1280  }
1281 
1282  public void setConfigurationFilePath(IProject project, String JavaDoc path) {
1283    String JavaDoc oldPath = getConfigurationFilePath(project);
1284    IFile file = oldPath != null ? project.getFile(oldPath) : null;
1285    if(file != null && file.exists()) {
1286      clearSAXMarkers(file);
1287      setSessionProperty(file, ACTIVE_CONFIGURATION_FILE, null);
1288    }
1289    
1290    setPersistentProperty(project, CONFIGURATION_FILE_PATH, path);
1291
1292    file = project.getFile(new Path(path));
1293    setSessionProperty(project, CONFIGURATION_FILE, file);
1294    setSessionProperty(file, ACTIVE_CONFIGURATION_FILE, "true");
1295    
1296    ConfigurationEditor configEditor = getConfigurationEditor(project);
1297    if(false && configEditor != null) {
1298      configEditor.newInputFile(file);
1299    }
1300  }
1301  
1302  public String JavaDoc getConfigurationFilePath(IProject project) {
1303    return getPersistentProperty(project, CONFIGURATION_FILE_PATH);
1304  }
1305    
1306  public IFile getConfigurationFile(IProject project) {
1307    IFile file = (IFile)getSessionProperty(project, CONFIGURATION_FILE);
1308    
1309    if(file == null) {
1310      String JavaDoc path = getConfigurationFilePath(project);
1311      
1312      if(path != null) {
1313        file = project.getFile(new Path(path));
1314        setSessionProperty(project, CONFIGURATION_FILE, file);
1315        setSessionProperty(file, ACTIVE_CONFIGURATION_FILE, "true");
1316      }
1317    }
1318    
1319    return file;
1320  }
1321
1322  public void setServerOptions(IProject project, String JavaDoc opts) {
1323    setPersistentProperty(project, SERVER_OPTIONS, opts);
1324  }
1325  
1326  public String JavaDoc getServerOptions(IProject project) {
1327    String JavaDoc options = getPersistentProperty(project, SERVER_OPTIONS);
1328    return options != null ? options : "";
1329  }
1330  
1331  public boolean hasTerracottaNature(IJavaElement element) {
1332    return hasTerracottaNature(element.getJavaProject().getProject());
1333  }
1334
1335  public boolean hasTerracottaNature(IProject project) {
1336    try {
1337      return project != null && project.hasNature(ProjectNature.NATURE_ID);
1338    } catch(CoreException ce) {/**/}
1339    return false;
1340  }
1341
1342  public void inspect(final ICompilationUnit cu) {
1343    if(cu != null) {
1344      getCompilationUnitVisitor().inspect(cu);
1345    }
1346  }
1347  
1348  private CompilationUnitVisitor getCompilationUnitVisitor() {
1349    if(m_compilationUnitVisitor == null) {
1350      m_compilationUnitVisitor = new CompilationUnitVisitor();
1351    }
1352    return m_compilationUnitVisitor;
1353  }
1354  
1355  private ResourceDeltaVisitor getResourceDeltaVisitor() {
1356    if(m_resourceDeltaVisitor == null) {
1357      m_resourceDeltaVisitor = new ResourceDeltaVisitor();
1358    }
1359    return m_resourceDeltaVisitor;
1360  }
1361  
1362  class ResourceListener implements IResourceChangeListener {
1363    public void resourceChanged(final IResourceChangeEvent event) {
1364      switch(event.getType()) {
1365        case IResourceChangeEvent.POST_BUILD: {
1366          try {
1367            event.getDelta().accept(getResourceDeltaVisitor());
1368          } catch(CoreException ce) {
1369            openError("Error handling resource change event for '"+
1370              event.getResource().getName()+"'", ce);
1371          }
1372          break;
1373        }
1374      }
1375    }
1376  }
1377  
1378  public void updateDecorator(final String JavaDoc id) {
1379    updateDecorators(new String JavaDoc[] {id});
1380  }
1381
1382  private DecoratorUpdateAction getDecoratorUpdateAction() {
1383    if(m_decoratorUpdateAction == null) {
1384      m_decoratorUpdateAction = new DecoratorUpdateAction();
1385    }
1386    return m_decoratorUpdateAction;
1387  }
1388  
1389  public void updateDecorators(String JavaDoc[] ids) {
1390    DecoratorUpdateAction updater = getDecoratorUpdateAction();
1391    
1392    updater.setDecorators(ids);
1393    Display.getDefault().asyncExec(updater);
1394  }
1395
1396  class DecoratorUpdateAction implements Runnable JavaDoc {
1397    IDecoratorManager m_decoratorManager;
1398    String JavaDoc[] m_decorators;
1399    
1400    DecoratorUpdateAction() {
1401      m_decoratorManager = PlatformUI.getWorkbench().getDecoratorManager();
1402    }
1403    
1404    void setDecorators(String JavaDoc[] ids) {
1405      m_decorators = ids;
1406    }
1407    
1408    public void run() {
1409      for(int i = 0; i < m_decorators.length; i++) {
1410        m_decoratorManager.update(m_decorators[i]);
1411      }
1412    }
1413  }
1414  
1415  private static final String JavaDoc[] DECORATOR_IDS = {
1416    "org.terracotta.dso.projectDecorator",
1417    ConfigFileDecorator.DECORATOR_ID,
1418    ServerRunningDecorator.DECORATOR_ID,
1419    AdaptedModuleDecorator.DECORATOR_ID,
1420    AdaptedTypeDecorator.DECORATOR_ID,
1421    AdaptedPackageFragmentDecorator.DECORATOR_ID,
1422    ExcludedTypeDecorator.DECORATOR_ID,
1423    ExcludedModuleDecorator.DECORATOR_ID,
1424    DistributedMethodDecorator.DECORATOR_ID,
1425    NameLockedDecorator.DECORATOR_ID,
1426    AutolockedDecorator.DECORATOR_ID,
1427    RootDecorator.DECORATOR_ID,
1428    TransientDecorator.DECORATOR_ID,
1429  };
1430
1431  public void updateDecorators() {
1432    updateDecorators(DECORATOR_IDS);
1433  }
1434  
1435  public boolean hasSAXMarkers(IResource res)
1436    throws CoreException
1437  {
1438    if(res != null && res.exists()) {
1439      IMarker[] markers = res.findMarkers("org.terracotta.dso.SAXMarker", false, IResource.DEPTH_ZERO);
1440      return markers.length > 0;
1441    }
1442    return false;
1443  }
1444
1445  public void clearSAXMarkers(IResource res) {
1446    if(res != null && res.exists()) {
1447      try {
1448        res.deleteMarkers("org.terracotta.dso.SAXMarker", false, IResource.DEPTH_ZERO);
1449      } catch(CoreException ce) {
1450        openError("Error clearing SAX markers on file'"+res.getName()+"'", ce);
1451      }
1452    }
1453  }
1454  
1455  public boolean hasProblemMarkers(IResource res)
1456    throws CoreException
1457  {
1458    if(res != null && res.exists()) {
1459      IMarker[] markers = res.findMarkers("org.eclipse.core.resources.problemmarker",
1460                                          true, IResource.DEPTH_ZERO);
1461      return markers.length > 0;
1462    }
1463    return false;
1464  }
1465  
1466  public void clearConfigProblemMarkers(IProject project) {
1467    try {
1468      IFile configFile = getConfigurationFile(project);
1469
1470      if(configFile != null && configFile.exists()) {
1471        configFile.deleteMarkers("org.terracotta.dso.ConfigProblemMarker", true, IResource.DEPTH_ZERO);
1472      }
1473    } catch(CoreException ce) {/**/}
1474  }
1475  
1476  public void clearConfigProblemMarkersOfType(IProject project, String JavaDoc markerType) {
1477    try {
1478      IFile configFile = getConfigurationFile(project);
1479
1480      if(configFile != null && configFile.exists()) {
1481        configFile.deleteMarkers(markerType, false, IResource.DEPTH_ZERO);
1482      }
1483    } catch(CoreException ce) {/**/}
1484  }
1485  
1486  public static ImageDescriptor getImageDescriptor(String JavaDoc path) {
1487    return AbstractUIPlugin.imageDescriptorFromPlugin(getPluginId(), path);
1488  }
1489
1490  public ConfigurationEditor openConfigurationEditor(IProject project)
1491    throws PartInitException
1492  {
1493    IWorkbench workbench = PlatformUI.getWorkbench();
1494    IWorkbenchWindow wbWin = workbench.getActiveWorkbenchWindow();
1495    
1496    if(wbWin != null) {
1497      IWorkbenchPage wbPage = wbWin.getActivePage();
1498
1499      if(wbPage != null) {
1500        IFile configFile = getConfigurationFile(project);
1501        FileEditorInput fileEditorInput = new FileEditorInput(configFile);
1502        IEditorPart editorPart = wbPage.findEditor(fileEditorInput);
1503        
1504        if(editorPart != null) {
1505          if(editorPart instanceof ConfigurationEditor) {
1506            wbPage.activate(editorPart);
1507            return (ConfigurationEditor)editorPart;
1508          }
1509          else {
1510            wbPage.closeEditor(editorPart, true);
1511          }
1512        }
1513        
1514        if(configFile != null) {
1515          String JavaDoc configEditorID = "editors.configurationEditor";
1516          
1517          return (ConfigurationEditor)
1518            IDE.openEditor(wbPage, configFile, configEditorID, false);
1519        }
1520      }
1521    }
1522    
1523    return null;
1524  }
1525  
1526  public void closeConfigurationEditor(IProject project) {
1527    ConfigurationEditor configEditor = getConfigurationEditor(project);
1528    
1529    if(configEditor != null) {
1530      configEditor.closeEditor();
1531    }
1532  }
1533  
1534  private XmlOptions createXmlOptions() {
1535    XmlOptions opts = new XmlOptions();
1536    
1537    opts.setLoadLineNumbers();
1538    opts.setSavePrettyPrint();
1539    opts.setSavePrettyPrintIndent(2);
1540    opts.remove(XmlOptions.LOAD_STRIP_WHITESPACE);
1541    opts.remove(XmlOptions.LOAD_STRIP_COMMENTS);
1542    //opts.remove(XmlOptions.VALIDATE_ON_SET);
1543

1544    return opts;
1545  }
1546  
1547  public XmlOptions getXmlOptions() {
1548    return m_xmlOptions;
1549  }
1550
1551  public void openError(final String JavaDoc msg, final Throwable JavaDoc t) {
1552    ILog log = getLog();
1553    log.log(new Status(IStatus.ERROR, getPluginId(), INTERNAL_ERROR, msg, t));
1554  }
1555  
1556  public void openError(final String JavaDoc msg) {
1557    if(SwingUtilities.isEventDispatchThread()) {
1558      Display.getDefault().syncExec(new Runnable JavaDoc() {
1559        public void run(){
1560          MessageDialog.openError(null, "Terracotta Plugin", msg);
1561        }
1562      });
1563    }
1564    else {
1565      MessageDialog.openError(null, "Terracotta Plugin", msg);
1566    }
1567  }
1568  
1569  public boolean continueWithConfigProblems(final IProject project) throws CoreException {
1570    IFile configFile = getConfigurationFile(project);
1571
1572    setSessionProperty(project, CONFIG_PROBLEM_CONTINUE, null);
1573
1574    if(hasProblemMarkers(configFile)) {
1575      Display.getDefault().syncExec(new Runnable JavaDoc() {
1576        public void run() {
1577          Shell shell = Display.getDefault().getActiveShell();
1578          String JavaDoc title = "Terracotta";
1579          String JavaDoc msg = "The are problems with the Terracotta configuration. Continue?";
1580          
1581          if(MessageDialog.openConfirm(shell, title, msg)) {
1582            setSessionProperty(project, CONFIG_PROBLEM_CONTINUE, Boolean.TRUE);
1583          }
1584        }
1585      });
1586      
1587      return getSessionProperty(project, CONFIG_PROBLEM_CONTINUE) == Boolean.TRUE;
1588    }
1589    
1590    return true;
1591  }
1592
1593  public static Display getStandardDisplay() {
1594    Display display = Display.getCurrent();
1595    if (display == null) {
1596      display= Display.getDefault();
1597    }
1598    return display;
1599  }
1600  
1601  public void fireConfigurationChange(IProject project) {
1602    m_configurationListeners.fireConfigurationChange(project);
1603  }
1604  
1605  class ConfigurationManager extends EventManager {
1606    void addConfigurationListener(IConfigurationListener listener) {
1607      addListenerObject(listener);
1608    }
1609    
1610    void removeConfigurationListener(IConfigurationListener listener) {
1611      removeListenerObject(listener);
1612    }
1613    
1614    void fireConfigurationChange(IProject project) {
1615      Object JavaDoc[] listeners = getListeners();
1616      
1617      if(listeners != null) {
1618        for(int i = 0; i < listeners.length; i++) {
1619          ((IConfigurationListener)listeners[i]).configurationChanged(project);
1620        }
1621      }
1622    }
1623  }
1624  
1625  private ConfigurationManager m_configurationListeners = new ConfigurationManager();
1626  
1627  public void addConfigurationListener(IConfigurationListener listener) {
1628    m_configurationListeners.addConfigurationListener(listener);
1629  }
1630
1631  public void removeConfigurationListener(IConfigurationListener listener) {
1632    m_configurationListeners.removeConfigurationListener(listener);
1633  }
1634  
1635  public static Image createImage(String JavaDoc path) {
1636    return new JavaElementImageDescriptor(getImageDescriptor(path), 0, new Point(16, 16)).createImage(false);
1637  }
1638}
1639
Popular Tags