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