/*******************************************************************************
* Copyright (c) 2010 Sonatype, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sonatype, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.m2e.core.internal.markers;
import java.io.File;
import java.util.List;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.core.resources.IResource;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.InputLocation;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.project.MavenProject;
import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
public class SourceLocationHelper {
private static final String SELF = ""; //$NON-NLS-1$
private static final String PROJECT = "project"; //$NON-NLS-1$
private static final String PACKAGING = "packaging"; //$NON-NLS-1$
private static final String PLUGIN = "plugin"; //$NON-NLS-1$
private static final String PARENT = "parent"; //$NON-NLS-1$
public static final String CONFIGURATION = "configuration"; //$NON-NLS-1$
public static final String VERSION = "version"; //$NON-NLS-1$
public static final String EXECUTION = "execution"; //$NON-NLS-1$
public static final String DEPENDENCY = "dependency"; //$NON-NLS-1$
private static final int COLUMN_START_OFFSET = 2;
private static final int COLUMN_END_OFFSET = 1;
public static SourceLocation findPackagingLocation(MavenProject mavenProject) {
InputLocation inputLocation = mavenProject.getModel().getLocation(PACKAGING);
if(inputLocation != null) {
return new SourceLocation(inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - PACKAGING.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
}
inputLocation = mavenProject.getModel().getLocation(SELF);
return new SourceLocation(inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - PROJECT.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
}
public static SourceLocation findLocation(Plugin plugin, String attribute) {
InputLocation inputLocation = plugin.getLocation(attribute);
if(inputLocation != null) {
return new SourceLocation(inputLocation.getSource().getLocation(), inputLocation.getSource().getModelId(),
inputLocation.getLineNumber(), inputLocation.getColumnNumber() - attribute.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
}
inputLocation = plugin.getLocation(SELF);
return new SourceLocation(inputLocation.getSource().getLocation(), inputLocation.getSource().getModelId(),
inputLocation.getLineNumber(), inputLocation.getColumnNumber() - PLUGIN.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
}
public static SourceLocation findLocation(IResource pomResource, ModelProblem modelProblem) {
int lineNumber = Math.max(1, modelProblem.getLineNumber());
if(pomResource == null) {
return new SourceLocation(lineNumber, 1, 1);
}
int columnNumber = Math.max(1, modelProblem.getColumnNumber());
String pomFile = pomResource.getLocation().toOSString();
if(pomFile.equals(modelProblem.getSource())) {
return new SourceLocation(lineNumber, 1, columnNumber - COLUMN_END_OFFSET);
}
SourceLocation causeLocation = new SourceLocation(modelProblem.getSource(), modelProblem.getModelId(), lineNumber,
1, columnNumber - COLUMN_END_OFFSET);
return new SourceLocation(1, 1, 1, causeLocation);
}
public static SourceLocation findLocation(MavenProject mavenProject, MojoExecutionKey mojoExecutionKey) {
Plugin plugin = mavenProject.getPlugin(mojoExecutionKey.getGroupId() + ":" + mojoExecutionKey.getArtifactId());
InputLocation inputLocation = plugin.getLocation(SELF);
if(inputLocation == null) {
// Plugin is specified in the maven lifecycle definition, not explicit in current pom or parent pom
inputLocation = mavenProject.getModel().getLocation(PACKAGING);
if(inputLocation != null) {
return new SourceLocation(inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - PACKAGING.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
}
inputLocation = mavenProject.getModel().getLocation(SELF);
return new SourceLocation(inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - PROJECT.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
}
String elementName;
InputLocation executionInputLocation = findExecutionLocation(plugin, mojoExecutionKey.getExecutionId());
if(executionInputLocation != null) {
inputLocation = executionInputLocation;
elementName = EXECUTION;
} else {
elementName = PLUGIN;
}
File pomFile = mavenProject.getFile();
if(pomFile.getAbsolutePath().equals(inputLocation.getSource().getLocation())) {
// Plugin/execution is specified in current pom
return new SourceLocation(inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - elementName.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
}
// Plugin/execution is specified in some parent pom
SourceLocation causeLocation = new SourceLocation(inputLocation.getSource().getLocation(),
inputLocation.getSource().getModelId(), inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - elementName.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
inputLocation = mavenProject.getModel().getParent().getLocation(SELF);
if(inputLocation == null) {
// parent location cannot be determined for participant-added parents
return new SourceLocation(1, 1, 1, causeLocation);
}
return new SourceLocation(inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - PARENT.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET, causeLocation);
}
private static InputLocation findExecutionLocation(Plugin plugin, String executionId) {
if(executionId == null) {
return null;
}
PluginExecution pluginExecution = plugin.getExecutionsAsMap().get(executionId);
if(pluginExecution == null) {
return null;
}
return pluginExecution.getLocation(SELF);
}
private static org.apache.maven.model.Dependency getMavenDependency(MavenProject mavenProject,
Dependency dependency) {
org.apache.maven.model.Dependency found = findDependency(mavenProject.getDependencies(), dependency);
if(found == null) {
DependencyManagement depMgmt = mavenProject.getModel().getDependencyManagement();
if(depMgmt != null) {
found = findDependency(depMgmt.getDependencies(), dependency);
if(found != null) {
// missing transitive managed dependency
String projectId = mavenProject.getModel().getLocation(SELF).getSource().getModelId();
String depId = found.getLocation(SELF).getSource().getModelId();
if(!projectId.equals(depId)) {
// let's see if it comes from a directly imported pom
DependencyManagement origMgmt = mavenProject.getOriginalModel().getDependencyManagement();
org.apache.maven.model.Dependency importDep = findDependencyImport(origMgmt, depId);
if(importDep != null) {
// use it to show marker on
found = importDep;
} else {
found = null;
}
}
}
}
}
return found;
}
private static org.apache.maven.model.Dependency findDependencyImport(DependencyManagement origMgmt, String depId) {
if(origMgmt != null) {
for(org.apache.maven.model.Dependency dependency : origMgmt.getDependencies()) {
if("import".equals(dependency.getScope()) && "pom".equals(dependency.getType())) {
String importId = dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion();
if(depId.equals(importId)) {
return dependency;
}
}
}
}
return null;
}
private static org.apache.maven.model.Dependency findDependency(List<org.apache.maven.model.Dependency> dependencies,
Dependency dependency) {
for(org.apache.maven.model.Dependency mavenDependency : dependencies) {
if(mavenDependency.getArtifactId().equals(dependency.getArtifact().getArtifactId())
&& mavenDependency.getGroupId().equals(dependency.getArtifact().getGroupId())
&& mavenDependency.getVersion().equals(dependency.getArtifact().getVersion())
&& eq(mavenDependency.getClassifier(), dependency.getArtifact().getClassifier())) {
return mavenDependency;
}
}
return null;
}
private static <T> boolean eq(String s1, String s2) {
if(s1 != null && s1.trim().length() == 0) {
s1 = null;
}
if(s2 != null && s2.trim().length() == 0) {
s2 = null;
}
return s1 != null ? s1.equals(s2) : s2 == null;
}
public static SourceLocation findLocation(MavenProject mavenProject, Dependency dependency) {
org.apache.maven.model.Dependency mavenDependency = getMavenDependency(mavenProject, dependency);
return findLocation(mavenProject, mavenDependency);
}
public static SourceLocation findLocation(MavenProject mavenProject, org.apache.maven.model.Dependency dependency) {
InputLocation inputLocation = null;
if(dependency != null) {
inputLocation = dependency.getLocation(SELF);
}
if(inputLocation == null) {
// Should never happen
inputLocation = mavenProject.getModel().getLocation(SELF);
return new SourceLocation(inputLocation.getLineNumber(), 1, inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
}
File pomFile = mavenProject.getFile();
if(pomFile.getAbsolutePath().equals(inputLocation.getSource().getLocation())) {
// Dependency is specified in current pom
return new SourceLocation(inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - DEPENDENCY.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
}
// Plugin/execution is specified in some parent pom
SourceLocation causeLocation = new SourceLocation(inputLocation.getSource().getLocation(),
inputLocation.getSource().getModelId(), inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - DEPENDENCY.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET);
inputLocation = mavenProject.getModel().getParent().getLocation(SELF);
return new SourceLocation(inputLocation.getLineNumber(),
inputLocation.getColumnNumber() - PARENT.length() - COLUMN_START_OFFSET,
inputLocation.getColumnNumber() - COLUMN_END_OFFSET, causeLocation);
}
}