Skip to content

Commit

Permalink
Add ability to add source/resource folder outside of the project
Browse files Browse the repository at this point in the history
Such source/resource folders outside of the project are made accessible
using linked folder.

Furthermore fix handling of absolute paths pointing to project-directory
in AbstractJavaProjectConfigurator.getFolder().
  • Loading branch information
RoiSoleil authored and HannesWell committed Feb 2, 2024
1 parent 045f3cb commit 60e66ff
Show file tree
Hide file tree
Showing 14 changed files with 191 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
Expand All @@ -47,13 +46,17 @@ public class M2EUtils {
* @param monitor the progress monitor
* @throws CoreException if creating the given <code>folder</code> or any of its parents fails.
*/
public static void createFolder(IFolder folder, boolean derived, IProgressMonitor monitor) throws CoreException {
public static void createFolder(IContainer container, boolean derived, IProgressMonitor monitor)
throws CoreException {
if(!(container instanceof IFolder folder)) {
return; // don't create projects
}
// Recurse until we find a parent folder which already exists.
if(!folder.exists()) {
IContainer parent = folder.getParent();
// First, make sure that all parent folders exist.
if(parent != null && !parent.exists()) {
createFolder((IFolder) parent, false, monitor);
createFolder(parent, false, monitor);
}
try {
if(!folder.exists()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import java.io.Serializable;

class A implements Serializable {

}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import java.io.Serializable;

class ATest implements Serializable {

}
Empty file.
13 changes: 13 additions & 0 deletions org.eclipse.m2e.jdt.tests/projects/add-source-resource/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>foo.bar</groupId>
<artifactId>add-source-resource</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>submoduleA</module>
</modules>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>foo.bar</groupId>
<artifactId>submoduleA</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>java</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>../parent/src/main/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>test</id>
<phase>generate-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>../parent/src/test/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>resources</id>
<phase>generate-resources</phase>
<goals>
<goal>add-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>../parent/src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>test-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>add-test-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>../parent/src/test/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

import org.eclipse.core.resources.IFile;
Expand All @@ -29,12 +31,14 @@
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.internal.preferences.MavenConfigurationImpl;
import org.eclipse.m2e.core.project.ResolverConfiguration;
import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -124,14 +128,39 @@ public void testSkipNone() throws CoreException, IOException, InterruptedExcepti
assertEquals(1, classpathEntriesCount(project, TEST_RESOURCES));
}


@Test
public void testComplianceVsEnablePreviewSettings() throws CoreException, IOException, InterruptedException {
IJavaProject project = importResourceProject("/projects/compilerEnablePreviewSettings/pom.xml");
assertEquals("11", project.getOption(JavaCore.COMPILER_COMPLIANCE, false));
assertEquals(JavaCore.ENABLED, project.getOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, false));
assertEquals(JavaCore.IGNORE, project.getOption(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, false));
}

@Test
public void testAddSourceResource() throws CoreException, IOException, InterruptedException {
File baseDir = new File(FileLocator
.toFileURL(JavaConfigurationTest.class.getResource("/projects/add-source-resource/submoduleA/pom.xml"))
.getFile()).getParentFile().getParentFile();
waitForJobsToComplete();
IProject project = importProjects(baseDir.getAbsolutePath(), new String[] { "submoduleA/pom.xml" },
new ResolverConfiguration())[0];
waitForJobsToComplete();
IJavaProject javaProject = JavaCore.create(project);

List<String> srcEntryPaths = Arrays.stream(javaProject.getRawClasspath())
.filter(cp -> IClasspathEntry.CPE_SOURCE == cp.getEntryKind()).filter(cp -> !cp.isTest())
.map(IClasspathEntry::getPath).map(IPath::toString).toList();
assertEquals(Set.of("/submoduleA/src/main/java", "/submoduleA/src/main/resources", //
"/submoduleA/.._parent_src_main_java", "/submoduleA/.._parent_src_main_resources"),
Set.copyOf(srcEntryPaths));
List<String> testEntryPaths = Arrays.stream(javaProject.getRawClasspath())
.filter(cp -> IClasspathEntry.CPE_SOURCE == cp.getEntryKind()).filter(cp -> cp.isTest())
.map(IClasspathEntry::getPath).map(IPath::toString).toList();
assertEquals(Set.of("/submoduleA/src/test/java", "/submoduleA/src/test/resources", //
"/submoduleA/.._parent_src_test_java", "/submoduleA/.._parent_src_test_resources"),
Set.copyOf(testEntryPaths));
}

// --- utility methods ---

private static final Predicate<IClasspathEntry> TEST_SOURCES = cp -> cp.isTest()
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.m2e.jdt/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.m2e.jdt;singleton:=true
Bundle-Version: 2.3.3.qualifier
Bundle-Version: 2.3.400.qualifier
Bundle-Localization: plugin
Export-Package: org.eclipse.m2e.jdt,
org.eclipse.m2e.jdt.internal;x-friends:="org.eclipse.m2e.jdt.ui",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
package org.eclipse.m2e.jdt.internal;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -30,9 +33,11 @@
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
Expand Down Expand Up @@ -134,6 +139,9 @@ public abstract class AbstractJavaProjectConfigurator extends AbstractProjectCon

protected static final String DEFAULT_COMPILER_LEVEL = "1.5"; //$NON-NLS-1$

private static final QualifiedName LINKED_MAVEN_RESOURCE = new QualifiedName(MavenJdtPlugin.PLUGIN_ID,
"linkedSource");

@Override
public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {
IProject project = request.mavenProjectFacade().getProject();
Expand Down Expand Up @@ -282,8 +290,8 @@ protected void addProjectSourceFolders(IClasspathDescriptor classpath, Map<Strin
MavenProject mavenProject = request.mavenProject();
IMavenProjectFacade projectFacade = request.mavenProjectFacade();

IFolder classes = getFolder(project, mavenProject.getBuild().getOutputDirectory());
IFolder testClasses = getFolder(project, mavenProject.getBuild().getTestOutputDirectory());
IContainer classes = getFolder(project, mavenProject.getBuild().getOutputDirectory());
IContainer testClasses = getFolder(project, mavenProject.getBuild().getTestOutputDirectory());

M2EUtils.createFolder(classes, true, mon.newChild(1));
M2EUtils.createFolder(testClasses, true, mon.newChild(1));
Expand Down Expand Up @@ -361,6 +369,9 @@ protected void addProjectSourceFolders(IClasspathDescriptor classpath, Map<Strin
isTestResourcesSkipped.add(Boolean.FALSE);
}
}

cleanLinkedSourceDirs(project, monitor);

addSourceDirs(classpath, project, mavenProject.getCompileSourceRoots(), classes.getFullPath(), inclusion,
exclusion, mainSourceEncoding, mon.newChild(1), false);
addResourceDirs(classpath, project, mavenProject, mavenProject.getBuild().getResources(), classes.getFullPath(),
Expand Down Expand Up @@ -429,7 +440,7 @@ protected void addSourceDirs(IClasspathDescriptor classpath, IProject project, L
boolean addTestFlag) throws CoreException {

for(String sourceRoot : sourceRoots) {
IFolder sourceFolder = getFolder(project, sourceRoot);
IContainer sourceFolder = getFolder(project, sourceRoot);

if(sourceFolder == null) {
// this cannot actually happen, unless I misunderstand how project.getFolder works
Expand Down Expand Up @@ -468,6 +479,14 @@ protected void addSourceDirs(IClasspathDescriptor classpath, IProject project, L

}

private void cleanLinkedSourceDirs(IProject project, IProgressMonitor monitor) throws CoreException {
for(IResource resource : project.members()) {
if(resource instanceof IFolder && "true".equals(resource.getPersistentProperty(LINKED_MAVEN_RESOURCE))) {
resource.delete(false, monitor);
}
}
}

private IClasspathEntryDescriptor getEnclosingEntryDescriptor(IClasspathDescriptor classpath, IPath fullPath) {
for(IClasspathEntryDescriptor cped : classpath.getEntryDescriptors()) {
if(cped.getPath().isPrefixOf(fullPath)) {
Expand Down Expand Up @@ -495,9 +514,13 @@ private void addResourceDirs(IClasspathDescriptor classpath, IProject project, M
if(directory == null) {
continue;
}
File resourceDirectory = new File(directory);
IPath relativePath = getProjectRelativePath(project, directory);
IResource r = project.findMember(relativePath);
File resourceDirectory = null;
try {
resourceDirectory = new File(directory).getCanonicalFile();
} catch(IOException ex) {
resourceDirectory = new File(directory).getAbsoluteFile();
}
IContainer r = getFolder(project, resourceDirectory.getPath());
if(r == project) {
/*
* Workaround for the Java Model Exception:
Expand All @@ -517,10 +540,6 @@ private void addResourceDirs(IClasspathDescriptor classpath, IProject project, M
log.error("Skipping resource folder " + r.getFullPath());
return;
}
if(r == null) {
//this means the resources does not exits (yet) but might be created later on!
r = project.getFolder(relativePath);
}
if(project.equals(r.getProject())) {
IPath path = r.getFullPath();
IClasspathEntryDescriptor enclosing = getEnclosingEntryDescriptor(classpath, path);
Expand All @@ -533,12 +552,11 @@ private void addResourceDirs(IClasspathDescriptor classpath, IProject project, M
addResourceFolder(classpath, path, outputPath, addTestFlag);
}
// Set folder encoding (null = platform default)
IFolder resourceFolder = project.getFolder(relativePath);
if(resourceFolder.exists()) {
resourceFolder.setDefaultCharset(resourceEncoding, monitor);
if(r.exists()) {
r.setDefaultCharset(resourceEncoding, monitor);
}
} else {
log.info("Not adding resources folder " + resourceDirectory.getAbsolutePath());
log.info("Not adding resources folder " + resourceDirectory);
}
}
}
Expand Down Expand Up @@ -864,11 +882,22 @@ private void removeMavenClasspathContainer(IProject project) throws JavaModelExc
}
}

protected IFolder getFolder(IProject project, String absolutePath) {
if(project.getLocation().makeAbsolute().equals(IPath.fromOSString(absolutePath))) {
return project.getFolder(project.getLocation());
protected IContainer getFolder(IProject project, String absolutePath) throws CoreException {
Path projectLocation = project.getLocation().toPath().toAbsolutePath();
Path folderPath = Path.of(absolutePath);
if(projectLocation.equals(folderPath)) {
return project;
}
IPath relativePath = getProjectRelativePath(project, absolutePath);
if(!project.exists(relativePath) && Files.exists(folderPath)
&& !ResourcesPlugin.getWorkspace().getRoot().getLocation().toPath().equals(folderPath)) {
String linkName = projectLocation.relativize(folderPath).toString().replace("/", "_");
IFolder folder = project.getFolder(linkName);
folder.createLink(folderPath.toUri(), IResource.REPLACE, null);
folder.setPersistentProperty(LINKED_MAVEN_RESOURCE, "true");
return folder;
}
return project.getFolder(getProjectRelativePath(project, absolutePath));
return project.getFolder(relativePath);
}

protected IPath getProjectRelativePath(IProject project, String absolutePath) {
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.m2e.mavenarchiver/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: m2e connector for the mavenarchiver and pom properties
Bundle-SymbolicName: org.eclipse.m2e.mavenarchiver;singleton:=true
Bundle-Version: 2.0.401.qualifier
Bundle-Version: 2.0.500.qualifier
Bundle-Vendor: Eclipse.org - m2e
Bundle-RequiredExecutionEnvironment: JavaSE-17
Require-Bundle: org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.m2e.pde.connector/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: M2E PDE Connector
Bundle-SymbolicName: org.eclipse.m2e.pde.connector;singleton:=true
Bundle-Version: 2.1.500.qualifier
Bundle-Version: 2.1.600.qualifier
Automatic-Module-Name: org.eclipse.m2e.pde.connector
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-Vendor: Eclipse.org - m2e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import org.apache.maven.project.MavenProject;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
Expand Down Expand Up @@ -96,7 +95,7 @@ protected void addProjectSourceFolders(IClasspathDescriptor classpath, Map<Strin
} else {
outputDirectory = mavenProject.getBuild().getOutputDirectory();
}
IFolder outputFolder = getFolder(project, outputDirectory);
IContainer outputFolder = getFolder(project, outputDirectory);
M2EUtils.createFolder(outputFolder, true, subMonitor.split(10));
IPath[] inclusion = new IPath[0];
IPath[] exclusion = new IPath[0];
Expand Down
Loading

0 comments on commit 60e66ff

Please sign in to comment.