Bug 324246 - Cannot pass the project classpath to external programs defined as builders
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
index 70eb5a5..33c739a 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
@@ -79,6 +79,7 @@
import org.eclipse.jdt.debug.tests.launching.LaunchTests;
import org.eclipse.jdt.debug.tests.launching.LaunchesTests;
import org.eclipse.jdt.debug.tests.launching.MigrationDelegateTests;
+import org.eclipse.jdt.debug.tests.launching.ProjectClasspathVariableTests;
import org.eclipse.jdt.debug.tests.launching.TabGroupWrapperTests;
import org.eclipse.jdt.debug.tests.refactoring.MoveCompilationUnitTests;
import org.eclipse.jdt.debug.tests.refactoring.RenameCompilationUnitUnitTests;
@@ -140,6 +141,7 @@
addTest(new TestSuite(ConfigurationResourceMappingTests.class));
addTest(new TestSuite(ConfigurationEncodingTests.class));
addTest(new TestSuite(LaunchConfigurationManagerTests.class));
+ addTest(new TestSuite(ProjectClasspathVariableTests.class));
//Breakpoints tests
addTest(new TestSuite(DeferredBreakpointTests.class));
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/launching/ProjectClasspathVariableTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/launching/ProjectClasspathVariableTests.java
new file mode 100644
index 0000000..9b8d310
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/launching/ProjectClasspathVariableTests.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.launching;
+
+import java.io.File;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.variables.IStringVariableManager;
+import org.eclipse.core.variables.VariablesPlugin;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+
+/**
+ * Tests for the ${project_classpath} variable
+ */
+public class ProjectClasspathVariableTests extends AbstractDebugTest {
+
+ public ProjectClasspathVariableTests(String name) {
+ super(name);
+ }
+
+ /**
+ * Tests that a project name must be specified.
+ *
+ * @throws Exception
+ */
+ public void testMissingProjectName() throws Exception {
+ IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
+ try {
+ manager.performStringSubstitution("${project_classpath}");
+ } catch (CoreException e) {
+ return; // expected
+ }
+ assertNotNull("Test should have thrown an exception due to missing project name", null);
+ }
+
+ /**
+ * Tests that a Java project must exist
+ *
+ * @throws Exception
+ */
+ public void testProjectDoesNotExist() throws Exception {
+ IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
+ try {
+ manager.performStringSubstitution("${project_classpath:a_non_existant_project}");
+ } catch (CoreException e) {
+ return; // expected
+ }
+ assertNotNull("Test should have thrown an exception due to project does not exist", null);
+ }
+
+ public void testProjectClasspath() throws Exception {
+ IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
+ String projectName = getJavaProject().getElementName();
+ String cp = manager.performStringSubstitution("${project_classpath:" + projectName + "}");
+ StringBuffer buffer = new StringBuffer();
+ // expecting default output location and A.jar
+ buffer.append(ResourcesPlugin.getWorkspace().getRoot().getFolder(getJavaProject().getOutputLocation()).getLocation().toOSString());
+ buffer.append(File.pathSeparatorChar);
+ buffer.append(getJavaProject().getProject().getFolder("src").getFile("A.jar").getLocation().toOSString());
+ assertEquals("Wrong classpath", buffer.toString(), cp);
+ }
+
+}
diff --git a/org.eclipse.jdt.debug.ui/plugin.xml b/org.eclipse.jdt.debug.ui/plugin.xml
index df1e01d..f9d2c10 100644
--- a/org.eclipse.jdt.debug.ui/plugin.xml
+++ b/org.eclipse.jdt.debug.ui/plugin.xml
Binary files differ
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java
index 4f992d2..dddcda8 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java
@@ -167,9 +167,11 @@
public static String JavaLaunchShortcut_3;
public static String JreResolutionGenerator_open_ee_prefs;
-
public static String JreResolutionGenerator_opens_ee_prefs;
+ public static String ProjectClasspathArugumentSelector_0;
+ public static String ProjectClasspathArugumentSelector_1;
+
static {
// load message values from bundle file
NLS.initializeMessages(BUNDLE_NAME, LauncherMessages.class);
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties
index fa1dc6d..b91ad9c 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties
@@ -150,3 +150,5 @@
AbstractJavaMainTab_3=Select a project to constrain your search.
ExecutionEnvironmentSelector_0=Select Execution Environment
ExecutionEnvironmentSelector_1=Choose an environment (? = any character, * = any string):
+ProjectClasspathArugumentSelector_0=Select Java Project
+ProjectClasspathArugumentSelector_1=Choose a project (? = any character, * = any string):
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/ProjectClasspathArugumentSelector.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/ProjectClasspathArugumentSelector.java
new file mode 100644
index 0000000..11d04ce
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/ProjectClasspathArugumentSelector.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.ui.launcher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.variables.IStringVariable;
+import org.eclipse.debug.internal.ui.stringsubstitution.IArgumentSelector;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * Allows a Java project to be selected for the ${project_classpath} variable.
+ */
+public class ProjectClasspathArugumentSelector implements IArgumentSelector {
+
+ public ProjectClasspathArugumentSelector() {
+ }
+
+ public String selectArgument(IStringVariable variable, Shell shell) {
+ ElementListSelectionDialog dialog = new ElementListSelectionDialog(shell, new WorkbenchLabelProvider());
+ dialog.setTitle(LauncherMessages.ProjectClasspathArugumentSelector_0);
+ dialog.setMultipleSelection(false);
+ dialog.setMessage(LauncherMessages.ProjectClasspathArugumentSelector_1);
+ List javaProjects = new ArrayList();
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ for (int i = 0; i < projects.length; i++) {
+ IJavaProject jp = JavaCore.create(projects[i]);
+ if (jp.exists()) {
+ javaProjects.add(jp);
+ }
+ }
+ dialog.setElements(javaProjects.toArray());
+ if (dialog.open() == Window.OK) {
+ return (((IJavaProject)dialog.getResult()[0]).getElementName());
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.java
index 8933b32..b9fdea5 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -211,6 +211,9 @@
public static String PackageFragmentRootSourceContainerTypeDelegate_7;
public static String PackageFragmentRootSourceContainerTypeDelegate_8;
+ public static String ProjectClasspathVariableResolver_0;
+ public static String ProjectClasspathVariableResolver_1;
+
static {
// load message values from bundle file
NLS.initializeMessages(BUNDLE_NAME, LaunchingMessages.class);
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.properties b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.properties
index 613d016..564a7c4 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.properties
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2000, 2008 IBM Corporation and others.
+# Copyright (c) 2000, 2010 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
@@ -174,6 +174,8 @@
PackageFragmentRootSourceContainerTypeDelegate_6=Missing required <handle> attribute
PackageFragmentRootSourceContainerTypeDelegate_7=Unable to restore package fragment root source container
PackageFragmentRootSourceContainerTypeDelegate_8=Missing required <packageFragmentRoot> attribute
+ProjectClasspathVariableResolver_0=Project name must be specified with ${project_classpath} variable.
+ProjectClasspathVariableResolver_1=Specified Java project ''{0}'' does not exist.
EEVMType_1=Description is missing required property ''{0}''
EEVMType_2=Execution Environment Description
EEVMType_3=Install location (-Djava.home) does not exist: {0}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/ProjectClasspathVariableResolver.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/ProjectClasspathVariableResolver.java
new file mode 100644
index 0000000..fced6a9
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/ProjectClasspathVariableResolver.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.variables.IDynamicVariable;
+import org.eclipse.core.variables.IDynamicVariableResolver;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
+import org.eclipse.jdt.launching.IRuntimeClasspathEntry2;
+import org.eclipse.jdt.launching.JavaRuntime;
+
+import com.ibm.icu.text.MessageFormat;
+
+/**
+ * Resolver for ${project_classpath:<project_name>}. Returns a string corresponding to the
+ * class path of the corresponding Java project.
+ */
+public class ProjectClasspathVariableResolver implements IDynamicVariableResolver {
+
+ public String resolveValue(IDynamicVariable variable, String argument) throws CoreException {
+ if (argument == null) {
+ throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN, LaunchingMessages.ProjectClasspathVariableResolver_0));
+ }
+ IProject proj = ResourcesPlugin.getWorkspace().getRoot().getProject(argument);
+ IJavaProject javaProject = JavaCore.create(proj);
+ if (javaProject.exists()) {
+ IRuntimeClasspathEntry2 defClassPath = (IRuntimeClasspathEntry2) JavaRuntime.newDefaultProjectClasspathEntry(javaProject);
+ IRuntimeClasspathEntry[] entries = defClassPath.getRuntimeClasspathEntries(null);
+ List collect = new ArrayList();
+ for (int i = 0; i < entries.length; i++) {
+ IRuntimeClasspathEntry[] children = JavaRuntime.resolveRuntimeClasspathEntry(entries[i], javaProject);
+ for (int j = 0; j < children.length; j++) {
+ collect.add(children[j]);
+ }
+ }
+ entries = (IRuntimeClasspathEntry[]) collect.toArray(new IRuntimeClasspathEntry[collect.size()]);
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < entries.length; i++) {
+ if (i > 0) {
+ buffer.append(File.pathSeparatorChar);
+ }
+ buffer.append(entries[i].getLocation());
+ }
+ return buffer.toString();
+ } else {
+ throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN, MessageFormat.format(LaunchingMessages.ProjectClasspathVariableResolver_1, new String[]{argument})));
+ }
+ }
+
+}
diff --git a/org.eclipse.jdt.launching/plugin.properties b/org.eclipse.jdt.launching/plugin.properties
index b66efc9..fde3ef1 100644
--- a/org.eclipse.jdt.launching/plugin.properties
+++ b/org.eclipse.jdt.launching/plugin.properties
@@ -58,3 +58,4 @@
classpathVariableInitializer.deprecated = Use the JRE System Library instead
ee.home.description = Returns the absolute file system path of the JRE home directory corresponding to the specified execution environment. An execution environment identifier must be provided as an argument.
+project.classpath.description = Returns the resolved class path of the specified project. A project name must be provided as an argument.
diff --git a/org.eclipse.jdt.launching/plugin.xml b/org.eclipse.jdt.launching/plugin.xml
index 57def57..a9afc7e 100644
--- a/org.eclipse.jdt.launching/plugin.xml
+++ b/org.eclipse.jdt.launching/plugin.xml
@@ -301,6 +301,11 @@
name="ee_home"
resolver="org.eclipse.jdt.internal.launching.environments.ExecutionEnvironmentVariableResolver">
</variable>
+ <variable
+ description="%project.classpath.description"
+ name="project_classpath"
+ resolver="org.eclipse.jdt.internal.launching.ProjectClasspathVariableResolver">
+ </variable>
</extension>
</plugin>