blob: 41408ed27a66e3dea46e69a416d9969a6b4b9eb7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
* Sian January - initial version
*******************************************************************************/
package org.eclipse.ajdt.internal.launching;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.ajdt.core.AspectJPlugin;
import org.eclipse.ajdt.internal.ui.text.UIMessages;
import org.eclipse.core.internal.resources.ResourceStatus;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.launching.LaunchingMessages;
import org.eclipse.jdt.launching.ExecutionArguments;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstall2;
import org.eclipse.jdt.launching.IVMRunner;
import org.eclipse.jdt.launching.JavaLaunchDelegate;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.VMRunnerConfiguration;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Version;
public class LTWApplicationLaunchConfigurationDelegate
extends JavaLaunchDelegate {
private static final String classLoaderOption = "-Djava.system.class.loader"; //$NON-NLS-1$
private static final String ajClasspathOption = "-Daj.class.path"; //$NON-NLS-1$
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ILaunchConfigurationDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
*/
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(NLS.bind("{0}...", new String[]{configuration.getName()}), 3); //$NON-NLS-1$
// check for cancellation
if (monitor.isCanceled()) {
return;
}
generateAOPConfigFiles(configuration);
monitor.subTask(LaunchingMessages.JavaLocalApplicationLaunchConfigurationDelegate_Verifying_launch_attributes____1);
String mainTypeName = verifyMainTypeName(configuration);
IVMRunner runner = getVMRunner(configuration, mode);
boolean isJava5OrLater = isJava5OrLater(configuration);
File workingDir = verifyWorkingDirectory(configuration);
String workingDirName = null;
if (workingDir != null) {
workingDirName = workingDir.getAbsolutePath();
}
// Environment variables
String[] envp= getEnvironment(configuration);
// Classpath
String[] classpath = getClasspath(configuration);
String[] ltwClasspath = null;
try {
ltwClasspath = getLTWClasspath(classpath, isJava5OrLater);
} catch (MalformedURLException e) {
throw new CoreException(new ResourceStatus(IStatus.ERROR, null, UIMessages.LTW_error_launching, e));
} catch (IOException e) {
throw new CoreException(new ResourceStatus(IStatus.ERROR, null, UIMessages.LTW_error_launching, e));
}
// Program & VM args
String pgmArgs = getProgramArguments(configuration);
String vmArgs = getVMArguments(configuration);
vmArgs = addExtraVMArgs(vmArgs, classpath, ltwClasspath[0], isJava5OrLater); // weaver is always first entry in ltwclassath arroy
ExecutionArguments execArgs = new ExecutionArguments(vmArgs, pgmArgs);
// VM-specific attributes
Map<String, Object> vmAttributesMap = getVMSpecificAttributesMap(configuration);
// Create VM config
VMRunnerConfiguration runConfig = new VMRunnerConfiguration(mainTypeName, ltwClasspath);
runConfig.setProgramArguments(execArgs.getProgramArgumentsArray());
runConfig.setEnvironment(envp);
runConfig.setVMArguments(execArgs.getVMArgumentsArray());
runConfig.setWorkingDirectory(workingDirName);
runConfig.setVMSpecificAttributesMap(vmAttributesMap);
// Bootpath
runConfig.setBootClassPath(getBootpath(configuration));
// check for cancellation
if (monitor.isCanceled()) {
return;
}
// stop in main
prepareStopInMain(configuration);
// done the verification phase
monitor.worked(1);
monitor.subTask(LaunchingMessages.JavaLocalApplicationLaunchConfigurationDelegate_Creating_source_locator____2);
// set the default source locator if required
setDefaultSourceLocator(launch, configuration);
monitor.worked(1);
// Launch the configuration - 1 unit of work
runner.run(runConfig, launch, monitor);
// check for cancellation
if (monitor.isCanceled()) {
return;
}
monitor.done();
}
public boolean isJava5OrLater(ILaunchConfiguration configuration) throws CoreException {
IVMInstall install = getVMInstall(configuration);
if (install instanceof IVMInstall2) {
String version = ((IVMInstall2) install).getJavaVersion();
if (version != null) {
// expecting n.n.n-identifier
// see http://java.sun.com/j2se/versioning_naming.html
int dashIndex = version.indexOf('-');
if (dashIndex >= 0) {
version = version.substring(0, dashIndex);
}
Version osgiVersion = new Version(version);
return osgiVersion.getMinor() > 4;
}
}
return false;
}
/**
* Generate aop-ajc.xml files for any projects on the LTW aspectpath
* @param configuration
* @throws CoreException
*/
private void generateAOPConfigFiles(ILaunchConfiguration configuration) throws CoreException {
IProject[] workspaceProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
IRuntimeClasspathEntry[] aspectPathEntries = getAspectPathEntries(configuration);
for (int i = 0; i < aspectPathEntries.length; i++) {
String location = aspectPathEntries[i].getLocation();
for (int j = 0; j < workspaceProjects.length; j++) {
IProject project = workspaceProjects[j];
if(project.isOpen()) {
IRuntimeClasspathEntry entry = JavaRuntime.newProjectRuntimeClasspathEntry(JavaCore.create(project));
String projectLocation = entry.getLocation();
if(projectLocation != null && projectLocation.equals(location)) {
LTWUtils.generateLTWConfigFile(JavaCore.create(project));
}
}
}
}
// Generate aop-ajc.xml file for main project if it's an AspectJ project
String projectName = configuration.getAttribute(
IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME,
(String) null);
if (projectName != null && !projectName.trim().equals("")) { //$NON-NLS-1$
IProject project = AspectJPlugin.getWorkspace().getRoot()
.getProject(projectName);
if(project.isOpen() && project.hasNature(AspectJPlugin.ID_NATURE)) {
LTWUtils.generateLTWConfigFile(JavaCore.create(project));
}
}
}
/**
* Override getClasspath so that we also include the load time weaving
* aspectpath
*/
public String[] getClasspath(ILaunchConfiguration configuration)
throws CoreException {
IRuntimeClasspathEntry[] entries = JavaRuntime
.computeUnresolvedRuntimeClasspath(configuration);
IRuntimeClasspathEntry[] aspectPathEntries = getAspectPathEntries(configuration);
entries = JavaRuntime.resolveRuntimeClasspath(entries, configuration);
List<String> userEntries = new ArrayList<String>(entries.length + aspectPathEntries.length);
for (int i = 0; i < entries.length; i++) {
if (entries[i].getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
String location = entries[i].getLocation();
if (location != null) {
userEntries.add(location);
}
}
}
for (int i = 0; i < aspectPathEntries.length; i++) {
String location = aspectPathEntries[i].getLocation();
if (location != null) {
userEntries.add(location);
}
}
return (String[]) userEntries.toArray(new String[userEntries.size()]);
}
/**
* Get the load time weaving aspectpath from the given configuration
* @param configuration
* @return
* @throws CoreException
*/
private IRuntimeClasspathEntry[] getAspectPathEntries(ILaunchConfiguration configuration) throws CoreException {
List<?> entries = configuration.getAttribute(LTWAspectPathTab.ATTR_ASPECTPATH, Collections.EMPTY_LIST);
IRuntimeClasspathEntry[] rtes = new IRuntimeClasspathEntry[entries.size()];
Iterator<?> iter = entries.iterator();
int i = 0;
while (iter.hasNext()) {
rtes[i] = JavaRuntime.newRuntimeClasspathEntry((String)iter.next());
i++;
}
return rtes;
}
private String[] getLTWClasspath(String[] classpath, boolean isJava5OrLater) throws IOException {
File resolvedaspectjWeaverJar = FileLocator.getBundleFile(Platform.getBundle(AspectJPlugin.WEAVER_PLUGIN_ID));
if (!resolvedaspectjWeaverJar.getName().endsWith(".jar")) {
// runtime workbench
resolvedaspectjWeaverJar = new File(resolvedaspectjWeaverJar, "classes");
}
File resolvedaspectjRTJar = FileLocator.getBundleFile(Platform.getBundle(AspectJPlugin.RUNTIME_PLUGIN_ID));
if (!resolvedaspectjRTJar.getName().endsWith(".jar")) {
// runtime workbench
resolvedaspectjRTJar = new File(resolvedaspectjRTJar, "classes");
}
String weaverPath = new Path(resolvedaspectjWeaverJar.getCanonicalPath()).toOSString();
String rtPath = new Path(resolvedaspectjRTJar.getCanonicalPath()).toOSString();
List<String> fullPath = new ArrayList<String>();
fullPath.add(weaverPath);
fullPath.add(rtPath);
if (isJava5OrLater) {
for (String pathEntry : classpath) {
fullPath.add(pathEntry);
}
}
return fullPath.toArray(new String[0]);
}
private String addExtraVMArgs(String vmArgs, String[] ajClasspath, String pathToWeaver, boolean isJava5OrLater) {
StringBuffer sb = new StringBuffer(vmArgs);
if (!isJava5OrLater) {
sb.append(' ');
sb.append(classLoaderOption);
sb.append('=');
sb.append("org.aspectj.weaver.loadtime.WeavingURLClassLoader"); //$NON-NLS-1$
}
sb.append(' ');
sb.append(ajClasspathOption);
sb.append('=');
sb.append('\"');
for (int i = 0; i < ajClasspath.length; i++) {
if(i != 0) {
sb.append(File.pathSeparator);
}
sb.append(ajClasspath[i]);
}
sb.append('\"');
if (isJava5OrLater) {
sb.append(" \"-javaagent:" + pathToWeaver + "\"");
}
return sb.toString();
}
}