0001: /*
0002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
0003: * notice. All rights reserved.
0004: */
0005: package org.terracotta.dso;
0006:
0007: import org.apache.commons.io.CopyUtils;
0008: import org.apache.commons.io.IOUtils;
0009: import org.apache.log4j.Level;
0010: import org.apache.log4j.Logger;
0011: import org.apache.xmlbeans.XmlError;
0012: import org.apache.xmlbeans.XmlException;
0013: import org.apache.xmlbeans.XmlOptions;
0014: import org.eclipse.core.resources.IFile;
0015: import org.eclipse.core.resources.IFolder;
0016: import org.eclipse.core.resources.IMarker;
0017: import org.eclipse.core.resources.IProject;
0018: import org.eclipse.core.resources.IProjectDescription;
0019: import org.eclipse.core.resources.IResource;
0020: import org.eclipse.core.resources.IResourceChangeEvent;
0021: import org.eclipse.core.resources.IResourceChangeListener;
0022: import org.eclipse.core.resources.ResourcesPlugin;
0023: import org.eclipse.core.runtime.CoreException;
0024: import org.eclipse.core.runtime.IAdapterFactory;
0025: import org.eclipse.core.runtime.IAdapterManager;
0026: import org.eclipse.core.runtime.ILog;
0027: import org.eclipse.core.runtime.IPath;
0028: import org.eclipse.core.runtime.IProgressMonitor;
0029: import org.eclipse.core.runtime.IStatus;
0030: import org.eclipse.core.runtime.Path;
0031: import org.eclipse.core.runtime.Platform;
0032: import org.eclipse.core.runtime.QualifiedName;
0033: import org.eclipse.core.runtime.Status;
0034: import org.eclipse.debug.core.DebugPlugin;
0035: import org.eclipse.debug.core.ILaunch;
0036: import org.eclipse.debug.core.ILaunchConfigurationType;
0037: import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
0038: import org.eclipse.debug.core.ILaunchManager;
0039: import org.eclipse.jdt.core.ElementChangedEvent;
0040: import org.eclipse.jdt.core.IClassFile;
0041: import org.eclipse.jdt.core.ICompilationUnit;
0042: import org.eclipse.jdt.core.IField;
0043: import org.eclipse.jdt.core.IJavaElement;
0044: import org.eclipse.jdt.core.IJavaProject;
0045: import org.eclipse.jdt.core.IMethod;
0046: import org.eclipse.jdt.core.IPackageFragment;
0047: import org.eclipse.jdt.core.IPackageFragmentRoot;
0048: import org.eclipse.jdt.core.IType;
0049: import org.eclipse.jdt.core.JavaCore;
0050: import org.eclipse.jdt.internal.core.BinaryMember;
0051: import org.eclipse.jdt.internal.core.SourceMethod;
0052: import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
0053: import org.eclipse.jdt.ui.JavaElementImageDescriptor;
0054: import org.eclipse.jface.dialogs.IDialogConstants;
0055: import org.eclipse.jface.dialogs.MessageDialog;
0056: import org.eclipse.jface.dialogs.ProgressMonitorDialog;
0057: import org.eclipse.jface.operation.IRunnableWithProgress;
0058: import org.eclipse.jface.resource.ImageDescriptor;
0059: import org.eclipse.jface.text.Document;
0060: import org.eclipse.jface.text.FindReplaceDocumentAdapter;
0061: import org.eclipse.jface.text.IDocument;
0062: import org.eclipse.jface.text.IRegion;
0063: import org.eclipse.jface.wizard.WizardDialog;
0064: import org.eclipse.swt.SWT;
0065: import org.eclipse.swt.graphics.Image;
0066: import org.eclipse.swt.graphics.Point;
0067: import org.eclipse.swt.widgets.Display;
0068: import org.eclipse.swt.widgets.Shell;
0069: import org.eclipse.ui.IDecoratorManager;
0070: import org.eclipse.ui.IEditorPart;
0071: import org.eclipse.ui.IEditorReference;
0072: import org.eclipse.ui.IFileEditorInput;
0073: import org.eclipse.ui.IWorkbench;
0074: import org.eclipse.ui.IWorkbenchPage;
0075: import org.eclipse.ui.IWorkbenchWindow;
0076: import org.eclipse.ui.PartInitException;
0077: import org.eclipse.ui.PlatformUI;
0078: import org.eclipse.ui.ide.IDE;
0079: import org.eclipse.ui.part.FileEditorInput;
0080: import org.eclipse.ui.plugin.AbstractUIPlugin;
0081: import org.eclipse.ui.texteditor.MarkerUtilities;
0082: import org.osgi.framework.Bundle;
0083: import org.osgi.framework.BundleContext;
0084: import org.osgi.framework.BundleException;
0085: import org.terracotta.dso.actions.ActionUtil;
0086: import org.terracotta.dso.actions.IProjectAction;
0087: import org.terracotta.dso.decorator.AdaptedModuleDecorator;
0088: import org.terracotta.dso.decorator.AdaptedPackageFragmentDecorator;
0089: import org.terracotta.dso.decorator.AdaptedTypeDecorator;
0090: import org.terracotta.dso.decorator.AutolockedDecorator;
0091: import org.terracotta.dso.decorator.ConfigFileDecorator;
0092: import org.terracotta.dso.decorator.DistributedMethodDecorator;
0093: import org.terracotta.dso.decorator.ExcludedModuleDecorator;
0094: import org.terracotta.dso.decorator.ExcludedTypeDecorator;
0095: import org.terracotta.dso.decorator.NameLockedDecorator;
0096: import org.terracotta.dso.decorator.RootDecorator;
0097: import org.terracotta.dso.decorator.ServerRunningDecorator;
0098: import org.terracotta.dso.decorator.TransientDecorator;
0099: import org.terracotta.dso.dialogs.ConfigProblemsDialog;
0100: import org.terracotta.dso.editors.ConfigurationEditor;
0101: import org.terracotta.dso.wizards.ProjectWizard;
0102:
0103: import com.tc.admin.common.InputStreamDrainer;
0104: import com.tc.bundles.EmbeddedOSGiEventHandler;
0105: import com.tc.bundles.EmbeddedOSGiRuntime;
0106: import com.tc.bundles.Resolver;
0107: import com.tc.bundles.exception.MissingBundleException;
0108: import com.tc.config.Loader;
0109: import com.tc.config.schema.dynamic.ParameterSubstituter;
0110: import com.tc.logging.CustomerLogging;
0111: import com.tc.logging.LogLevel;
0112: import com.tc.object.util.JarResourceLoader;
0113: import com.tc.plugins.ModulesLoader;
0114: import com.tc.server.ServerConstants;
0115: import com.tc.util.Assert;
0116: import com.tc.util.concurrent.ThreadUtil;
0117: import com.tc.util.runtime.Os;
0118: import com.terracottatech.config.Client;
0119: import com.terracottatech.config.DsoApplication;
0120: import com.terracottatech.config.Module;
0121: import com.terracottatech.config.Modules;
0122: import com.terracottatech.config.Server;
0123: import com.terracottatech.config.Servers;
0124: import com.terracottatech.config.TcConfigDocument;
0125: import com.terracottatech.config.TcConfigDocument.TcConfig;
0126:
0127: import java.io.ByteArrayInputStream;
0128: import java.io.File;
0129: import java.io.FileWriter;
0130: import java.io.IOException;
0131: import java.io.InputStream;
0132: import java.io.StringReader;
0133: import java.io.StringWriter;
0134: import java.lang.reflect.InvocationTargetException;
0135: import java.net.MalformedURLException;
0136: import java.net.URL;
0137: import java.util.ArrayList;
0138: import java.util.ConcurrentModificationException;
0139: import java.util.HashMap;
0140: import java.util.Iterator;
0141: import java.util.List;
0142: import java.util.Properties;
0143:
0144: /**
0145: * The Terracotta plugin. The whole enchilada centers around this singleton. The primary duties of this class are to
0146: * manage the configuration information associated with a Terracotta Eclipse project. Configuration information is
0147: * stored as session properties in the project, which are not persistent across sessions. The config information is made
0148: * up of: 1) the config file XML document 2) the parsed form of the XML document, aka the config object 3) the line
0149: * length information of the config document 3) a configuration helper, used by various actions.
0150: *
0151: * @see loadConfiguration(IProject) When there are errors instantiating the config document, those XmlErrors are turned
0152: * into SAXMarkers on the document, which appear as error indicators in the config document editor.
0153: * @see handleXmlErrors(IFile, LineLengths, Iterator) At times, it is necessary to inspect a module to determine where
0154: * to add annotations denoting configuration-related Java elements, such as a particular method being locked.
0155: * @see inspect(ICompilationUnit). Another responsibility of this class is to launch the server using the config
0156: * information, additional boot jar, etc.
0157: * @see launchServer(IJavaProject, String, String, String) Finally, this class provides methods for updating the
0158: * annotations used to indicate various states related to the config information, such as a field being a root.
0159: * @see updateDecorators()
0160: * @see org.eclipse.ui.plugin.AbstractUIPlugin
0161: * @see com.terracottatech.config.TCConfigDocument
0162: * @see com.terracottatech.config.TCConfigDocument.TCConfig
0163: */
0164:
0165: public class TcPlugin extends AbstractUIPlugin implements
0166: QualifiedNames, IJavaLaunchConfigurationConstants,
0167: TcPluginStatusConstants {
0168: private static TcPlugin m_plugin;
0169: private Loader m_configLoader;
0170: private CompilationUnitVisitor m_compilationUnitVisitor;
0171: private ResourceListener m_resourceListener;
0172: private ResourceDeltaVisitor m_resourceDeltaVisitor;
0173: private XmlOptions m_xmlOptions;
0174: private DecoratorUpdateAction m_decoratorUpdateAction;
0175: private ArrayList<IProjectAction> m_projectActionList;
0176: private BootClassHelper m_bootClassHelper;
0177: private ConfigurationEventManager m_configurationEventManager;
0178:
0179: public static final String PLUGIN_ID = "org.terracotta.dso";
0180:
0181: public static final String DEFAULT_CONFIG_FILENAME = "tc-config.xml";
0182: public static final String DEFAULT_SERVER_OPTIONS = "-Xms256m -Xmx256m";
0183: public static final boolean DEFAULT_AUTO_START_SERVER_OPTION = false;
0184: public static final boolean DEFAULT_WARN_CONFIG_PROBLEMS_OPTION = true;
0185: public static final boolean DEFAULT_QUERY_RESTART_OPTION = true;
0186:
0187: static {
0188: CustomerLogging.getConsoleLogger().setLevel(LogLevel.OFF);
0189: Logger.getLogger("com.terracottatech").setLevel(Level.OFF);
0190: Logger.getLogger("com.tc").setLevel(Level.OFF);
0191: }
0192:
0193: public TcPlugin() {
0194: super ();
0195: if (m_plugin != null)
0196: throw new IllegalStateException(
0197: "Plugin already instantiated.");
0198: m_plugin = this ;
0199: m_configurationEventManager = new ConfigurationEventManager();
0200: }
0201:
0202: public static String getPluginId() {
0203: return PLUGIN_ID;
0204: }
0205:
0206: public BootClassHelper getBootClassHelper() {
0207: return m_bootClassHelper;
0208: }
0209:
0210: public boolean isBootClass(final ICompilationUnit module) {
0211: if (m_bootClassHelper != null) {
0212: return module != null ? isBootClass(module
0213: .findPrimaryType()) : false;
0214: }
0215: return false;
0216: }
0217:
0218: public boolean isBootClass(final IClassFile classFile) {
0219: if (m_bootClassHelper != null && classFile != null) {
0220: try {
0221: return isBootClass(classFile.getType());
0222: } catch (Exception e) {/**/
0223: }
0224: }
0225: return false;
0226: }
0227:
0228: public boolean isBootClass(final IType type) {
0229: if (m_bootClassHelper != null && type != null) {
0230: return isBootClass(PatternHelper
0231: .getFullyQualifiedName(type));
0232: }
0233: return false;
0234: }
0235:
0236: public boolean isBootClass(String name) {
0237: return m_bootClassHelper != null ? m_bootClassHelper
0238: .isAdaptable(name) : false;
0239: }
0240:
0241: public void registerProjectAction(IProjectAction action) {
0242: if (action != null) {
0243: m_projectActionList.add(action);
0244: }
0245: }
0246:
0247: public void notifyProjectActions(IProject project) {
0248: Iterator iter = m_projectActionList.iterator();
0249:
0250: while (iter.hasNext()) {
0251: ((IProjectAction) iter.next()).update(project);
0252: }
0253: }
0254:
0255: private void addResourceChangeListener() {
0256: ResourcesPlugin.getWorkspace().addResourceChangeListener(
0257: m_resourceListener, IResourceChangeEvent.POST_BUILD);
0258: }
0259:
0260: private IPath m_location;
0261:
0262: public IPath getLocation() {
0263: return m_location;
0264: }
0265:
0266: public IPath getLibDirPath() {
0267: return getLocation().append("lib");
0268: }
0269:
0270: public void start(BundleContext context) throws Exception {
0271: super .start(context);
0272:
0273: m_configLoader = new Loader();
0274:
0275: // TODO: after we remove 3.1 support, change to FileLocator.resolve
0276: URL url = Platform.resolve(context.getBundle().getEntry("/"));
0277: m_location = new Path(url.getPath()).removeTrailingSeparator();
0278:
0279: JavaCore.addElementChangedListener(
0280: new ElementChangedListener(),
0281: ElementChangedEvent.POST_RECONCILE);
0282:
0283: m_resourceListener = new ResourceListener();
0284: addResourceChangeListener();
0285:
0286: IPath tcInstallPath = getLocation();
0287: if (tcInstallPath != null) {
0288: System.setProperty("tc.install", tcInstallPath.toString());
0289: }
0290:
0291: m_xmlOptions = createXmlOptions();
0292: m_projectActionList = new ArrayList<IProjectAction>();
0293:
0294: IAdapterManager manager = Platform.getAdapterManager();
0295: IAdapterFactory factory = new JavaElementAdapter();
0296: manager.registerAdapters(factory, IField.class);
0297: manager.registerAdapters(factory, IType.class);
0298: manager.registerAdapters(factory, IMethod.class);
0299: manager.registerAdapters(factory, IClassFile.class);
0300:
0301: // TODO: REMOVE the following when 3.1 is no longer supported
0302: // SourceMethod and BinaryMember are internal types
0303: manager.registerAdapters(factory, SourceMethod.class);
0304: manager.registerAdapters(factory, BinaryMember.class);
0305:
0306: try {
0307: m_bootClassHelper = BootClassHelper.initialize();
0308: } catch (Exception e) {
0309: buildBootJarForThisVM();
0310: }
0311: }
0312:
0313: private static String getJavaCmd() {
0314: String javaCmd = System.getProperty("java.home")
0315: + File.separatorChar + "bin" + File.separatorChar
0316: + "java";
0317: if (Os.isWindows()) {
0318: javaCmd += ".exe";
0319: }
0320: return javaCmd;
0321: }
0322:
0323: private void buildBootJarForThisVM() {
0324: new Thread() {
0325: public void run() {
0326: try {
0327: IPath tcJarPath = TcPlugin.getDefault()
0328: .getLibDirPath().append("tc.jar");
0329: File bootJarFile = BootJarHelper.getHelper()
0330: .getBootJarFileForThisVM();
0331:
0332: System.setProperty("tc.install-root", getLocation()
0333: .toOSString());
0334:
0335: String[] args = { getJavaCmd(), "-cp",
0336: tcJarPath.toOSString(),
0337: "com.tc.object.tools.BootJarTool", "-q",
0338: "-o", bootJarFile.getAbsolutePath() };
0339:
0340: Process p = Runtime.getRuntime().exec(args);
0341:
0342: InputStreamDrainer outReader = new InputStreamDrainer(
0343: p.getInputStream());
0344: InputStreamDrainer errReader = new InputStreamDrainer(
0345: p.getErrorStream());
0346:
0347: outReader.start();
0348: errReader.start();
0349:
0350: while (true) {
0351: try {
0352: p.waitFor();
0353: break;
0354: } catch (InterruptedException ie) {/**/
0355: }
0356:
0357: ThreadUtil.reallySleep(1000);
0358: }
0359:
0360: m_bootClassHelper = BootClassHelper.initialize();
0361: } catch (Throwable t) {
0362: openError("Plugin Initialization Error", t);
0363: }
0364: }
0365: }.start();
0366: }
0367:
0368: public void stop(BundleContext context) throws Exception {
0369: ServerTracker.getDefault().shutdownAllServers();
0370: super .stop(context);
0371: m_plugin = null;
0372: }
0373:
0374: public static TcPlugin getDefault() {
0375: return m_plugin;
0376: }
0377:
0378: public void setup(IProject project, String configFilePath) {
0379: boolean isConfigEditorVisible = getConfigurationEditor(project) != null;
0380:
0381: if (isConfigEditorVisible)
0382: closeConfigurationEditor(project);
0383:
0384: clearConfigurationSessionProperties(project);
0385: setConfigurationFilePath(project, configFilePath);
0386: reloadConfiguration(project);
0387:
0388: if (isConfigEditorVisible)
0389: ensureConfigurationEditor(project);
0390: }
0391:
0392: public void setup(IProject project, String configFilePath,
0393: String serverOpts) {
0394: setPersistentProperty(project, SERVER_OPTIONS, serverOpts);
0395: setup(project, configFilePath);
0396: }
0397:
0398: public void setup(IFile configFile) {
0399: setup(configFile.getProject(), configFile
0400: .getProjectRelativePath().toString());
0401: }
0402:
0403: public void addTerracottaNature(IJavaProject currentProject) {
0404: IWorkbench workbench = PlatformUI.getWorkbench();
0405: IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
0406: Shell shell = window != null ? window.getShell() : null;
0407:
0408: try {
0409: ProjectWizard wizard = new ProjectWizard(currentProject);
0410: WizardDialog dialog = new WizardDialog(shell, wizard);
0411:
0412: wizard.setWindowTitle("Terracotta Project Wizard");
0413: dialog.open();
0414: } catch (Exception e) {
0415: MessageDialog.openInformation(shell, "Terracotta",
0416: "Cannot add Terracotta nature:\n"
0417: + ActionUtil.getStatusMessages(e));
0418: } finally {
0419: if (shell != null)
0420: shell.setCursor(null);
0421: }
0422: }
0423:
0424: public void removeTerracottaNature(IJavaProject javaProject) {
0425: IWorkbench workbench = PlatformUI.getWorkbench();
0426: IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
0427: Shell shell = window != null ? window.getShell() : null;
0428:
0429: try {
0430: IRunnableWithProgress op = new TCNatureRemover(javaProject);
0431: new ProgressMonitorDialog(shell).run(true, false, op);
0432: } catch (InvocationTargetException e) {
0433: openError("Cannot remove Terracotta nature", e.getCause());
0434: } catch (InterruptedException e) {/**/
0435: }
0436: }
0437:
0438: class TCNatureRemover implements IRunnableWithProgress {
0439: IJavaProject m_javaProject;
0440:
0441: TCNatureRemover(IJavaProject javaProject) {
0442: m_javaProject = javaProject;
0443: }
0444:
0445: public void run(IProgressMonitor monitor)
0446: throws InvocationTargetException {
0447: try {
0448: monitor.beginTask("Removing project nature", 4);
0449: IProject project = m_javaProject.getProject();
0450: IProjectDescription description = project
0451: .getDescription();
0452: String[] natures = description.getNatureIds();
0453: ArrayList<String> natureList = new ArrayList<String>();
0454:
0455: for (int i = 0; i < natures.length; i++) {
0456: if (!natures[i].equals(ProjectNature.NATURE_ID)) {
0457: natureList.add(natures[i]);
0458: }
0459: }
0460: description.setNatureIds(natureList
0461: .toArray(new String[0]));
0462: project.setDescription(description, monitor);
0463: project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
0464: monitor.worked(1);
0465:
0466: monitor.beginTask("Closing configuration editor", 4);
0467: closeConfigurationEditor(project);
0468: monitor.worked(2);
0469:
0470: monitor.beginTask("Stopping server", 4);
0471: final ServerTracker tracker = ServerTracker
0472: .getDefault();
0473: if (tracker.anyRunning(m_javaProject)) {
0474: Display.getDefault().syncExec(new Runnable() {
0475: public void run() {
0476: tracker.shutdownAllServers();
0477: }
0478: });
0479: }
0480: monitor.worked(3);
0481:
0482: monitor.beginTask("Removing markers", 4);
0483: IPackageFragment[] fragments = m_javaProject
0484: .getPackageFragments();
0485: ICompilationUnit[] cus;
0486: IResource file;
0487:
0488: for (int i = 0; i < fragments.length; i++) {
0489: if (fragments[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
0490: cus = fragments[i].getCompilationUnits();
0491:
0492: for (int j = 0; j < cus.length; j++) {
0493: file = cus[j].getResource();
0494: monitor.subTask(file.getLocation()
0495: .toString());
0496: file.deleteMarkers(
0497: "org.terracotta.dso.baseMarker",
0498: true, IResource.DEPTH_INFINITE);
0499: }
0500: }
0501: }
0502:
0503: IFile configFile = getConfigurationFile(m_javaProject
0504: .getProject());
0505: if (configFile != null && configFile.exists()) {
0506: clearSAXMarkers(configFile);
0507: }
0508:
0509: clearConfigProblemMarkers(project);
0510: clearConfigurationSessionProperties(project);
0511: notifyProjectActions(project);
0512: updateDecorators();
0513: fireConfigurationChange(project);
0514:
0515: monitor.worked(4);
0516: } catch (CoreException e) {
0517: throw new InvocationTargetException(e);
0518: }
0519: }
0520: }
0521:
0522: public ILaunch launchServer(IJavaProject javaProject,
0523: String projectName, String serverName,
0524: IProgressMonitor monitor) throws CoreException {
0525: IProject project = javaProject.getProject();
0526: ILaunchManager manager = DebugPlugin.getDefault()
0527: .getLaunchManager();
0528: String id = ID_JAVA_APPLICATION;
0529: ILaunchConfigurationType type = manager
0530: .getLaunchConfigurationType(id);
0531: String installPath = getLocation().makeAbsolute().toOSString();
0532:
0533: ILaunchConfigurationWorkingCopy wc = type.newInstance(null,
0534: projectName + "." + serverName);
0535:
0536: wc.setAttribute(ATTR_PROJECT_NAME, project.getName());
0537: wc.setAttribute(ATTR_MAIN_TYPE_NAME,
0538: ServerConstants.SERVER_MAIN_CLASS_NAME);
0539:
0540: IFile configFile = getConfigurationFile(project);
0541:
0542: if (configFile != null) {
0543: String configPath = configFile.getLocation().toOSString();
0544: String vmargs = " -Dtc.install-root=\""
0545: + installPath
0546: + "\""
0547: + " -Dtc.config=\""
0548: + configPath
0549: + "\""
0550: + " -Dtc.server.name=\""
0551: + serverName
0552: + "\""
0553: + " -Dcom.sun.management.jmxremote"
0554: + " -Dcom.sun.management.jmxremote.authenticate=false";
0555: String origVMArgs = wc.getAttribute(ATTR_VM_ARGUMENTS, "")
0556: + " " + getServerOptions(project) + " ";
0557:
0558: wc.setAttribute(ATTR_VM_ARGUMENTS, vmargs + origVMArgs);
0559: wc.setAttribute(ATTR_CLASSPATH_PROVIDER,
0560: "org.terracotta.dso.classpathProvider");
0561: wc.setAttribute(ATTR_WORKING_DIRECTORY, project
0562: .getLocation().append("terracotta").makeAbsolute()
0563: .toOSString());
0564:
0565: ensureRuntimeDirectory(project, monitor);
0566:
0567: return wc.launch(ILaunchManager.DEBUG_MODE, monitor);
0568: } else {
0569: System.out
0570: .println("No config file specified. Set in project properties");
0571: return null;
0572: }
0573: }
0574:
0575: public String getAnyServerName(IProject project) {
0576: TcConfig config = getConfiguration(project);
0577:
0578: if (config != null) {
0579: Servers servers = config.getServers();
0580:
0581: if (servers != null) {
0582: Server[] serverArr = servers.getServerArray();
0583:
0584: for (int i = 0; i < serverArr.length; i++) {
0585: String name = serverArr[i].getName();
0586: if (name != null && name.length() > 0) {
0587: return ParameterSubstituter.substitute(name);
0588: }
0589: }
0590: }
0591: }
0592:
0593: return "default";
0594: }
0595:
0596: public int getJmxPort(IProject project, String name) {
0597: TcConfig config = getConfiguration(project);
0598:
0599: if (config != null) {
0600: Servers servers = config.getServers();
0601:
0602: if (servers != null) {
0603: Server[] serverArr = servers.getServerArray();
0604: Server server;
0605:
0606: for (int i = 0; i < serverArr.length; i++) {
0607: server = serverArr[i];
0608:
0609: if (name.equals(server.getName())) {
0610: return server.getJmxPort();
0611: }
0612: }
0613: }
0614: }
0615:
0616: return -1;
0617: }
0618:
0619: /**
0620: * Instantiate the config information, either from the serialized form, or directly from the config document.
0621: */
0622: private void loadConfiguration(IProject project)
0623: throws XmlException, IOException, CoreException,
0624: ConcurrentModificationException {
0625: if (!project.isOpen()) {
0626: return;
0627: }
0628:
0629: IFile configFile = getConfigurationFile(project);
0630:
0631: if (configFile != null) {
0632: IPath path = configFile.getLocation();
0633: File file = path.toFile();
0634: List errors = new ArrayList();
0635:
0636: if (!configFile.isSynchronized(IResource.DEPTH_ZERO)) {
0637: ignoreNextConfigChange();
0638: configFile.refreshLocal(IResource.DEPTH_ZERO, null);
0639: }
0640:
0641: LineLengths lineLengths = new LineLengths(configFile);
0642: setSessionProperty(project, CONFIGURATION_LINE_LENGTHS,
0643: lineLengths);
0644:
0645: if (m_configLoader.testIsOld(file)) {
0646: m_configLoader.updateToCurrent(file);
0647: }
0648:
0649: clearSAXMarkers(configFile);
0650:
0651: // The following line may throw XmlException if the doc is not well-formed.
0652: // That's why LineLengths are setup earlier, they are used by the catching
0653: // block to apply SAXMarkers to the config IFile. Otherwise, it's done
0654: // below.
0655:
0656: TcConfigDocument doc;
0657: TcConfig config;
0658:
0659: doc = m_configLoader.parse(file, m_xmlOptions);
0660: config = doc.getTcConfig();
0661:
0662: m_xmlOptions.setErrorListener(errors);
0663: if (!doc.validate(m_xmlOptions)) {
0664: handleXmlErrors(configFile, lineLengths, errors
0665: .iterator());
0666: }
0667: m_xmlOptions.setErrorListener(null);
0668:
0669: clearModulesConfiguration(project);
0670: Client client = config.getClients();
0671: if (client != null && client.isSetModules()
0672: && client.getModules().sizeOfModuleArray() > 0) {
0673: ModulesConfiguration modulesConfig = createModulesConfiguration(project);
0674: initModules(client.getModules(), modulesConfig);
0675: }
0676:
0677: setSessionProperty(project, CONFIGURATION, config);
0678:
0679: if (config != null) {
0680: getConfigurationHelper(project).validateAll();
0681: fireConfigurationChange(project);
0682: }
0683: }
0684: }
0685:
0686: private void clearModulesConfiguration(IProject project) {
0687: setSessionProperty(project, MODULES_CONFIGURATION, null);
0688: }
0689:
0690: private ModulesConfiguration createModulesConfiguration(
0691: IProject project) {
0692: ModulesConfiguration modulesConfig = new ModulesConfiguration();
0693: setSessionProperty(project, MODULES_CONFIGURATION,
0694: modulesConfig);
0695: return modulesConfig;
0696: }
0697:
0698: public ModulesConfiguration getModulesConfiguration(IProject project) {
0699: return (ModulesConfiguration) getSessionProperty(project,
0700: MODULES_CONFIGURATION);
0701: }
0702:
0703: private void initModules(final Modules modules,
0704: final ModulesConfiguration modulesConfig) {
0705: EmbeddedOSGiRuntime osgiRuntime = null;
0706:
0707: try {
0708: Modules modulesCopy = (Modules) modules.copy();
0709: Module[] origModules = modulesCopy.getModuleArray();
0710:
0711: for (Module origModule : origModules) {
0712: Modules tmpModules = (Modules) modulesCopy.copy();
0713: tmpModules.setModuleArray(new Module[] { origModule });
0714: osgiRuntime = EmbeddedOSGiRuntime.Factory
0715: .createOSGiRuntime(tmpModules);
0716: final Resolver resolver = new Resolver(osgiRuntime
0717: .getRepositories());
0718: Module[] allModules = tmpModules.getModuleArray();
0719: ModuleInfo origModuleInfo = modulesConfig
0720: .getOrAdd(origModule);
0721:
0722: for (Module module : allModules) {
0723: ModuleInfo moduleInfo = modulesConfig
0724: .getOrAdd(module);
0725: try {
0726: moduleInfo
0727: .setLocation(resolver.resolve(module));
0728: final URL[] locations = resolver
0729: .getResolvedUrls();
0730: for (URL location : locations) {
0731: osgiRuntime.installBundle(location);
0732: }
0733: } catch (BundleException be) {
0734: if (be instanceof MissingBundleException) {
0735: String msg = be.getMessage();
0736: msg = msg.substring(0, msg.indexOf(';'));
0737: be = new MissingBundleException(msg);
0738: }
0739: moduleInfo.setError(be);
0740: origModuleInfo.setError(be);
0741: }
0742: }
0743: osgiRuntime.shutdown();
0744: }
0745:
0746: osgiRuntime = EmbeddedOSGiRuntime.Factory
0747: .createOSGiRuntime(modulesCopy);
0748: final Resolver resolver = new Resolver(osgiRuntime
0749: .getRepositories());
0750: Module[] allModules = modulesCopy.getModuleArray();
0751:
0752: for (Module module : allModules) {
0753: try {
0754: resolver.resolve(module);
0755: } catch (BundleException be) {
0756: /**/
0757: }
0758: }
0759:
0760: final URL[] locations = resolver.getResolvedUrls();
0761: for (URL location : locations) {
0762: try {
0763: osgiRuntime.installBundle(location);
0764: } catch (BundleException be) {
0765: be.printStackTrace();
0766: }
0767: }
0768:
0769: osgiRuntime
0770: .registerService(
0771: "com.tc.object.config.StandardDSOClientConfigHelper",
0772: new FakeDSOClientConfigHelper(),
0773: new Properties());
0774:
0775: osgiRuntime.startBundles(locations,
0776: new EmbeddedOSGiEventHandler() {
0777: public void callback(final Object payload)
0778: throws BundleException {
0779: Assert
0780: .assertTrue(payload instanceof Bundle);
0781: Bundle bundle = (Bundle) payload;
0782: if (bundle != null) {
0783: loadModuleConfiguration(bundle,
0784: modulesConfig);
0785: }
0786: }
0787: });
0788: } catch (Exception e) {
0789: //e.printStackTrace();
0790: } finally {
0791: if (osgiRuntime != null) {
0792: osgiRuntime.shutdown();
0793: }
0794: }
0795: }
0796:
0797: private void loadModuleConfiguration(final Bundle bundle,
0798: final ModulesConfiguration modulesConfig)
0799: throws BundleException {
0800: ModuleInfo moduleInfo = modulesConfig.associateBundle(bundle);
0801: if (moduleInfo == null)
0802: return;
0803:
0804: final String[] paths = ModulesLoader.getConfigPath(bundle);
0805: for (int i = 0; i < paths.length; i++) {
0806: final String configPath = paths[i];
0807: InputStream is = null;
0808:
0809: try {
0810: is = JarResourceLoader.getJarResource(new URL(bundle
0811: .getLocation()), configPath);
0812: } catch (MalformedURLException murle) {
0813: moduleInfo.setError(new BundleException(
0814: "Unable to create URL from: "
0815: + bundle.getLocation(), murle));
0816: } catch (IOException ioe) {
0817: moduleInfo.setError(new BundleException(
0818: "Unable to extract " + configPath
0819: + " from URL: " + bundle.getLocation(),
0820: ioe));
0821: }
0822:
0823: if (is == null) {
0824: continue;
0825: }
0826:
0827: try {
0828: final DsoApplication application = DsoApplication.Factory
0829: .parse(is);
0830: if (application != null) {
0831: modulesConfig.setModuleApplication(moduleInfo,
0832: application);
0833: }
0834: } catch (Exception e) {
0835: /**/
0836: } finally {
0837: if (is != null) {
0838: IOUtils.closeQuietly(is);
0839: }
0840: }
0841: }
0842: }
0843:
0844: /**
0845: * Instantiate the config information from the passed-in text.
0846: */
0847: private void loadConfiguration(IProject project, String xmlText)
0848: throws XmlException, ConcurrentModificationException,
0849: IOException {
0850: IFile configFile = getConfigurationFile(project);
0851:
0852: if (configFile != null) {
0853: List errors = new ArrayList();
0854:
0855: LineLengths lineLengths = new LineLengths(new StringReader(
0856: xmlText));
0857: setSessionProperty(project, CONFIGURATION_LINE_LENGTHS,
0858: lineLengths);
0859:
0860: clearSAXMarkers(configFile);
0861:
0862: // The following line may throw XmlException if the doc is not well-formed.
0863: // That's why LineLengths are setup earlier, they are used by the catching
0864: // block to apply SAXMarkers to the config IFile. Otherwise, it's done
0865: // below.
0866:
0867: TcConfigDocument doc;
0868: TcConfig config;
0869:
0870: doc = m_configLoader.parse(xmlText, m_xmlOptions);
0871: config = doc.getTcConfig();
0872:
0873: m_xmlOptions.setErrorListener(errors);
0874: if (!doc.validate(m_xmlOptions)) {
0875: handleXmlErrors(configFile, lineLengths, errors
0876: .iterator());
0877: }
0878: m_xmlOptions.setErrorListener(null);
0879:
0880: clearModulesConfiguration(project);
0881: Client client = config.getClients();
0882: if (client != null && client.isSetModules()
0883: && client.getModules().sizeOfModuleArray() > 0) {
0884: ModulesConfiguration modulesConfig = createModulesConfiguration(project);
0885: initModules(client.getModules(), modulesConfig);
0886: }
0887:
0888: setSessionProperty(project, CONFIGURATION, config);
0889:
0890: if (config != null) {
0891: getConfigurationHelper(project).validateAll();
0892: fireConfigurationChange(project);
0893: }
0894: }
0895: }
0896:
0897: public void fileMoved(IFile file, IPath movedFromPath) {
0898: IProject project = file.getProject();
0899: IPath path = file.getProjectRelativePath();
0900: String extension = path.getFileExtension();
0901: IPath fromPath = movedFromPath.removeFirstSegments(1);
0902:
0903: if (extension.equals("xml")) {
0904: String configPath = getConfigurationFilePath(project);
0905:
0906: if (fromPath.toString().equals(configPath)) {
0907: setConfigurationFilePath(project, path.toString());
0908: }
0909: }
0910: }
0911:
0912: public void replaceConfigText(IProject project, String oldText,
0913: String newText) {
0914: ConfigurationEditor editor = getConfigurationEditor(project);
0915: IDocument doc;
0916:
0917: if (editor != null) {
0918: doc = editor.getDocument();
0919: } else {
0920: try {
0921: IFile configFile = getConfigurationFile(project);
0922: String content = IOUtils.toString(configFile
0923: .getContents());
0924:
0925: doc = new Document(content);
0926: } catch (Exception e) {
0927: openError("Problem handling refactor", e);
0928: return;
0929: }
0930: }
0931:
0932: FindReplaceDocumentAdapter finder = new FindReplaceDocumentAdapter(
0933: doc);
0934: int offset = 0;
0935: IRegion region;
0936:
0937: try {
0938: while ((region = finder.find(offset, "\\Q" + oldText
0939: + "\\E", true, true, true, false)) != null) {
0940: region = finder.replace(newText, false);
0941: offset = region.getOffset() + region.getLength();
0942: }
0943:
0944: IFile configFile = getConfigurationFile(project);
0945: InputStream stream = new ByteArrayInputStream(doc.get()
0946: .getBytes());
0947:
0948: configFile.setContents(stream, true, true, null);
0949: JavaSetupParticipant.inspectAll();
0950: } catch (Exception e) {
0951: openError("Problem handling refactor", e);
0952: return;
0953: }
0954: }
0955:
0956: /**
0957: * Called when a new project is created and it has a leftover Terracotta nature. This can happen because it doesn't
0958: * appear to be possible to do anything useful with IResourceChangeEvent.PRE_DELETE because the workspace is locked
0959: * then... and after, the project doesn't exists anymore.
0960: */
0961: public void staleProjectAdded(IProject project) {
0962: try {
0963: IProjectDescription description = project.getDescription();
0964: String[] natures = description.getNatureIds();
0965: String[] newNatures = new String[natures.length - 1];
0966:
0967: for (int i = 0; i < natures.length; i++) {
0968: if (!natures[i].equals(ProjectNature.NATURE_ID)) {
0969: newNatures[i] = natures[i];
0970: }
0971: }
0972: description.setNatureIds(newNatures);
0973: project.setDescription(description, null);
0974: updateDecorator("org.terracotta.dso.projectDecorator");
0975: } catch (CoreException ce) {
0976: ce.printStackTrace();
0977: }
0978: }
0979:
0980: public void fileRemoved(IFile file) {
0981: IPath path = file.getProjectRelativePath();
0982: String extension = path.getFileExtension();
0983:
0984: if (extension.equals("java")) {
0985: getConfigurationHelper(file.getProject()).validateAll();
0986: } else if (extension.equals("xml")) {
0987: final IProject project = file.getProject();
0988: IFile configFile = getConfigurationFile(project);
0989:
0990: if (file.equals(configFile)) {
0991: Display.getDefault().asyncExec(new Runnable() {
0992: public void run() {
0993: removeTerracottaNature(JavaCore.create(project));
0994: }
0995: });
0996: }
0997: }
0998: }
0999:
1000: /**
1001: * Sets the new config information from the passed-in text. This is invoked by the ConfigurationEditor after the user
1002: * modifies its contents manually.
1003: */
1004: public void setConfigurationFromString(IProject project,
1005: String xmlText) throws IOException {
1006: TcConfig config = null;
1007:
1008: try {
1009: loadConfiguration(project, xmlText);
1010: config = (TcConfig) getSessionProperty(project,
1011: CONFIGURATION);
1012: } catch (XmlException e) {
1013: LineLengths lineLengths = getConfigurationLineLengths(project);
1014: handleXmlException(getConfigurationFile(project),
1015: lineLengths, e);
1016: }
1017:
1018: if (config == null) {
1019: config = BAD_CONFIG;
1020: setSessionProperty(project, CONFIGURATION, config);
1021: fireConfigurationChange(project);
1022: }
1023: }
1024:
1025: /**
1026: * Return the config document's line length information, which might not exist.
1027: */
1028: public LineLengths getConfigurationLineLengths(IProject project) {
1029: return (LineLengths) getSessionProperty(project,
1030: CONFIGURATION_LINE_LENGTHS);
1031: }
1032:
1033: public ConfigurationHelper getConfigurationHelper(IProject project) {
1034: ConfigurationHelper helper = (ConfigurationHelper) getSessionProperty(
1035: project, CONFIGURATION_HELPER);
1036:
1037: if (helper == null) {
1038: helper = new ConfigurationHelper(project);
1039: }
1040:
1041: return helper;
1042: }
1043:
1044: public static final TcConfig BAD_CONFIG = createTemplateConfigDoc()
1045: .getTcConfig();
1046:
1047: public static TcConfigDocument createTemplateConfigDoc() {
1048: TcConfigDocument doc = TcConfigDocument.Factory.newInstance();
1049: TcConfig config = doc.addNewTcConfig();
1050: Servers servers = config.addNewServers();
1051: Server server = servers.addNewServer();
1052:
1053: server.setHost("%i");
1054: server.setName("localhost");
1055: server.setDsoPort(9510);
1056: server.setJmxPort(9520);
1057: server.setData("terracotta/server-data");
1058: server.setLogs("terracotta/server-logs");
1059:
1060: config.addNewClients().setLogs("terracotta/client-logs");
1061:
1062: return doc;
1063: }
1064:
1065: public synchronized TcConfig getConfiguration(IProject project) {
1066: TcConfig config = (TcConfig) getSessionProperty(project,
1067: CONFIGURATION);
1068:
1069: if (config == null) {
1070: try {
1071: loadConfiguration(project);
1072: config = (TcConfig) getSessionProperty(project,
1073: CONFIGURATION);
1074: } catch (XmlException e) {
1075: LineLengths lineLengths = getConfigurationLineLengths(project);
1076: handleXmlException(getConfigurationFile(project),
1077: lineLengths, e);
1078: } catch (Exception e) {
1079: /**/
1080: } catch (NoClassDefFoundError noClassDef) {
1081: noClassDef.printStackTrace();
1082: }
1083:
1084: if (config == null) {
1085: config = BAD_CONFIG;
1086: setSessionProperty(project, CONFIGURATION, config);
1087: fireConfigurationChange(project);
1088: }
1089: }
1090:
1091: return config;
1092: }
1093:
1094: public void handleXmlException(IFile configFile,
1095: LineLengths lineLengths, XmlException e) {
1096: if (configFile != null) {
1097: handleXmlErrors(configFile, lineLengths, e.getErrors()
1098: .iterator());
1099: }
1100: }
1101:
1102: public void handleXmlErrors(IFile configFile,
1103: LineLengths lineLengths, Iterator errors) {
1104: try {
1105: XmlError error;
1106:
1107: while (errors.hasNext()) {
1108: error = (XmlError) errors.next();
1109:
1110: HashMap<String, Object> map = new HashMap<String, Object>();
1111: int line = error.getLine();
1112: int col = error.getColumn();
1113: String msg = error.getMessage();
1114: int severity = XmlError2IMarkerSeverity(error
1115: .getSeverity());
1116: int start = lineLengths.offset(line - 1);
1117: int end = start
1118: + ((col == -1) ? lineLengths.lineSize(line - 1)
1119: : col);
1120:
1121: MarkerUtilities.setMessage(map, msg);
1122: MarkerUtilities.setLineNumber(map, line);
1123: MarkerUtilities.setCharStart(map, start);
1124: MarkerUtilities.setCharEnd(map, end);
1125:
1126: map.put(IMarker.PRIORITY, Integer
1127: .valueOf(IMarker.PRIORITY_HIGH));
1128: map.put(IMarker.SEVERITY, Integer.valueOf(severity));
1129: map.put(IMarker.LOCATION, "line " + line);
1130:
1131: MarkerUtilities.createMarker(configFile, map,
1132: "org.terracotta.dso.SAXMarker");
1133: }
1134: } catch (CoreException ce) {
1135: openError("Error handling XML error", ce);
1136: }
1137: }
1138:
1139: private int XmlError2IMarkerSeverity(int severity) {
1140: switch (severity) {
1141: case XmlError.SEVERITY_ERROR:
1142: return IMarker.SEVERITY_ERROR;
1143: case XmlError.SEVERITY_INFO:
1144: return IMarker.SEVERITY_INFO;
1145: case XmlError.SEVERITY_WARNING:
1146: return IMarker.SEVERITY_WARNING;
1147: default:
1148: return IMarker.SEVERITY_INFO;
1149: }
1150: }
1151:
1152: ConfigurationEditor[] getConfigurationEditors(IProject project) {
1153: ArrayList<ConfigurationEditor> list = new ArrayList<ConfigurationEditor>();
1154: IWorkbenchWindow[] windows = PlatformUI.getWorkbench()
1155: .getWorkbenchWindows();
1156:
1157: for (int i = 0; i < windows.length; i++) {
1158: IWorkbenchPage[] pages = windows[i].getPages();
1159:
1160: for (int j = 0; j < pages.length; j++) {
1161: IEditorReference[] editorRefs = pages[j]
1162: .getEditorReferences();
1163:
1164: for (int k = 0; k < editorRefs.length; k++) {
1165: IEditorPart editorPart = editorRefs[k]
1166: .getEditor(false);
1167:
1168: if (editorPart != null) {
1169: if (editorPart instanceof ConfigurationEditor) {
1170: ConfigurationEditor configEditor = (ConfigurationEditor) editorPart;
1171: IFile file = ((IFileEditorInput) editorPart
1172: .getEditorInput()).getFile();
1173:
1174: if (file.getProject().equals(project)) {
1175: list.add(configEditor);
1176: }
1177: }
1178: }
1179: }
1180: }
1181: }
1182: return list.toArray(new ConfigurationEditor[0]);
1183: }
1184:
1185: public void reloadConfiguration(IProject project) {
1186: clearConfigurationSessionProperties(project);
1187: getConfiguration(project);
1188:
1189: ConfigurationEditor[] configEditors = getConfigurationEditors(project);
1190: for (int i = 0; i < configEditors.length; i++) {
1191: IFileEditorInput fileEditorInput = (IFileEditorInput) configEditors[i]
1192: .getEditorInput();
1193: IFile file = fileEditorInput.getFile();
1194:
1195: configEditors[i].newInputFile(file);
1196: }
1197: }
1198:
1199: public synchronized void clearConfigurationSessionProperties(
1200: IProject project) {
1201: IFile file = getConfigurationFile(project);
1202: if (file != null && file.exists()) {
1203: setSessionProperty(file, ACTIVE_CONFIGURATION_FILE, null);
1204: }
1205:
1206: setSessionProperty(project, CONFIGURATION_LINE_LENGTHS, null);
1207: setSessionProperty(project, CONFIGURATION_FILE, null);
1208: setSessionProperty(project, CONFIGURATION, null);
1209:
1210: setConfigurationFileDirty(project, Boolean.FALSE);
1211: }
1212:
1213: public void setConfigurationFileDirty(IProject project,
1214: Boolean dirty) {
1215: setSessionProperty(project, IS_DIRTY, dirty);
1216: }
1217:
1218: public boolean isConfigurationFileDirty(IProject project) {
1219: if (project.isOpen()) {
1220: Boolean dirty = (Boolean) getSessionProperty(project,
1221: IS_DIRTY);
1222: return dirty != null ? dirty.booleanValue() : false;
1223: }
1224: return false;
1225: }
1226:
1227: public void ignoreNextConfigChange() {
1228: ResourceDeltaVisitor rdv = getResourceDeltaVisitor();
1229: rdv.fIgnoreNextConfigChange = true;
1230: }
1231:
1232: public void saveConfiguration(IProject project) {
1233: IFile configFile;
1234: TcConfig config;
1235: TcConfigDocument configDoc;
1236: XmlOptions opts;
1237: InputStream stream;
1238:
1239: ignoreNextConfigChange();
1240:
1241: opts = getXmlOptions();
1242: configFile = getConfigurationFile(project);
1243: config = getConfiguration(project);
1244: configDoc = TcConfigDocument.Factory.newInstance();
1245: stream = null;
1246:
1247: try {
1248: if (config != null) {
1249: configDoc.setTcConfig(config);
1250: stream = configDoc.newInputStream(opts);
1251: configFile.setContents(stream, true, true, null);
1252: stream = null;
1253:
1254: getConfigurationHelper(project).validateAll();
1255: fireConfigurationChange(project);
1256: }
1257: } catch (Exception e) {
1258: openError("Error saving '" + configFile.getName() + "'", e);
1259: } finally {
1260: if (stream != null) {
1261: IOUtils.closeQuietly(stream);
1262: }
1263: }
1264: }
1265:
1266: public void saveConfigurationQuietly(IProject project) {
1267: IFile configFile;
1268: TcConfig config;
1269: TcConfigDocument configDoc;
1270: XmlOptions opts;
1271: InputStream inStream;
1272: FileWriter outWriter;
1273:
1274: opts = getXmlOptions();
1275: configFile = getConfigurationFile(project);
1276: config = getConfiguration(project);
1277: configDoc = TcConfigDocument.Factory.newInstance();
1278: inStream = null;
1279: outWriter = null;
1280:
1281: try {
1282: if (config != null) {
1283: configDoc.setTcConfig(config);
1284:
1285: inStream = configDoc.newInputStream(opts);
1286: outWriter = new FileWriter(configFile.getLocation()
1287: .toOSString());
1288:
1289: CopyUtils.copy(inStream, outWriter);
1290: }
1291: } catch (Exception e) {
1292: openError("Error saving '" + configFile.getName() + "'", e);
1293: } finally {
1294: IOUtils.closeQuietly(inStream);
1295: IOUtils.closeQuietly(outWriter);
1296: }
1297: }
1298:
1299: public void setSessionProperty(IResource res, QualifiedName name,
1300: Object value) {
1301: if (res != null && res.exists()) {
1302: try {
1303: res.setSessionProperty(name, value);
1304: } catch (CoreException ce) {
1305: ce.printStackTrace();
1306: }
1307: }
1308: }
1309:
1310: public Object getSessionProperty(IResource res, QualifiedName name) {
1311: if (res != null && res.exists()) {
1312: try {
1313: return res.getSessionProperty(name);
1314: } catch (CoreException ce) {
1315: ce.printStackTrace();
1316: }
1317: }
1318:
1319: return null;
1320: }
1321:
1322: public void setPersistentProperty(IResource resource,
1323: QualifiedName name, String value) {
1324: if (resource != null && resource.exists()) {
1325: try {
1326: resource.setPersistentProperty(name, value);
1327: } catch (CoreException ce) {
1328: ce.printStackTrace();
1329: }
1330: }
1331: }
1332:
1333: public String getPersistentProperty(IResource resource,
1334: QualifiedName name) {
1335: if (resource != null && resource.exists()) {
1336: try {
1337: return resource.getPersistentProperty(name);
1338: } catch (CoreException ce) {
1339: return null;
1340: }
1341: }
1342:
1343: return null;
1344: }
1345:
1346: public ConfigurationEditor getConfigurationEditor(IProject project) {
1347: ConfigurationEditor[] configEditors = getConfigurationEditors(project);
1348: IFile configFile = getConfigurationFile(project);
1349:
1350: for (int i = 0; i < configEditors.length; i++) {
1351: IFileEditorInput fileEditorInput = (IFileEditorInput) configEditors[i]
1352: .getEditorInput();
1353: IFile file = fileEditorInput.getFile();
1354:
1355: if (file.equals(configFile)) {
1356: return configEditors[i];
1357: }
1358: }
1359:
1360: return null;
1361: }
1362:
1363: public ConfigurationEditor ensureConfigurationEditor(
1364: IProject project) {
1365: ConfigurationEditor editor = getConfigurationEditor(project);
1366:
1367: if (editor == null) {
1368: try {
1369: editor = openConfigurationEditor(project);
1370: } catch (PartInitException pie) {
1371: openError("Unable to open configuration editor", pie);
1372: }
1373: }
1374:
1375: return editor;
1376: }
1377:
1378: public void setConfigurationFilePath(IProject project, String path) {
1379: String oldPath = getConfigurationFilePath(project);
1380: IFile file = oldPath != null ? project.getFile(oldPath) : null;
1381: if (file != null && file.exists()) {
1382: clearSAXMarkers(file);
1383: setSessionProperty(file, ACTIVE_CONFIGURATION_FILE, null);
1384: }
1385:
1386: setPersistentProperty(project, CONFIGURATION_FILE_PATH, path);
1387:
1388: file = project.getFile(new Path(path));
1389: setSessionProperty(project, CONFIGURATION_FILE, file);
1390: setSessionProperty(file, ACTIVE_CONFIGURATION_FILE, "true");
1391: }
1392:
1393: public String getConfigurationFilePath(IProject project) {
1394: return getPersistentProperty(project, CONFIGURATION_FILE_PATH);
1395: }
1396:
1397: public IFile getConfigurationFile(IProject project) {
1398: IFile file = (IFile) getSessionProperty(project,
1399: CONFIGURATION_FILE);
1400:
1401: if (file == null) {
1402: String path = getConfigurationFilePath(project);
1403:
1404: if (path != null) {
1405: file = project.getFile(new Path(path));
1406: setSessionProperty(project, CONFIGURATION_FILE, file);
1407: setSessionProperty(file, ACTIVE_CONFIGURATION_FILE,
1408: "true");
1409: }
1410: }
1411:
1412: return file;
1413: }
1414:
1415: public void setServerOptions(IProject project, String opts) {
1416: setPersistentProperty(project, SERVER_OPTIONS, opts);
1417: }
1418:
1419: public String getServerOptions(IProject project) {
1420: String options = getPersistentProperty(project, SERVER_OPTIONS);
1421: return options != null ? options : "";
1422: }
1423:
1424: public void setAutoStartServerOption(IProject project,
1425: boolean autoStartServer) {
1426: setPersistentProperty(project, AUTO_START_SERVER_OPTION,
1427: Boolean.toString(autoStartServer));
1428: }
1429:
1430: public boolean getAutoStartServerOption(IProject project) {
1431: String option = getPersistentProperty(project,
1432: AUTO_START_SERVER_OPTION);
1433: return option != null ? Boolean.parseBoolean(option)
1434: : DEFAULT_AUTO_START_SERVER_OPTION;
1435: }
1436:
1437: public void setWarnConfigProblemsOption(IProject project,
1438: boolean warnConfigProblems) {
1439: setPersistentProperty(project, WARN_CONFIG_PROBLEMS_OPTION,
1440: Boolean.toString(warnConfigProblems));
1441: }
1442:
1443: public boolean getWarnConfigProblemsOption(IProject project) {
1444: String option = getPersistentProperty(project,
1445: WARN_CONFIG_PROBLEMS_OPTION);
1446: return option != null ? Boolean.parseBoolean(option)
1447: : DEFAULT_WARN_CONFIG_PROBLEMS_OPTION;
1448: }
1449:
1450: public void setQueryRestartOption(IProject project,
1451: boolean queryRestart) {
1452: setPersistentProperty(project, QUERY_RESTART_OPTION, Boolean
1453: .toString(queryRestart));
1454: }
1455:
1456: public boolean getQueryRestartOption(IProject project) {
1457: String option = getPersistentProperty(project,
1458: QUERY_RESTART_OPTION);
1459: return option != null ? Boolean.parseBoolean(option)
1460: : DEFAULT_QUERY_RESTART_OPTION;
1461: }
1462:
1463: public boolean hasTerracottaNature(IJavaElement element) {
1464: return hasTerracottaNature(element.getJavaProject()
1465: .getProject());
1466: }
1467:
1468: public boolean hasTerracottaNature(IProject project) {
1469: try {
1470: return project != null
1471: && project.hasNature(ProjectNature.NATURE_ID);
1472: } catch (CoreException ce) {/**/
1473: }
1474: return false;
1475: }
1476:
1477: public void inspect(final ICompilationUnit cu) {
1478: if (cu != null) {
1479: getCompilationUnitVisitor().inspect(cu);
1480: }
1481: }
1482:
1483: private CompilationUnitVisitor getCompilationUnitVisitor() {
1484: if (m_compilationUnitVisitor == null) {
1485: m_compilationUnitVisitor = new CompilationUnitVisitor();
1486: }
1487: return m_compilationUnitVisitor;
1488: }
1489:
1490: private ResourceDeltaVisitor getResourceDeltaVisitor() {
1491: if (m_resourceDeltaVisitor == null) {
1492: m_resourceDeltaVisitor = new ResourceDeltaVisitor();
1493: }
1494: return m_resourceDeltaVisitor;
1495: }
1496:
1497: class ResourceListener implements IResourceChangeListener {
1498: public void resourceChanged(final IResourceChangeEvent event) {
1499: switch (event.getType()) {
1500: case IResourceChangeEvent.POST_BUILD: {
1501: try {
1502: event.getDelta().accept(getResourceDeltaVisitor());
1503: } catch (CoreException ce) {
1504: openError(
1505: "Error handling resource change event for '"
1506: + event.getResource().getName()
1507: + "'", ce);
1508: }
1509: break;
1510: }
1511: }
1512: }
1513: }
1514:
1515: public void updateDecorator(final String id) {
1516: updateDecorators(new String[] { id });
1517: }
1518:
1519: private DecoratorUpdateAction getDecoratorUpdateAction() {
1520: if (m_decoratorUpdateAction == null) {
1521: m_decoratorUpdateAction = new DecoratorUpdateAction();
1522: }
1523: return m_decoratorUpdateAction;
1524: }
1525:
1526: public void updateDecorators(String[] ids) {
1527: DecoratorUpdateAction updater = getDecoratorUpdateAction();
1528:
1529: updater.setDecorators(ids);
1530: Display.getDefault().asyncExec(updater);
1531: }
1532:
1533: static class DecoratorUpdateAction implements Runnable {
1534: IDecoratorManager m_decoratorManager;
1535: String[] m_decorators;
1536:
1537: DecoratorUpdateAction() {
1538: m_decoratorManager = PlatformUI.getWorkbench()
1539: .getDecoratorManager();
1540: }
1541:
1542: void setDecorators(String[] ids) {
1543: m_decorators = ids;
1544: }
1545:
1546: public void run() {
1547: for (int i = 0; i < m_decorators.length; i++) {
1548: m_decoratorManager.update(m_decorators[i]);
1549: }
1550: }
1551: }
1552:
1553: private static final String[] DECORATOR_IDS = {
1554: "org.terracotta.dso.projectDecorator",
1555: ConfigFileDecorator.DECORATOR_ID,
1556: ServerRunningDecorator.DECORATOR_ID,
1557: AdaptedModuleDecorator.DECORATOR_ID,
1558: AdaptedTypeDecorator.DECORATOR_ID,
1559: AdaptedPackageFragmentDecorator.DECORATOR_ID,
1560: ExcludedTypeDecorator.DECORATOR_ID,
1561: ExcludedModuleDecorator.DECORATOR_ID,
1562: DistributedMethodDecorator.DECORATOR_ID,
1563: NameLockedDecorator.DECORATOR_ID,
1564: AutolockedDecorator.DECORATOR_ID,
1565: RootDecorator.DECORATOR_ID,
1566: TransientDecorator.DECORATOR_ID, };
1567:
1568: public void updateDecorators() {
1569: updateDecorators(DECORATOR_IDS);
1570: }
1571:
1572: public boolean hasSAXMarkers(IResource res) throws CoreException {
1573: if (res != null && res.exists()) {
1574: IMarker[] markers = res.findMarkers(
1575: "org.terracotta.dso.SAXMarker", false,
1576: IResource.DEPTH_ZERO);
1577: return markers.length > 0;
1578: }
1579: return false;
1580: }
1581:
1582: public void clearSAXMarkers(IResource res) {
1583: if (res != null && res.exists()) {
1584: try {
1585: res.deleteMarkers("org.terracotta.dso.SAXMarker",
1586: false, IResource.DEPTH_ZERO);
1587: } catch (CoreException ce) {
1588: openError("Error clearing SAX markers on file'"
1589: + res.getName() + "'", ce);
1590: }
1591: }
1592: }
1593:
1594: public boolean hasProblemMarkers(IResource res)
1595: throws CoreException {
1596: if (res != null && res.exists()) {
1597: IMarker[] markers = res.findMarkers(
1598: "org.eclipse.core.resources.problemmarker", true,
1599: IResource.DEPTH_ZERO);
1600: return markers.length > 0;
1601: }
1602: return false;
1603: }
1604:
1605: public void clearConfigProblemMarkers(IProject project) {
1606: try {
1607: IFile configFile = getConfigurationFile(project);
1608:
1609: if (configFile != null && configFile.exists()) {
1610: configFile.deleteMarkers(
1611: "org.terracotta.dso.ConfigProblemMarker", true,
1612: IResource.DEPTH_ZERO);
1613: }
1614: } catch (CoreException ce) {/**/
1615: }
1616: }
1617:
1618: public void clearConfigProblemMarkersOfType(IProject project,
1619: String markerType) {
1620: try {
1621: IFile configFile = getConfigurationFile(project);
1622:
1623: if (configFile != null && configFile.exists()) {
1624: configFile.deleteMarkers(markerType, false,
1625: IResource.DEPTH_ZERO);
1626: }
1627: } catch (CoreException ce) {/**/
1628: }
1629: }
1630:
1631: public static ImageDescriptor getImageDescriptor(String path) {
1632: return AbstractUIPlugin.imageDescriptorFromPlugin(
1633: getPluginId(), path);
1634: }
1635:
1636: public ConfigurationEditor openConfigurationEditor(IProject project)
1637: throws PartInitException {
1638: IWorkbench workbench = PlatformUI.getWorkbench();
1639: IWorkbenchWindow wbWin = workbench.getActiveWorkbenchWindow();
1640:
1641: if (wbWin != null) {
1642: IWorkbenchPage wbPage = wbWin.getActivePage();
1643:
1644: if (wbPage != null) {
1645: IFile configFile = getConfigurationFile(project);
1646: FileEditorInput fileEditorInput = new FileEditorInput(
1647: configFile);
1648: IEditorPart editorPart = wbPage
1649: .findEditor(fileEditorInput);
1650:
1651: if (editorPart != null) {
1652: if (editorPart instanceof ConfigurationEditor) {
1653: wbPage.activate(editorPart);
1654: return (ConfigurationEditor) editorPart;
1655: } else {
1656: wbPage.closeEditor(editorPart, true);
1657: }
1658: }
1659:
1660: if (configFile != null) {
1661: String configEditorID = "editors.configurationEditor";
1662:
1663: return (ConfigurationEditor) IDE.openEditor(wbPage,
1664: configFile, configEditorID, false);
1665: }
1666: }
1667: }
1668:
1669: return null;
1670: }
1671:
1672: public void closeConfigurationEditor(IProject project) {
1673: final ConfigurationEditor configEditor = getConfigurationEditor(project);
1674:
1675: if (configEditor != null) {
1676: if (Display.getCurrent() == null) {
1677: Display.getDefault().syncExec(new Runnable() {
1678: public void run() {
1679: configEditor.closeEditor();
1680: }
1681: });
1682: } else {
1683: configEditor.closeEditor();
1684: }
1685: }
1686: }
1687:
1688: private XmlOptions createXmlOptions() {
1689: XmlOptions opts = new XmlOptions();
1690:
1691: opts.setLoadLineNumbers();
1692: opts.setSavePrettyPrint();
1693: opts.setSavePrettyPrintIndent(2);
1694: opts.remove(XmlOptions.LOAD_STRIP_WHITESPACE);
1695: opts.remove(XmlOptions.LOAD_STRIP_COMMENTS);
1696:
1697: return opts;
1698: }
1699:
1700: public XmlOptions getXmlOptions() {
1701: return m_xmlOptions;
1702: }
1703:
1704: public void openError(final String msg, final Throwable t) {
1705: ILog log = getLog();
1706: log.log(new Status(IStatus.ERROR, getPluginId(),
1707: INTERNAL_ERROR, msg, t));
1708: }
1709:
1710: public void openError(final String msg) {
1711: Display.getDefault().asyncExec(new Runnable() {
1712: public void run() {
1713: ErrorDialog.showError(msg);
1714: }
1715: });
1716: }
1717:
1718: public boolean continueWithConfigProblems(final IProject project)
1719: throws CoreException {
1720: IFile configFile = getConfigurationFile(project);
1721:
1722: setSessionProperty(project, CONFIG_PROBLEM_CONTINUE, null);
1723:
1724: if (getWarnConfigProblemsOption(project)
1725: && hasProblemMarkers(configFile)) {
1726: Display.getDefault().syncExec(new Runnable() {
1727: public void run() {
1728: Shell shell = Display.getDefault().getActiveShell();
1729: ConfigProblemsDialog dialog = new ConfigProblemsDialog(
1730: shell, project);
1731:
1732: if (dialog.open() == IDialogConstants.OK_ID) {
1733: setSessionProperty(project,
1734: CONFIG_PROBLEM_CONTINUE, Boolean.TRUE);
1735: }
1736: }
1737: });
1738:
1739: return getSessionProperty(project, CONFIG_PROBLEM_CONTINUE) == Boolean.TRUE;
1740: }
1741:
1742: return true;
1743: }
1744:
1745: public static Display getStandardDisplay() {
1746: Display display = Display.getCurrent();
1747: if (display == null) {
1748: display = Display.getDefault();
1749: }
1750: return display;
1751: }
1752:
1753: public void fireConfigurationChange(IProject project) {
1754: m_configurationEventManager.fireConfigurationChange(project);
1755: JavaSetupParticipant.inspectAll();
1756: updateDecorators();
1757: }
1758:
1759: public void fireServerChanged(IProject project, int index) {
1760: m_configurationEventManager.fireServerChanged(project, index);
1761: }
1762:
1763: public void fireServersChanged(IProject project) {
1764: m_configurationEventManager.fireServersChanged(project);
1765: }
1766:
1767: public void fireRootChanged(IProject project, int index) {
1768: m_configurationEventManager.fireRootChanged(project, index);
1769: JavaSetupParticipant.inspectAll();
1770: updateDecorator(RootDecorator.DECORATOR_ID);
1771: }
1772:
1773: public void fireRootsChanged(IProject project) {
1774: m_configurationEventManager.fireRootsChanged(project);
1775: JavaSetupParticipant.inspectAll();
1776: updateDecorator(RootDecorator.DECORATOR_ID);
1777: }
1778:
1779: public void fireNamedLockChanged(IProject project, int index) {
1780: m_configurationEventManager
1781: .fireNamedLockChanged(project, index);
1782: JavaSetupParticipant.inspectAll();
1783: updateDecorator(NameLockedDecorator.DECORATOR_ID);
1784: }
1785:
1786: public void fireNamedLocksChanged(IProject project) {
1787: m_configurationEventManager.fireNamedLocksChanged(project);
1788: JavaSetupParticipant.inspectAll();
1789: updateDecorator(NameLockedDecorator.DECORATOR_ID);
1790: }
1791:
1792: public void fireAutolockChanged(IProject project, int index) {
1793: m_configurationEventManager.fireAutolockChanged(project, index);
1794: JavaSetupParticipant.inspectAll();
1795: updateDecorator(AutolockedDecorator.DECORATOR_ID);
1796: }
1797:
1798: public void fireAutolocksChanged(IProject project) {
1799: m_configurationEventManager.fireAutolocksChanged(project);
1800: JavaSetupParticipant.inspectAll();
1801: updateDecorator(AutolockedDecorator.DECORATOR_ID);
1802: }
1803:
1804: public void fireIncludeRuleChanged(IProject project, int index) {
1805: m_configurationEventManager.fireIncludeRuleChanged(project,
1806: index);
1807: JavaSetupParticipant.inspectAll();
1808: updateDecorators(new String[] {
1809: AdaptedModuleDecorator.DECORATOR_ID,
1810: AdaptedTypeDecorator.DECORATOR_ID,
1811: AdaptedPackageFragmentDecorator.DECORATOR_ID });
1812: }
1813:
1814: public void fireIncludeRulesChanged(IProject project) {
1815: m_configurationEventManager.fireIncludeRulesChanged(project);
1816: JavaSetupParticipant.inspectAll();
1817: updateDecorators(new String[] {
1818: AdaptedModuleDecorator.DECORATOR_ID,
1819: AdaptedTypeDecorator.DECORATOR_ID,
1820: AdaptedPackageFragmentDecorator.DECORATOR_ID });
1821: }
1822:
1823: public void fireExcludeRuleChanged(IProject project, int index) {
1824: m_configurationEventManager.fireExcludeRuleChanged(project,
1825: index);
1826: JavaSetupParticipant.inspectAll();
1827: updateDecorators(new String[] {
1828: ExcludedTypeDecorator.DECORATOR_ID,
1829: ExcludedModuleDecorator.DECORATOR_ID });
1830: }
1831:
1832: public void fireExcludeRulesChanged(IProject project) {
1833: m_configurationEventManager.fireExcludeRulesChanged(project);
1834: JavaSetupParticipant.inspectAll();
1835: updateDecorators(new String[] {
1836: ExcludedTypeDecorator.DECORATOR_ID,
1837: ExcludedModuleDecorator.DECORATOR_ID });
1838: }
1839:
1840: public void fireInstrumentationRulesChanged(IProject project) {
1841: m_configurationEventManager
1842: .fireInstrumentationRulesChanged(project);
1843: JavaSetupParticipant.inspectAll();
1844: updateDecorators(new String[] {
1845: AdaptedModuleDecorator.DECORATOR_ID,
1846: AdaptedTypeDecorator.DECORATOR_ID,
1847: AdaptedPackageFragmentDecorator.DECORATOR_ID,
1848: ExcludedTypeDecorator.DECORATOR_ID,
1849: ExcludedModuleDecorator.DECORATOR_ID });
1850: }
1851:
1852: public void fireTransientFieldsChanged(IProject project) {
1853: m_configurationEventManager.fireTransientFieldsChanged(project);
1854: JavaSetupParticipant.inspectAll();
1855: updateDecorator(TransientDecorator.DECORATOR_ID);
1856: }
1857:
1858: public void fireTransientFieldChanged(IProject project, int index) {
1859: m_configurationEventManager.fireTransientFieldChanged(project,
1860: index);
1861: JavaSetupParticipant.inspectAll();
1862: updateDecorator(TransientDecorator.DECORATOR_ID);
1863: }
1864:
1865: public void fireBootClassesChanged(IProject project) {
1866: m_configurationEventManager.fireBootClassesChanged(project);
1867: JavaSetupParticipant.inspectAll();
1868: }
1869:
1870: public void fireBootClassChanged(IProject project, int index) {
1871: m_configurationEventManager
1872: .fireBootClassChanged(project, index);
1873: JavaSetupParticipant.inspectAll();
1874: }
1875:
1876: public void fireDistributedMethodsChanged(IProject project) {
1877: m_configurationEventManager
1878: .fireDistributedMethodsChanged(project);
1879: updateDecorator(DistributedMethodDecorator.DECORATOR_ID);
1880: JavaSetupParticipant.inspectAll();
1881: }
1882:
1883: public void fireDistributedMethodChanged(IProject project, int index) {
1884: m_configurationEventManager.fireDistributedMethodChanged(
1885: project, index);
1886: updateDecorator(DistributedMethodDecorator.DECORATOR_ID);
1887: JavaSetupParticipant.inspectAll();
1888: }
1889:
1890: public void fireClientChanged(IProject project) {
1891: m_configurationEventManager.fireClientChanged(project);
1892: }
1893:
1894: public void fireModuleRepoChanged(IProject project, int index) {
1895: m_configurationEventManager.fireModuleRepoChanged(project,
1896: index);
1897: }
1898:
1899: public void fireModuleReposChanged(IProject project) {
1900: m_configurationEventManager.fireModuleReposChanged(project);
1901: }
1902:
1903: public void fireModuleChanged(IProject project, int index) {
1904: m_configurationEventManager.fireModuleChanged(project, index);
1905: }
1906:
1907: public void fireModulesChanged(IProject project) {
1908: m_configurationEventManager.fireModulesChanged(project);
1909: }
1910:
1911: public void addConfigurationListener(IConfigurationListener listener) {
1912: m_configurationEventManager.addConfigurationListener(listener);
1913: }
1914:
1915: public void removeConfigurationListener(
1916: IConfigurationListener listener) {
1917: m_configurationEventManager
1918: .removeConfigurationListener(listener);
1919: }
1920:
1921: public static Image createImage(String path) {
1922: return new JavaElementImageDescriptor(getImageDescriptor(path),
1923: 0, new Point(16, 16)).createImage(false);
1924: }
1925:
1926: public String configDocumentAsString(TcConfigDocument configDoc) {
1927: InputStream is = configDoc.newInputStream(getXmlOptions());
1928: StringWriter writer = new StringWriter();
1929: try {
1930: CopyUtils.copy(is, writer);
1931: } catch (IOException ioe) {/**/
1932: }
1933: return writer.toString();
1934: }
1935:
1936: public IFolder ensureRuntimeDirectory(IProject project,
1937: IProgressMonitor monitor) throws CoreException {
1938: IFolder folder = project.getFolder("terracotta");
1939: if (!folder.exists()) {
1940: folder.create(true, true, monitor);
1941: }
1942: return project.getFolder("terracotta");
1943: }
1944: }
1945:
1946: class ErrorDialog extends MessageDialog {
1947: ErrorDialog(String msg) {
1948: super (null, "Terracotta Plugin", null, msg,
1949: MessageDialog.ERROR,
1950: new String[] { IDialogConstants.OK_LABEL }, 0);
1951: }
1952:
1953: static void showError(String msg) {
1954: ErrorDialog dialog = new ErrorDialog(msg);
1955: dialog.setShellStyle(dialog.getShellStyle() | SWT.RESIZE);
1956: dialog.open();
1957: }
1958: }
|