com.igormaznitsa.upom.UPomMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of uber-pom Show documentation
Show all versions of uber-pom Show documentation
Merging pom hierarchy parameters
The newest version!
/*
* Copyright 2015 Igor Maznitsa (http://www.igormaznitsa.com).
*
* 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 com.igormaznitsa.upom;
import java.io.File;
import java.util.*;
import org.apache.commons.io.FileUtils;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.*;
import org.apache.maven.project.MavenProject;
/**
* Maven plugin to merge pom files in project hierarchy, also it can make
* modifications in the result pom.
*
* @author Igor Maznitsa (http://www.igormaznitsa.com)
*/
@Mojo(name = "upom", defaultPhase = LifecyclePhase.INITIALIZE, threadSafe = true, requiresDependencyResolution = ResolutionScope.NONE)
public class UPomMojo extends AbstractMojo {
public static final String LINE_SEPARATOR = System.getProperty("line.separator", "/r/n");
/**
* The Project to be processed.
*/
@Parameter(defaultValue = "${project}", readonly = true)
protected MavenProject project;
/**
* The Folder where the uber-pom should be saved.
*/
@Parameter(name = "folder", defaultValue = "${basedir}")
protected File folder;
/**
* Turn on checking of result XML for duplicated sibling elements and remove
* all them.
*
* @since 1.0.1
*/
@Parameter(name = "removeSiblingDuplications", defaultValue = "false")
protected boolean removeSiblingDuplications;
/**
* The Name of the uber-pom file.
*/
@Parameter(name = "name", defaultValue = "uber-pom.xml")
protected String name;
/**
* List of paths to be removed from the result pom file. Example of a path:
* "build/plugins"
*/
@Parameter(name = "remove")
protected String[] remove;
/**
* List of sections to not be modified in the result. Example of a path:
* "build/plugins"
*/
@Parameter(name = "keep")
protected String[] keep;
/**
* Enforce filling project parameters by values the generated uber-pom. By
* default the uber-pom will be just saved and link to new the file will be
* redirected. If the parameter is true then uber-pom model values will be
* injected in fields of the current maven project model.
*/
@Parameter(name = "enforceInjecting", defaultValue = "false")
protected boolean enforceInjecting;
/**
* Delete generated pom file after session. Also can be replaced externally
* through system property 'upom.delete.on.exit' which has bigger priority
*/
@Parameter(name = "deleteOnExit", property = "upom.delete.on.exit", defaultValue = "true")
protected boolean deleteOnExit;
/**
* List of dependency patterns to be removed. Wildcards ('*' and '?') are
* supported. Patterns can be provided for all dependency qualifiers.
*
* @since 1.0.2
*/
@Parameter(name = "removeDependencies")
protected List removeDependencies = new ArrayList();
/**
* Number of levels in hierarchy to merge, If less than zero then whole
* hierarchy will be merged.
*/
@Parameter(name = "depth", defaultValue = "-1")
protected int depth;
/**
* String properties to be set in the result pom.
*/
@Parameter(name = "set")
protected Properties set;
public List getRemoveDependencies() {
return this.removeDependencies;
}
public File getFolder() {
return this.folder;
}
public String getName() {
return this.name;
}
public boolean isRemoveSiblingDuplications() {
return this.removeSiblingDuplications;
}
public boolean isDeleteOnExit() {
return this.deleteOnExit;
}
public int getDepth() {
return this.depth;
}
public String[] getRemove() {
return this.remove == null ? null : this.remove.clone();
}
public String[] getKeep() {
return this.keep == null ? null : this.keep.clone();
}
public boolean isEnforceInjecting() {
return this.enforceInjecting;
}
public Properties getSet() {
return this.set;
}
private Model[] collectFullHierarchy(final MavenProject project) {
final List result = new ArrayList();
MavenProject current = project;
while (current != null) {
result.add(0, current.getOriginalModel());
current = current.getParent() == null ? null : current.getParent();
}
return result.toArray(new Model[result.size()]);
}
private static UPomModel[] collectModels(final MavenProject project, final int depth) {
final List result = new ArrayList();
int levels = depth < 0 ? Integer.MAX_VALUE : depth;
MavenProject current = project;
while (current != null && levels-- >= 0) {
result.add(0, new UPomModel(current.getOriginalModel()));
current = current.getParent();
}
return result.toArray(new UPomModel[result.size()]);
}
private void updateProjectForNewPom(final UPomModel upomModel, final File uberPomFile) throws Exception {
upomModel.assignTo(this.project);
getLog().debug("Model assigned to project");
this.project.setFile(uberPomFile);
getLog().debug("File has been set to project");
}
private File saveUberPom(final UPomModel model) throws Exception {
final File uberPomFile = new File(this.folder, this.name);
FileUtils.write(uberPomFile, model.asXML(getLog(), isRemoveSiblingDuplications()), "UTF-8");
if (isDeleteOnExit()) {
getLog().info("NB! The Result uber-pom file marked to be removed after JVM session");
uberPomFile.deleteOnExit();
}
return uberPomFile;
}
private static String getNameOfModel(final Model model) {
if (model == null) {
return "";
}
final String group = model.getGroupId();
final String artifact = model.getArtifactId();
final String name = model.getName();
final String version = model.getVersion();
final StringBuilder result = new StringBuilder();
if (group == null) {
result.append("[inherited]");
} else {
result.append(group);
}
result.append(':');
if (artifact == null) {
result.append("[inherited]");
} else {
result.append(artifact);
}
result.append(':');
if (name == null) {
result.append("[inherited]");
} else {
result.append(name);
}
result.append(':');
if (version == null) {
result.append("[inherited]");
} else {
result.append(version);
}
return result.toString();
}
private static void spaces(final StringBuilder buffer, int len) {
while (len-- > 0) {
buffer.append(' ');
}
}
private static String drawHierarchy(final Model[] fullHierarchy, final UPomModel[] processedHierarchy) {
final StringBuilder result = new StringBuilder();
final int TAB = 4;
int startIndex = fullHierarchy.length - processedHierarchy.length;
int insets = 0;
// draw non-included
for (int i = 0; i <= startIndex; i++) {
if (result.length() > 0) {
result.append(LINE_SEPARATOR);
spaces(result, insets);
result.append((char) 0x2506);
result.append(LINE_SEPARATOR);
spaces(result, insets);
result.append((char) 0x2570).append((char) 0x2504);
}
result.append(getNameOfModel(fullHierarchy[i]));
insets += TAB;
}
// draw included
for (int i = 1; i < processedHierarchy.length; i++) {
if (result.length() > 0) {
result.append(LINE_SEPARATOR);
spaces(result, insets);
result.append((char) 0x2503);
result.append(LINE_SEPARATOR);
spaces(result, insets);
result.append((char) 0x2517).append((char) 0x2501);
}
result.append(getNameOfModel(processedHierarchy[i].getModel()));
insets += TAB;
}
return result.toString();
}
private static int getMaxStrLength(final String[] strs) {
if (strs == null || strs.length == 0) {
return 0;
}
int max = 0;
for (final String s : strs) {
if (s.length() > max) {
max = s.length();
}
}
return max;
}
private static String makeDotString(final int length) {
final StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
result.append('.');
}
return result.toString();
}
private static String dependency2str(final Dependency dependency) {
final StringBuilder result = new StringBuilder();
result.append("groupId=").append(dependency.getGroupId()).append(',')
.append("artifactId=").append(dependency.getArtifactId()).append(',')
.append("version=").append(dependency.getVersion()).append(',')
.append("type=").append(dependency.getType()).append(',')
.append("scope=").append(dependency.getScope()).append(',')
.append("systemPath=").append(dependency.getSystemPath()).append(',')
.append("classifier=").append(dependency.getClassifier()).append(',')
.append("optional=").append(dependency.getOptional());
return result.toString();
}
@Override
public void execute() throws MojoExecutionException {
String strToPrint = null;
try {
final Model[] fullModuleHierarchy = collectFullHierarchy(this.project);
final UPomModel[] modelsForProcessing = collectModels(this.project, this.depth);
getLog().debug("Full hierarchy: " + Arrays.toString(fullModuleHierarchy));
getLog().debug("Models to be processed: " + Arrays.toString(modelsForProcessing));
getLog().info(".........................................................");
for (final String s : drawHierarchy(fullModuleHierarchy, modelsForProcessing).split("\\n")) {
getLog().info(s);
}
getLog().info(".........................................................");
final UPomModel main = modelsForProcessing[0];
for (int i = 1; i < modelsForProcessing.length; i++) {
final boolean last = i == modelsForProcessing.length - 1;
final UPomModel model = modelsForProcessing[i];
if (last && this.keep != null && this.keep.length > 0) {
getLog().info("");
getLog().debug("Freezing state of sections for result project pom:" + Arrays.toString(this.keep));
model.saveState(this.keep);
for (final String s : this.keep) {
getLog().info("Freezing path \'" + s + "\' in the result pom");
}
getLog().debug("Merging last model");
main.merge(model);
getLog().debug("Restoring state of sections for project pom:" + Arrays.toString(this.keep));
main.restoreStateFrom(model);
} else {
getLog().debug("Merging model");
main.merge(model);
}
}
getLog().info("");
final String REMOVE_PREFIX = "Remove ";
int maxLength = REMOVE_PREFIX.length() + getMaxStrLength(this.remove) + 12;
if (this.remove != null && this.remove.length > 0) {
for (final String path : this.remove) {
final String prefix = REMOVE_PREFIX + '\'' + path + '\'';
strToPrint = prefix + makeDotString(maxLength - prefix.length());
final boolean removed = main.remove(path);
getLog().info(strToPrint + (removed ? "OK" : "NOT FOUND"));
}
}
getLog().info("");
if (this.set != null && !this.set.isEmpty()) {
strToPrint = null;
for (final String key : this.set.stringPropertyNames()) {
final String value = this.set.getProperty(key);
try {
getLog().info("Set value to path : '" + key + "\'=\'" + value + '\'');
main.set(key, value);
} catch (Exception ex) {
getLog().debug(ex);
throw new UPomException("Can't set string value to '" + key + '\'');
}
}
getLog().info("");
}
final List removedDependencies = main.removeDependencies(this.removeDependencies);
if (!removedDependencies.isEmpty()) {
for (final Dependency d : removedDependencies) {
getLog().info("Removed dependency: " + dependency2str(d));
}
}
getLog().debug("Saving uber-pom into project");
final File saveUberPom = saveUberPom(main);
getLog().info("Uber-pom saved as '" + saveUberPom.getAbsolutePath() + '\'');
getLog().debug("Injecting new uber-pom into project");
updateProjectForNewPom(main, saveUberPom);
getLog().info("Uber-pom assigned to project");
if (this.isEnforceInjecting()) {
getLog().info("NB! Injecting generated uber-pom parameters into internal project fields!");
main.injectIntoProject(getLog(), this.project);
}
} catch (UPomException ex) {
getLog().debug(ex);
if (strToPrint != null) {
getLog().info(strToPrint + "ERROR");
}
getLog().error(ex.getMessage());
throw new MojoExecutionException("Error during processing", ex);
} catch (Exception ex) {
throw new MojoExecutionException("Error during processing", ex);
}
}
public static String findProperty(
final MavenProject project,
final String key,
final String dflt
) {
String projectProperty;
MavenProject curProject = project;
do {
projectProperty = curProject.getProperties().getProperty(key);
curProject = curProject.getParent();
} while (projectProperty == null && curProject != null);
return projectProperty == null ? System.getProperty(key, dflt) : projectProperty;
}
}