/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.maven.server;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.maven.AbstractMavenLifecycleParticipant;
import org.apache.maven.DefaultMaven;
import org.apache.maven.Maven;
import org.apache.maven.MavenExecutionException;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.InvalidRepositoryException;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.resolver.ResolutionListener;
import org.apache.maven.cli.MavenCli;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.DefaultMavenExecutionResult;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequestPopulationException;
import org.apache.maven.execution.MavenExecutionRequestPopulator;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Activation;
import org.apache.maven.model.Model;
import org.apache.maven.model.Profile;
import org.apache.maven.model.profile.DefaultProfileInjector;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.profiles.activation.JdkPrefixProfileActivator;
import org.apache.maven.profiles.activation.OperatingSystemProfileActivator;
import org.apache.maven.profiles.activation.ProfileActivationException;
import org.apache.maven.profiles.activation.ProfileActivator;
import org.apache.maven.profiles.activation.SystemPropertyProfileActivator;
import org.apache.maven.project.DefaultProjectBuilderConfiguration;
import org.apache.maven.project.DependencyResolutionResult;
import org.apache.maven.project.InvalidProjectModelException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuilderConfiguration;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingResult;
import org.apache.maven.project.ProjectUtils;
import org.apache.maven.project.interpolation.AbstractStringBasedModelInterpolator;
import org.apache.maven.project.interpolation.ModelInterpolationException;
import org.apache.maven.project.path.DefaultPathTranslator;
import org.apache.maven.project.validation.ModelValidationResult;
import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
import org.apache.maven.settings.building.SettingsBuilder;
import org.apache.maven.settings.building.SettingsBuildingException;
import org.apache.maven.settings.building.SettingsBuildingRequest;
import org.apache.maven.shared.dependency.tree.DependencyTreeResolutionListener;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.context.DefaultContext;
import org.codehaus.plexus.logging.BaseLoggerManager;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.internal.impl.DefaultArtifactResolver;
import org.eclipse.aether.internal.impl.DefaultRepositorySystem;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import org.eclipse.che.maven.CheArtifactResolver;
import org.eclipse.che.maven.data.MavenArtifact;
import org.eclipse.che.maven.data.MavenArtifactKey;
import org.eclipse.che.maven.data.MavenConstants;
import org.eclipse.che.maven.data.MavenExplicitProfiles;
import org.eclipse.che.maven.data.MavenKey;
import org.eclipse.che.maven.data.MavenModel;
import org.eclipse.che.maven.data.MavenProjectProblem;
import org.eclipse.che.maven.data.MavenRemoteRepository;
import org.eclipse.che.maven.data.MavenWorkspaceCache;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
* @author Evgen Vidolob
*/
public class MavenServerImpl extends MavenRmiObject implements MavenServer {
private static final String[] CLI_METHODS = new String[]{"initialize", "cli", "logging", "properties", "container"};
private final MavenServerTerminalLogger terminalLogger;
private final File localRepository;
private boolean updateSnapshots;
private DefaultPlexusContainer container;
private Settings settings;
private Properties properties;
private ArtifactRepository localRepo;
private Date buildDate;
private MavenWorkspaceCache workspaceCache;
private MavenServerProgressNotifierImpl mavenProgressNotifier;
public MavenServerImpl(MavenSettings settings) throws RemoteException {
BasicConfigurator.configure();
Logger.getRootLogger().setLevel(getLog4jLogLevel(settings.getLoggingLevel()));
File mavenHome = settings.getMavenHome();
if (mavenHome != null) {
System.setProperty("maven.home", mavenHome.getPath());
}
terminalLogger = new MavenServerTerminalLogger();
terminalLogger.setThreshold(settings.getLoggingLevel());
ClassWorld classWorld = new ClassWorld("plexus.core", Thread.currentThread().getContextClassLoader());
MavenCli cli = new MavenCli(classWorld) {
@Override
protected void customizeContainer(PlexusContainer container) {
((DefaultPlexusContainer)container).setLoggerManager(new BaseLoggerManager() {
@Override
protected org.codehaus.plexus.logging.Logger createLogger(String s) {
return terminalLogger;
}
});
}
};
//maven 3.2.2 has org.apache.maven.cli.MavenCli$CliRequest class
//but maven 3.3.3 has org.apache.maven.cli.CliRequest so try to support both classes
Class<?> cliRequestClass;
SettingsBuilder settingsBuilder = null;
try {
cliRequestClass = MavenCli.class.getClassLoader().loadClass("org.apache.maven.cli.CliRequest");
System.setProperty("maven.multiModuleProjectDirectory", new File("").getPath());
settingsBuilder = new DefaultSettingsBuilderFactory().newInstance();
} catch (ClassNotFoundException e) {
try {
cliRequestClass = MavenCli.class.getClassLoader().loadClass("org.apache.maven.cli.MavenCli$CliRequest");
} catch (ClassNotFoundException cnfe) {
throw new RuntimeException(cnfe);
}
}
Object request;
List<String> commandLine = new ArrayList<>(settings.getUserProperties().size());
commandLine.addAll(settings.getUserProperties().entrySet().stream().map(entry -> "-D" + entry.getKey() + "=" + entry.getValue())
.collect(Collectors.toList()));
if (settings.getLoggingLevel() == MavenTerminal.LEVEL_DEBUG) {
commandLine.add("-X");
commandLine.add("-e");
}
if (settings.getLoggingLevel() == MavenTerminal.LEVEL_DISABLED) {
commandLine.add("-q");
}
if (commandLine.contains("-U") || commandLine.contains("--update-snapshots")) {
updateSnapshots = true;
}
try {
Constructor constructor = cliRequestClass.getDeclaredConstructor(String[].class, ClassWorld.class);
constructor.setAccessible(true);
request = constructor.newInstance(commandLine.toArray(new String[commandLine.size()]), classWorld);
for (String method : CLI_METHODS) {
Method m = MavenCli.class.getDeclaredMethod(method, cliRequestClass);
m.setAccessible(true);
m.invoke(cli, request);
}
Method containerMethod = MavenCli.class.getDeclaredMethod("container", cliRequestClass);
containerMethod.setAccessible(true);
container = (DefaultPlexusContainer)containerMethod.invoke(cli, request);
container.getLoggerManager().setThreshold(settings.getLoggingLevel());
Field systemProperties = cliRequestClass.getDeclaredField("systemProperties");
systemProperties.setAccessible(true);
properties = (Properties)systemProperties.get(request);
Field userPropertiesField = cliRequestClass.getDeclaredField("userProperties");
userPropertiesField.setAccessible(true);
Properties userProperties = (Properties)userPropertiesField.get(request);
this.settings = getSettings(settingsBuilder, settings, properties, userProperties);
} catch (NoSuchMethodException | NoSuchFieldException | IllegalAccessException | InvocationTargetException |
InstantiationException e) {
throw new RuntimeException(e);
}
try {
localRepository = new File(this.settings.getLocalRepository());
localRepo = getMavenComponent(RepositorySystem.class).createLocalRepository(localRepository);
} catch (InvalidRepositoryException e) {
throw new RuntimeException(e);
}
}
public static MavenModel interpolateModel(MavenModel model, File projectDir) throws RemoteException {
Model result = MavenModelUtil.convertToMavenModel(model);
result = internalInterpolate(result, projectDir);
// PathTranslator pathTranslator = new DefaultPathTranslator();
// pathTranslator.alignToBaseDirectory(result, projectDir);
return MavenModelUtil.convertModel(result);
}
/**
* Analyzes all profiles and if it's activated, applied it to the model.
*
* @param model
* maven model
* @param projectDir
* base directory of the analysed project
* @param explicitProfiles
* information about all profiles from the current model
* @param alwaysOnProfiles
* list of profiles which sre always activated
* @return returns model with applied profiles and information about profiles
* @throws RemoteException
* throws if some problem happens whens profile's activation is checked
*/
public static ProfileApplicationResult applyProfiles(MavenModel model,
File projectDir,
MavenExplicitProfiles explicitProfiles,
Collection<String> alwaysOnProfiles) throws RemoteException {
Model nativeModel = MavenModelUtil.convertToMavenModel(model);
Collection<String> enabledProfiles = explicitProfiles.getEnabledProfiles();
Collection<String> disabledProfiles = explicitProfiles.getDisabledProfiles();
List<Profile> activatedPom = new ArrayList<>();
List<Profile> activatedExternal = new ArrayList<>();
List<Profile> activeByDefault = new ArrayList<>();
List<Profile> rawProfiles = nativeModel.getProfiles();
List<Profile> expandedProfilesCache = null;
List<Profile> deactivatedProfiles = new ArrayList<>();
for (int i = 0; i < rawProfiles.size(); i++) {
Profile profile = rawProfiles.get(i);
if (disabledProfiles.contains(profile.getId())) {
deactivatedProfiles.add(profile);
continue;
}
boolean shouldAdd = enabledProfiles.contains(profile.getId()) || alwaysOnProfiles.contains(profile.getId());
Activation activation = profile.getActivation();
if (activation != null) {
if (activation.isActiveByDefault()) {
activeByDefault.add(profile);
}
if (expandedProfilesCache == null) {
expandedProfilesCache = internalInterpolate(nativeModel, projectDir).getProfiles();
}
Profile eachExpandedProfile = expandedProfilesCache.get(i);
for (ProfileActivator eachActivator : getProfileActivators(projectDir)) {
try {
if (eachActivator.canDetermineActivation(eachExpandedProfile) && eachActivator.isActive(eachExpandedProfile)) {
shouldAdd = true;
break;
}
} catch (ProfileActivationException e) {
MavenServerContext.getLogger().warning(e);
}
}
}
if (shouldAdd) {
if (MavenConstants.PROFILE_FROM_POM.equals(profile.getSource())) {
activatedPom.add(profile);
} else {
activatedExternal.add(profile);
}
}
}
List<Profile> activatedProfiles = new ArrayList<>(activatedPom.isEmpty() ? activeByDefault : activatedPom);
activatedProfiles.addAll(activatedExternal);
for (Profile each : activatedProfiles) {
new DefaultProfileInjector().injectProfile(nativeModel, each, null, null);
}
return new ProfileApplicationResult(MavenModelUtil.convertModel(nativeModel),
new MavenExplicitProfiles(collectProfilesIds(activatedProfiles),
collectProfilesIds(deactivatedProfiles))
);
}
private static Collection<String> collectProfilesIds(List<Profile> profiles) {
Collection<String> result = new HashSet<>();
for (Profile each : profiles) {
if (each.getId() != null) {
result.add(each.getId());
}
}
return result;
}
private static ProfileActivator[] getProfileActivators(File basedir) throws RemoteException {
SystemPropertyProfileActivator sysPropertyActivator = new SystemPropertyProfileActivator();
DefaultContext context = new DefaultContext();
context.put("SystemProperties", collectSystemProperties());
try {
sysPropertyActivator.contextualize(context);
} catch (ContextException e) {
MavenServerContext.getLogger().error(e);
return new ProfileActivator[0];
}
return new ProfileActivator[]{new MavenFileProfileActivator(basedir),
sysPropertyActivator,
new JdkPrefixProfileActivator(),
new OperatingSystemProfileActivator()};
}
private static Properties collectSystemProperties() {
Properties properties = new Properties();
properties.putAll((Properties)System.getProperties().clone());
return properties;
}
private static Model internalInterpolate(Model model, File projectDir) throws RemoteException {
try {
AbstractStringBasedModelInterpolator interpolator =
new org.apache.maven.project.interpolation.StringSearchModelInterpolator(new DefaultPathTranslator());
interpolator.initialize();
Properties props = new Properties(); //MavenServerUtil.collectSystemProperties();
ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration().setExecutionProperties(props);
config.setBuildStartTime(new Date());
model = interpolator.interpolate(model, projectDir, config, false);
} catch (ModelInterpolationException e) {
MavenServerContext.getLogger().warning(e);
} catch (InitializationException e) {
MavenServerContext.getLogger().error(e);
}
return model;
}
private Settings getSettings(SettingsBuilder builder, MavenSettings settings, Properties systemProperties, Properties userProperties)
throws RemoteException {
SettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
request.setGlobalSettingsFile(settings.getGlobalSettings());
request.setUserSettingsFile(settings.getUserSettings());
request.setSystemProperties(systemProperties);
request.setUserProperties(userProperties);
Settings result = new Settings();
try {
result = builder.build(request).getEffectiveSettings();
} catch (SettingsBuildingException e) {
MavenServerContext.getLogger().info(e);
}
result.setOffline(settings.isOffline());
if (settings.getLocalRepository() != null) {
result.setLocalRepository(settings.getLocalRepository().getPath());
}
if (result.getLocalRepository() == null) {
result.setLocalRepository(new File(System.getProperty("user.home"), ".m2/repository").getPath());
}
return result;
}
private Level getLog4jLogLevel(int level) {
switch (level) {
case MavenTerminal.LEVEL_DEBUG:
return Level.DEBUG;
case MavenTerminal.LEVEL_DISABLED:
return Level.OFF;
case MavenTerminal.LEVEL_ERROR:
return Level.ERROR;
case MavenTerminal.LEVEL_FATAL:
return Level.FATAL;
case MavenTerminal.LEVEL_INFO:
return Level.INFO;
case MavenTerminal.LEVEL_WARN:
return Level.WARN;
}
return Level.INFO;
}
public <T> T getMavenComponent(Class<T> clazz) {
try {
return container.lookup(clazz);
} catch (ComponentLookupException e) {
throw new RuntimeException(e);
}
}
public <T> T getMavenComponent(Class<T> clazz, String role) {
try {
return container.lookup(clazz, role);
} catch (ComponentLookupException e) {
throw new RuntimeException(e);
}
}
private void logWarn(String message) {
try {
MavenServerContext.getLogger().warning(new RuntimeException(message));
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
/**
* method from org.apache.maven.DefaultMaven#getLifecycleParticipants
*/
private Collection<AbstractMavenLifecycleParticipant> getLifecycleParticipants(Collection<MavenProject> projects) {
Collection<AbstractMavenLifecycleParticipant> lifecycleListeners = new LinkedHashSet<AbstractMavenLifecycleParticipant>();
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
try {
lifecycleListeners.addAll(container.lookupList(AbstractMavenLifecycleParticipant.class));
} catch (ComponentLookupException e) {
// this is just silly, lookupList should return an empty list!
logWarn("Failed to lookup lifecycle participants: " + e.getMessage());
}
Collection<ClassLoader> scannedRealms = new HashSet<ClassLoader>();
for (MavenProject project : projects) {
ClassLoader projectRealm = project.getClassRealm();
if (projectRealm != null && scannedRealms.add(projectRealm)) {
Thread.currentThread().setContextClassLoader(projectRealm);
try {
lifecycleListeners.addAll(container.lookupList(AbstractMavenLifecycleParticipant.class));
} catch (ComponentLookupException e) {
// this is just silly, lookupList should return an empty list!
logWarn("Failed to lookup lifecycle participants: " + e.getMessage());
}
}
}
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
return lifecycleListeners;
}
@Override
public void setComponents(MavenWorkspaceCache cache,
boolean failOnUnresolvedDependency,
MavenTerminal mavenTerminal,
MavenServerProgressNotifier notifier,
boolean alwaysUpdateSnapshot) throws RemoteException {
container.addComponent(getMavenComponent(ArtifactResolver.class, "che"), ArtifactResolver.ROLE);
ArtifactResolver artifactResolver = getMavenComponent(ArtifactResolver.class);
if (artifactResolver instanceof CheArtifactResolver) {
((CheArtifactResolver)artifactResolver).setWorkspaceCache(cache, failOnUnresolvedDependency);
}
buildDate = new Date();
workspaceCache = cache;
updateSnapshots = updateSnapshots || alwaysUpdateSnapshot;
terminalLogger.setTerminal(mavenTerminal);
mavenProgressNotifier = new MavenServerProgressNotifierImpl(notifier);
}
@Override
public String getEffectivePom(File pom, List<String> activeProfiles, List<String> inactiveProfiles)
throws RemoteException {
return EffectivePomWriter.getEffectivePom(this, pom, new ArrayList<>(activeProfiles), new ArrayList<>(inactiveProfiles));
}
@Override
public MavenServerResult resolveProject(File pom, List<String> activeProfiles, List<String> inactiveProfiles) throws RemoteException {
DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(terminalLogger);
MavenResult mavenResult = internalResolveProject(pom, activeProfiles, inactiveProfiles, Collections.singletonList(listener));
return createResult(pom, mavenResult);
}
@Override
public MavenArtifact resolveArtifact(MavenArtifactKey artifactKey, List<MavenRemoteRepository> repositories) throws RemoteException {
Artifact artifact = getMavenComponent(ArtifactFactory.class)
.createArtifactWithClassifier(artifactKey.getGroupId(), artifactKey.getArtifactId(), artifactKey.getVersion(),
artifactKey.getPackaging(), artifactKey.getClassifier());
List<ArtifactRepository> repos = new ArrayList<>();
ArtifactRepositoryFactory factory = getMavenComponent(ArtifactRepositoryFactory.class);
for (MavenRemoteRepository repository : repositories) {
try {
ArtifactRepository artifactRepository =
ProjectUtils.buildArtifactRepository(MavenModelUtil.convertToMavenRepository(repository), factory, container);
repos.add(artifactRepository);
} catch (InvalidRepositoryException e) {
MavenServerContext.getLogger().error(e);
}
}
MavenExecutionRequest request = newMavenRequest(null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
repos.forEach(request::addRemoteRepository);
DefaultMaven maven = (DefaultMaven)getMavenComponent(Maven.class);
RepositorySystemSession repositorySystemSession = maven.newRepositorySession(request);
org.eclipse.aether.impl.ArtifactResolver artifactResolver = getMavenComponent(org.eclipse.aether.impl.ArtifactResolver.class);
InternalLoggerFactory loggerFactory = new InternalLoggerFactory();
if (artifactResolver instanceof DefaultArtifactResolver) {
((DefaultArtifactResolver)artifactResolver).setLoggerFactory(loggerFactory);
}
org.eclipse.aether.RepositorySystem repositorySystem = getMavenComponent(org.eclipse.aether.RepositorySystem.class);
if (repositorySystem instanceof DefaultRepositorySystem) {
((DefaultRepositorySystem)repositorySystem).setLoggerFactory(loggerFactory);
}
List<RemoteRepository> remoteRepositories = RepositoryUtils.toRepos(request.getRemoteRepositories());
remoteRepositories = repositorySystem.newResolutionRepositories(repositorySystemSession, remoteRepositories);
try {
ArtifactResult artifactResult = repositorySystem.resolveArtifact(repositorySystemSession,
new ArtifactRequest(RepositoryUtils.toArtifact(artifact),
remoteRepositories, null));
return MavenModelUtil.convertArtifact(RepositoryUtils.toArtifact(artifactResult.getArtifact()), localRepository);
} catch (ArtifactResolutionException ignored) {
//we need ignore exception, it's some times has class that client doesn't has
// .printStackTrace() may be solution, but it will spam wsagent logs
}
return MavenModelUtil.convertArtifact(artifact, localRepository);
}
@Override
public void reset() throws RemoteException {
terminalLogger.setTerminal(null);
mavenProgressNotifier = null;
ArtifactResolver artifactResolver = getMavenComponent(ArtifactResolver.class);
if (artifactResolver instanceof CheArtifactResolver) {
((CheArtifactResolver)artifactResolver).reset();
}
}
@Override
public void dispose() throws RemoteException {
container.dispose();
}
@Override
public File getLocalRepository() {
return localRepository;
}
private MavenServerResult createResult(File pom, MavenResult mavenResult) throws RemoteException {
List<MavenProjectProblem> problems = new ArrayList<>();
Set<MavenKey> unresolvedArtifacts = new HashSet<>();
validate(pom, mavenResult.getExceptions(), problems);
MavenProject project = mavenResult.getMavenProject();
if (project == null) {
return new MavenServerResult(null, problems, unresolvedArtifacts);
}
MavenModel model = null;
try {
DependencyResolutionResult resolutionResult = mavenResult.getDependencyResolutionResult();
org.eclipse.aether.graph.DependencyNode dependencyNode = null;
if (resolutionResult != null) {
dependencyNode = resolutionResult.getDependencyGraph();
}
List<org.eclipse.aether.graph.DependencyNode> dependencyNodes = null;
if (dependencyNode != null) {
dependencyNodes = dependencyNode.getChildren();
}
model = MavenModelUtil.convertProjectToModel(project, dependencyNodes, new File(localRepo.getBasedir()));
} catch (Exception e) {
validate(project.getFile(), Collections.singletonList(e), problems);
}
List<String> activeProfiles = getActiveProfiles(project);
MavenProjectInfo projectInfo = new MavenProjectInfo(model, null, activeProfiles);
return new MavenServerResult(projectInfo, problems, unresolvedArtifacts);
}
private List<String> getActiveProfiles(MavenProject project) throws RemoteException {
List<Profile> profiles = new ArrayList<>();
try {
while (project != null) {
profiles.addAll(project.getActiveProfiles());
project = project.getParent();
}
} catch (Exception e) {
MavenServerContext.getLogger().info(e);
}
return profiles.stream().filter(p -> p.getId() != null).map(Profile::getId).collect(Collectors.toList());
}
private void validate(File pom, List<Exception> exceptions, List<MavenProjectProblem> problems)
throws RemoteException {
for (Throwable exception : exceptions) {
if (exception instanceof IllegalStateException && exception.getCause() != null) {
exception = exception.getCause();
}
if (exception instanceof InvalidProjectModelException) {
ModelValidationResult validationResult = ((InvalidProjectModelException)exception).getValidationResult();
if (validationResult != null) {
problems.addAll(validationResult.getMessages().stream()
.map(s -> MavenProjectProblem.newStructureProblem(pom.getPath(), s))
.collect(Collectors.toList()));
} else {
problems.add(MavenProjectProblem.newStructureProblem(pom.getPath(), exception.getCause().getMessage()));
}
}
if (exception instanceof ProjectBuildingException) {
String message = exception.getCause() == null ? exception.getMessage() : exception.getCause().getMessage();
problems.add(MavenProjectProblem.newStructureProblem(pom.getPath(), message));
} else {
MavenServerContext.getLogger().info(exception);
problems.add(MavenProjectProblem.newStructureProblem(pom.getPath(), exception.getMessage()));
}
}
}
private MavenResult internalResolveProject(File pom, List<String> activeProfiles, List<String> inactiveProfiles,
List<ResolutionListener> dependencyTreeResolutionListeners) {
MavenExecutionRequest request = newMavenRequest(pom, activeProfiles, inactiveProfiles, Collections.emptyList());
request.setUpdateSnapshots(updateSnapshots);
AtomicReference<MavenResult> reference = new AtomicReference<>();
runMavenRequest(request, () -> {
try {
ProjectBuilder builder = getMavenComponent(ProjectBuilder.class);
List<ProjectBuildingResult> resultList =
builder.build(Collections.singletonList(pom), false, request.getProjectBuildingRequest());
ProjectBuildingResult result = resultList.get(0);
MavenProject mavenProject = result.getProject();
RepositorySystemSession repositorySession = getMavenComponent(LegacySupport.class).getRepositorySession();
if (repositorySession instanceof DefaultRepositorySystemSession) {
((DefaultRepositorySystemSession)repositorySession)
.setTransferListener(new ArtifactTransferListener(mavenProgressNotifier));
if (workspaceCache != null) {
((DefaultRepositorySystemSession)repositorySession).setWorkspaceReader(new MavenWorkspaceReader(workspaceCache));
}
}
List<Exception> exceptions = new ArrayList<>();
loadExtensions(mavenProject, exceptions);
mavenProject.setDependencyArtifacts(mavenProject.createArtifacts(getMavenComponent(ArtifactFactory.class), null, null));
ArtifactResolutionRequest resolutionRequest = new ArtifactResolutionRequest();
resolutionRequest.setArtifact(mavenProject.getArtifact());
resolutionRequest.setRemoteRepositories(mavenProject.getRemoteArtifactRepositories());
resolutionRequest.setArtifactDependencies(mavenProject.getDependencyArtifacts());
resolutionRequest.setListeners(dependencyTreeResolutionListeners);
resolutionRequest.setLocalRepository(localRepo);
resolutionRequest.setManagedVersionMap(mavenProject.getManagedVersionMap());
resolutionRequest.setResolveTransitively(true);
resolutionRequest.setResolveRoot(false);
ArtifactResolver resolver = getMavenComponent(ArtifactResolver.class);
ArtifactResolutionResult resolve = resolver.resolve(resolutionRequest);
mavenProject.setArtifacts(resolve.getArtifacts());
reference.set(new MavenResult(mavenProject, exceptions));
} catch (Exception e) {
reference.set(new MavenResult(null, null, Collections.singletonList(e)));
}
});
return reference.get();
}
private void loadExtensions(MavenProject project, List<Exception> exceptions) {
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
Collection<AbstractMavenLifecycleParticipant> participants = getLifecycleParticipants(Collections.singletonList(project));
if (!participants.isEmpty()) {
LegacySupport legacySupport = getMavenComponent(LegacySupport.class);
MavenSession session = legacySupport.getSession();
session.setCurrentProject(project);
session.setProjects(Collections.singletonList(project));
for (AbstractMavenLifecycleParticipant participant : participants) {
Thread.currentThread().setContextClassLoader(participant.getClass().getClassLoader());
try {
participant.afterProjectsRead(session);
} catch (MavenExecutionException e) {
exceptions.add(e);
} finally {
Thread.currentThread().setContextClassLoader(currentClassLoader);
}
}
}
}
public void runMavenRequest(MavenExecutionRequest request, Runnable runnable) {
DefaultMaven maven = (DefaultMaven)getMavenComponent(Maven.class);
RepositorySystemSession repositorySystemSession = maven.newRepositorySession(request);
request.getProjectBuildingRequest().setRepositorySession(repositorySystemSession);
MavenSession mavenSession = new MavenSession(container, repositorySystemSession, request, new DefaultMavenExecutionResult());
LegacySupport legacySupport = getMavenComponent(LegacySupport.class);
MavenSession previousSession = legacySupport.getSession();
legacySupport.setSession(mavenSession);
try {
for (AbstractMavenLifecycleParticipant participant : getLifecycleParticipants(Collections.emptyList())) {
participant.afterSessionStart(mavenSession);
}
runnable.run();
} catch (MavenExecutionException e) {
throw new RuntimeException(e);
} finally {
legacySupport.setSession(previousSession);
}
}
public MavenExecutionRequest newMavenRequest(File pom, List<String> activeProfiles, List<String> inactiveProfiles, List<String> goals) {
MavenExecutionRequest request = new DefaultMavenExecutionRequest();
try {
getMavenComponent(MavenExecutionRequestPopulator.class).populateFromSettings(request, settings);
request.setGoals(goals);
request.setPom(pom);
getMavenComponent(MavenExecutionRequestPopulator.class).populateDefaults(request);
request.setSystemProperties(properties);
request.setActiveProfiles(activeProfiles);
request.setInactiveProfiles(inactiveProfiles);
request.setStartTime(buildDate);
return request;
} catch (MavenExecutionRequestPopulationException e) {
throw new RuntimeException(e);
}
}
private class InternalLoggerFactory implements org.eclipse.aether.spi.log.LoggerFactory {
@Override
public org.eclipse.aether.spi.log.Logger getLogger(String s) {
return new org.eclipse.aether.spi.log.Logger() {
@Override
public boolean isDebugEnabled() {
return terminalLogger.isDebugEnabled();
}
@Override
public void debug(String s) {
terminalLogger.debug(s);
}
@Override
public void debug(String s, Throwable throwable) {
terminalLogger.debug(s, throwable);
}
@Override
public boolean isWarnEnabled() {
return terminalLogger.isWarnEnabled();
}
@Override
public void warn(String s) {
terminalLogger.warn(s);
}
@Override
public void warn(String s, Throwable throwable) {
terminalLogger.debug(s, throwable);
}
};
}
}
}