blob: ba3d265b7d100040ecd79190d873614a63127049 [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.dom;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
import com.intellij.util.xml.DomUtil;
import com.intellij.util.xml.GenericDomValue;
import com.intellij.util.xml.impl.GenericDomValueReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.model.*;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.project.*;
import org.jetbrains.idea.maven.utils.MavenUtil;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
public class MavenDomProjectProcessorUtils {
private MavenDomProjectProcessorUtils() {
}
@NotNull
public static Set<MavenDomProjectModel> getChildrenProjects(@NotNull final MavenDomProjectModel model) {
Set<MavenDomProjectModel> models = new HashSet<MavenDomProjectModel>();
collectChildrenProjects(model, models);
return models;
}
private static void collectChildrenProjects(@NotNull final MavenDomProjectModel model, @NotNull Set<MavenDomProjectModel> models) {
MavenProject mavenProject = MavenDomUtil.findProject(model);
if (mavenProject != null) {
final Project project = model.getManager().getProject();
for (MavenProject inheritor : MavenProjectsManager.getInstance(project).findInheritors(mavenProject)) {
MavenDomProjectModel inheritorProjectModel = MavenDomUtil.getMavenDomProjectModel(project, inheritor.getFile());
if (inheritorProjectModel != null && !models.contains(inheritorProjectModel)) {
models.add(inheritorProjectModel);
collectChildrenProjects(inheritorProjectModel, models);
}
}
}
}
@NotNull
public static Set<MavenDomProjectModel> collectParentProjects(@NotNull final MavenDomProjectModel projectDom) {
final Set<MavenDomProjectModel> parents = new HashSet<MavenDomProjectModel>();
Processor<MavenDomProjectModel> collectProcessor = new Processor<MavenDomProjectModel>() {
public boolean process(MavenDomProjectModel model) {
parents.add(model);
return false;
}
};
processParentProjects(projectDom, collectProcessor);
return parents;
}
public static void processParentProjects(@NotNull final MavenDomProjectModel projectDom,
@NotNull final Processor<MavenDomProjectModel> processor) {
Set<MavenDomProjectModel> processed = new HashSet<MavenDomProjectModel>();
Project project = projectDom.getManager().getProject();
MavenDomProjectModel parent = findParent(projectDom, project);
while (parent != null) {
if (processed.contains(parent)) break;
processed.add(parent);
if (processor.process(parent)) break;
parent = findParent(parent, project);
}
}
@Nullable
public static MavenDomProjectModel findParent(@NotNull MavenDomProjectModel model, Project project) {
return findParent(model.getMavenParent(), project);
}
@Nullable
public static MavenDomProjectModel findParent(@NotNull MavenDomParent mavenDomParent, Project project) {
if (!DomUtil.hasXml(mavenDomParent)) return null;
MavenId id = new MavenId(mavenDomParent.getGroupId().getStringValue(), mavenDomParent.getArtifactId().getStringValue(),
mavenDomParent.getVersion().getStringValue());
MavenProject mavenProject = MavenProjectsManager.getInstance(project).findProject(id);
return mavenProject != null ? MavenDomUtil.getMavenDomProjectModel(project, mavenProject.getFile()) : null;
}
@Nullable
public static XmlTag searchProperty(@NotNull final String propertyName,
@NotNull MavenDomProjectModel projectDom,
@NotNull final Project project) {
SearchProcessor<XmlTag, MavenDomProperties> searchProcessor = new SearchProcessor<XmlTag, MavenDomProperties>() {
@Override
protected XmlTag find(MavenDomProperties element) {
return findProperty(element, propertyName);
}
};
processProperties(projectDom, searchProcessor, project);
return searchProcessor.myResult;
}
@Nullable
public static XmlTag findProperty(@NotNull MavenDomProperties mavenDomProperties, @NotNull String propertyName) {
XmlTag propertiesTag = mavenDomProperties.getXmlTag();
if (propertiesTag == null) return null;
for (XmlTag each : propertiesTag.getSubTags()) {
if (each.getName().equals(propertyName)) {
return each;
}
}
return null;
}
public static Set<XmlTag> collectProperties(@NotNull MavenDomProjectModel projectDom, @NotNull final Project project) {
final Set<XmlTag> properties = new HashSet<XmlTag>();
Processor<MavenDomProperties> collectProcessor = new Processor<MavenDomProperties>() {
public boolean process(MavenDomProperties mavenDomProperties) {
XmlTag propertiesTag = mavenDomProperties.getXmlTag();
if (propertiesTag != null) {
ContainerUtil.addAll(properties, propertiesTag.getSubTags());
}
return false;
}
};
processProperties(projectDom, collectProcessor, project);
return properties;
}
@NotNull
public static Set<MavenDomDependency> searchDependencyUsages(@NotNull final MavenDomDependency dependency) {
final MavenDomProjectModel model = dependency.getParentOfType(MavenDomProjectModel.class, false);
if (model != null) {
DependencyConflictId dependencyId = DependencyConflictId.create(dependency);
if (dependencyId != null) {
return searchDependencyUsages(model, dependencyId, Collections.singleton(dependency));
}
}
return Collections.emptySet();
}
@NotNull
public static Set<MavenDomDependency> searchDependencyUsages(@NotNull final MavenDomProjectModel model,
@NotNull final DependencyConflictId dependencyId,
@NotNull final Set<MavenDomDependency> excludes) {
Project project = model.getManager().getProject();
final Set<MavenDomDependency> usages = new HashSet<MavenDomDependency>();
Processor<MavenDomProjectModel> collectProcessor = new Processor<MavenDomProjectModel>() {
public boolean process(MavenDomProjectModel mavenDomProjectModel) {
for (MavenDomDependency domDependency : mavenDomProjectModel.getDependencies().getDependencies()) {
if (excludes.contains(domDependency)) continue;
if (dependencyId.equals(DependencyConflictId.create(domDependency))) {
usages.add(domDependency);
}
}
return false;
}
};
processChildrenRecursively(model, collectProcessor, project, new HashSet<MavenDomProjectModel>(), true);
return usages;
}
@NotNull
public static Collection<MavenDomPlugin> searchManagedPluginUsages(@NotNull final MavenDomPlugin plugin) {
String artifactId = plugin.getArtifactId().getStringValue();
if (artifactId == null) return Collections.emptyList();
String groupId = plugin.getGroupId().getStringValue();
MavenDomProjectModel model = plugin.getParentOfType(MavenDomProjectModel.class, false);
if (model == null) return Collections.emptyList();
return searchManagedPluginUsages(model, groupId, artifactId);
}
@NotNull
public static Collection<MavenDomPlugin> searchManagedPluginUsages(@NotNull final MavenDomProjectModel model,
@Nullable final String groupId,
@NotNull final String artifactId) {
Project project = model.getManager().getProject();
final Set<MavenDomPlugin> usages = new HashSet<MavenDomPlugin>();
Processor<MavenDomProjectModel> collectProcessor = new Processor<MavenDomProjectModel>() {
public boolean process(MavenDomProjectModel mavenDomProjectModel) {
for (MavenDomPlugin domPlugin : mavenDomProjectModel.getBuild().getPlugins().getPlugins()) {
if (MavenPluginDomUtil.isPlugin(domPlugin, groupId, artifactId)) {
usages.add(domPlugin);
}
}
return false;
}
};
processChildrenRecursively(model, collectProcessor, project, new HashSet<MavenDomProjectModel>(), true);
return usages;
}
public static void processChildrenRecursively(@Nullable MavenDomProjectModel model,
@NotNull Processor<MavenDomProjectModel> processor) {
processChildrenRecursively(model, processor, true);
}
public static void processChildrenRecursively(@Nullable MavenDomProjectModel model,
@NotNull Processor<MavenDomProjectModel> processor,
boolean processCurrentModel) {
if (model != null) {
processChildrenRecursively(model, processor, model.getManager().getProject(), new HashSet<MavenDomProjectModel>(),
processCurrentModel);
}
}
public static void processChildrenRecursively(@Nullable MavenDomProjectModel model,
@NotNull Processor<MavenDomProjectModel> processor,
@NotNull Project project,
@NotNull Set<MavenDomProjectModel> processedModels,
boolean strict) {
if (model != null && !processedModels.contains(model)) {
processedModels.add(model);
if (strict && processor.process(model)) return;
MavenProject mavenProject = MavenDomUtil.findProject(model);
if (mavenProject != null) {
for (MavenProject childProject : MavenProjectsManager.getInstance(project).findInheritors(mavenProject)) {
MavenDomProjectModel childProjectModel = MavenDomUtil.getMavenDomProjectModel(project, childProject.getFile());
processChildrenRecursively(childProjectModel, processor, project, processedModels, true);
}
}
}
}
@Nullable
public static MavenDomDependency searchManagingDependency(@NotNull final MavenDomDependency dependency) {
return searchManagingDependency(dependency, dependency.getManager().getProject());
}
@Nullable
public static MavenDomDependency searchManagingDependency(@NotNull final MavenDomDependency dependency, @NotNull final Project project) {
final DependencyConflictId depId = DependencyConflictId.create(dependency);
if (depId == null) return null;
final MavenDomProjectModel model = dependency.getParentOfType(MavenDomProjectModel.class, false);
if (model == null) return null;
final Ref<MavenDomDependency> res = new Ref<MavenDomDependency>();
Processor<MavenDomDependency> processor = new Processor<MavenDomDependency>() {
@Override
public boolean process(MavenDomDependency dependency) {
if (depId.equals(DependencyConflictId.create(dependency))) {
res.set(dependency);
return true;
}
return false;
}
};
processDependenciesInDependencyManagement(model, processor, project);
return res.get();
}
@Nullable
public static MavenDomPlugin searchManagingPlugin(@NotNull final MavenDomPlugin plugin) {
final String artifactId = plugin.getArtifactId().getStringValue();
final String groupId = plugin.getGroupId().getStringValue();
if (artifactId == null) return null;
final MavenDomProjectModel model = plugin.getParentOfType(MavenDomProjectModel.class, false);
if (model == null) return null;
SearchProcessor<MavenDomPlugin, MavenDomPlugins> processor = new SearchProcessor<MavenDomPlugin, MavenDomPlugins>() {
@Override
protected MavenDomPlugin find(MavenDomPlugins mavenDomPlugins) {
if (!model.equals(mavenDomPlugins.getParentOfType(MavenDomProjectModel.class, true))) {
for (MavenDomPlugin domPlugin : mavenDomPlugins.getPlugins()) {
if (MavenPluginDomUtil.isPlugin(domPlugin, groupId, artifactId)) {
return domPlugin;
}
}
}
return null;
}
};
Function<MavenDomProjectModelBase, MavenDomPlugins> domProfileFunction = new Function<MavenDomProjectModelBase, MavenDomPlugins>() {
public MavenDomPlugins fun(MavenDomProjectModelBase mavenDomProfile) {
return mavenDomProfile.getBuild().getPluginManagement().getPlugins();
}
};
process(model, processor, model.getManager().getProject(), domProfileFunction, domProfileFunction);
return processor.myResult;
}
public static boolean processDependenciesInDependencyManagement(@NotNull MavenDomProjectModel projectDom,
@NotNull final Processor<MavenDomDependency> processor,
@NotNull final Project project) {
Processor<MavenDomDependencies> managedDependenciesListProcessor = new Processor<MavenDomDependencies>() {
@Override
public boolean process(MavenDomDependencies dependencies) {
SmartList<MavenDomDependency> importDependencies = null;
for (MavenDomDependency domDependency : dependencies.getDependencies()) {
if ("import".equals(domDependency.getScope().getRawText())) {
if (importDependencies == null) {
importDependencies = new SmartList<MavenDomDependency>();
}
importDependencies.add(domDependency);
}
else {
if (processor.process(domDependency)) return true;
}
}
if (importDependencies != null) {
for (MavenDomDependency domDependency : importDependencies) {
GenericDomValue<String> version = domDependency.getVersion();
if (version.getXmlElement() != null) {
GenericDomValueReference reference = new GenericDomValueReference(version);
PsiElement resolve = reference.resolve();
if (resolve instanceof XmlFile) {
MavenDomProjectModel dependModel = MavenDomUtil.getMavenDomModel((PsiFile)resolve, MavenDomProjectModel.class);
if (dependModel != null) {
for (MavenDomDependency dep : dependModel.getDependencyManagement().getDependencies().getDependencies()) {
if (processor.process(dep)) return true;
}
}
}
}
}
}
return false;
}
};
Function<MavenDomProjectModelBase, MavenDomDependencies> domFunction = new Function<MavenDomProjectModelBase, MavenDomDependencies>() {
public MavenDomDependencies fun(MavenDomProjectModelBase mavenDomProfile) {
return mavenDomProfile.getDependencyManagement().getDependencies();
}
};
return process(projectDom, managedDependenciesListProcessor, project, domFunction, domFunction);
}
public static boolean processDependencies(@NotNull MavenDomProjectModel projectDom,
@NotNull final Processor<MavenDomDependencies> processor) {
Function<MavenDomProjectModelBase, MavenDomDependencies> domFunction = new Function<MavenDomProjectModelBase, MavenDomDependencies>() {
public MavenDomDependencies fun(MavenDomProjectModelBase mavenDomProfile) {
return mavenDomProfile.getDependencies();
}
};
return process(projectDom, processor, projectDom.getManager().getProject(), domFunction, domFunction);
}
public static boolean processProperties(@NotNull MavenDomProjectModel projectDom,
@NotNull final Processor<MavenDomProperties> processor,
@NotNull final Project project) {
Function<MavenDomProjectModelBase, MavenDomProperties> domFunction = new Function<MavenDomProjectModelBase, MavenDomProperties>() {
public MavenDomProperties fun(MavenDomProjectModelBase mavenDomProfile) {
return mavenDomProfile.getProperties();
}
};
return process(projectDom, processor, project, domFunction, domFunction);
}
public static <T> boolean process(@NotNull MavenDomProjectModel projectDom,
@NotNull final Processor<T> processor,
@NotNull final Project project,
@NotNull final Function<? super MavenDomProfile , T> domProfileFunction,
@NotNull final Function<? super MavenDomProjectModel, T> projectDomFunction) {
return process(projectDom, processor, project, domProfileFunction, projectDomFunction, new HashSet<MavenDomProjectModel>());
}
public static <T> boolean process(@NotNull MavenDomProjectModel projectDom,
@NotNull final Processor<T> processor,
@NotNull final Project project,
@NotNull final Function<? super MavenDomProfile, T> domProfileFunction,
@NotNull final Function<? super MavenDomProjectModel, T> projectDomFunction,
final Set<MavenDomProjectModel> processed) {
if (processed.contains(projectDom)) return true;
processed.add(projectDom);
MavenProject mavenProjectOrNull = MavenDomUtil.findProject(projectDom);
if (processSettingsXml(mavenProjectOrNull, processor, project, domProfileFunction)) return true;
if (processProject(projectDom, mavenProjectOrNull, processor, project, domProfileFunction, projectDomFunction)) return true;
return processParentProjectFile(projectDom, processor, project, domProfileFunction, projectDomFunction, processed);
}
private static <T> boolean processParentProjectFile(MavenDomProjectModel projectDom,
final Processor<T> processor,
final Project project,
final Function<? super MavenDomProfile, T> domProfileFunction,
final Function<? super MavenDomProjectModel, T> projectDomFunction,
final Set<MavenDomProjectModel> processed) {
Boolean aBoolean = new DomParentProjectFileProcessor<Boolean>(MavenProjectsManager.getInstance(project)) {
protected Boolean doProcessParent(VirtualFile parentFile) {
MavenDomProjectModel parentProjectDom = MavenDomUtil.getMavenDomProjectModel(project, parentFile);
if (parentProjectDom == null) return false;
return MavenDomProjectProcessorUtils
.process(parentProjectDom, processor, project, domProfileFunction, projectDomFunction, processed);
}
}.process(projectDom);
return aBoolean == null ? false : aBoolean.booleanValue();
}
private static <T> boolean processSettingsXml(@Nullable MavenProject mavenProject,
@NotNull Processor<T> processor,
@NotNull Project project,
Function<? super MavenDomProfile, T> domProfileFunction) {
MavenGeneralSettings settings = MavenProjectsManager.getInstance(project).getGeneralSettings();
for (VirtualFile each : settings.getEffectiveSettingsFiles()) {
MavenDomSettingsModel settingsDom = MavenDomUtil.getMavenDomModel(project, each, MavenDomSettingsModel.class);
if (settingsDom == null) continue;
if (processProfiles(settingsDom.getProfiles(), mavenProject, processor, domProfileFunction)) return true;
}
return false;
}
private static <T> boolean processProject(MavenDomProjectModel projectDom,
MavenProject mavenProjectOrNull,
Processor<T> processor,
Project project,
Function<? super MavenDomProfile, T> domProfileFunction,
Function<? super MavenDomProjectModel, T> projectDomFunction) {
if (processProfilesXml(MavenDomUtil.getVirtualFile(projectDom), mavenProjectOrNull, processor, project, domProfileFunction)) {
return true;
}
if (processProfiles(projectDom.getProfiles(), mavenProjectOrNull, processor, domProfileFunction)) return true;
T t = projectDomFunction.fun(projectDom);
return t == null ? false : processor.process(t);
}
private static <T> boolean processProfilesXml(VirtualFile projectFile,
MavenProject mavenProjectOrNull,
Processor<T> processor,
Project project,
Function<? super MavenDomProfile, T> f) {
VirtualFile profilesFile = MavenUtil.findProfilesXmlFile(projectFile);
if (profilesFile == null) return false;
MavenDomProfiles profiles = MavenDomUtil.getMavenDomProfilesModel(project, profilesFile);
if (profiles == null) return false;
return processProfiles(profiles, mavenProjectOrNull, processor, f);
}
private static <T> boolean processProfiles(MavenDomProfiles profilesDom,
MavenProject mavenProjectOrNull,
Processor<T> processor,
Function<? super MavenDomProfile, T> f) {
Collection<String> activeProfiles =
mavenProjectOrNull == null ? null : mavenProjectOrNull.getActivatedProfilesIds().getEnabledProfiles();
for (MavenDomProfile each : profilesDom.getProfiles()) {
XmlTag idTag = each.getId().getXmlTag();
if (idTag == null) continue;
if (activeProfiles != null && !activeProfiles.contains(idTag.getValue().getTrimmedText())) continue;
if (processProfile(each, processor, f)) return true;
}
return false;
}
private static <T> boolean processProfile(MavenDomProfile profileDom,
Processor<T> processor,
Function<? super MavenDomProfile, T> f) {
T t = f.fun(profileDom);
return t != null && processor.process(t);
}
public abstract static class DomParentProjectFileProcessor<T> extends MavenParentProjectFileProcessor<T> {
private final MavenProjectsManager myManager;
public DomParentProjectFileProcessor(MavenProjectsManager manager) {
myManager = manager;
}
protected VirtualFile findManagedFile(@NotNull MavenId id) {
MavenProject project = myManager.findProject(id);
return project == null ? null : project.getFile();
}
@Nullable
public T process(@NotNull MavenDomProjectModel projectDom) {
MavenDomParent parent = projectDom.getMavenParent();
MavenParentDesc parentDesc = null;
if (DomUtil.hasXml(parent)) {
String parentGroupId = parent.getGroupId().getStringValue();
String parentArtifactId = parent.getArtifactId().getStringValue();
String parentVersion = parent.getVersion().getStringValue();
String parentRelativePath = parent.getRelativePath().getStringValue();
if (StringUtil.isEmptyOrSpaces(parentRelativePath)) parentRelativePath = "../pom.xml";
MavenId parentId = new MavenId(parentGroupId, parentArtifactId, parentVersion);
parentDesc = new MavenParentDesc(parentId, parentRelativePath);
}
return process(myManager.getGeneralSettings(), MavenDomUtil.getVirtualFile(projectDom), parentDesc);
}
}
public abstract static class SearchProcessor<R, T> implements Processor<T> {
private R myResult;
@Override
public final boolean process(T t) {
R res = find(t);
if (res != null) {
myResult = res;
return true;
}
return false;
}
@Nullable
protected abstract R find(T element);
public R getResult() {
return myResult;
}
}
}