1 package org.apache.maven.plugins.help;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.io.StringWriter;
24 import java.io.Writer;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.Properties;
30
31 import org.apache.maven.model.InputLocation;
32 import org.apache.maven.model.Model;
33 import org.apache.maven.model.InputSource;
34 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
35 import org.apache.maven.model.io.xpp3.MavenXpp3WriterExOldSupport;
36 import org.apache.maven.plugin.MojoExecution;
37 import org.apache.maven.plugin.MojoExecution.Source;
38 import org.apache.maven.plugin.MojoExecutionException;
39 import org.apache.maven.plugins.annotations.Mojo;
40 import org.apache.maven.plugins.annotations.Parameter;
41 import org.apache.maven.project.MavenProject;
42 import org.apache.maven.shared.utils.logging.MessageUtils;
43 import org.codehaus.plexus.util.StringUtils;
44 import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
45 import org.codehaus.plexus.util.xml.XMLWriter;
46 import org.codehaus.plexus.util.xml.XmlWriterUtil;
47 import org.codehaus.plexus.util.xml.Xpp3Dom;
48 import org.codehaus.plexus.util.xml.pull.XmlSerializer;
49
50
51
52
53
54
55
56 @Mojo( name = "effective-pom", aggregator = true )
57 public class EffectivePomMojo
58 extends AbstractEffectiveMojo
59 {
60
61
62
63
64
65
66
67
68
69 @Parameter( defaultValue = "${project}", readonly = true, required = true )
70 private MavenProject project;
71
72
73
74
75
76 @Parameter( defaultValue = "${reactorProjects}", required = true, readonly = true )
77 private List<MavenProject> projects;
78
79
80
81
82 @Parameter( defaultValue = "${mojo}", required = true, readonly = true )
83 private MojoExecution mojoExecution;
84
85
86
87
88
89
90
91
92
93 @Parameter( property = "artifact" )
94 private String artifact;
95
96
97
98
99
100
101 @Parameter( property = "verbose", defaultValue = "false" )
102 private boolean verbose = false;
103
104
105
106
107
108
109 public void execute()
110 throws MojoExecutionException
111 {
112 if ( StringUtils.isNotEmpty( artifact ) )
113 {
114 project = getMavenProject( artifact );
115 projects = Collections.singletonList( project );
116 }
117
118 StringWriter w = new StringWriter();
119 String encoding = output != null ? project.getModel().getModelEncoding()
120 : System.getProperty( "file.encoding" );
121 XMLWriter writer =
122 new PrettyPrintXMLWriter( w, StringUtils.repeat( " ", XmlWriterUtil.DEFAULT_INDENTATION_SIZE ),
123 encoding, null );
124
125 writeHeader( writer );
126
127 if ( shouldWriteAllEffectivePOMsInReactor() )
128 {
129
130 writer.startElement( "projects" );
131 for ( MavenProject subProject : projects )
132 {
133 writeEffectivePom( subProject, writer );
134 }
135 writer.endElement();
136 }
137 else
138 {
139 writeEffectivePom( project, writer );
140 }
141
142 String effectivePom = prettyFormat( w.toString(), encoding, false );
143 if ( verbose )
144 {
145
146 effectivePom = effectivePom.replaceAll( "(?m)>\\s+<!--}", "> <!-- " );
147 }
148
149 if ( output != null )
150 {
151 try
152 {
153 writeXmlFile( output, effectivePom );
154 }
155 catch ( IOException e )
156 {
157 throw new MojoExecutionException( "Cannot write effective-POM to output: " + output, e );
158 }
159
160 getLog().info( "Effective-POM written to: " + output );
161 }
162 else
163 {
164 if ( MessageUtils.isColorEnabled() )
165 {
166
167 String comment = MessageUtils.buffer().project( "<!--.-->" ).toString();
168 int dotIndex = comment.indexOf( "." );
169 String commentStart = comment.substring( 0, dotIndex );
170 String commentEnd = comment.substring( dotIndex + 1 );
171 effectivePom = effectivePom.replace( "<!--", commentStart ).replace( "-->", commentEnd );
172 }
173
174 getLog().info( LS + "Effective POMs, after inheritance, interpolation, and profiles are applied:"
175 + LS + LS + effectivePom + LS );
176 }
177 }
178
179
180
181
182
183
184
185
186 private boolean shouldWriteAllEffectivePOMsInReactor()
187 {
188 Source source = mojoExecution.getSource();
189
190 return projects.size() > 1 && ( source == Source.CLI || projects.get( 0 ).equals( project ) );
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204 private void writeEffectivePom( MavenProject project, XMLWriter writer )
205 throws MojoExecutionException
206 {
207 Model pom = project.getModel();
208 cleanModel( pom );
209
210 StringWriter sWriter = new StringWriter();
211 try
212 {
213 if ( verbose )
214 {
215
216 if ( ! writeMavenXpp3WriterEx( sWriter, pom ) )
217 {
218
219 new EffectiveWriterExOldSupport().write( sWriter, pom );
220 }
221 }
222 else
223 {
224 new MavenXpp3Writer().write( sWriter, pom );
225 }
226 }
227 catch ( IOException e )
228 {
229 throw new MojoExecutionException( "Cannot serialize POM to XML.", e );
230 }
231
232
233 String effectivePom = prettyFormat( sWriter.toString(), null, true );
234
235 writeComment( writer, "Effective POM for project '" + project.getId() + "'" );
236
237 writer.writeMarkup( effectivePom );
238 }
239
240
241
242
243
244
245 private static void cleanModel( Model pom )
246 {
247 Properties properties = new SortedProperties();
248 properties.putAll( pom.getProperties() );
249 pom.setProperties( properties );
250 }
251
252 private void warnWriteMavenXpp3WriterEx( Throwable t )
253 {
254 getLog().warn( "Unexpected exception while running Maven Model Extended Writer, "
255 + "falling back to old internal implementation.", t );
256 }
257
258 private boolean writeMavenXpp3WriterEx( Writer writer, Model model )
259 throws IOException
260 {
261 try
262 {
263 Class<?> mavenXpp3WriterExClass = Class.forName( "org.apache.maven.model.io.xpp3.MavenXpp3WriterEx" );
264 Object mavenXpp3WriterEx = mavenXpp3WriterExClass.getDeclaredConstructor().newInstance();
265
266 Method setStringFormatter =
267 mavenXpp3WriterExClass.getMethod( "setStringFormatter", InputLocation.StringFormatter.class );
268 setStringFormatter.invoke( mavenXpp3WriterEx, new InputLocationStringFormatter() );
269
270 Method write = mavenXpp3WriterExClass.getMethod( "write", Writer.class, Model.class );
271 write.invoke( mavenXpp3WriterEx, writer, model );
272
273 return true;
274 }
275 catch ( ClassNotFoundException e )
276 {
277
278 }
279 catch ( NoSuchMethodException | SecurityException | IllegalArgumentException | IllegalAccessException
280 | InstantiationException e )
281 {
282 warnWriteMavenXpp3WriterEx( e );
283 }
284 catch ( InvocationTargetException e )
285 {
286 if ( e.getTargetException() instanceof IOException )
287 {
288 throw (IOException) e.getTargetException();
289 }
290 else if ( e.getTargetException() instanceof RuntimeException )
291 {
292 throw (RuntimeException) e.getTargetException();
293 }
294 warnWriteMavenXpp3WriterEx( e );
295 }
296 return false;
297 }
298
299 private static String toString( InputLocation location )
300 {
301 InputSource source = location.getSource();
302
303 String s = source.getModelId();
304
305 if ( StringUtils.isBlank( s ) || s.contains( "[unknown-version]" ) )
306 {
307
308 s = source.toString();
309 }
310
311 return '}' + s + ( ( location.getLineNumber() >= 0 ) ? ", line " + location.getLineNumber() : "" ) + ' ';
312 }
313
314 private static class InputLocationStringFormatter
315 extends InputLocation.StringFormatter
316 {
317
318 public String toString( InputLocation location )
319 {
320 return EffectivePomMojo.toString( location );
321 }
322
323 }
324
325
326
327
328 private static class EffectiveWriterExOldSupport
329 extends MavenXpp3WriterExOldSupport
330 {
331
332 @Override
333 public String toString( InputLocation location )
334 {
335 return EffectivePomMojo.toString( location );
336 }
337
338 @Override
339 protected void writeXpp3DomToSerializer( Xpp3Dom dom, XmlSerializer serializer )
340 throws java.io.IOException
341 {
342
343
344 dom.writeToSerializer( null, serializer );
345 }
346 }
347 }