001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.extensions.enforcer; 020 021import javax.inject.Named; 022 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.Reader; 026import java.nio.charset.StandardCharsets; 027import java.nio.file.Files; 028import java.nio.file.Path; 029import java.nio.file.Paths; 030import java.util.ArrayList; 031import java.util.Collections; 032import java.util.List; 033import java.util.Properties; 034 035import org.apache.maven.AbstractMavenLifecycleParticipant; 036import org.apache.maven.MavenExecutionException; 037import org.apache.maven.execution.MavenSession; 038import org.apache.maven.model.Build; 039import org.apache.maven.model.Plugin; 040import org.apache.maven.model.PluginExecution; 041import org.apache.maven.project.MavenProject; 042import org.codehaus.plexus.util.xml.Xpp3Dom; 043import org.codehaus.plexus.util.xml.Xpp3DomBuilder; 044import org.codehaus.plexus.util.xml.pull.XmlPullParserException; 045 046/** 047 * Extends every MavenProject with the maven-enforcer-plugin, adding executions as defined in 048 * <code>.mvn/enforcer-extension.xml</code> 049 * 050 * @since 3.0.0 051 */ 052@Named("enforcer") 053public class EnforceExtension extends AbstractMavenLifecycleParticipant { 054 private static final String ENFORCER_EXTENSION_XML = ".mvn/enforcer-extension.xml"; 055 056 private static final String POM_PROPERTIES = 057 "/META-INF/maven/org.apache.maven.extensions/maven-enforcer-extension/pom.properties"; 058 059 @Override 060 public void afterProjectsRead(MavenSession session) throws MavenExecutionException { 061 Xpp3Dom configuration; 062 Path config = Paths.get(session.getExecutionRootDirectory(), ENFORCER_EXTENSION_XML); 063 if (Files.isRegularFile(config)) { 064 try (Reader reader = Files.newBufferedReader(config, StandardCharsets.UTF_8)) { 065 configuration = Xpp3DomBuilder.build(reader); 066 } catch (XmlPullParserException | IOException e) { 067 throw new MavenExecutionException("Failed to read " + ENFORCER_EXTENSION_XML, e); 068 } 069 } else { 070 return; 071 } 072 073 List<PluginExecution> executions = null; 074 Xpp3Dom executionsDom = configuration.getChild("executions"); 075 if (executionsDom != null) { 076 executions = new ArrayList<>(); 077 for (Xpp3Dom executionDom : executionsDom.getChildren("execution")) { 078 executions.add(getPluginExecution(executionDom)); 079 } 080 } 081 082 if (executions == null) { 083 return; 084 } 085 086 for (MavenProject project : session.getProjects()) { 087 Plugin enforcerPlugin = null; 088 for (Plugin plugin : project.getBuildPlugins()) { 089 if ("maven-enforcer-plugin".equals(plugin.getArtifactId()) 090 && "org.apache.maven.plugins".equals(plugin.getGroupId())) { 091 enforcerPlugin = plugin; 092 } 093 } 094 095 if (enforcerPlugin == null) { 096 enforcerPlugin = new Plugin(); 097 enforcerPlugin.setGroupId("org.apache.maven.plugins"); 098 enforcerPlugin.setArtifactId("maven-enforcer-plugin"); 099 100 try (InputStream is = EnforceExtension.class.getResourceAsStream(POM_PROPERTIES)) { 101 Properties properties = new Properties(); 102 properties.load(is); 103 enforcerPlugin.setVersion(properties.getProperty("version")); 104 } catch (IOException e) { 105 // noop 106 } 107 108 if (project.getBuildPlugins().isEmpty()) { 109 Build build = project.getBuild(); 110 if (build == null) { 111 build = new Build(); 112 project.setBuild(build); 113 } 114 build.setPlugins(Collections.singletonList(enforcerPlugin)); 115 } else { 116 List<Plugin> buildPlugins = new ArrayList<>(project.getBuildPlugins()); 117 buildPlugins.add(enforcerPlugin); 118 project.getBuild().setPlugins(buildPlugins); 119 } 120 } 121 122 for (PluginExecution pe : executions) { 123 enforcerPlugin.addExecution(pe); 124 } 125 } 126 } 127 128 private static PluginExecution getPluginExecution(Xpp3Dom execution) { 129 PluginExecution pluginExecution = new PluginExecution(); 130 pluginExecution.setId(get(execution, "id", "default-extension")); 131 pluginExecution.addGoal("enforce"); 132 pluginExecution.setPhase(get(execution, "phase", "validate")); 133 // here we must use Mavens internal configuration implementation 134 pluginExecution.setConfiguration(execution.getChild("configuration")); 135 return pluginExecution; 136 } 137 138 private static String get(Xpp3Dom elm, String name, String defaultValue) { 139 if (elm == null || elm.getChild(name) == null) { 140 return defaultValue; 141 } else { 142 return elm.getChild(name).getValue(); 143 } 144 } 145}