diff options
Diffstat (limited to 'org.eclipse.m2e.launching/src')
3 files changed, 318 insertions, 178 deletions
diff --git a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java index fbcb1a78..f3e489d8 100644 --- a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java +++ b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java @@ -11,10 +11,9 @@ package org.eclipse.m2e.internal.launch; +import static org.eclipse.m2e.internal.launch.MavenLaunchUtils.quote; + import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -25,45 +24,27 @@ import org.slf4j.LoggerFactory; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.debug.core.DebugEvent; -import org.eclipse.debug.core.DebugPlugin; -import org.eclipse.debug.core.IDebugEventSetListener; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant; -import org.eclipse.debug.ui.RefreshTab; import org.eclipse.jdt.launching.IVMRunner; import org.eclipse.jdt.launching.JavaLaunchDelegate; -import org.eclipse.jdt.launching.VMRunnerConfiguration; import org.eclipse.jdt.launching.sourcelookup.containers.JavaSourceLookupParticipant; import org.eclipse.osgi.util.NLS; import org.eclipse.m2e.actions.MavenLaunchConstants; import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.embedder.IMavenConfiguration; -import org.eclipse.m2e.core.embedder.IMavenLauncherConfiguration; -import org.eclipse.m2e.core.embedder.MavenRuntime; -import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.eclipse.m2e.internal.launch.MavenRuntimeLaunchSupport.VMArguments; public class MavenLaunchDelegate extends JavaLaunchDelegate implements MavenLaunchConstants { - private static final Logger log = LoggerFactory.getLogger(MavenLaunchDelegate.class); + static final Logger log = LoggerFactory.getLogger(MavenLaunchDelegate.class); private static final String LAUNCHER_TYPE = "org.codehaus.classworlds.Launcher"; //$NON-NLS-1$ - private static final String LAUNCHER_TYPE3 = "org.codehaus.plexus.classworlds.launcher.Launcher"; // classworlds 2.0 //$NON-NLS-1$ - - private static final String LAUNCH_M2CONF_FILE = "org.eclipse.m2e.internal.launch.M2_CONF"; //$NON-NLS-1$ - - private MavenRuntime runtime; - - private MavenLauncherConfigurationHandler m2conf; - - private File confFile; + //classworlds 2.0 + private static final String LAUNCHER_TYPE3 = "org.codehaus.plexus.classworlds.launcher.Launcher"; //$NON-NLS-1$ private ILaunch launch; @@ -73,6 +54,8 @@ public class MavenLaunchDelegate extends JavaLaunchDelegate implements MavenLaun private String programArguments; + private MavenRuntimeLaunchSupport launchSupport; + public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { this.launch = launch; @@ -84,31 +67,7 @@ public class MavenLaunchDelegate extends JavaLaunchDelegate implements MavenLaun log.info(" mvn" + getProgramArguments(configuration)); //$NON-NLS-1$ try { - runtime = MavenLaunchUtils.getMavenRuntime(configuration); - - m2conf = new MavenLauncherConfigurationHandler(); - if(shouldResolveWorkspaceArtifacts(configuration)) { - m2conf.addArchiveEntry(MavenLaunchUtils.getCliResolver(runtime)); - } - MavenLaunchUtils.addUserComponents(configuration, m2conf); - runtime.createLauncherConfiguration(m2conf, monitor); - - File state = MavenPluginActivator.getDefault().getStateLocation().toFile(); - try { - File dir = new File(state, "launches"); //$NON-NLS-1$ - dir.mkdirs(); - confFile = File.createTempFile("m2conf", ".tmp", dir); //$NON-NLS-1$ //$NON-NLS-2$ - launch.setAttribute(LAUNCH_M2CONF_FILE, confFile.getCanonicalPath()); - OutputStream os = new FileOutputStream(confFile); - try { - m2conf.save(os); - } finally { - os.close(); - } - } catch(IOException e) { - throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, -1, - Messages.MavenLaunchDelegate_error_cannot_create_conf, e)); - } + this.launchSupport = MavenRuntimeLaunchSupport.create(configuration, launch, monitor); if(launch.getSourceLocator() instanceof MavenSourceLocator) { final MavenSourceLocator sourceLocator = (MavenSourceLocator) launch.getSourceLocator(); @@ -134,30 +93,15 @@ public class MavenLaunchDelegate extends JavaLaunchDelegate implements MavenLaun } public IVMRunner getVMRunner(final ILaunchConfiguration configuration, String mode) throws CoreException { - final IVMRunner runner = super.getVMRunner(configuration, mode); - - return new IVMRunner() { - public void run(VMRunnerConfiguration runnerConfiguration, ILaunch launch, IProgressMonitor monitor) - throws CoreException { - runner.run(runnerConfiguration, launch, monitor); - - IProcess[] processes = launch.getProcesses(); - if(processes != null && processes.length > 0) { - BackgroundResourceRefresher refresher = new BackgroundResourceRefresher(configuration, launch); - refresher.init(); - } else { - removeTempFiles(launch); - } - } - }; + return launchSupport.decorateVMRunner(super.getVMRunner(configuration, mode)); } - public String getMainTypeName(ILaunchConfiguration configuration) throws CoreException { - return runtime.getVersion().startsWith("3.0") ? LAUNCHER_TYPE3 : LAUNCHER_TYPE; //$NON-NLS-1$ + public String getMainTypeName(ILaunchConfiguration configuration) { + return launchSupport.getVersion().startsWith("3.0") ? LAUNCHER_TYPE3 : LAUNCHER_TYPE; //$NON-NLS-1$ } - public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException { - List<String> cp = m2conf.getRealmEntries(IMavenLauncherConfiguration.LAUNCHER_REALM); + public String[] getClasspath(ILaunchConfiguration configuration) { + List<String> cp = launchSupport.getBootClasspath(); return cp.toArray(new String[cp.size()]); } @@ -180,53 +124,16 @@ public class MavenLaunchDelegate extends JavaLaunchDelegate implements MavenLaun } public String getVMArguments(ILaunchConfiguration configuration) throws CoreException { - /* - * <pre> - * %MAVEN_JAVA_EXE% %MAVEN_OPTS% - * -classpath %CLASSWORLDS_JAR% - * "-Dclassworlds.conf=%M2_HOME%\bin\m2.conf" - * "-Dmaven.home=%M2_HOME%" - * org.codehaus.classworlds.Launcher - * %MAVEN_CMD_LINE_ARGS% - * </pre> - */ - - StringBuffer sb = new StringBuffer(); - - // workspace artifact resolution - if(shouldResolveWorkspaceArtifacts(configuration)) { - File state = MavenPluginActivator.getDefault().getMavenProjectManager().getWorkspaceStateFile(); - sb.append(" -Dm2eclipse.workspace.state=").append(quote(state.getAbsolutePath())); //$NON-NLS-1$ - } - - // maven.home - String location = runtime.getLocation(); - if(location != null) { - sb.append(" -Dmaven.home=").append(quote(location)); //$NON-NLS-1$ - } - - // m2.conf - sb.append(" -Dclassworlds.conf=").append(quote(confFile.getAbsolutePath())); //$NON-NLS-1$ + VMArguments arguments = launchSupport.getVMArguments(); // user configured entries - sb.append(" ").append(super.getVMArguments(configuration)); //$NON-NLS-1$ + arguments.append(super.getVMArguments(configuration)); for(IMavenLaunchParticipant participant : participants) { - String vmArguments = participant.getVMArguments(configuration, launch, monitor); - if(vmArguments != null) { - sb.append(" ").append(vmArguments); - } + arguments.append(participant.getVMArguments(configuration, launch, monitor)); } - return sb.toString(); - } - - private String quote(String string) { - return string.indexOf(' ') > -1 ? "\"" + string + "\"" : string; //$NON-NLS-1$ //$NON-NLS-2$ - } - - private boolean shouldResolveWorkspaceArtifacts(ILaunchConfiguration configuration) throws CoreException { - return configuration.getAttribute(ATTR_WORKSPACE_RESOLUTION, false); + return arguments.toString(); } protected String getGoals(ILaunchConfiguration configuration) throws CoreException { @@ -344,73 +251,7 @@ public class MavenLaunchDelegate extends JavaLaunchDelegate implements MavenLaun } static void removeTempFiles(ILaunch launch) { - String m2confName = launch.getAttribute(LAUNCH_M2CONF_FILE); - if(m2confName != null) { - new File(m2confName).delete(); - } - } - - /** - * Refreshes resources as specified by a launch configuration, when an associated process terminates. Adapted from - * org.eclipse.ui.externaltools.internal.program.launchConfigurations.BackgroundResourceRefresher - */ - public static class BackgroundResourceRefresher implements IDebugEventSetListener { - final ILaunchConfiguration configuration; - - final IProcess process; - - final ILaunch launch; - - public BackgroundResourceRefresher(ILaunchConfiguration configuration, ILaunch launch) { - this.configuration = configuration; - this.process = launch.getProcesses()[0]; - this.launch = launch; - } - - /** - * If the process has already terminated, resource refreshing is done immediately in the current thread. Otherwise, - * refreshing is done when the process terminates. - */ - public void init() { - synchronized(process) { - if(process.isTerminated()) { - processResources(); - } else { - DebugPlugin.getDefault().addDebugEventListener(this); - } - } - } - - /* (non-Javadoc) - * @see org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse.debug.core.DebugEvent[]) - */ - public void handleDebugEvents(DebugEvent[] events) { - for(int i = 0; i < events.length; i++ ) { - DebugEvent event = events[i]; - if(event.getSource() == process && event.getKind() == DebugEvent.TERMINATE) { - DebugPlugin.getDefault().removeDebugEventListener(this); - processResources(); - break; - } - } - } - - protected void processResources() { - removeTempFiles(launch); - - Job job = new Job(Messages.MavenLaunchDelegate_job_name) { - public IStatus run(IProgressMonitor monitor) { - try { - RefreshTab.refreshResources(configuration, monitor); - return Status.OK_STATUS; - } catch(CoreException e) { - log.error(e.getMessage(), e); - return e.getStatus(); - } - } - }; - job.schedule(); - } + MavenRuntimeLaunchSupport.removeTempFiles(launch); } private List<IMavenLaunchParticipant> getParticipants(ILaunchConfiguration configuration, ILaunch launch) diff --git a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchUtils.java b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchUtils.java index 0418c7ac..44761cc1 100644 --- a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchUtils.java +++ b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchUtils.java @@ -123,4 +123,26 @@ public class MavenLaunchUtils { } } } + + /** + * @since 1.4 + */ + public static String quote(String string) { + return string.indexOf(' ') > -1 ? "\"" + string + "\"" : string; //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * @since 1.4 + */ + public static String toPath(List<String> cp) { + StringBuilder sb = new StringBuilder(); + for(String cpe : cp) { + if(sb.length() > 0) { + sb.append(File.pathSeparator); + } + sb.append(cpe); + } + return sb.toString(); + } + } diff --git a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenRuntimeLaunchSupport.java b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenRuntimeLaunchSupport.java new file mode 100644 index 00000000..b2f5fcbf --- /dev/null +++ b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenRuntimeLaunchSupport.java @@ -0,0 +1,277 @@ +/******************************************************************************* + * Copyright (c) 2008-2010 Sonatype, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Sonatype, Inc. - initial API and implementation + *******************************************************************************/ + +package org.eclipse.m2e.internal.launch; + +import static org.eclipse.m2e.actions.MavenLaunchConstants.ATTR_WORKSPACE_RESOLUTION; +import static org.eclipse.m2e.actions.MavenLaunchConstants.PLUGIN_ID; +import static org.eclipse.m2e.internal.launch.MavenLaunchUtils.quote; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugEvent; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.IDebugEventSetListener; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.model.IProcess; +import org.eclipse.debug.ui.RefreshTab; +import org.eclipse.jdt.launching.IVMRunner; +import org.eclipse.jdt.launching.VMRunnerConfiguration; + +import org.eclipse.m2e.core.embedder.IMavenLauncherConfiguration; +import org.eclipse.m2e.core.embedder.MavenRuntime; +import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.eclipse.m2e.core.internal.project.WorkspaceStateWriter; + + +/** + * Helper class to configure and launch MavenRuntime instance. + * <p> + * Generates classworld configuration file, i.e. m2.conf. Generated classworld configuration file will include + * cliresolver for launch configuration that have workspace resolution enabled. + * <p> + * Sets the following conventional launch configuration attributes. + * <ul> + * <li>m2eclipse.workspace.state, full absolute path of m2e workspace state file. See {@link WorkspaceStateWriter} for + * details of the state file format. Only set if workspace dependency resolution is enabled for the launch + * configuration.</li> + * <li>maven.bootclasspath, maven runtime bootstrap classpath, normally only contains classworlds jar.</li> + * <li>maven.home, location of maven runtime, logical name is used for embedded and workspace runtimes</li> + * <li>classworlds.conf, location of classworlds configuration file, i.e. m2.conf</li> + * </ul> + * + * @since 1.4 + */ +public class MavenRuntimeLaunchSupport { + private static final String LAUNCH_M2CONF_FILE = "org.eclipse.m2e.internal.launch.M2_CONF"; //$NON-NLS-1$ + + private final MavenRuntime runtime; + + private final MavenLauncherConfigurationHandler cwconf; + + private final boolean resolveWorkspaceArtifacts; + + private final File cwconfFile; + + public static class VMArguments { + + private final StringBuilder properties = new StringBuilder(); + + public void append(String str) { + if(str != null) { + str = str.trim(); + } + if(str != null && str.length() > 0) { + if(properties.length() > 0) { + properties.append(' '); + } + properties.append(str); + } + } + + public void appendProperty(String key, String value) { + append("-D" + key + "=" + value); + } + + @Override + public String toString() { + return properties.toString(); + } + } + + private MavenRuntimeLaunchSupport(MavenRuntime runtime, MavenLauncherConfigurationHandler cwconf, File cwconfFile, + boolean resolveWorkspaceArtifacts) { + this.runtime = runtime; + this.cwconf = cwconf; + this.cwconfFile = cwconfFile; + this.resolveWorkspaceArtifacts = resolveWorkspaceArtifacts; + } + + public static MavenRuntimeLaunchSupport create(ILaunchConfiguration configuration, ILaunch launch, + IProgressMonitor monitor) throws CoreException { + MavenRuntime runtime = MavenLaunchUtils.getMavenRuntime(configuration); + + boolean resolveWorkspaceArtifacts = configuration.getAttribute(ATTR_WORKSPACE_RESOLUTION, false); + + MavenLauncherConfigurationHandler cwconf = new MavenLauncherConfigurationHandler(); + if(resolveWorkspaceArtifacts) { + cwconf.addArchiveEntry(MavenLaunchUtils.getCliResolver(runtime)); + } + MavenLaunchUtils.addUserComponents(configuration, cwconf); + runtime.createLauncherConfiguration(cwconf, monitor); + + File cwconfFile; + try { + File state = MavenLaunchPlugin.getDefault().getStateLocation().toFile(); + File dir = new File(state, "launches"); //$NON-NLS-1$ + dir.mkdirs(); + cwconfFile = File.createTempFile("m2conf", ".tmp", dir); //$NON-NLS-1$ //$NON-NLS-2$ + launch.setAttribute(LAUNCH_M2CONF_FILE, cwconfFile.getCanonicalPath()); + OutputStream os = new FileOutputStream(cwconfFile); + try { + cwconf.save(os); + } finally { + os.close(); + } + } catch(IOException e) { + throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, -1, + Messages.MavenLaunchDelegate_error_cannot_create_conf, e)); + } + + return new MavenRuntimeLaunchSupport(runtime, cwconf, cwconfFile, resolveWorkspaceArtifacts); + } + + public static void removeTempFiles(ILaunch launch) { + String m2confName = launch.getAttribute(LAUNCH_M2CONF_FILE); + if(m2confName != null) { + new File(m2confName).delete(); + } + } + + /** + * MAVEN_HOME or equivalent location of the Maven runtime. + */ + public String getLocation() { + return runtime.getLocation(); + } + + /** + * Location of classworld configuration file, i.e. m2.conf, of the Maven runtime. + */ + public File getClassworldConfFile() { + return cwconfFile; + } + + /** + * Bootstrap classpath of the Maven runtime, normally only contains classworlds jar. + */ + public List<String> getBootClasspath() { + return cwconf.getRealmEntries(IMavenLauncherConfiguration.LAUNCHER_REALM); + } + + public String getVersion() { + return runtime.getVersion(); + } + + public VMArguments getVMArguments() { + VMArguments properties = new VMArguments(); + + // workspace artifact resolution + if(resolveWorkspaceArtifacts) { + File state = MavenPluginActivator.getDefault().getMavenProjectManager().getWorkspaceStateFile(); + properties.appendProperty("m2eclipse.workspace.state", quote(state.getAbsolutePath())); //$NON-NLS-1$ + } + + // maven.home + String location = runtime.getLocation(); + if(location != null) { + properties.appendProperty("maven.home", quote(location)); //$NON-NLS-1$ + } + + // m2.conf + properties.appendProperty("classworlds.conf", quote(cwconfFile.getAbsolutePath())); //$NON-NLS-1$ + + // maven bootclasspath, i.e. classworlds jar. + // TODO only used by ITs, so consider making optional + properties.appendProperty("maven.bootclasspath", MavenLaunchUtils.toPath(getBootClasspath())); + + return properties; + } + + public IVMRunner decorateVMRunner(final IVMRunner runner) { + return new IVMRunner() { + public void run(VMRunnerConfiguration runnerConfiguration, ILaunch launch, IProgressMonitor monitor) + throws CoreException { + runner.run(runnerConfiguration, launch, monitor); + + IProcess[] processes = launch.getProcesses(); + if(processes != null && processes.length > 0) { + ILaunchConfiguration configuration = launch.getLaunchConfiguration(); + BackgroundResourceRefresher refresher = new BackgroundResourceRefresher(configuration, launch); + refresher.init(); + } else { + removeTempFiles(launch); + } + } + }; + } +} + + +/** + * Refreshes resources as specified by a launch configuration, when an associated process terminates. Adapted from + * org.eclipse.ui.externaltools.internal.program.launchConfigurations.BackgroundResourceRefresher + */ +class BackgroundResourceRefresher implements IDebugEventSetListener { + final ILaunchConfiguration configuration; + + final IProcess process; + + final ILaunch launch; + + public BackgroundResourceRefresher(ILaunchConfiguration configuration, ILaunch launch) { + this.configuration = configuration; + this.process = launch.getProcesses()[0]; + this.launch = launch; + } + + /** + * If the process has already terminated, resource refreshing is done immediately in the current thread. Otherwise, + * refreshing is done when the process terminates. + */ + public void init() { + synchronized(process) { + if(process.isTerminated()) { + processResources(); + } else { + DebugPlugin.getDefault().addDebugEventListener(this); + } + } + } + + public void handleDebugEvents(DebugEvent[] events) { + for(int i = 0; i < events.length; i++ ) { + DebugEvent event = events[i]; + if(event.getSource() == process && event.getKind() == DebugEvent.TERMINATE) { + DebugPlugin.getDefault().removeDebugEventListener(this); + processResources(); + break; + } + } + } + + protected void processResources() { + MavenLaunchDelegate.removeTempFiles(launch); + + Job job = new Job(Messages.MavenLaunchDelegate_job_name) { + public IStatus run(IProgressMonitor monitor) { + try { + RefreshTab.refreshResources(configuration, monitor); + return Status.OK_STATUS; + } catch(CoreException e) { + MavenLaunchDelegate.log.error(e.getMessage(), e); + return e.getStatus(); + } + } + }; + job.schedule(); + } +} |