Skip to content
This repository has been archived by the owner on Jul 13, 2022. It is now read-only.

Commit

Permalink
Filter test classpath elements from running Gradle Boot App
Browse files Browse the repository at this point in the history
See: #264

Signed-off-by: Kris De Volder <[email protected]>
  • Loading branch information
kdvolder committed Jan 10, 2019
1 parent 7842bab commit ff7968f
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
import java.net.URL;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.function.Predicate;

import javax.xml.transform.stream.StreamResult;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
Expand All @@ -38,6 +41,7 @@
import org.springframework.ide.eclipse.boot.launch.process.BootProcessFactory;
import org.springframework.ide.eclipse.boot.test.util.LaunchResult;
import org.springframework.ide.eclipse.boot.test.util.LaunchUtil;
import org.springsource.ide.eclipse.commons.frameworks.test.util.ACondition;
import org.springsource.ide.eclipse.commons.frameworks.test.util.Timewatch;
import org.springsource.ide.eclipse.commons.tests.util.StsTestUtil;

Expand Down Expand Up @@ -372,6 +376,47 @@ private void doThinWrapperLaunchTest(File thinWrapper, String importStrategy) th
}
}

/**
* Name fragments that, when seen in a dependency, probably mean the dependency is a test dependency
*/
private static final String[] testFragments = {
"test",
"junit",
"assertj",
"mockito",
};

private static boolean isTestClasspathEntry(String cpe) {
for (String testFrag : testFragments) {
String normalizedEntry = cpe.replace('\\', '/');
int slash = normalizedEntry.lastIndexOf('/');
if (slash>=0) {
normalizedEntry = normalizedEntry.substring(slash);
}
if (normalizedEntry.contains(testFrag)) {
return true;
}
}
return false;
}


public void testRuntimeClasspathNoTestStuffGradle() throws Exception {
IProject project = projects.createBootProject("gradle-test-project", withImportStrategy("GRADLE-Buildship 3.x"));
ILaunchConfigurationWorkingCopy wc = createBaseWorkingCopy(project.getName(), "com.example.demo.GradleTestProjectApplication");
String[] cp = getClasspath(new BootLaunchConfigurationDelegate(), wc);

ArrayList<String> testDependencies = new ArrayList<>();
for (String cpe : cp) {
if (isTestClasspathEntry(cpe)) {
testDependencies.add(cpe);
}
}
if (!testDependencies.isEmpty()) {
fail("Shouldn't have test dependencies but found: "+testDependencies);
}
}

