blob: 854c099d25b479bcd1e6eb02707214939bc03877 [file] [log] [blame]
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.maven.server;
import com.intellij.openapi.util.Comparing;
import com.intellij.util.SystemProperties;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.apache.maven.*;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.InvalidRepositoryException;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager;
import org.apache.maven.artifact.resolver.*;
import org.apache.maven.cli.MavenCli;
import org.apache.maven.execution.*;
import org.apache.maven.model.Activation;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Profile;
import org.apache.maven.model.interpolation.ModelInterpolator;
import org.apache.maven.model.profile.DefaultProfileInjector;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.plugin.internal.PluginDependenciesResolver;
import org.apache.maven.profiles.activation.*;
import org.apache.maven.project.*;
import org.apache.maven.project.inheritance.DefaultModelInheritanceAssembler;
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.path.PathTranslator;
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.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.DependencyNode;
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.logging.Logger;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.model.*;
import org.jetbrains.idea.maven.server.embedder.*;
import org.jetbrains.idea.maven.server.embedder.MavenExecutionResult;
import org.sonatype.aether.RepositorySystemSession;
import org.sonatype.aether.util.DefaultRepositorySystemSession;
import org.sonatype.aether.util.graph.PreorderNodeListGenerator;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* Overridden maven components:
maven-compat:
org.jetbrains.idea.maven.server.embedder.CustomMaven3RepositoryMetadataManager <-> org.apache.maven.artifact.repository.metadata.DefaultRepositoryMetadataManager
org.jetbrains.idea.maven.server.embedder.CustomMaven3ArtifactResolver <-> org.apache.maven.artifact.resolver.DefaultArtifactResolver
org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator <-> org.apache.maven.project.interpolation.StringSearchModelInterpolator
maven-core:
org.jetbrains.idea.maven.server.embedder.CustomMaven3ArtifactFactory <-> org.apache.maven.artifact.factory.DefaultArtifactFactory
org.jetbrains.idea.maven.server.embedder.CustomPluginDescriptorCache <-> org.apache.maven.plugin.DefaultPluginDescriptorCache
maven-model-builder:
org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator2 <-> org.apache.maven.model.interpolation.StringSearchModelInterpolator
*/
public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements MavenServerEmbedder {
@NotNull private final DefaultPlexusContainer myContainer;
@NotNull private final Settings myMavenSettings;
private final ArtifactRepository myLocalRepository;
private final Maven3ServerConsoleLogger myConsoleWrapper;
private final Properties mySystemProperties;
private volatile MavenServerProgressIndicator myCurrentIndicator;
private MavenWorkspaceMap myWorkspaceMap;
private Date myBuildStartTime;
private boolean myAlwaysUpdateSnapshots;
public Maven3ServerEmbedderImpl(MavenServerSettings settings) throws RemoteException {
File mavenHome = settings.getMavenHome();
if (mavenHome != null) {
System.setProperty("maven.home", mavenHome.getPath());
}
myConsoleWrapper = new Maven3ServerConsoleLogger();
myConsoleWrapper.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 Logger createLogger(String s) {
return myConsoleWrapper;
}
});
}
};
Class cliRequestClass;
try {
cliRequestClass = MavenCli.class.getClassLoader().loadClass("org.apache.maven.cli.MavenCli$CliRequest");
}
catch (ClassNotFoundException e) {
throw new RuntimeException("Class \"org.apache.maven.cli.MavenCli$CliRequest\" not found");
}
Object cliRequest;
try {
String[] commandLineOptions = new String[settings.getUserProperties().size()];
int idx = 0;
for (Map.Entry<Object, Object> each : settings.getUserProperties().entrySet()) {
commandLineOptions[idx++] = "-D" + each.getKey() + "=" + each.getValue();
}
Constructor constructor = cliRequestClass.getDeclaredConstructor(String[].class, ClassWorld.class);
constructor.setAccessible(true);
cliRequest = constructor.newInstance(commandLineOptions, classWorld);
for (String each : new String[]{"initialize", "cli", "properties", "container"}) {
Method m = MavenCli.class.getDeclaredMethod(each, cliRequestClass);
m.setAccessible(true);
m.invoke(cli, cliRequest);
}
}
catch (InstantiationException e) {
throw new RuntimeException(e);
}
catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
// reset threshold
myContainer = FieldAccessor.get(MavenCli.class, cli, "container");
myContainer.getLoggerManager().setThreshold(settings.getLoggingLevel());
mySystemProperties = FieldAccessor.<Properties>get(cliRequestClass, cliRequest, "systemProperties");
if (settings.getProjectJdk() != null) {
mySystemProperties.setProperty("java.home", settings.getProjectJdk());
}
myMavenSettings =
buildSettings(FieldAccessor.<SettingsBuilder>get(MavenCli.class, cli, "settingsBuilder"), settings, mySystemProperties,
FieldAccessor.<Properties>get(cliRequestClass, cliRequest, "userProperties"));
myLocalRepository = createLocalRepository();
}
private static Settings buildSettings(SettingsBuilder builder,
MavenServerSettings settings,
Properties systemProperties,
Properties userProperties) throws RemoteException {
SettingsBuildingRequest settingsRequest = new DefaultSettingsBuildingRequest();
settingsRequest.setGlobalSettingsFile(settings.getGlobalSettingsFile());
settingsRequest.setUserSettingsFile(settings.getUserSettingsFile());
settingsRequest.setSystemProperties(systemProperties);
settingsRequest.setUserProperties(userProperties);
Settings result = new Settings();
try {
result = builder.build(settingsRequest).getEffectiveSettings();
}
catch (SettingsBuildingException e) {
Maven3ServerGlobals.getLogger().info(e);
}
result.setOffline(settings.isOffline());
if (settings.getLocalRepository() != null) {
result.setLocalRepository(settings.getLocalRepository().getPath());
}
if (result.getLocalRepository() == null) {
result.setLocalRepository(new File(SystemProperties.getUserHome(), ".m2/repository").getPath());
}
return result;
}
@SuppressWarnings({"unchecked"})
public <T> T getComponent(Class<T> clazz, String roleHint) {
try {
return (T)myContainer.lookup(clazz.getName(), roleHint);
}
catch (ComponentLookupException e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings({"unchecked"})
public <T> T getComponent(Class<T> clazz) {
try {
return (T)myContainer.lookup(clazz.getName());
}
catch (ComponentLookupException e) {
throw new RuntimeException(e);
}
}
private ArtifactRepository createLocalRepository() {
try {
return getComponent(RepositorySystem.class).createLocalRepository(new File(myMavenSettings.getLocalRepository()));
}
catch (InvalidRepositoryException e) {
throw new RuntimeException(e);
// Legacy code.
}
//ArtifactRepositoryLayout layout = getComponent(ArtifactRepositoryLayout.class, "default");
//ArtifactRepositoryFactory factory = getComponent(ArtifactRepositoryFactory.class);
//
//String url = myMavenSettings.getLocalRepository();
//if (!url.startsWith("file:")) url = "file://" + url;
//
//ArtifactRepository localRepository = factory.createArtifactRepository("local", url, layout, null, null);
//
//boolean snapshotPolicySet = myMavenSettings.isOffline();
//if (!snapshotPolicySet && snapshotUpdatePolicy == MavenServerSettings.UpdatePolicy.ALWAYS_UPDATE) {
// factory.setGlobalUpdatePolicy(ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS);
//}
//factory.setGlobalChecksumPolicy(ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN);
//
//return localRepository;
}
@Override
public void customize(@Nullable MavenWorkspaceMap workspaceMap,
boolean failOnUnresolvedDependency,
@NotNull MavenServerConsole console,
@NotNull MavenServerProgressIndicator indicator,
boolean alwaysUpdateSnapshots) throws RemoteException {
try {
((CustomMaven3ArtifactFactory)getComponent(ArtifactFactory.class)).customize();
((CustomMaven3ArtifactResolver)getComponent(ArtifactResolver.class)).customize(workspaceMap, failOnUnresolvedDependency);
((CustomMaven3RepositoryMetadataManager)getComponent(RepositoryMetadataManager.class)).customize(workspaceMap);
//((CustomMaven3WagonManager)getComponent(WagonManager.class)).customize(failOnUnresolvedDependency);
myWorkspaceMap = workspaceMap;
myBuildStartTime = new Date();
myAlwaysUpdateSnapshots = alwaysUpdateSnapshots;
setConsoleAndIndicator(console, new MavenServerProgressIndicatorWrapper(indicator));
}
catch (Exception e) {
throw rethrowException(e);
}
}
private void setConsoleAndIndicator(MavenServerConsole console, MavenServerProgressIndicator indicator) {
myConsoleWrapper.setWrappee(console);
myCurrentIndicator = indicator;
}
@NotNull
@Override
public MavenServerExecutionResult resolveProject(@NotNull File file,
@NotNull Collection<String> activeProfiles,
@NotNull Collection<String> inactiveProfiles)
throws RemoteException, MavenServerProcessCanceledException {
DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myConsoleWrapper);
MavenExecutionResult result = doResolveProject(file, new ArrayList<String>(activeProfiles), new ArrayList<String>(inactiveProfiles),
Arrays.<ResolutionListener>asList(listener));
return createExecutionResult(file, result, listener.getRootNode());
}
@Nullable
@Override
public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles, @NotNull List<String> inactiveProfiles)
throws RemoteException, MavenServerProcessCanceledException {
return MavenEffectivePomDumper.evaluateEffectivePom(this, file, activeProfiles, inactiveProfiles);
}
public void executeWithMavenSession(MavenExecutionRequest request, Runnable runnable) {
DefaultMaven maven = (DefaultMaven)getComponent(Maven.class);
RepositorySystemSession repositorySession = maven.newRepositorySession(request);
request.getProjectBuildingRequest().setRepositorySession(repositorySession);
MavenSession mavenSession = new MavenSession(myContainer, repositorySession, request, new DefaultMavenExecutionResult());
LegacySupport legacySupport = getComponent(LegacySupport.class);
MavenSession oldSession = legacySupport.getSession();
legacySupport.setSession(mavenSession);
/** adapted from {@link org.apache.maven.DefaultMaven#doExecute(org.apache.maven.execution.MavenExecutionRequest)} */
try {
for (AbstractMavenLifecycleParticipant listener : getLifecycleParticipants(Collections.<MavenProject>emptyList())) {
listener.afterSessionStart(mavenSession);
}
}
catch (MavenExecutionException e) {
throw new RuntimeException(e);
}
try {
runnable.run();
}
finally {
legacySupport.setSession(oldSession);
}
}
@NotNull
public MavenExecutionResult doResolveProject(@NotNull final File file,
@NotNull final List<String> activeProfiles,
@NotNull final List<String> inactiveProfiles,
final List<ResolutionListener> listeners) throws RemoteException {
final MavenExecutionRequest request = createRequest(file, activeProfiles, inactiveProfiles, Collections.<String>emptyList());
request.setUpdateSnapshots(myAlwaysUpdateSnapshots);
final AtomicReference<MavenExecutionResult> ref = new AtomicReference<MavenExecutionResult>();
executeWithMavenSession(request, new Runnable() {
@Override
public void run() {
try {
// copied from DefaultMavenProjectBuilder.buildWithDependencies
ProjectBuilder builder = getComponent(ProjectBuilder.class);
CustomMaven3ModelInterpolator2 modelInterpolator = (CustomMaven3ModelInterpolator2)getComponent(ModelInterpolator.class);
String savedLocalRepository = modelInterpolator.getLocalRepository();
modelInterpolator.setLocalRepository(request.getLocalRepositoryPath().getAbsolutePath());
List<ProjectBuildingResult> results;
try {
// Don't use build(File projectFile, ProjectBuildingRequest request) , because it don't use cache !!!!!!!! (see http://devnet.jetbrains.com/message/5500218)
results = builder.build(Collections.singletonList(new File(file.getPath())), false, request.getProjectBuildingRequest());
}
finally {
modelInterpolator.setLocalRepository(savedLocalRepository);
}
ProjectBuildingResult buildingResult = results.get(0);
MavenProject project = buildingResult.getProject();
RepositorySystemSession repositorySession = getComponent(LegacySupport.class).getRepositorySession();
if (repositorySession instanceof DefaultRepositorySystemSession) {
((DefaultRepositorySystemSession)repositorySession).setTransferListener(new TransferListenerAdapter(myCurrentIndicator));
if (myWorkspaceMap != null) {
((DefaultRepositorySystemSession)repositorySession).setWorkspaceReader(new Maven3WorkspaceReader(myWorkspaceMap));
}
}
List<Exception> exceptions = new ArrayList<Exception>();
loadExtensions(project, exceptions);
//Artifact projectArtifact = project.getArtifact();
//Map managedVersions = project.getManagedVersionMap();
//ArtifactMetadataSource metadataSource = getComponent(ArtifactMetadataSource.class);
project.setDependencyArtifacts(project.createArtifacts(getComponent(ArtifactFactory.class), null, null));
//
ArtifactResolutionRequest resolutionRequest = new ArtifactResolutionRequest();
resolutionRequest.setArtifactDependencies(project.getDependencyArtifacts());
resolutionRequest.setArtifact(project.getArtifact());
resolutionRequest.setManagedVersionMap(project.getManagedVersionMap());
resolutionRequest.setLocalRepository(myLocalRepository);
resolutionRequest.setRemoteRepositories(project.getRemoteArtifactRepositories());
resolutionRequest.setListeners(listeners);
resolutionRequest.setResolveRoot(false);
resolutionRequest.setResolveTransitively(true);
ArtifactResolver resolver = getComponent(ArtifactResolver.class);
ArtifactResolutionResult result = resolver.resolve(resolutionRequest);
project.setArtifacts(result.getArtifacts());
// end copied from DefaultMavenProjectBuilder.buildWithDependencies
ref.set(new MavenExecutionResult(project, exceptions));
}
catch (Exception e) {
ref.set(handleException(e));
}
}
});
return ref.get();
}
/**
* adapted from {@link org.apache.maven.DefaultMaven#doExecute(org.apache.maven.execution.MavenExecutionRequest)}
*/
private void loadExtensions(MavenProject project, List<Exception> exceptions) {
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
Collection<AbstractMavenLifecycleParticipant> lifecycleParticipants = getLifecycleParticipants(Arrays.asList(project));
if (!lifecycleParticipants.isEmpty()) {
LegacySupport legacySupport = getComponent(LegacySupport.class);
MavenSession session = legacySupport.getSession();
session.setCurrentProject(project);
session.setProjects(Arrays.asList(project));
for (AbstractMavenLifecycleParticipant listener : lifecycleParticipants) {
Thread.currentThread().setContextClassLoader(listener.getClass().getClassLoader());
try {
listener.afterProjectsRead(session);
}
catch (MavenExecutionException e) {
exceptions.add(e);
}
finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
}
}
/**
* adapted from {@link org.apache.maven.DefaultMaven#getLifecycleParticipants(java.util.Collection)}
*/
private Collection<AbstractMavenLifecycleParticipant> getLifecycleParticipants(Collection<MavenProject> projects) {
Collection<AbstractMavenLifecycleParticipant> lifecycleListeners = new LinkedHashSet<AbstractMavenLifecycleParticipant>();
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
try {
lifecycleListeners.addAll(myContainer.lookupList(AbstractMavenLifecycleParticipant.class));
}
catch (ComponentLookupException e) {
// this is just silly, lookupList should return an empty list!
warn("Failed to lookup lifecycle participants", e);
}
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(myContainer.lookupList(AbstractMavenLifecycleParticipant.class));
}
catch (ComponentLookupException e) {
// this is just silly, lookupList should return an empty list!
warn("Failed to lookup lifecycle participants", e);
}
}
}
}
finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
return lifecycleListeners;
}
private static void warn(String message, Throwable e) {
try {
Maven3ServerGlobals.getLogger().warn(new RuntimeException(message, e));
}
catch (RemoteException e1) {
throw new RuntimeException(e1);
}
}
public MavenExecutionRequest createRequest(File file, List<String> activeProfiles, List<String> inactiveProfiles, List<String> goals)
throws RemoteException {
//Properties executionProperties = myMavenSettings.getProperties();
//if (executionProperties == null) {
// executionProperties = new Properties();
//}
MavenExecutionRequest result = new DefaultMavenExecutionRequest();
try {
getComponent(MavenExecutionRequestPopulator.class).populateFromSettings(result, myMavenSettings);
result.setGoals(goals);
result.setPom(file);
getComponent(MavenExecutionRequestPopulator.class).populateDefaults(result);
result.setSystemProperties(mySystemProperties);
result.setActiveProfiles(activeProfiles);
result.setInactiveProfiles(inactiveProfiles);
result.setStartTime(myBuildStartTime);
return result;
}
catch (MavenExecutionRequestPopulationException e) {
throw new RuntimeException(e);
}
}
private static MavenExecutionResult handleException(Throwable e) {
if (e instanceof Error) throw (Error)e;
return new MavenExecutionResult(null, Collections.singletonList((Exception)e));
}
@NotNull
public File getLocalRepositoryFile() {
return new File(myLocalRepository.getBasedir());
}
@NotNull
private MavenServerExecutionResult createExecutionResult(File file, MavenExecutionResult result, DependencyNode rootNode)
throws RemoteException {
Collection<MavenProjectProblem> problems = MavenProjectProblem.createProblemsList();
THashSet<MavenId> unresolvedArtifacts = new THashSet<MavenId>();
validate(file, result.getExceptions(), problems, unresolvedArtifacts);
MavenProject mavenProject = result.getMavenProject();
if (mavenProject == null) return new MavenServerExecutionResult(null, problems, unresolvedArtifacts);
MavenModel model = null;
try {
model = MavenModelConverter
.convertModel(mavenProject.getModel(), mavenProject.getCompileSourceRoots(), mavenProject.getTestCompileSourceRoots(),
mavenProject.getArtifacts(), (rootNode == null ? Collections.emptyList() : rootNode.getChildren()),
mavenProject.getExtensionArtifacts(), getLocalRepositoryFile());
}
catch (Exception e) {
validate(mavenProject.getFile(), Collections.singleton(e), problems, null);
}
RemoteNativeMavenProjectHolder holder = new RemoteNativeMavenProjectHolder(mavenProject);
try {
UnicastRemoteObject.exportObject(holder, 0);
}
catch (RemoteException e) {
throw new RuntimeException(e);
}
Collection<String> activatedProfiles = collectActivatedProfiles(mavenProject);
MavenServerExecutionResult.ProjectData data =
new MavenServerExecutionResult.ProjectData(model, MavenModelConverter.convertToMap(mavenProject.getModel()), holder,
activatedProfiles);
return new MavenServerExecutionResult(data, problems, unresolvedArtifacts);
}
private static Collection<String> collectActivatedProfiles(MavenProject mavenProject)
throws RemoteException {
// for some reason project's active profiles do not contain parent's profiles - only local and settings'.
// parent's profiles do not contain settings' profiles.
List<Profile> profiles = new ArrayList<Profile>();
try {
while (mavenProject != null) {
profiles.addAll(mavenProject.getActiveProfiles());
mavenProject = mavenProject.getParent();
}
}
catch (Exception e) {
// don't bother user if maven failed to build parent project
Maven3ServerGlobals.getLogger().info(e);
}
return collectProfilesIds(profiles);
}
private void validate(@NotNull File file,
@NotNull Collection<Exception> exceptions,
@NotNull Collection<MavenProjectProblem> problems,
@Nullable Collection<MavenId> unresolvedArtifacts) throws RemoteException {
for (Throwable each : exceptions) {
Maven3ServerGlobals.getLogger().info(each);
if(each instanceof IllegalStateException && each.getCause() != null) {
each = each.getCause();
}
if (each instanceof InvalidProjectModelException) {
ModelValidationResult modelValidationResult = ((InvalidProjectModelException)each).getValidationResult();
if (modelValidationResult != null) {
for (Object eachValidationProblem : modelValidationResult.getMessages()) {
problems.add(MavenProjectProblem.createStructureProblem(file.getPath(), (String)eachValidationProblem));
}
}
else {
problems.add(MavenProjectProblem.createStructureProblem(file.getPath(), each.getCause().getMessage()));
}
}
else if (each instanceof ProjectBuildingException) {
String causeMessage = each.getCause() != null ? each.getCause().getMessage() : each.getMessage();
problems.add(MavenProjectProblem.createStructureProblem(file.getPath(), causeMessage));
}
else {
problems.add(MavenProjectProblem.createStructureProblem(file.getPath(), each.getMessage()));
}
}
if (unresolvedArtifacts != null) {
unresolvedArtifacts.addAll(retrieveUnresolvedArtifactIds());
}
}
private Set<MavenId> retrieveUnresolvedArtifactIds() {
Set<MavenId> result = new THashSet<MavenId>();
// TODO collect unresolved artifacts
//((CustomMaven3WagonManager)getComponent(WagonManager.class)).getUnresolvedCollector().retrieveUnresolvedIds(result);
//((CustomMaven3ArtifactResolver)getComponent(ArtifactResolver.class)).getUnresolvedCollector().retrieveUnresolvedIds(result);
return result;
}
@NotNull
@Override
public MavenArtifact resolve(@NotNull MavenArtifactInfo info, @NotNull List<MavenRemoteRepository> remoteRepositories)
throws RemoteException, MavenServerProcessCanceledException {
return doResolve(info, remoteRepositories);
}
@NotNull
@Override
public List<MavenArtifact> resolveTransitively(@NotNull List<MavenArtifactInfo> artifacts,
@NotNull List<MavenRemoteRepository> remoteRepositories)
throws RemoteException, MavenServerProcessCanceledException {
try {
Set<Artifact> toResolve = new LinkedHashSet<Artifact>();
for (MavenArtifactInfo each : artifacts) {
toResolve.add(createArtifact(each));
}
Artifact project = getComponent(ArtifactFactory.class).createBuildArtifact("temp", "temp", "666", "pom");
Set<Artifact> res = getComponent(ArtifactResolver.class)
.resolveTransitively(toResolve, project, Collections.EMPTY_MAP, myLocalRepository, convertRepositories(remoteRepositories),
getComponent(ArtifactMetadataSource.class)).getArtifacts();
return MavenModelConverter.convertArtifacts(res, new THashMap<Artifact, MavenArtifact>(), getLocalRepositoryFile());
}
catch (ArtifactResolutionException e) {
Maven3ServerGlobals.getLogger().info(e);
}
catch (ArtifactNotFoundException e) {
Maven3ServerGlobals.getLogger().info(e);
}
catch (Exception e) {
throw rethrowException(e);
}
return Collections.emptyList();
}
@Override
public Collection<MavenArtifact> resolvePlugin(@NotNull final MavenPlugin plugin,
@NotNull final List<MavenRemoteRepository> repositories,
int nativeMavenProjectId,
final boolean transitive) throws RemoteException, MavenServerProcessCanceledException {
try {
Plugin mavenPlugin = new Plugin();
mavenPlugin.setGroupId(plugin.getGroupId());
mavenPlugin.setArtifactId(plugin.getArtifactId());
mavenPlugin.setVersion(plugin.getVersion());
MavenProject project = RemoteNativeMavenProjectHolder.findProjectById(nativeMavenProjectId);
Plugin pluginFromProject = project.getBuild().getPluginsAsMap().get(plugin.getGroupId() + ':' + plugin.getArtifactId());
if (pluginFromProject != null) {
mavenPlugin.setDependencies(pluginFromProject.getDependencies());
}
final MavenExecutionRequest request =
createRequest(null, Collections.<String>emptyList(), Collections.<String>emptyList(), Collections.<String>emptyList());
DefaultMaven maven = (DefaultMaven)getComponent(Maven.class);
RepositorySystemSession repositorySystemSession = maven.newRepositorySession(request);
PluginDependenciesResolver pluginDependenciesResolver = getComponent(PluginDependenciesResolver.class);
org.sonatype.aether.artifact.Artifact pluginArtifact =
pluginDependenciesResolver.resolve(mavenPlugin, project.getRemotePluginRepositories(), repositorySystemSession);
org.sonatype.aether.graph.DependencyNode node = pluginDependenciesResolver
.resolve(mavenPlugin, pluginArtifact, null, project.getRemotePluginRepositories(), repositorySystemSession);
PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
node.accept(nlg);
List<MavenArtifact> res = new ArrayList<MavenArtifact>();
for (org.sonatype.aether.artifact.Artifact artifact : nlg.getArtifacts(true)) {
if (!Comparing.equal(artifact.getArtifactId(), plugin.getArtifactId()) ||
!Comparing.equal(artifact.getGroupId(), plugin.getGroupId())) {
res.add(MavenModelConverter.convertArtifact(RepositoryUtils.toArtifact(artifact), getLocalRepositoryFile()));
}
}
return res;
}
catch (Exception e) {
Maven3ServerGlobals.getLogger().info(e);
return Collections.emptyList();
}
}
private MavenArtifact doResolve(MavenArtifactInfo info, List<MavenRemoteRepository> remoteRepositories) throws RemoteException {
Artifact resolved = doResolve(createArtifact(info), convertRepositories(remoteRepositories));
return MavenModelConverter.convertArtifact(resolved, getLocalRepositoryFile());
}
private Artifact doResolve(Artifact artifact, List<ArtifactRepository> remoteRepositories) throws RemoteException {
try {
resolve(artifact, remoteRepositories);
return artifact;
}
catch (Exception e) {
Maven3ServerGlobals.getLogger().info(e);
}
return artifact;
}
public void resolve(@NotNull final Artifact artifact, @NotNull final List<ArtifactRepository> repos)
throws ArtifactResolutionException, ArtifactNotFoundException {
MavenExecutionRequest request = new DefaultMavenExecutionRequest();
request.setRemoteRepositories(repos);
try {
getComponent(MavenExecutionRequestPopulator.class).populateFromSettings(request, myMavenSettings);
getComponent(MavenExecutionRequestPopulator.class).populateDefaults(request);
}
catch (MavenExecutionRequestPopulationException e) {
throw new RuntimeException(e);
}
getComponent(ArtifactResolver.class).resolve(artifact, request.getRemoteRepositories(), myLocalRepository);
}
private List<ArtifactRepository> convertRepositories(List<MavenRemoteRepository> repositories) throws RemoteException {
List<ArtifactRepository> result = new ArrayList<ArtifactRepository>();
for (MavenRemoteRepository each : repositories) {
try {
ArtifactRepositoryFactory factory = getComponent(ArtifactRepositoryFactory.class);
result.add(ProjectUtils.buildArtifactRepository(MavenModelConverter.toNativeRepository(each), factory, myContainer));
}
catch (InvalidRepositoryException e) {
Maven3ServerGlobals.getLogger().warn(e);
}
}
return result;
}
private Artifact createArtifact(MavenArtifactInfo info) {
return getComponent(ArtifactFactory.class)
.createArtifactWithClassifier(info.getGroupId(), info.getArtifactId(), info.getVersion(), info.getPackaging(), info.getClassifier());
}
@NotNull
@Override
public MavenServerExecutionResult execute(@NotNull File file,
@NotNull Collection<String> activeProfiles,
@NotNull Collection<String> inactiveProfiles,
@NotNull List<String> goals,
@NotNull List<String> selectedProjects,
boolean alsoMake,
boolean alsoMakeDependents) throws RemoteException, MavenServerProcessCanceledException {
MavenExecutionResult result =
doExecute(file, new ArrayList<String>(activeProfiles), new ArrayList<String>(inactiveProfiles), goals, selectedProjects, alsoMake,
alsoMakeDependents);
return createExecutionResult(file, result, null);
}
private MavenExecutionResult doExecute(@NotNull final File file,
@NotNull final List<String> activeProfiles,
@NotNull final List<String> inactiveProfiles,
@NotNull final List<String> goals,
@NotNull final List<String> selectedProjects,
boolean alsoMake,
boolean alsoMakeDependents) throws RemoteException {
MavenExecutionRequest request = createRequest(file, activeProfiles, inactiveProfiles, goals);
if (!selectedProjects.isEmpty()) {
request.setRecursive(true);
request.setSelectedProjects(selectedProjects);
if (alsoMake && alsoMakeDependents) {
request.setMakeBehavior(ReactorManager.MAKE_BOTH_MODE);
}
else if (alsoMake) {
request.setMakeBehavior(ReactorManager.MAKE_MODE);
}
else if (alsoMakeDependents) {
request.setMakeBehavior(ReactorManager.MAKE_DEPENDENTS_MODE);
}
}
org.apache.maven.execution.MavenExecutionResult executionResult = safeExecute(request, getComponent(Maven.class));
return new MavenExecutionResult(executionResult.getProject(), filterExceptions(executionResult.getExceptions()));
}
private org.apache.maven.execution.MavenExecutionResult safeExecute(MavenExecutionRequest request, Maven maven) throws RemoteException {
MavenLeakDetector detector = new MavenLeakDetector().mark();
org.apache.maven.execution.MavenExecutionResult result = maven.execute(request);
detector.check();
return result;
}
private static List<Exception> filterExceptions(List<Throwable> list) {
for (Throwable throwable : list) {
if (!(throwable instanceof Exception)) {
throw new RuntimeException(throwable);
}
}
return (List<Exception>)((List)list);
}
@Override
public void reset() throws RemoteException {
try {
setConsoleAndIndicator(null, null);
((CustomMaven3ArtifactFactory)getComponent(ArtifactFactory.class)).reset();
((CustomMaven3ArtifactResolver)getComponent(ArtifactResolver.class)).reset();
((CustomMaven3RepositoryMetadataManager)getComponent(RepositoryMetadataManager.class)).reset();
//((CustomWagonManager)getComponent(WagonManager.class)).reset();
}
catch (Exception e) {
throw rethrowException(e);
}
}
@Override
public void release() throws RemoteException {
myContainer.dispose();
}
public void clearCaches() throws RemoteException {
// do nothing
}
public void clearCachesFor(final MavenId projectId) throws RemoteException {
// do nothing
}
public static MavenModel interpolateAndAlignModel(MavenModel model, File basedir) throws RemoteException {
Model result = MavenModelConverter.toNativeModel(model);
result = doInterpolate(result, basedir);
PathTranslator pathTranslator = new DefaultPathTranslator();
pathTranslator.alignToBaseDirectory(result, basedir);
return MavenModelConverter.convertModel(result, null);
}
public static MavenModel assembleInheritance(MavenModel model, MavenModel parentModel) throws RemoteException {
Model result = MavenModelConverter.toNativeModel(model);
new DefaultModelInheritanceAssembler().assembleModelInheritance(result, MavenModelConverter.toNativeModel(parentModel));
return MavenModelConverter.convertModel(result, null);
}
public static ProfileApplicationResult applyProfiles(MavenModel model,
File basedir,
MavenExplicitProfiles explicitProfiles,
Collection<String> alwaysOnProfiles) throws RemoteException {
Model nativeModel = MavenModelConverter.toNativeModel(model);
Collection<String> enabledProfiles = explicitProfiles.getEnabledProfiles();
Collection<String> disabledProfiles = explicitProfiles.getDisabledProfiles();
List<Profile> activatedPom = new ArrayList<Profile>();
List<Profile> activatedExternal = new ArrayList<Profile>();
List<Profile> activeByDefault = new ArrayList<Profile>();
List<Profile> rawProfiles = nativeModel.getProfiles();
List<Profile> expandedProfilesCache = null;
List<Profile> deactivatedProfiles = new ArrayList<Profile>();
for (int i = 0; i < rawProfiles.size(); i++) {
Profile eachRawProfile = rawProfiles.get(i);
if (disabledProfiles.contains(eachRawProfile.getId())) {
deactivatedProfiles.add(eachRawProfile);
continue;
}
boolean shouldAdd = enabledProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId());
Activation activation = eachRawProfile.getActivation();
if (activation != null) {
if (activation.isActiveByDefault()) {
activeByDefault.add(eachRawProfile);
}
// expand only if necessary
if (expandedProfilesCache == null) expandedProfilesCache = doInterpolate(nativeModel, basedir).getProfiles();
Profile eachExpandedProfile = expandedProfilesCache.get(i);
for (ProfileActivator eachActivator : getProfileActivators(basedir)) {
try {
if (eachActivator.canDetermineActivation(eachExpandedProfile) && eachActivator.isActive(eachExpandedProfile)) {
shouldAdd = true;
break;
}
}
catch (ProfileActivationException e) {
Maven3ServerGlobals.getLogger().warn(e);
}
}
}
if (shouldAdd) {
if (MavenConstants.PROFILE_FROM_POM.equals(eachRawProfile.getSource())) {
activatedPom.add(eachRawProfile);
}
else {
activatedExternal.add(eachRawProfile);
}
}
}
List<Profile> activatedProfiles = new ArrayList<Profile>(activatedPom.isEmpty() ? activeByDefault : activatedPom);
activatedProfiles.addAll(activatedExternal);
for (Profile each : activatedProfiles) {
new DefaultProfileInjector().injectProfile(nativeModel, each, null, null);
}
return new ProfileApplicationResult(MavenModelConverter.convertModel(nativeModel, null),
new MavenExplicitProfiles(collectProfilesIds(activatedProfiles),
collectProfilesIds(deactivatedProfiles))
);
}
private static Model doInterpolate(Model result, File basedir) throws RemoteException {
try {
AbstractStringBasedModelInterpolator interpolator = new CustomMaven3ModelInterpolator(new DefaultPathTranslator());
interpolator.initialize();
Properties props = MavenServerUtil.collectSystemProperties();
ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration().setExecutionProperties(props);
config.setBuildStartTime(new Date());
result = interpolator.interpolate(result, basedir, config, false);
}
catch (ModelInterpolationException e) {
Maven3ServerGlobals.getLogger().warn(e);
}
catch (InitializationException e) {
Maven3ServerGlobals.getLogger().error(e);
}
return result;
}
private static Collection<String> collectProfilesIds(List<Profile> profiles) {
Collection<String> result = new THashSet<String>();
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", MavenServerUtil.collectSystemProperties());
try {
sysPropertyActivator.contextualize(context);
}
catch (ContextException e) {
Maven3ServerGlobals.getLogger().error(e);
return new ProfileActivator[0];
}
return new ProfileActivator[]{new MyFileProfileActivator(basedir), sysPropertyActivator, new JdkPrefixProfileActivator(),
new OperatingSystemProfileActivator()};
}
public interface Computable<T> {
T compute();
}
}