You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@maven.apache.org by Michel Pawlak <mi...@gmail.com> on 2017/01/28 14:51:10 UTC
What's the correct way to use InputLocationTracker?
Hi all,
I need some help with issues I’m facing when using org.apache.maven.model.InputLocationTracker.
Let’s first have a look at this sample class file (I tried to only keep what is relevant to the issue.)
-[snip]—
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.model.Build;
import org.apache.maven.model.InputLocation;
import org.apache.maven.model.InputLocationTracker;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Sample check that verifies if Java source version is the ones that is expected.
*/
public class JavaSourceVersionCheck {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaSourceVersionCheck.class);
private static final String MAVEN_COMPILER_PLUGIN_GROUPID = "org.apache.maven.plugins";
private static final String MAVEN_COMPILER_PLUGIN_ARTIFACTID = "maven-compiler-plugin";
/**
* Default Java source version.
*/
public static final String EXPECTED_JAVA_SOURCE_VERSION = "1.7";
/**
* Default Java target version.
*/
public static final String EXPECTED_JAVA_TARGET_VERSION = "1.7";
/**
* Executes the check on a Maven Model instance.
*
* @param model Maven raw Model (i.e. with unresolved pom inheritance)
*/
public void execute(final Model model) {
LOGGER.debug("checking Model");
final Build build = model.getBuild();
if (build != null) {
for (final Plugin plugin : build.getPlugins()) {
if (isMavenCompilerPlugin(plugin)) {
LOGGER.debug("Maven compiler plugin found!");
checkJavaSourceVersion(plugin);
}
}
}
LOGGER.debug("done");
}
private boolean isMavenCompilerPlugin(final Plugin plugin) {
return MAVEN_COMPILER_PLUGIN_GROUPID.equals(plugin.getGroupId()) && MAVEN_COMPILER_PLUGIN_ARTIFACTID.equals(plugin.getArtifactId());
}
private void checkJavaSourceVersion(final Plugin plugin) {
final Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration();
final Xpp3Dom sourceDom = configuration.getChild("source");
LOGGER.debug("Configuration DOM: {}", configuration.toString());
if (sourceDom != null) {
LOGGER.debug("Found <source> tag, checking its value");
final String sourceValue = sourceDom.getValue();
if (!sourceValue.equals(EXPECTED_JAVA_SOURCE_VERSION)) {
final InputLocation location = locate(plugin, “configuration", "source");
// here I should do something else with the location instance, but as I want to keep the sample as simple as possible, let’s just log a message
LOGGER.warn(“non compliant value: is {} but should be {} (issue was found at {} column {})", sourceValue, EXPECTED_JAVA_SOURCE_VERSION, location.getLineNumber(),
location.getColumnNumber());
}
}
}
/**
* Locates the line in the {@link Model} POM where XML tags below an {@link InputLocationTracker} is located.
*
* @param locationTracker Maven {@link Model} {@link InputLocationTracker} for which the line has to be retrieved.
* @param tags list of tags to drill down, the last one representing the tag for which the line has to be retrieved.
* @return an IssueLocation representing the line and column in the {@link Model} where the last tag of the {@code tags} list below {@link InputLocationTracker} is located.
*/
public final InputLocation locate(final InputLocationTracker locationTracker, final String... tags) {
final List<String> tagsList = new ArrayList<>();
if (tags.length == 0) {
tagsList.add("");
} else {
for (final String tag : tags) {
tagsList.add(tag);
}
}
final InputLocation inputLocation = locate(locationTracker, tagsList);
LOGGER.debug("\t<{}> tag located at line {}, column {})", tagsList.get(tagsList.size() - 1), inputLocation.getLineNumber(), inputLocation.getColumnNumber());
return inputLocation;
}
private final InputLocation locate(final InputLocationTracker locationTracker, final List<String> tags) {
InputLocation inputLocation = null;
for (final String tag : tags) {
if (inputLocation == null) {
inputLocation = locationTracker.getLocation(tag);
} else {
// InputLocation is an InputLocationTracker
final InputLocation tempInputLocation = inputLocation.getLocation(tag); // (1)
if (tempInputLocation == null) {
LOGGER.error("InputLocation for tag <{}> is null, returning position of last tag that has been found", tag);
break;
} else {
inputLocation = tempInputLocation;
}
}
}
return inputLocation;
}
public static void main(final String[] args) throws Exception {
final Model model = RawMavenModelFactory.instance()
.buildWith(FileUtils.toFile(JavaSourceVersionCheck.class.getClassLoader()
.getResource("pom.xml")));
final JavaSourceVersionCheck check = new JavaSourceVersionCheck();
check.execute(model);
}
}
-[snip]—
Here is the code of the buildWith() method:
-[snip]—
public Model buildWith(final File pomFile) throws MavenModelBuildingException {
final MavenXpp3ReaderEx reader = new MavenXpp3ReaderEx();
reader.setAddDefaultEntities(false);
try {
return reader.read(new FileInputStream(pomFile), true, new InputSource());
} catch (IOException | XmlPullParserException e) {
throw new MavenModelBuildingException("Could not build Maven model.", e);
}
}
-[snip]—
The dependencies I’m using here are the following:
-[snip]—
<lib.maven.version>3.3.3</lib.maven.version>
<lib.aether.version>1.0.2.v20150114</lib.aether.version>
-[snip]—
And here is the sample pom.xml file that is used by the main method:
-[snip]—
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<plugin.maven-compiler-plugin.version>3.3</plugin.maven-compiler-plugin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${plugin.maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
-[snip]—
When run the code, I get the following output:
-[snip]—
15:21:35.822 [main] DEBUG JavaSourceVersionCheck - checking Model
15:21:35.826 [main] DEBUG JavaSourceVersionCheck - Maven compiler plugin found!
15:21:35.830 [main] DEBUG JavaSourceVersionCheck - Configuration DOM: <?xml version="1.0" encoding="UTF-8"?>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
15:21:35.831 [main] DEBUG JavaSourceVersionCheck - Found <source> tag, checking its value
15:21:35.831 [main] ERROR JavaSourceVersionCheck - InputLocation for tag <source> is null, returning position of last tag that has been found
15:21:35.831 [main] DEBUG JavaSourceVersionCheck - <source> tag located at line 15, column 24)
15:21:35.831 [main] WARN JavaSourceVersionCheck - non compliant value: is 1.8 but should be 1.7 (issue was found at 15 column 24)
15:21:35.832 [main] DEBUG JavaSourceVersionCheck - done
-[snip]—
So I have two problems here:
I cannot retrieve the line and column number for the <source> tag, as calling inputLocation.getLocation(tag); is null (see (1) in above source code)
getColumnNumber() returns “line 15 column 24” which is the last column of the line of the pom.xml where <configuration> is located.
My questions are the following:
Is it a bug or am I doing something wrong? (source is reachable from the DOM, but when calling getLocation())
How can I retrieve the line and column of the opening <source> tag?
How can I retrieve the line and column of the closing <source> tag?
Why does getColumnNumber() always return the last column of the line?
Thanks a lot in advance for your help and best regards!
Michel