Skip to content

Commit e467844

Browse files
committed
[MPH-183] Reflectively use enhanced formatting of InputLocations
1 parent df70cf2 commit e467844

File tree

6 files changed

+277
-40
lines changed

6 files changed

+277
-40
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
<dependency>
9191
<groupId>org.apache.maven</groupId>
9292
<artifactId>maven-model</artifactId>
93-
<version>4.0.0-alpha-1-SNAPSHOT</version> <!-- TODO: Should check reflectively whether we can do this -->
93+
<version>3.8.5</version>
9494
</dependency>
9595
<dependency>
9696
<groupId>org.apache.maven</groupId>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.apache.maven.plugins.help;
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
import org.apache.maven.model.InputLocation;
23+
import org.apache.maven.model.InputSource;
24+
import org.codehaus.plexus.util.StringUtils;
25+
26+
/**
27+
* Maven 3.x-based implementation of {@link InputLocation.StringFormatter}.
28+
*/
29+
public class DefaultInputLocationFormatter extends InputLocation.StringFormatter
30+
{
31+
@Override
32+
public String toString( InputLocation location )
33+
{
34+
InputSource source = location.getSource();
35+
36+
String s = source.getModelId(); // by default, display modelId
37+
38+
if ( StringUtils.isBlank( s ) || s.contains( "[unknown-version]" ) )
39+
{
40+
// unless it is blank or does not provide version information
41+
s = source.toString();
42+
}
43+
44+
return '}' + s + ( ( location.getLineNumber() >= 0 ) ? ", line " + location.getLineNumber() : "" ) + ' ';
45+
}
46+
}

src/main/java/org/apache/maven/plugins/help/EffectivePomMojo.java

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import org.apache.maven.artifact.ArtifactUtils;
2323
import org.apache.maven.model.InputLocation;
24-
import org.apache.maven.model.InputSource;
2524
import org.apache.maven.model.Model;
2625
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
2726
import org.apache.maven.model.io.xpp3.MavenXpp3WriterExOldSupport;
@@ -64,6 +63,8 @@
6463
public class EffectivePomMojo
6564
extends AbstractEffectiveMojo
6665
{
66+
private final InputLocation.StringFormatter inputLocationFormatter = InputLocationFormatterFactory.produce( getLog() );
67+
6768
// ----------------------------------------------------------------------
6869
// Mojo parameters
6970
// ----------------------------------------------------------------------
@@ -225,7 +226,7 @@ private void writeEffectivePom( MavenProject project, XMLWriter writer )
225226
if ( !writeMavenXpp3WriterEx( sWriter, project, pom ) )
226227
{
227228
// xpp3 extended writer not provided by Maven core, use local code
228-
new EffectiveWriterExOldSupport().write( sWriter, pom );
229+
new EffectiveWriterExOldSupport( inputLocationFormatter ).write( sWriter, pom );
229230
}
230231
}
231232
else
@@ -304,7 +305,7 @@ private boolean writeMavenXpp3WriterEx( Writer writer, MavenProject project, Mod
304305

305306
Method setStringFormatter =
306307
mavenXpp3WriterExClass.getMethod( "setStringFormatter", InputLocation.StringFormatter.class );
307-
setStringFormatter.invoke( mavenXpp3WriterEx, new InputLocationStringFormatter() );
308+
setStringFormatter.invoke( mavenXpp3WriterEx, inputLocationFormatter );
308309

309310
Method write = mavenXpp3WriterExClass.getMethod( "write", Writer.class, Model.class );
310311
write.invoke( mavenXpp3WriterEx, writer, model );
@@ -335,52 +336,23 @@ else if ( e.getTargetException() instanceof RuntimeException )
335336
return false;
336337
}
337338