public void testRuntimeClasspathNoTestStuff() throws Exception {
createLaunchReadyProject(TEST_PROJECT);
ILaunchConfigurationWorkingCopy wc = createBaseWorkingCopy();
Expand Down Expand Up @@ -443,7 +488,8 @@ private static void assertClasspathHasEntry(String[] cp, String expect) {
private String[] getClasspath(JavaLaunchDelegate delegate,
ILaunchConfigurationWorkingCopy wc) throws CoreException {
System.out.println("\n====classpath according to "+delegate.getClass().getSimpleName());
String[] classpath = delegate.getClasspath(wc);
String[][] cpAndMp = delegate.getClasspathAndModulepath(wc);
String[] classpath = cpAndMp[0];
for (String element : classpath) {
int chop = element.lastIndexOf('/');
System.out.println('"'+element.substring(chop+1)+"\",");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@

public abstract class AbstractBootLaunchConfigurationDelegate extends JavaLaunchDelegate {

private static final String JDT_JAVA_APPLICATION = "org.eclipse.jdt.launching.localJavaApplication";

private static final String SILENT_EXIT_EXCEPTION = "org.springframework.boot.devtools.restart.SilentExitExceptionHandler$SilentExitException";

private static final String M2E_CLASSPATH_PROVIDER = "org.eclipse.m2e.launchconfig.classpathProvider";
Expand All @@ -59,6 +61,7 @@ public abstract class AbstractBootLaunchConfigurationDelegate extends JavaLaunch

private static final String BOOT_MAVEN_SOURCE_PATH_PROVIDER = "org.springframework.ide.eclipse.boot.launch.BootMavenSourcePathProvider";
private static final String BOOT_MAVEN_CLASS_PATH_PROVIDER = "org.springframework.ide.eclipse.boot.launch.BootMavenClassPathProvider";
private static final String BUILDSHIP_CLASS_PATH_PROVIDER = "org.eclipse.buildship.core.classpathprovider";

/**
* Spring boot properties are stored as launch confiuration properties with
Expand Down Expand Up @@ -369,17 +372,71 @@ protected ILaunchConfiguration configureClassPathProviders(ILaunchConfiguration
IProject project = BootLaunchConfigurationDelegate.getProject(conf);
if (project.hasNature(SpringBootCore.M2E_NATURE)) {
conf = modify(conf, (ILaunchConfigurationWorkingCopy wc) -> {
enableClasspathProviders(wc);
enableMavenClasspathProviders(wc);
});
} else if (project.hasNature(SpringBootCore.BUILDSHIP_NATURE)) {
conf = modify(conf, wc -> {
enableGradleClasspathProviders(wc);
});
}
return conf;
}

public static void enableClasspathProviders(ILaunchConfigurationWorkingCopy wc) {
@Override
public String[][] getClasspathAndModulepath(ILaunchConfiguration configuration) throws CoreException {
if (configuration.hasAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE)) {
//TODO: This is a dirty hack. We 'trick' BuildShip to treat our launch config as if it is a plain JDT launch by making
// a temporary copy of it.
//A request to make BuildShip provide a cleaner way to do this was filed here:
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=543328
//If that bug is resolved this code should be removed.
configuration = BootLaunchConfigurationDelegate.copyAs(configuration, JDT_JAVA_APPLICATION);
}
return super.getClasspathAndModulepath(configuration);
}

@Override
public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException {
if (configuration.hasAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE)) {
//TODO: This is a dirty hack. We 'trick' BuildShip to treat our launch config as if it is a plain JDT launch by making
// a temporary copy of it.
//A request to make BuildShip provide a cleaner way to do this was filed here:
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=543328
//If that bug is resolved this code should be removed.
configuration = BootLaunchConfigurationDelegate.copyAs(configuration, JDT_JAVA_APPLICATION);
}
return super.getClasspath(configuration);
}

@Override
public String[][] getBootpathExt(ILaunchConfiguration configuration) throws CoreException {
if (configuration.hasAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE)) {
//TODO: This is a dirty hack. We 'trick' BuildShip to treat our launch config as if it is a plain JDT launch by making
// a temporary copy of it.
//A request to make BuildShip provide a cleaner way to do this was filed here:
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=543328
//If that bug is resolved this code should be removed.
configuration = BootLaunchConfigurationDelegate.copyAs(configuration, JDT_JAVA_APPLICATION);
}
return super.getBootpathExt(configuration);
}

public static void enableMavenClasspathProviders(ILaunchConfigurationWorkingCopy wc) {
setAttribute(wc, IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER, BOOT_MAVEN_SOURCE_PATH_PROVIDER);
setAttribute(wc, IJavaLaunchConfigurationConstants.ATTR_CLASSPATH_PROVIDER, BOOT_MAVEN_CLASS_PATH_PROVIDER);
}

public static void enableGradleClasspathProviders(ILaunchConfigurationWorkingCopy wc) {
/* This is found in typical java launch config for buildship project. It plays a crucial role in
* computing correct runtime classpath:
*
* <booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/>
* <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.buildship.core.classpathprovider"/>
*/
setAttribute(wc, IJavaLaunchConfigurationConstants.ATTR_CLASSPATH_PROVIDER, BUILDSHIP_CLASS_PATH_PROVIDER);
setAttribute(wc, IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, true);
}

private ILaunchConfiguration modify(ILaunchConfiguration conf, Consumer<ILaunchConfigurationWorkingCopy> mutator) throws CoreException {
ILaunchConfigurationWorkingCopy wc = conf.getWorkingCopy();
try {
Expand All @@ -392,6 +449,16 @@ private ILaunchConfiguration modify(ILaunchConfiguration conf, Consumer<ILaunchC
return conf;
}

private static void setAttribute(ILaunchConfigurationWorkingCopy wc, String a, boolean v) {
try {
if (!wc.hasAttribute(a) || v != wc.getAttribute(a, false)) {
wc.setAttribute(a, v);
}
} catch (CoreException e) {
Log.log(e);
}
}

private static void setAttribute(ILaunchConfigurationWorkingCopy wc, String a, String v) {
try {
if (!Objects.equals(v, wc.getAttribute(a, (String)null))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void initializeFrom(ILaunchConfiguration conf) {
try {
if (project!=null && project.hasNature(SpringBootCore.M2E_NATURE) && !conf.hasAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH_PROVIDER)) {
ILaunchConfigurationWorkingCopy wc = conf.getWorkingCopy();
BootLaunchConfigurationDelegate.enableClasspathProviders(wc);
BootLaunchConfigurationDelegate.enableMavenClasspathProviders(wc);
conf = wc;
}
} catch (CoreException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
Expand Down Expand Up @@ -335,7 +336,9 @@ public static void setDefaults(ILaunchConfigurationWorkingCopy wc,
setProcessFactory(wc, BootProcessFactory.class);
setProject(wc, project);
if (project!=null && project.hasNature(SpringBootCore.M2E_NATURE)) {
enableClasspathProviders(wc);
enableMavenClasspathProviders(wc);
} else if (project!=null && project.hasNature(SpringBootCore.BUILDSHIP_NATURE)) {
enableGradleClasspathProviders(wc);
}
if (mainType!=null) {
setMainType(wc, mainType);
Expand Down Expand Up @@ -614,6 +617,21 @@ protected String getThinWrapperMain(ILaunchConfiguration conf) throws Exception
}
}

/**
* Copy a given launch config into a 'clone' that has all the same attributes but
* a different type id.
*/
public static ILaunchConfigurationWorkingCopy copyAs(ILaunchConfiguration conf,
String newType) throws CoreException {
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType launchConfigurationType = launchManager
.getLaunchConfigurationType(newType);
ILaunchConfigurationWorkingCopy wc = launchConfigurationType.newInstance(null,
launchManager.generateLaunchConfigurationName(conf.getName()));
wc.setAttributes(conf.getAttributes());
return wc;
}

public static boolean useThinWrapper(ILaunchConfiguration conf) {
try {
return BootPreferences.getInstance().getThinWrapper()!=null && conf.getAttribute(USE_THIN_WRAPPER, DEFAULT_USE_THIN_WRAPPER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,15 @@
package org.springframework.ide.eclipse.boot.launch;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.m2e.jdt.internal.launch.MavenRuntimeClasspathProvider;

@SuppressWarnings("restriction")
public class BootMavenClassPathProvider extends MavenRuntimeClasspathProvider {

/**
* Copy a given launch config into a 'clone' that has all the same attributes but
* a different type id.
*/
private static ILaunchConfigurationWorkingCopy copyAs(ILaunchConfiguration conf,
String newType) throws CoreException {
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType launchConfigurationType = launchManager
.getLaunchConfigurationType(newType);
ILaunchConfigurationWorkingCopy wc = launchConfigurationType.newInstance(null,
launchManager.generateLaunchConfigurationName(conf.getName()));
wc.setAttributes(conf.getAttributes());
return wc;
}



@Override
protected int getArtifactScope(ILaunchConfiguration configuration) throws CoreException {
//Trick superclass in executing the right logic (i.e. as if this is a plain JDT launch config)
return super.getArtifactScope(copyAs(configuration, JDT_JAVA_APPLICATION));
return super.getArtifactScope(BootLaunchConfigurationDelegate.copyAs(configuration, JDT_JAVA_APPLICATION));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
public class SpringBootCore {

public static final String M2E_NATURE = "org.eclipse.m2e.core.maven2Nature";
public static final String BUILDSHIP_NATURE = "org.eclipse.buildship.core.gradleprojectnature";

private static final StsProperties stsProps = StsProperties.getInstance();
private InitializrService initializr;

Expand Down

0 comments on commit ff7968f

Please sign in to comment.