Skip to content

Commit 3aa12f5

Browse files
sebthomHannesWell
authored andcommitted
Keep external annotations paths when updating the project configuration
Prior to this commit, the manually configured external annotation paths for the "JRE System Library" and "Maven Dependencies" classpath entries of an m2e managed Eclipse project were being unset when m2e updated the Eclipse project configuration, e.g. due to changes in the underlying Maven project or due to manual execution of "Maven -> Update project...". This commit ensures that the external annotation path settings are still present after m2e updated the Eclipse project configuration. Fixes #391
1 parent d4d77aa commit 3aa12f5

File tree

5 files changed

+69
-12
lines changed

5 files changed

+69
-12
lines changed

org.eclipse.m2e.jdt.tests/src/org/eclipse/m2e/jdt/tests/JavaConfigurationTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,18 @@
3232
import org.eclipse.core.runtime.CoreException;
3333
import org.eclipse.core.runtime.FileLocator;
3434
import org.eclipse.core.runtime.IPath;
35+
import org.eclipse.jdt.core.IClasspathAttribute;
3536
import org.eclipse.jdt.core.IClasspathEntry;
3637
import org.eclipse.jdt.core.IJavaProject;
3738
import org.eclipse.jdt.core.JavaCore;
3839
import org.eclipse.jdt.core.JavaModelException;
40+
import org.eclipse.jdt.launching.JavaRuntime;
3941
import org.eclipse.m2e.core.MavenPlugin;
4042
import org.eclipse.m2e.core.internal.preferences.MavenConfigurationImpl;
4143
import org.eclipse.m2e.core.project.ResolverConfiguration;
44+
import org.eclipse.m2e.jdt.IClasspathManager;
45+
import org.eclipse.m2e.jdt.internal.ClasspathDescriptor;
46+
import org.eclipse.m2e.jdt.internal.MavenClasspathHelpers;
4247
import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase;
4348
import org.junit.Before;
4449
import org.junit.Test;
@@ -57,13 +62,33 @@ public void setUp() throws Exception {
5762
@Test
5863
public void testFileChangeUpdatesJDTSettings() throws CoreException, IOException, InterruptedException {
5964
IJavaProject project = importResourceProject("/projects/compilerSettings/pom.xml");
65+
66+
// set external annotation path to JRE and Maven classpaths
67+
var classpath = new ClasspathDescriptor(project);
68+
var containerPath = classpath.getEntryDescriptors().stream().filter(e -> JavaRuntime.JRE_CONTAINER.equals(e.getPath().segment(0)))
69+
.findFirst().get().getPath();
70+
classpath.addEntry(MavenClasspathHelpers.newContainerEntry(containerPath, JavaCore.newClasspathAttribute(
71+
IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, "/jre_external_anno_path")));
72+
classpath.addEntry(MavenClasspathHelpers.getDefaultContainerEntry(
73+
JavaCore.newClasspathAttribute(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, "/maven_external_anno_path")));
74+
project.setRawClasspath(classpath.getEntries(), project.getOutputLocation(), monitor);
75+
6076
assertEquals("1.8", project.getOption(JavaCore.COMPILER_SOURCE, false));
6177
IFile pomFileWS = project.getProject().getFile("pom.xml");
6278
String pomContent = Files.readString(Path.of(pomFileWS.getLocationURI()));
6379
pomContent = pomContent.replace("1.8", "11");
6480
pomFileWS.setContents(new ByteArrayInputStream(pomContent.getBytes()), true, false, null);
6581
waitForJobsToComplete();
6682
assertEquals("11", project.getOption(JavaCore.COMPILER_SOURCE, false));
83+
84+
// ensure external annotation paths are still present after update
85+
classpath = new ClasspathDescriptor(project);
86+
var jreCpe = classpath.getEntryDescriptors().stream().filter(e -> JavaRuntime.JRE_CONTAINER.equals(e.getPath().segment(0)))
87+
.findFirst().get();
88+
assertEquals("/jre_external_anno_path", jreCpe.getClasspathAttributes().get(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH));
89+
var mavenCpePath = IPath.fromOSString(IClasspathManager.CONTAINER_ID);
90+
var mavenCpe = classpath.getEntryDescriptors().stream().filter(e -> mavenCpePath.equals(e.getPath())).findFirst().get();
91+
assertEquals("/maven_external_anno_path", mavenCpe.getClasspathAttributes().get(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH));
6792
}
6893

6994
@Test

org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/AbstractJavaProjectConfigurator.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
import java.util.LinkedHashMap;
2424
import java.util.List;
2525
import java.util.Map;
26+
import java.util.Objects;
27+
import java.util.Optional;
2628
import java.util.Set;
29+
import java.util.function.Predicate;
2730

2831
import org.osgi.framework.Version;
2932
import org.slf4j.Logger;
@@ -221,14 +224,15 @@ protected void invokeJavaProjectConfigurators(IClasspathDescriptor classpath, Pr
221224

222225
protected void addJREClasspathContainer(IClasspathDescriptor classpath, String environmentId) {
223226

224-
IClasspathEntry cpe;
225227
IExecutionEnvironment executionEnvironment = getExecutionEnvironment(environmentId);
226-
if(executionEnvironment == null) {
227-
cpe = JavaRuntime.getDefaultJREContainerEntry();
228-
} else {
229-
IPath containerPath = JavaRuntime.newJREContainerPath(executionEnvironment);
230-
cpe = JavaCore.newContainerEntry(containerPath);
231-
}
228+
IPath containerPath = executionEnvironment == null //
229+
? JavaRuntime.newDefaultJREContainerPath() //
230+
: JavaRuntime.newJREContainerPath(executionEnvironment);
231+
232+
// ensure the external annotation path is kept
233+
IClasspathAttribute[] externalAnnotations = readExternalAnnotationAttributes(classpath,
234+
p -> JavaRuntime.JRE_CONTAINER.equals(p.getPath().segment(0)));
235+
IClasspathEntry cpe = MavenClasspathHelpers.newContainerEntry(containerPath, externalAnnotations);
232236

233237
IClasspathEntryDescriptor cped = classpath
234238
.replaceEntry(descriptor -> JavaRuntime.JRE_CONTAINER.equals(descriptor.getPath().segment(0)), cpe);
@@ -268,7 +272,11 @@ protected void addMavenClasspathContainer(IClasspathDescriptor classpath) {
268272
}
269273
}
270274

271-
IClasspathEntry cpe = MavenClasspathHelpers.getDefaultContainerEntry();
275+
// ensure the external annotation path is kept
276+
IClasspathAttribute[] externalAnnotations = readExternalAnnotationAttributes(classpath,
277+
p -> MavenClasspathHelpers.MAVEN_CLASSPATH_CONTAINER_PATH.equals(p.getPath()));
278+
IClasspathEntry cpe = MavenClasspathHelpers.getDefaultContainerEntry(externalAnnotations);
279+
272280
// add new entry without removing existing entries first, see bug398121
273281
IClasspathEntryDescriptor entryDescriptor = classpath.addEntry(cpe);
274282
entryDescriptor.setExported(isExported);
@@ -277,6 +285,15 @@ protected void addMavenClasspathContainer(IClasspathDescriptor classpath) {
277285
}
278286
}
279287

288+
private static IClasspathAttribute[] readExternalAnnotationAttributes(IClasspathDescriptor classpath,
289+
Predicate<IClasspathEntryDescriptor> annotationSourceEntry) {
290+
Optional<String> annotationPath = classpath.getEntryDescriptors().stream().filter(annotationSourceEntry)
291+
.map(descr -> descr.getClasspathAttributes().get(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH))
292+
.filter(Objects::nonNull).filter(p -> !p.isBlank()).findFirst();
293+
return annotationPath.map(p -> JavaCore.newClasspathAttribute(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, p))
294+
.map(a -> new IClasspathAttribute[] {a}).orElseGet(() -> new IClasspathAttribute[] {});
295+
}
296+
280297
protected void addProjectSourceFolders(IClasspathDescriptor classpath, ProjectConfigurationRequest request,
281298
IProgressMonitor monitor) throws CoreException {
282299
addProjectSourceFolders(classpath, new HashMap<>(), request, monitor);

org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/ClasspathEntryDescriptor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,4 +384,9 @@ public void setPomDerived(boolean derived) {
384384
attributes.remove(IClasspathManager.POMDERIVED_ATTRIBUTE);
385385
}
386386
}
387+
388+
@Override
389+
public String toString() {
390+
return getClass().getSimpleName() + "@" + System.identityHashCode(this) + "{path=" + path + "}";
391+
}
387392
}

