Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to add source/resource folder outside of the project basedir using linked folder #1603

Merged
merged 1 commit into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {

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

class ATest implements Serializable {

}
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) {
HannesWell marked this conversation as resolved.
Show resolved Hide resolved
/*
* 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
Loading