338-
private static String toString( InputLocation location )
339-
{
340-
InputSource source = location.getSource();
341-
342-
String s = source.getModelId(); // by default, display modelId
343-
344-
if ( StringUtils.isBlank( s ) || s.contains( "[unknown-version]" ) )
345-
{
346-
// unless it is blank or does not provide version information
347-
s = source.toString();
348-
}
349-
350-
InputSource managedBy = source.getManagedBy();
351-
StringBuilder p = new StringBuilder();
352-
353-
while ( managedBy != null )
354-
{
355-
p.append( " via " ).append( managedBy.getModelId() );
356-
managedBy = managedBy.getManagedBy();
357-
}
358-
359-
return '}' + s + ( ( location.getLineNumber() >= 0 ) ? ", line " + location.getLineNumber() : "" ) + p;
360-
}
361-
362-
private static class InputLocationStringFormatter
363-
extends InputLocation.StringFormatter
364-
{
365-
366-
public String toString( InputLocation location )
367-
{
368-
return EffectivePomMojo.toString( location );
369-
}
370-
371-
}
372-
373339
/**
374340
* Xpp3 extended writer extension to improve default InputSource display
375341
*/
376342
private static class EffectiveWriterExOldSupport
377343
extends MavenXpp3WriterExOldSupport
378344
{
345+
private final InputLocation.StringFormatter inputLocationFormatter;
346+
347+
public EffectiveWriterExOldSupport( final InputLocation.StringFormatter inputLocationFormatter )
348+
{
349+
this.inputLocationFormatter = inputLocationFormatter;
350+
}
379351

380352
@Override
381353
public String toString( InputLocation location )
382354
{
383-
return EffectivePomMojo.toString( location );
355+
return inputLocationFormatter.toString( location );
384356
}
385357

386358
@Override
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.apache.maven.plugins.help;
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
import org.apache.maven.model.InputLocation;
23+
import org.apache.maven.plugin.logging.Log;
24+
25+
import java.lang.reflect.Method;
26+
27+
/**
28+
* Selects the most suitable implementation for {@link InputLocation.StringFormatter}.
29+
*/
30+
public class InputLocationFormatterFactory
31+
{
32+
public static InputLocation.StringFormatter produce( final Log log )
33+
{
34+
try
35+
{
36+
// This method was introduced in Maven 4.
37+
Method getReferencedByMethod = InputLocation.class.getDeclaredMethod( "getReferencedBy", InputLocation.class );
38+
return new Maven4InputLocationFormatter( getReferencedByMethod );
39+
}
40+
catch ( NoSuchMethodException nsme )
41+
{
42+
// Fallback to pre-Maven 4 implementation.
43+
log.info( "Unable to print chain of POM imports, falling back to printing the source POM "
44+
+ "without import information. This feature is available in Maven 4.0.0+." );
45+
return new DefaultInputLocationFormatter();
46+
}
47+
}
48+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package org.apache.maven.plugins.help;
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
import org.apache.maven.model.InputLocation;
23+
import org.apache.maven.model.InputSource;
24+
import org.codehaus.plexus.util.StringUtils;
25+
26+
import java.lang.reflect.InvocationTargetException;
27+
import java.lang.reflect.Method;
28+
29+
/**
30+
* Maven 4.x-based implementation of {@link InputLocation.StringFormatter}. Enhances the default implementation
31+
* with support for following "references" (caused by e.g. dependency management imports).
32+
*/
33+
public class Maven4InputLocationFormatter extends InputLocation.StringFormatter
34+
{
35+
private final Method getReferencedByMethod;
36+
37+
public Maven4InputLocationFormatter( final Method getReferencedByMethod )
38+
{
39+
this.getReferencedByMethod = getReferencedByMethod;
40+
}
41+
42+
@Override
43+
public String toString( InputLocation location )
44+
{
45+
InputSource source = location.getSource();
46+
47+
String s = source.getModelId(); // by default, display modelId
48+
49+
if ( StringUtils.isBlank( s ) || s.contains( "[unknown-version]" ) )
50+
{
51+
// unless it is blank or does not provide version information
52+
s = source.toString();
53+
}
54+
55+
InputLocation referencedBy = getReferencedBy( location );
56+
57+
StringBuilder p = new StringBuilder();
58+
59+
while ( referencedBy != null )
60+
{
61+
p.append( " from " ).append( referencedBy.getSource().getModelId() );
62+
referencedBy = getReferencedBy( referencedBy );
63+
}
64+
65+
return '}' + s + ( ( location.getLineNumber() >= 0 ) ? ", line " + location.getLineNumber() : "" ) + p;
66+
}
67+
68+
private InputLocation getReferencedBy( final InputLocation location )
69+
{
70+
try
71+
{
72+
return (InputLocation) getReferencedByMethod.invoke( location );
73+
}
74+
catch ( IllegalAccessException | InvocationTargetException e )
75+
{
76+
throw new RuntimeException( e );
77+
}
78+
}
79+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package org.apache.maven.plugins.help;
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
import org.apache.maven.model.InputLocation;
23+
import org.apache.maven.model.InputSource;
24+
import org.junit.Test;
25+
26+
import static org.hamcrest.MatcherAssert.assertThat;
27+
import static org.hamcrest.CoreMatchers.not;
28+
import static org.hamcrest.core.StringContains.containsString;
29+
30+
public class DefaultInputLocationFormatterTest
31+
{
32+
private final InputLocation.StringFormatter formatter = new DefaultInputLocationFormatter();
33+
34+
@Test
35+
public void withLineNumberShouldIncludeLineNumber() {
36+
// Arrange
37+
final InputSource source = new InputSource();
38+
source.setModelId( "foo:bar:1.0-SNAPSHOT" );
39+
source.setLocation( "/tmp/project/pom.xml" );
40+
final InputLocation location = new InputLocation( 3, 5, source );
41+
42+
// Act
43+
final String result = formatter.toString( location );
44+
45+
// Assert
46+
assertThat( result, containsString( "line 3" ) );
47+
}
48+
49+
@Test
50+
public void withoutLineNumberShouldNotIncludeLineNumber() {
51+
// Arrange
52+
final InputSource source = new InputSource();
53+
source.setModelId( "foo:bar:1.0-SNAPSHOT" );
54+
source.setLocation( "/tmp/project/pom.xml" );
55+
final InputLocation location = new InputLocation( -1, -1, source );
56+
57+
// Act
58+
final String result = formatter.toString( location );
59+
60+
// Assert
61+
assertThat( result, not( containsString( "line" ) ) );
62+
}
63+
64+
@Test
65+
public void withModelIdShouldIncludeModelId() {
66+
// Arrange
67+
final InputSource source = new InputSource();
68+
source.setModelId( "foo:bar:1.0-SNAPSHOT" );
69+
source.setLocation( "/tmp/project/pom.xml" );
70+
final InputLocation location = new InputLocation( 3, 5, source );
71+
72+
// Act
73+
final String result = formatter.toString( location );
74+
75+
// Assert
76+
assertThat( result, containsString( "foo:bar:1.0-SNAPSHOT" ) );
77+
}
78+
79+
@Test
80+
public void withoutModelIdShouldIncludeUnknownVersion() {
81+
// Arrange
82+
final InputSource source = new InputSource();
83+
source.setLocation( "/tmp/project/pom.xml" );
84+
final InputLocation location = new InputLocation( 3, 5, source );
85+
86+
// Act
87+
final String result = formatter.toString( location );
88+
89+
// Assert
90+
assertThat( result, not( containsString( "foo:bar:1.0-SNAPSHOT" ) ) );
91+
}
92+
}

0 commit comments

Comments
 (0)