org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/MavenClasspathContainer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,8 @@ public IPath getPath() {
5555
return path;
5656
}
5757

58+
@Override
59+
public String toString() {
60+
return getClass().getSimpleName() + "@" + System.identityHashCode(this) + "{path=" + path + "}";
61+
}
5862
}

org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/MavenClasspathHelpers.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
public class MavenClasspathHelpers {
3232

33+
public static final IPath MAVEN_CLASSPATH_CONTAINER_PATH = IPath.fromOSString(IClasspathManager.CONTAINER_ID);
34+
3335
public static IClasspathEntry getJREContainerEntry(IJavaProject javaProject) {
3436
if(javaProject != null) {
3537
try {
@@ -55,12 +57,16 @@ public static boolean isJREClasspathContainer(IPath containerPath) {
5557
&& JavaRuntime.JRE_CONTAINER.equals(containerPath.segment(0));
5658
}
5759

58-
public static IClasspathEntry getDefaultContainerEntry() {
59-
return JavaCore.newContainerEntry(IPath.fromOSString(IClasspathManager.CONTAINER_ID));
60+
public static IClasspathEntry getDefaultContainerEntry(boolean isExported) {
61+
return JavaCore.newContainerEntry(MAVEN_CLASSPATH_CONTAINER_PATH, isExported);
6062
}
6163

62-
public static IClasspathEntry getDefaultContainerEntry(boolean isExported) {
63-
return JavaCore.newContainerEntry(IPath.fromOSString(IClasspathManager.CONTAINER_ID), isExported);
64+
public static IClasspathEntry getDefaultContainerEntry(IClasspathAttribute... attributes) {
65+
return JavaCore.newContainerEntry(MAVEN_CLASSPATH_CONTAINER_PATH, null, attributes, false/*not exported*/);
66+
}
67+
68+
public static IClasspathEntry newContainerEntry(IPath path, IClasspathAttribute... attributes) {
69+
return JavaCore.newContainerEntry(path, null, attributes, false/*not exported*/);
6470
}
6571

6672
public static boolean isTestSource(IClasspathEntry entry) {

0 commit comments

Comments
 (0)