diff options
3 files changed, 191 insertions, 1 deletions
diff --git a/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/AbstractJavaProjectConfigurator.java b/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/AbstractJavaProjectConfigurator.java index 645d695f..1acdf1a6 100644 --- a/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/AbstractJavaProjectConfigurator.java +++ b/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/AbstractJavaProjectConfigurator.java @@ -61,7 +61,8 @@ import org.eclipse.m2e.jdt.MavenJdtPlugin; * * @author igor */ -public abstract class AbstractJavaProjectConfigurator extends AbstractProjectConfigurator { +public abstract class AbstractJavaProjectConfigurator extends AbstractProjectConfigurator + implements IJavaProjectConfigurator { private static final IPath[] DEFAULT_INCLUSIONS = new IPath[0]; @@ -650,4 +651,14 @@ public abstract class AbstractJavaProjectConfigurator extends AbstractProjectCon } return new Path(relative.replace('\\', '/')); //$NON-NLS-1$ //$NON-NLS-2$ } + + @SuppressWarnings("restriction") + public void configureClasspath(IMavenProjectFacade facade, IClasspathDescriptor classpath, IProgressMonitor monitor) + throws CoreException { + ModuleSupport.configureClasspath(facade, classpath, monitor); + } + + public void configureRawClasspath(ProjectConfigurationRequest request, IClasspathDescriptor classpath, + IProgressMonitor monitor) throws CoreException { + } } diff --git a/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/ModuleSupport.java b/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/ModuleSupport.java new file mode 100644 index 00000000..6f591c56 --- /dev/null +++ b/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/ModuleSupport.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2017 Red Hat, Inc. + * 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: + * Red Hat, Inc. - initial API and implementation + *******************************************************************************/ + +package org.eclipse.m2e.jdt.internal; + +import java.io.File; +import java.io.IOException; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipFile; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspaceRoot; +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.jdt.core.IClasspathAttribute; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.env.AutomaticModuleNaming; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.core.AbstractModule; + +import org.apache.maven.project.MavenProject; + +import org.eclipse.m2e.core.MavenPlugin; +import org.eclipse.m2e.core.project.IMavenProjectFacade; +import org.eclipse.m2e.jdt.IClasspathDescriptor; +import org.eclipse.m2e.jdt.IClasspathEntryDescriptor; + + +/** + * Helper for Java Module Support + * + * @author Fred Bricon + * @since 1.8.2 + */ +@SuppressWarnings("restriction") +public class ModuleSupport { + + static final boolean IS_MODULE_SUPPORT_AVAILABLE; + + private static final Logger log = LoggerFactory.getLogger(ModuleSupport.class); + + static { + boolean isModuleSupportAvailable = false; + try { + Class.forName("org.eclipse.jdt.core.IModuleDescription"); + isModuleSupportAvailable = true; + } catch(ClassNotFoundException ignored) { + } + IS_MODULE_SUPPORT_AVAILABLE = isModuleSupportAvailable; + } + + /** + * Sets <code>module</code flag to <code>true</code> to classpath dependencies declared in module-info.java + * + * @param facade a Maven facade project + * @param classpath a classpath descriptor + * @param monitor a progress monitor + */ + public static void configureClasspath(IMavenProjectFacade facade, IClasspathDescriptor classpath, + IProgressMonitor monitor) throws CoreException { + if(!IS_MODULE_SUPPORT_AVAILABLE) { + return; + } + IJavaProject javaProject = JavaCore.create(facade.getProject()); + IModuleDescription moduleDescription = javaProject.getModuleDescription(); + if(!(moduleDescription instanceof AbstractModule)) { + return; + } + AbstractModule module = (AbstractModule) moduleDescription; + Set<String> requiredModules = Stream.of(module.getRequiredModules()).map(m -> new String(m.name())) + .collect(Collectors.toSet()); + for(IClasspathEntryDescriptor entry : classpath.getEntryDescriptors()) { + String moduleName = getModuleName(entry, monitor); + if(requiredModules.contains(moduleName)) { + entry.setClasspathAttribute(IClasspathAttribute.MODULE, Boolean.TRUE.toString()); + } + } + } + + private static String getModuleName(IClasspathEntryDescriptor entry, IProgressMonitor monitor) { + String module = null; + if(IClasspathEntry.CPE_LIBRARY == entry.getEntryKind()) { + module = getModuleNameFromJar(entry.getPath().toFile()); + } else if(IClasspathEntry.CPE_PROJECT == entry.getEntryKind()) { + module = getModuleNameFromProject(entry.getPath(), monitor); + } + return module; + } + + private static String getModuleNameFromProject(IPath projectPath, IProgressMonitor monitor) { + IJavaProject project = getJavaProject(projectPath); + String module = null; + if(project != null) { + try { + if(project.getModuleDescription() == null) { + String buildName = null; + IMavenProjectFacade facade = MavenPlugin.getMavenProjectRegistry().getProject(project.getProject()); + if(facade != null) { + MavenProject mavenProject = facade.getMavenProject(monitor); + if(mavenProject != null) { + buildName = mavenProject.getBuild().getFinalName(); + } + } + if(buildName == null || buildName.isEmpty()) { + buildName = project.getElementName(); + } + module = new String(AutomaticModuleNaming.determineAutomaticModuleName(buildName, false, null)); + } else { + module = project.getModuleDescription().getElementName(); + } + } catch(CoreException ex) { + log.error(ex.getMessage(), ex); + } + } + return module; + } + + private static IJavaProject getJavaProject(IPath projectPath) { + if(projectPath == null || projectPath.isEmpty()) { + return null; + } + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IProject project = root.getProject(projectPath.lastSegment()); + if(project.isAccessible()) { + return JavaCore.create(project); + } + return null; + } + + private static String getModuleNameFromJar(File file) { + if(!file.isFile()) { + return null; + } + char[] moduleName = null; + try (ZipFile zipFile = new ZipFile(file)) { + IModule module = null; + ClassFileReader reader = ClassFileReader.read(zipFile, IModule.MODULE_INFO_CLASS); + if(reader != null) { + module = reader.getModuleDeclaration(); + if(module != null) { + moduleName = module.name(); + } + } + } catch(ClassFormatException | IOException ex) { + log.error(ex.getMessage(), ex); + } + if(moduleName == null) { + moduleName = AutomaticModuleNaming.determineAutomaticModuleName(file.getAbsolutePath()); + } + return new String(moduleName); + } + +} diff --git a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java index 6bc660db..c1ba2640 100644 --- a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java +++ b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java @@ -113,6 +113,12 @@ public class MavenLaunchDelegate extends JavaLaunchDelegate implements MavenLaun return cp.toArray(new String[cp.size()]); } + public String[][] getClasspathAndModulepath(ILaunchConfiguration configuration) throws CoreException { + String[][] paths = new String[2][]; + paths[0] = getClasspath(configuration); + return paths; + } + public String getProgramArguments(ILaunchConfiguration configuration) throws CoreException { if(programArguments == null) { String goals = getGoals(configuration); |