001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package org.terracotta.dso.launch;
005:
006: import org.eclipse.core.resources.IFile;
007: import org.eclipse.core.resources.IProject;
008: import org.eclipse.core.resources.IResource;
009: import org.eclipse.core.runtime.CoreException;
010: import org.eclipse.core.runtime.IPath;
011: import org.eclipse.core.runtime.IProgressMonitor;
012: import org.eclipse.core.runtime.IStatus;
013: import org.eclipse.core.runtime.QualifiedName;
014: import org.eclipse.core.runtime.Status;
015: import org.eclipse.core.variables.IStringVariableManager;
016: import org.eclipse.core.variables.VariablesPlugin;
017: import org.eclipse.debug.core.ILaunch;
018: import org.eclipse.debug.core.ILaunchConfiguration;
019: import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
020: import org.eclipse.jdt.core.IJavaProject;
021: import org.eclipse.jdt.launching.IVMInstall;
022: import org.eclipse.jface.action.IAction;
023: import org.eclipse.jface.dialogs.IDialogConstants;
024: import org.eclipse.jface.dialogs.MessageDialog;
025: import org.eclipse.swt.SWT;
026: import org.eclipse.swt.events.SelectionAdapter;
027: import org.eclipse.swt.events.SelectionEvent;
028: import org.eclipse.swt.widgets.Button;
029: import org.eclipse.swt.widgets.Composite;
030: import org.eclipse.swt.widgets.Control;
031: import org.eclipse.swt.widgets.Display;
032: import org.eclipse.swt.widgets.Label;
033: import org.eclipse.swt.widgets.Shell;
034: import org.eclipse.ui.IWorkbench;
035: import org.eclipse.ui.PlatformUI;
036: import org.terracotta.dso.BootJarHelper;
037: import org.terracotta.dso.ClasspathProvider;
038: import org.terracotta.dso.ConfigurationHelper;
039: import org.terracotta.dso.ServerTracker;
040: import org.terracotta.dso.TcPlugin;
041: import org.terracotta.dso.actions.BuildBootJarAction;
042:
043: import java.util.concurrent.atomic.AtomicBoolean;
044: import java.util.concurrent.atomic.AtomicReference;
045:
046: /**
047: * Launcher helper for standard DSO applications, Eclipse applications, and JUnit tests.
048: */
049:
050: public class LaunchHelper implements IDSOLaunchConfigurationConstants {
051: private IDSOLaunchDelegate fLaunchDelegate;
052:
053: LaunchHelper(IDSOLaunchDelegate launchDelegate) {
054: fLaunchDelegate = launchDelegate;
055: }
056:
057: public ILaunchConfigurationWorkingCopy setup(
058: ILaunchConfiguration config, String mode, ILaunch launch,
059: IProgressMonitor monitor) throws CoreException {
060: try {
061: Display.getDefault().syncExec(new Runnable() {
062: public void run() {
063: IWorkbench workbench = PlatformUI.getWorkbench();
064: if (workbench != null) {
065: workbench.saveAllEditors(true);
066: }
067: }
068: });
069:
070: ILaunchConfigurationWorkingCopy wc = config
071: .getWorkingCopy();
072: final IJavaProject javaProject = fLaunchDelegate
073: .getJavaProject(wc);
074: final IProject project = javaProject.getProject();
075:
076: if (wc.getAttribute(ATTR_PROJECT_NAME, (String) null) == null) {
077: wc.setAttribute(ATTR_PROJECT_NAME, project.getName());
078: }
079:
080: final TcPlugin plugin = TcPlugin.getDefault();
081: String vmArgs = wc.getAttribute(ATTR_VM_ARGUMENTS, "");
082: IPath libDirPath = plugin.getLibDirPath();
083:
084: if (!plugin.continueWithConfigProblems(project)) {
085: return null;
086: }
087:
088: String serverProp = wc.getAttribute(ID_SERVER_SPEC,
089: (String) null);
090: if (serverProp == null
091: || (serverProp = serverProp.trim()) == null
092: || serverProp.length() == 0) {
093: String configServerSpec = wc.getAttribute(
094: ID_CONFIG_SERVER_SPEC, (String) null);
095: if (configServerSpec == null) {
096: ServerTracker tracker = ServerTracker.getDefault();
097: boolean autoStartServer = plugin
098: .getAutoStartServerOption(project);
099: if (!tracker.anyRunning(javaProject)
100: && (autoStartServer || queryStartServer(
101: project, monitor))) {
102: tracker.startServer(javaProject, plugin
103: .getAnyServerName(project), monitor);
104: }
105: if (monitor.isCanceled()) {
106: return null;
107: }
108: }
109: } else {
110: vmArgs += " -Dtc.server=" + serverProp;
111: }
112:
113: String configProp = " -Dtc.config=\"" + getConfigSpec(wc)
114: + "\"";
115:
116: IVMInstall vmInstall = fLaunchDelegate.getVMInstall(wc);
117: String portablePath = null;
118: String vmName = "default";
119: if (vmInstall != null) {
120: String vmType = vmInstall.getVMInstallType().getId();
121: vmName = vmInstall.getName();
122: portablePath = ATTR_JRE_CONTAINER_PATH + "/" + vmType
123: + "/" + vmName;
124: }
125: String jreContainerPath = wc.getAttribute(
126: ATTR_JRE_CONTAINER_PATH, portablePath);
127: String bootJarName = BootJarHelper.getHelper()
128: .getBootJarName(jreContainerPath);
129:
130: if (bootJarName == null || bootJarName.length() == 0) {
131: throw new RuntimeException(
132: "Can't determine BootJar name for runtime '"
133: + vmName + "'");
134: }
135:
136: IFile localBootJar = project.getFile(bootJarName);
137: IPath bootPath;
138:
139: testEnsureBootJar(plugin, javaProject, localBootJar,
140: jreContainerPath);
141:
142: if (localBootJar.exists()) {
143: bootPath = localBootJar.getLocation();
144: } else {
145: bootPath = BootJarHelper.getHelper().getBootJarPath(
146: bootJarName);
147: }
148:
149: String bootProp = " -Xbootclasspath/p:\""
150: + toOSString(bootPath) + "\"";
151:
152: if (!bootPath.toFile().exists()) {
153: String path = bootPath.toOSString();
154: plugin.openError("System bootjar '" + path
155: + "' not found", new RuntimeException(
156: "bootjar not found: " + path));
157: }
158:
159: String cpProp;
160: if (libDirPath.append("tc.jar").toFile().exists()) {
161: cpProp = " -Dtc.install-root=\""
162: + toOSString(plugin.getLocation()) + "\"";
163: } else {
164: cpProp = " -Dtc.classpath=\""
165: + ClasspathProvider.makeDevClasspath()
166: + "\" -Dtc.install-root=\""
167: + System.getProperty("tc.install-root") + "\"";
168: }
169:
170: String projectNameProp = "-Dproject.name=\""
171: + project.getName() + "\"";
172:
173: wc.setAttribute(ATTR_VM_ARGUMENTS, cpProp + configProp
174: + bootProp + " " + projectNameProp + " " + vmArgs);
175:
176: plugin.ensureRuntimeDirectory(project, monitor);
177:
178: return wc;
179: } catch (Throwable t) {
180: String msg = "Unable to launch '" + config.getName()
181: + "': " + t.getLocalizedMessage();
182: Status status = new Status(IStatus.ERROR, TcPlugin
183: .getPluginId(), 1, msg, t);
184: throw new CoreException(status);
185: }
186: }
187:
188: private static String toOSString(IPath path) {
189: return path != null ? path.makeAbsolute().toOSString() : "";
190: }
191:
192: private void testEnsureBootJar(final TcPlugin plugin,
193: final IJavaProject javaProject, final IFile bootJar,
194: final String jreContainerPath) {
195: IProject project = javaProject.getProject();
196: ConfigurationHelper configHelper = plugin
197: .getConfigurationHelper(project);
198: IFile configFile = plugin.getConfigurationFile(project);
199: boolean stdBootJarExists = false;
200: boolean configHasBootJarClasses = configHelper
201: .hasBootJarClasses();
202: boolean configHasModules = configHelper.hasModules();
203:
204: try {
205: stdBootJarExists = BootJarHelper.getHelper()
206: .getBootJarFile().exists();
207: } catch (CoreException ce) {/**/
208: }
209:
210: if (!stdBootJarExists
211: || (configFile != null && configHasBootJarClasses)) {
212: try {
213: bootJar.refreshLocal(IResource.DEPTH_ZERO, null);
214: } catch (CoreException ce) {/**/
215: }
216:
217: long bootStamp = bootJar.getLocation().toFile()
218: .lastModified();
219: long confStamp = configFile.getLocation().toFile()
220: .lastModified();
221:
222: if (!bootJar.exists()
223: || ((configHasModules || configHasBootJarClasses) && bootStamp < confStamp)) {
224: Display.getDefault().syncExec(new Runnable() {
225: public void run() {
226: BuildBootJarAction bbja = new BuildBootJarAction(
227: javaProject);
228: bbja.setJREContainerPath(jreContainerPath);
229: bbja.run((IAction) null);
230: }
231: });
232: }
233: }
234: }
235:
236: private String getConfigSpec(ILaunchConfigurationWorkingCopy wc)
237: throws CoreException {
238: IJavaProject javaProject = fLaunchDelegate.getJavaProject(wc);
239: IProject project = javaProject.getProject();
240: IFile configFile = TcPlugin.getDefault().getConfigurationFile(
241: project);
242: IPath configPath = configFile != null ? configFile
243: .getLocation() : null;
244: String configSpec;
245:
246: if ((configSpec = wc.getAttribute(ID_CONFIG_SERVER_SPEC,
247: (String) null)) == null) {
248: configSpec = wc.getAttribute(ID_CONFIG_FILE_SPEC,
249: toOSString(configPath));
250: IStringVariableManager variableManager = VariablesPlugin
251: .getDefault().getStringVariableManager();
252: configSpec = variableManager
253: .performStringSubstitution(configSpec);
254: }
255:
256: return configSpec;
257: }
258:
259: class QueryStartServerDialog extends MessageDialog {
260: Label msgLabel;
261: final AtomicBoolean quitAsking = new AtomicBoolean();
262:
263: QueryStartServerDialog(String title, String msg) {
264: super (new Shell(Display.getDefault()), title, null, msg,
265: MessageDialog.QUESTION, new String[] {
266: IDialogConstants.YES_LABEL,
267: IDialogConstants.NO_LABEL,
268: IDialogConstants.CANCEL_LABEL }, 0);
269: }
270:
271: protected Control createCustomArea(Composite parent) {
272: final Button quitAskingButton = new Button(parent,
273: SWT.CHECK);
274: quitAskingButton.setText("Remember this setting");
275: quitAskingButton
276: .addSelectionListener(new SelectionAdapter() {
277: public void widgetSelected(SelectionEvent e) {
278: quitAsking.set(quitAskingButton
279: .getSelection());
280: }
281: });
282:
283: return quitAskingButton;
284: }
285:
286: boolean quitAsking() {
287: return quitAsking.get();
288: }
289: }
290:
291: public static final QualifiedName QUERY_START_SERVER = new QualifiedName(
292: LaunchHelper.class.getName(), "QueryStartServer");
293:
294: private boolean queryStartServer(final IProject project,
295: final IProgressMonitor monitor) throws CoreException {
296: if (project.getSessionProperty(QUERY_START_SERVER) != null) {
297: return false;
298: }
299:
300: final AtomicBoolean startServer = new AtomicBoolean();
301: final AtomicReference errorRef = new AtomicReference();
302: Display.getDefault().syncExec(new Runnable() {
303: public void run() {
304: String title = "Terracotta";
305: String msg = "Start a local Terracotta Server?";
306: QueryStartServerDialog dialog = new QueryStartServerDialog(
307: title, msg);
308: int result = dialog.open();
309:
310: if (result == 2) {
311: monitor.setCanceled(true);
312: } else {
313: boolean start = (result == 0);
314: startServer.set(start);
315: if (dialog.quitAsking()) {
316: TcPlugin.getDefault().setAutoStartServerOption(
317: project, start);
318: try {
319: project.setSessionProperty(
320: QUERY_START_SERVER, "true");
321: } catch (CoreException ce) {
322: errorRef.set(ce);
323: }
324: }
325: }
326: }
327: });
328:
329: CoreException ce = (CoreException) errorRef.get();
330: if (ce != null) {
331: throw ce;
332: }
333:
334: return startServer.get();
335: }
336: }
|