From febce07c90a4630ecccfa9ef35803a5a249c1270 Mon Sep 17 00:00:00 2001 From: John Dennis Casey Date: Wed, 7 Nov 2007 19:24:30 +0000 Subject: [PATCH] Adding more context information to existing exceptions, cleaning up construction in exceptions, and adjusting the inheritance hierarchy for exceptions to make them make a little more sense for error reporting. Also, adding improved (but not complete, yet) reporting for BuildFailureExceptions and ProjectBuildingExceptions, with some tests to make sure pertinent information is in the output. git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@592859 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/maven/DefaultMaven.java | 23 +- .../apache/maven/InvalidTaskException.java | 22 +- .../lifecycle/DefaultLifecycleExecutor.java | 8 +- .../maven/lifecycle/TaskValidationResult.java | 56 ++- .../reactor/MavenExecutionException.java | 23 +- .../apache/maven/cli/CLIReportingUtils.java | 453 ++++++++++++++++-- .../maven/cli/CLIReportingUtilsTest.java | 317 ++++++++---- .../project/DefaultMavenProjectBuilder.java | 112 ++--- .../project/InvalidProjectModelException.java | 38 +- .../InvalidProjectVersionException.java | 39 ++ .../project/ProjectBuildingException.java | 216 ++++----- .../InvalidDependencyVersionException.java | 26 +- .../project/artifact/MavenMetadataSource.java | 3 +- .../model/DefaultModelLineageBuilder.java | 14 +- 14 files changed, 979 insertions(+), 371 deletions(-) create mode 100644 maven-project/src/main/java/org/apache/maven/project/InvalidProjectVersionException.java diff --git a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java index b135d36885..fdabe4e14b 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -193,7 +193,7 @@ public class DefaultMaven if ( !tvr.isTaskValid() ) { - result.addBuildFailureException( new InvalidTaskException( tvr ) ); + result.addBuildFailureException( tvr.generateInvalidTaskException() ); return result; } @@ -295,10 +295,7 @@ public class DefaultMaven { throw new MavenExecutionException( e.getMessage(), e ); } - catch ( ProjectBuildingException e ) - { - throw new MavenExecutionException( e.getMessage(), e ); - } + return projects; } @@ -307,7 +304,7 @@ public class DefaultMaven boolean recursive, ProfileManager globalProfileManager, boolean isRoot ) - throws ArtifactResolutionException, ProjectBuildingException, MavenExecutionException + throws ArtifactResolutionException, MavenExecutionException { List projects = new ArrayList( files.size() ); @@ -324,7 +321,15 @@ public class DefaultMaven usingReleasePom = true; } - MavenProject project = projectBuilder.build( file, localRepository, globalProfileManager ); + MavenProject project; + try + { + project = projectBuilder.build( file, localRepository, globalProfileManager ); + } + catch ( ProjectBuildingException e ) + { + throw new MavenExecutionException( "Failed to build MavenProject instance for: " + file, file, e ); + } if ( isRoot ) { @@ -338,8 +343,8 @@ public class DefaultMaven if ( runtimeInformation.getApplicationVersion().compareTo( version ) < 0 ) { throw new MavenExecutionException( - "Unable to build project '" + project.getFile() + - "; it requires Maven version " + version.toString() ); + "Unable to build project '" + file + + "; it requires Maven version " + version.toString(), file ); } } diff --git a/maven-core/src/main/java/org/apache/maven/InvalidTaskException.java b/maven-core/src/main/java/org/apache/maven/InvalidTaskException.java index 41cde23d9b..e0bb30d765 100644 --- a/maven-core/src/main/java/org/apache/maven/InvalidTaskException.java +++ b/maven-core/src/main/java/org/apache/maven/InvalidTaskException.java @@ -1,6 +1,9 @@ package org.apache.maven; +import org.apache.maven.lifecycle.LifecycleLoaderException; +import org.apache.maven.lifecycle.LifecycleSpecificationException; import org.apache.maven.lifecycle.TaskValidationResult; +import org.apache.maven.plugin.loader.PluginLoaderException; /** * Exception which occurs when a task or goal is specified on the command line @@ -17,9 +20,24 @@ public class InvalidTaskException private final String task; - public InvalidTaskException( TaskValidationResult result ) + public InvalidTaskException( TaskValidationResult result, + LifecycleLoaderException cause ) { - super( result.getMessage(), result.getCause() ); + super( result.getMessage(), cause ); + task = result.getInvalidTask(); + } + + public InvalidTaskException( TaskValidationResult result, + LifecycleSpecificationException cause ) + { + super( result.getMessage(), cause ); + task = result.getInvalidTask(); + } + + public InvalidTaskException( TaskValidationResult result, + PluginLoaderException cause ) + { + super( result.getMessage(), cause ); task = result.getInvalidTask(); } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java index 73124579e2..b95a21ce26 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java @@ -630,7 +630,7 @@ public class DefaultLifecycleExecutor return new TaskValidationResult( task, "Cannot find mojo descriptor for: \'" + task - + "\' - Treating as non-aggregator." ); + + "\' - Treating as non-aggregator.", e ); } catch ( LifecycleSpecificationException e ) { @@ -642,16 +642,16 @@ public class DefaultLifecycleExecutor return new TaskValidationResult( task, - message ); + message, e ); } catch ( LifecycleLoaderException e ) { - String message = "Cannot find plugin to match task '" + task + "'."; + String message = "Failed to load one or more lifecycle definitions which may contain task: '" + task + "'."; return new TaskValidationResult( task, - message ); + message, e ); } } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/TaskValidationResult.java b/maven-core/src/main/java/org/apache/maven/lifecycle/TaskValidationResult.java index 47f68b1d04..e9c74decb2 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/TaskValidationResult.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/TaskValidationResult.java @@ -1,29 +1,46 @@ package org.apache.maven.lifecycle; +import org.apache.maven.InvalidTaskException; +import org.apache.maven.plugin.loader.PluginLoaderException; + /** @author Jason van Zyl */ public class TaskValidationResult { private String invalidTask; - private Throwable cause; - private String message; + private Throwable cause; + public TaskValidationResult() { } - public TaskValidationResult( String invalidTask, String message ) + public TaskValidationResult( String invalidTask, + String message, + PluginLoaderException cause ) { this.invalidTask = invalidTask; this.message = message; - } - - public TaskValidationResult( String invalidTask, String message, Throwable cause ) - { - this.message = message; this.cause = cause; + } + + public TaskValidationResult( String invalidTask, + String message, + LifecycleSpecificationException cause ) + { this.invalidTask = invalidTask; + this.message = message; + this.cause = cause; + } + + public TaskValidationResult( String invalidTask, + String message, + LifecycleLoaderException cause ) + { + this.invalidTask = invalidTask; + this.message = message; + this.cause = cause; } public String getInvalidTask() @@ -45,4 +62,27 @@ public class TaskValidationResult { return invalidTask == null; } + + public InvalidTaskException generateInvalidTaskException() + { + InvalidTaskException e = null; + if ( cause instanceof LifecycleLoaderException ) + { + e = new InvalidTaskException( this, (LifecycleLoaderException)cause ); + } + else if ( cause instanceof LifecycleSpecificationException ) + { + e = new InvalidTaskException( this, (LifecycleSpecificationException)cause ); + } + else if ( cause instanceof PluginLoaderException ) + { + e = new InvalidTaskException( this, (PluginLoaderException)cause ); + } + else + { + throw new IllegalStateException( "No matching constructor in InvalidTaskException for TaskValidationResult cause: " + cause + " ( invalid task: " + invalidTask + ")" ); + } + + return e; + } } diff --git a/maven-core/src/main/java/org/apache/maven/reactor/MavenExecutionException.java b/maven-core/src/main/java/org/apache/maven/reactor/MavenExecutionException.java index 511f25b28e..4fc5db71a0 100644 --- a/maven-core/src/main/java/org/apache/maven/reactor/MavenExecutionException.java +++ b/maven-core/src/main/java/org/apache/maven/reactor/MavenExecutionException.java @@ -4,6 +4,7 @@ import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.extension.ExtensionScanningException; import org.apache.maven.project.ProjectBuildingException; +import java.io.File; import java.io.IOException; /* @@ -51,18 +52,18 @@ import java.io.IOException; public class MavenExecutionException extends Exception { - public MavenExecutionException() - { - } + private File pomFile; - public MavenExecutionException( String message ) + public MavenExecutionException( String message, File pomFile ) { super( message ); + this.pomFile = pomFile; } - public MavenExecutionException( Throwable cause ) + public MavenExecutionException( String message, File pomFile, ProjectBuildingException cause ) { - super( cause ); + super( message, cause ); + this.pomFile = pomFile; } public MavenExecutionException( String message, IOException cause ) @@ -70,11 +71,6 @@ public class MavenExecutionException super( message, cause ); } - public MavenExecutionException( String message, ProjectBuildingException cause ) - { - super( message, cause ); - } - public MavenExecutionException( String message, ArtifactResolutionException cause ) { super( message, cause ); @@ -84,4 +80,9 @@ public class MavenExecutionException { super( message, cause ); } + + public File getPomFile() + { + return pomFile; + } } diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CLIReportingUtils.java b/maven-embedder/src/main/java/org/apache/maven/cli/CLIReportingUtils.java index 8418f8dc6b..a4626167d4 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/CLIReportingUtils.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/CLIReportingUtils.java @@ -2,8 +2,13 @@ package org.apache.maven.cli; import org.apache.maven.AggregatedBuildFailureException; import org.apache.maven.BuildFailureException; +import org.apache.maven.InvalidTaskException; +import org.apache.maven.NoGoalsSpecifiedException; import org.apache.maven.ProjectBuildFailureException; +import org.apache.maven.ProjectCycleException; +import org.apache.maven.artifact.InvalidRepositoryException; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.embedder.MavenEmbedderConsoleLogger; import org.apache.maven.embedder.MavenEmbedderLogger; import org.apache.maven.execution.BuildFailure; @@ -13,12 +18,17 @@ import org.apache.maven.execution.ReactorManager; import org.apache.maven.extension.ExtensionScanningException; import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.lifecycle.MojoBindingUtils; +import org.apache.maven.model.Dependency; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.PluginNotFoundException; +import org.apache.maven.plugin.loader.PluginLoaderException; +import org.apache.maven.profiles.activation.ProfileActivationException; import org.apache.maven.project.DuplicateProjectException; import org.apache.maven.project.InvalidProjectModelException; +import org.apache.maven.project.InvalidProjectVersionException; import org.apache.maven.project.MavenProject; import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.artifact.InvalidDependencyVersionException; import org.apache.maven.reactor.MavenExecutionException; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -31,6 +41,7 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.Properties; import java.util.TimeZone; @@ -226,7 +237,7 @@ public final class CLIReportingUtils logger.error( writer.toString() ); } - private static void buildErrorMessage( Exception e, + public static void buildErrorMessage( Exception e, boolean showStackTraces, StringWriter writer ) { @@ -234,11 +245,15 @@ public final class CLIReportingUtils if ( e instanceof BuildFailureException ) { - handled = handleBuildFailureException( (BuildFailureException) e, writer ); + handled = handleBuildFailureException( (BuildFailureException) e, + showStackTraces, + writer ); } else if ( e instanceof ProjectBuildingException ) { - handled = handleProjectBuildingException( (ProjectBuildingException) e, writer ); + handled = handleProjectBuildingException( (ProjectBuildingException) e, + showStackTraces, + writer ); } else if ( e instanceof LifecycleExecutionException ) { @@ -248,25 +263,42 @@ public final class CLIReportingUtils } else if ( e instanceof DuplicateProjectException ) { - handled = handleDuplicateProjectException( (DuplicateProjectException) e, writer ); + handled = handleDuplicateProjectException( (DuplicateProjectException) e, + showStackTraces, + writer ); } else if ( e instanceof MavenExecutionException ) { - handled = handleMavenExecutionException( (MavenExecutionException) e, writer ); + handled = handleMavenExecutionException( (MavenExecutionException) e, + showStackTraces, + writer ); } if ( !handled ) { - handleGenericException( e, writer ); + handleGenericException( e, showStackTraces, writer ); } } private static boolean handleMavenExecutionException( MavenExecutionException e, + boolean showStackTraces, StringWriter writer ) { - writer.write( "While scanning for build extensions:" ); - writer.write( NEWLINE ); - writer.write( NEWLINE ); + + // ===================================================================== + // Cases covered: + // ===================================================================== + // + // MavenExecutionException(String, File, ProjectBuildingException) + // MavenExecutionException(String, ExtensionScanningException) + // MavenExecutionException(String, IOException) + // + // ===================================================================== + // Cases left to cover: + // ===================================================================== + // + // MavenExecutionException(String, ArtifactResolutionException) + // MavenExecutionException(String, File) Throwable cause = e.getCause(); if ( cause != null ) @@ -276,37 +308,69 @@ public final class CLIReportingUtils writer.write( e.getMessage() ); writer.write( NEWLINE ); - handleGenericException( cause, writer ); + handleGenericException( cause, showStackTraces, writer ); return true; } else if ( cause instanceof ExtensionScanningException ) { + writer.write( "While scanning for build extensions:" ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + Throwable nestedCause = cause.getCause(); if ( ( nestedCause != null ) && ( nestedCause instanceof ProjectBuildingException ) ) { return handleProjectBuildingException( (ProjectBuildingException) nestedCause, + showStackTraces, writer ); } else { - handleGenericException( cause, writer ); + handleGenericException( cause, showStackTraces, writer ); return true; } } else if ( cause instanceof ProjectBuildingException ) { - return handleProjectBuildingException( (ProjectBuildingException) cause, writer ); + return handleProjectBuildingException( (ProjectBuildingException) cause, + showStackTraces, + writer ); + } + else if ( cause instanceof ArtifactResolutionException ) + { + } } + else + { - return false; + } + + if ( e.getPomFile() != null ) + { + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "POM File: " ); + writer.write( e.getPomFile().getAbsolutePath() ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + } + + return true; } private static boolean handleDuplicateProjectException( DuplicateProjectException e, + boolean showStackTraces, StringWriter writer ) { + // ===================================================================== + // Cases covered: + // ===================================================================== + // + // DuplicateProjectException(String, File, File, String) + File existing = e.getExistingProjectFile(); File conflicting = e.getConflictingProjectFile(); String projectId = e.getProjectId(); @@ -326,6 +390,7 @@ public final class CLIReportingUtils } private static void handleGenericException( Throwable exception, + boolean showStackTraces, StringWriter writer ) { writer.write( exception.getMessage() ); @@ -336,6 +401,31 @@ public final class CLIReportingUtils boolean showStackTraces, StringWriter writer ) { + + // ===================================================================== + // Cases covered: + // ===================================================================== + // + // LifecycleExecutionException(String, MavenProject, PluginNotFoundException) + // + // ===================================================================== + // Cases left to cover: + // ===================================================================== + // + // LifecycleExecutionException(String, MavenProject, ArtifactNotFoundException) + // LifecycleExecutionException(String, MavenProject, ArtifactResolutionException) + // LifecycleExecutionException(String, MavenProject, InvalidDependencyVersionException) + // LifecycleExecutionException(String, MavenProject, InvalidPluginException) + // LifecycleExecutionException(String, MavenProject, InvalidVersionSpecificationException) + // LifecycleExecutionException(String, MavenProject, LifecycleException) + // LifecycleExecutionException(String, MavenProject, MojoExecutionException) + // LifecycleExecutionException(String, MavenProject, PlexusContainerException) + // LifecycleExecutionException(String, MavenProject, PluginConfigurationException) + // LifecycleExecutionException(String, MavenProject, PluginLoaderException) + // LifecycleExecutionException(String, MavenProject, PluginManagerException) + // LifecycleExecutionException(String, MavenProject, PluginVersionNotFoundException) + // LifecycleExecutionException(String, MavenProject, PluginVersionResolutionException) + Throwable cause = e.getCause(); if ( cause != null ) { @@ -348,7 +438,7 @@ public final class CLIReportingUtils writer.write( NEWLINE ); writer.write( NEWLINE ); - handleGenericException( artifactException, writer ); + handleGenericException( artifactException, showStackTraces, writer ); return true; } @@ -358,34 +448,50 @@ public final class CLIReportingUtils } private static boolean handleProjectBuildingException( ProjectBuildingException e, + boolean showStackTraces, StringWriter writer ) { + // ===================================================================== + // Cases covered: + // ===================================================================== + // + // ProjectBuildingException(String, String, File, XmlPullParserException) + // + // ProjectBuildingException(String, String, IOException) + // ProjectBuildingException(String, String, File, IOException) + // + // ProjectBuildingException(String, String, ArtifactNotFoundException) + // ProjectBuildingException(String, String, File, ArtifactNotFoundException) + // + // ProjectBuildingException(String, String, ArtifactResolutionException) + // ProjectBuildingException(String, String, File, ArtifactResolutionException) + // + // ProjectBuildingException(String, String, File, ProfileActivationException) + // + // ProjectBuildingException(String, String, InvalidRepositoryException) + // ProjectBuildingException(String, String, File, InvalidRepositoryException) + // + // ===================================================================== + // Subclass cases: + // ===================================================================== + // + // InvalidProjectModelException(all) + // InvalidProjectVersionException(all) + // InvalidDependencyVersionException(all) + boolean result = false; Throwable cause = e.getCause(); - if ( cause instanceof XmlPullParserException ) - { - writer.write( "Error parsing POM:" ); - writer.write( NEWLINE ); - writer.write( NEWLINE ); - writer.write( cause.getMessage() ); - writer.write( NEWLINE ); - writer.write( NEWLINE ); - writer.write( "Line: " ); - writer.write( "" + ( (XmlPullParserException) cause ).getLineNumber() ); - writer.write( NEWLINE ); - writer.write( "Column: " ); - writer.write( "" + ( (XmlPullParserException) cause ).getColumnNumber() ); - - result = true; - } - else if ( e instanceof InvalidProjectModelException ) + // Start by looking at whether we can handle the PBE as a specific sub-class of ProjectBuildingException... + if ( e instanceof InvalidProjectModelException ) { InvalidProjectModelException error = (InvalidProjectModelException) e; + writer.write( error.getMessage() ); writer.write( NEWLINE ); - writer.write( "The following POM validation errors occurred:" ); + writer.write( NEWLINE ); + writer.write( "The following POM validation errors were detected:" ); writer.write( NEWLINE ); for ( Iterator it = error.getValidationResult().getMessages().iterator(); it.hasNext(); ) @@ -401,23 +507,210 @@ public final class CLIReportingUtils result = true; } + else if ( e instanceof InvalidDependencyVersionException ) + { + writer.write( NEWLINE ); + writer.write( "Your project declares a dependency with an invalid version." ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + + Dependency dep = ((InvalidDependencyVersionException)e).getDependency(); + writer.write( "Dependency:" ); + writer.write( NEWLINE ); + writer.write( "Group-Id: " ); + writer.write( dep.getGroupId() ); + writer.write( NEWLINE ); + writer.write( "Artifact-Id: " ); + writer.write( dep.getArtifactId() ); + writer.write( NEWLINE ); + writer.write( "Version: " ); + writer.write( dep.getVersion() ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + + writer.write( "Reason: " ); + writer.write( cause.getMessage() ); + writer.write( NEWLINE ); + + result = true; + } + // InvalidDependencyVersionException extends from InvalidProjectVersionException, so it comes first. + else if ( e instanceof InvalidProjectVersionException ) + { + writer.write( NEWLINE ); + writer.write( "You have an invalid version in your POM:" ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "Location: " ); + writer.write( ((InvalidProjectVersionException)e).getLocationInPom() ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "Reason: " ); + writer.write( cause.getMessage() ); + writer.write( NEWLINE ); + + result = true; + } + // now that we've sorted through all the sub-classes of ProjectBuildingException, + // let's look at causes of a basic PBE instance. + else if ( ( cause instanceof ArtifactNotFoundException ) + || ( cause instanceof ArtifactResolutionException ) ) + { + writer.write( NEWLINE ); + writer.write( e.getMessage() ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "Reason: " ); + writer.write( cause.getMessage() ); + writer.write( NEWLINE ); + + result = true; + } + else if ( cause instanceof ProfileActivationException ) + { + writer.write( NEWLINE ); + writer.write( "Profile activation failed. One or more named profile activators may be missing." ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "Reason: " ); + writer.write( cause.getMessage() ); + writer.write( NEWLINE ); + + result = true; + } + else if ( cause instanceof IOException ) + { + writer.write( NEWLINE ); + if ( e.getPomFile() == null ) + { + writer.write( "Error reading built-in super POM!" ); + } + else + { + writer.write( "Error reading POM." ); + } + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( cause.getMessage() ); + writer.write( NEWLINE ); + } + else if ( cause instanceof XmlPullParserException ) + { + writer.write( NEWLINE ); + if ( e.getPomFile() == null ) + { + writer.write( "Error parsing built-in super POM!" ); + } + else + { + writer.write( "Error parsing POM." ); + } + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( cause.getMessage() ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "Line: " ); + writer.write( "" + ( (XmlPullParserException) cause ).getLineNumber() ); + writer.write( NEWLINE ); + writer.write( "Column: " ); + writer.write( "" + ( (XmlPullParserException) cause ).getColumnNumber() ); + writer.write( NEWLINE ); + + result = true; + } + else if ( cause instanceof InvalidRepositoryException ) + { + writer.write( NEWLINE ); + writer.write( "You have an invalid repository/pluginRepository declaration in your POM:" ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "Repository-Id: " ); + writer.write( ((InvalidRepositoryException)cause).getRepositoryId() ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "Reason: " ); + writer.write( cause.getMessage() ); + writer.write( NEWLINE ); + + result = true; + } writer.write( NEWLINE ); writer.write( "Project Id: " ); writer.write( e.getProjectId() ); writer.write( NEWLINE ); - writer.write( "Project File: " ); - writer.write( e.getPomLocation() ); + if ( e.getPomFile() == null ) + { + writer.write( "Source: Super POM (implied root ancestor of all Maven POMs)" ); + } + else + { + writer.write( "Project File: " ); + writer.write( e.getPomFile().getAbsolutePath() ); + } writer.write( NEWLINE ); return result; } private static boolean handleBuildFailureException( BuildFailureException e, + boolean showStackTraces, StringWriter writer ) { - if ( e instanceof AggregatedBuildFailureException ) + // ===================================================================== + // Cases covered (listed exceptions extend BuildFailureException): + // ===================================================================== + // + // AggregatedBuildFailureException(String, MojoBinding, MojoFailureException) + // + // InvalidTaskException(TaskValidationResult, LifecycleLoaderException) + // InvalidTaskException(TaskValidationResult, LifecycleSpecificationException) + // InvalidTaskException(TaskValidationResult, PluginLoaderException) + // + // NoGoalsSpecifiedException(String) + // + // ProjectBuildFailureException(String, MojoBinding, MojoFailureException) + // + // ProjectCycleException(List, String, CycleDetectedException) + + if ( e instanceof NoGoalsSpecifiedException ) { + writer.write( NEWLINE ); + writer.write( "You have not specified any goals or lifecycle phases for Maven to execute." ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "Please, either specify a goal or lifecycle phase on the command line" ); + writer.write( NEWLINE ); + writer.write( "(you may want to try \'package\' to get started), or configure the " ); + writer.write( NEWLINE ); + writer.write( " element in the build section of your project POM." ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "NOTE: You can also chain multiple goals/phases together, as in the following example:" ); + writer.write( NEWLINE ); + writer.write( "mvn clean package" ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + writer.write( "For more information about which goals and phases are available, see the following:" ); + writer.write( NEWLINE ); + writer.write( "- Maven in 5 Minutes guide (http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html)" ); + writer.write( NEWLINE ); + writer.write( "- Maven User's documentation (http://maven.apache.org/users/)" ); + writer.write( NEWLINE ); + writer.write( "- Maven Plugins page (http://maven.apache.org/plugins/)" ); + writer.write( NEWLINE ); + writer.write( "- CodeHaus Mojos Project page (http://mojo.codehaus.org/plugins.html)" ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + + return true; + } + else if ( e instanceof AggregatedBuildFailureException ) + { + writer.write( NEWLINE ); writer.write( "Mojo (aggregator): " ); writer.write( NEWLINE ); writer.write( NEWLINE ); @@ -439,7 +732,6 @@ public final class CLIReportingUtils handleMojoFailureException( ( (AggregatedBuildFailureException) e ).getMojoFailureException(), writer ); - return true; } else if ( e instanceof ProjectBuildFailureException ) @@ -451,6 +743,7 @@ public final class CLIReportingUtils writer.write( " " ); writer.write( MojoBindingUtils.toString( ( (ProjectBuildFailureException) e ).getBinding() ) ); writer.write( NEWLINE ); + writer.write( NEWLINE ); writer.write( "FAILED for project: " ); writer.write( NEWLINE ); writer.write( NEWLINE ); @@ -467,6 +760,94 @@ public final class CLIReportingUtils return true; } + else if ( e instanceof InvalidTaskException ) + { + String task = ( (InvalidTaskException) e ).getTask(); + Throwable cause = e.getCause(); + + writer.write( NEWLINE ); + writer.write( "Invalid mojo or lifecycle phase: " ); + writer.write( task ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + + if ( cause instanceof PluginLoaderException ) + { + writer.write( "Failed to load plugin: " ); + writer.write( ( (PluginLoaderException) cause ).getPluginKey() ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + } + else + { + writer.write( "Error message was: " ); + writer.write( e.getMessage() ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + + } + + if ( showStackTraces ) + { + writer.write( "Original error:" ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + handleGenericException( cause, showStackTraces, writer ); + } + else + { + writer.write( "Original error message was: " ); + writer.write( cause.getMessage() ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + } + + return true; + } + else if ( e instanceof ProjectCycleException ) + { + writer.write( NEWLINE ); + writer.write( "Maven has detected a cyclic relationship among a set of projects in the current build." ); + writer.write( NEWLINE ); + writer.write( "The projects involved are:" ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + + List projects = ( (ProjectCycleException) e ).getProjects(); + for ( Iterator it = projects.iterator(); it.hasNext(); ) + { + MavenProject project = (MavenProject) it.next(); + writer.write( "- " ); + writer.write( project.getId() ); + writer.write( " (path: " ); + writer.write( project.getFile().getPath() ); + writer.write( ")" ); + writer.write( NEWLINE ); + } + + writer.write( NEWLINE ); + writer.write( "NOTE: This cycle usually indicates two projects listing one another as dependencies, but" ); + writer.write( NEWLINE ); + writer.write( "may also indicate one project using another as a parent, plugin, or extension." ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + + if ( showStackTraces ) + { + writer.write( "Original error:" ); + writer.write( NEWLINE ); + writer.write( NEWLINE ); + + handleGenericException( ( (ProjectCycleException) e ).getCause(), + showStackTraces, + writer ); + + writer.write( NEWLINE ); + writer.write( NEWLINE ); + } + + return true; + } return false; } diff --git a/maven-embedder/src/test/java/org/apache/maven/cli/CLIReportingUtilsTest.java b/maven-embedder/src/test/java/org/apache/maven/cli/CLIReportingUtilsTest.java index 073ffb5103..cf85f82311 100644 --- a/maven-embedder/src/test/java/org/apache/maven/cli/CLIReportingUtilsTest.java +++ b/maven-embedder/src/test/java/org/apache/maven/cli/CLIReportingUtilsTest.java @@ -1,70 +1,54 @@ package org.apache.maven.cli; -import java.io.File; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import junit.framework.TestCase; - +import org.apache.maven.AggregatedBuildFailureException; import org.apache.maven.BuildFailureException; +import org.apache.maven.InvalidTaskException; +import org.apache.maven.NoGoalsSpecifiedException; import org.apache.maven.ProjectBuildFailureException; -import org.apache.maven.execution.DefaultMavenExecutionRequest; -import org.apache.maven.execution.DefaultMavenExecutionResult; -import org.apache.maven.execution.MavenExecutionRequest; -import org.apache.maven.execution.MavenExecutionResult; -import org.apache.maven.execution.ReactorManager; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.lifecycle.LifecycleLoaderException; +import org.apache.maven.lifecycle.TaskValidationResult; import org.apache.maven.lifecycle.model.MojoBinding; import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; +import org.apache.maven.model.Plugin; import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.project.DuplicateProjectException; import org.apache.maven.project.InvalidProjectModelException; -import org.apache.maven.project.MavenProject; +import org.apache.maven.project.InvalidProjectVersionException; +import org.apache.maven.project.artifact.InvalidDependencyVersionException; import org.apache.maven.project.validation.ModelValidationResult; -import org.codehaus.plexus.util.dag.CycleDetectedException; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; + +import junit.framework.TestCase; public class CLIReportingUtilsTest extends TestCase { - private TestEmbedderLogger logger = new TestEmbedderLogger(); + // ===================================================================== + // Still left to test for ProjectBuildingException: + // ===================================================================== + // + // ProjectBuildingException(String, String, File, XmlPullParserException) + // + // ProjectBuildingException(String, String, IOException) + // ProjectBuildingException(String, String, File, IOException) + // + // ProjectBuildingException(String, String, ArtifactNotFoundException) + // ProjectBuildingException(String, String, File, ArtifactNotFoundException) + // + // ProjectBuildingException(String, String, ArtifactResolutionException) + // ProjectBuildingException(String, String, File, ArtifactResolutionException) + // + // ProjectBuildingException(String, String, File, ProfileActivationException) + // + // ProjectBuildingException(String, String, InvalidRepositoryException) + // ProjectBuildingException(String, String, File, InvalidRepositoryException) - public void test_logResult_ShowLongMessageForMojoFailureException() - throws CycleDetectedException, DuplicateProjectException - { - String longMessage = "This is a longer message."; - - MojoFailureException e = new MojoFailureException( "test-id", "Short Message", longMessage ); - - MojoBinding binding = new MojoBinding(); - binding.setGroupId( "plugin.group" ); - binding.setArtifactId( "plugin-artifact" ); - binding.setVersion( "10" ); - - BuildFailureException buildError = new ProjectBuildFailureException( "test:project:1", binding, e ); - - MavenExecutionRequest request = new DefaultMavenExecutionRequest(); - MavenExecutionResult result = new DefaultMavenExecutionResult(); - - request.setStartTime( new Date() ); - - MavenProject project = createProject( "test", "project", "1" ); - - ReactorManager reactorManager = new ReactorManager( Collections.singletonList( project ), - ReactorManager.FAIL_FAST ); - reactorManager.registerBuildFailure( project, e, "task", 0 ); - - result.setReactorManager( reactorManager ); - result.addBuildFailureException( buildError ); - - CLIReportingUtils.logResult( request, result, logger ); - assertPresent( longMessage, logger.getErrorMessages() ); - } - - public void test_logResult_ShowReasonableMessageForInvalidProject() - throws CycleDetectedException, DuplicateProjectException + public void test_handleProjectBuildingException_ShowReasonableMessageForInvalidProjectModel() { String validationMessage = "dependencies.dependency.version is required"; @@ -75,63 +59,214 @@ public class CLIReportingUtilsTest File projectPath = new File( "/path/to/somewhere" ); String message = "message"; - InvalidProjectModelException e = new InvalidProjectModelException( projectId, message, projectPath, results ); + InvalidProjectModelException e = new InvalidProjectModelException( projectId, message, + projectPath, results ); - MavenExecutionRequest request = new DefaultMavenExecutionRequest(); - MavenExecutionResult result = new DefaultMavenExecutionResult(); + StringWriter writer = new StringWriter(); + CLIReportingUtils.buildErrorMessage( e, false, writer ); - request.setStartTime( new Date() ); + toConsole( writer ); - MavenProject project = createProject( "test", "project", "1" ); - - Dependency dep = new Dependency(); - dep.setGroupId( "test" ); - dep.setArtifactId( "dep" ); - - project.getModel().addDependency( dep ); - - ReactorManager reactorManager = new ReactorManager( Collections.singletonList( project ), - ReactorManager.FAIL_FAST ); - reactorManager.registerBuildFailure( project, e, "task", 0 ); - - result.setReactorManager( reactorManager ); - result.addProjectBuildingException( e ); - - CLIReportingUtils.logResult( request, result, logger ); - assertPresent( projectId, logger.getErrorMessages() ); - assertPresent( projectPath.getPath(), logger.getErrorMessages() ); - assertPresent( message, logger.getErrorMessages() ); - assertPresent( validationMessage, logger.getErrorMessages() ); + String[] contentLines = writer.toString().split( "\r?\n" ); + assertPresent( projectId, contentLines ); + assertPresent( projectPath.getPath(), contentLines ); + assertPresent( message, contentLines ); + assertPresent( validationMessage, contentLines ); } - private MavenProject createProject( String groupId, - String artifactId, - String version ) + public void test_handleProjectBuildingException_ShowLocationInfoForInvalidDependencyVersionException() + throws IOException { - Model model = new Model(); - model.setGroupId( groupId ); - model.setArtifactId( artifactId ); - model.setVersion( version ); + String version = "[1.0"; - return new MavenProject( model ); + InvalidVersionSpecificationException cause = null; + try + { + VersionRange.createFromVersionSpec( version ); + fail( "Version should be invalid." ); + } + catch ( InvalidVersionSpecificationException versionException ) + { + cause = versionException; + } + + Dependency dep = new Dependency(); + dep.setGroupId( "org.group" ); + dep.setArtifactId( "dep-artifact" ); + dep.setVersion( version ); + + File pomFile = File.createTempFile( "CLIReportingUtils.test.", "" ); + pomFile.deleteOnExit(); + + String projectId = "org.group.id:some-artifact:1"; + + InvalidDependencyVersionException e = new InvalidDependencyVersionException( projectId, + dep, pomFile, + cause ); + + StringWriter writer = new StringWriter(); + CLIReportingUtils.buildErrorMessage( e, false, writer ); + + toConsole( writer ); + + String[] contentLines = writer.toString().split( "\r?\n" ); + assertPresent( projectId, contentLines ); + assertPresent( "Group-Id: " + dep.getGroupId(), contentLines ); + assertPresent( "Artifact-Id: " + dep.getArtifactId(), contentLines ); + assertPresent( version, contentLines ); + } + + public void test_handleProjectBuildingException_ShowLocationInfoForInvalidProjectVersionException() + throws IOException + { + String version = "[1.0"; + + InvalidVersionSpecificationException cause = null; + try + { + VersionRange.createFromVersionSpec( version ); + fail( "Version should be invalid." ); + } + catch ( InvalidVersionSpecificationException versionException ) + { + cause = versionException; + } + + File pomFile = File.createTempFile( "CLIReportingUtils.test.", "" ); + pomFile.deleteOnExit(); + + String projectId = "org.group.id:some-artifact:1"; + String extLocation = "extension: org.group:extension-artifact"; + + InvalidProjectVersionException e = new InvalidProjectVersionException( projectId, + extLocation, + version, pomFile, + cause ); + + StringWriter writer = new StringWriter(); + CLIReportingUtils.buildErrorMessage( e, false, writer ); + + toConsole( writer ); + + String[] contentLines = writer.toString().split( "\r?\n" ); + assertPresent( projectId, contentLines ); + assertPresent( extLocation, contentLines ); + assertPresent( version, contentLines ); + } + + // ===================================================================== + // Still left to test for BuildFailureException: + // ===================================================================== + // ProjectCycleException(List, String, CycleDetectedException) + + public void test_handleBuildFailureException_ShowAdviceMessageForNoGoalsSpecifiedException() + { + NoGoalsSpecifiedException e = new NoGoalsSpecifiedException( "No goals were specified." ); + + StringWriter writer = new StringWriter(); + CLIReportingUtils.buildErrorMessage( e, false, writer ); + + toConsole( writer ); + + String[] contentLines = writer.toString().split( "\r?\n" ); + assertPresent( "http://maven.apache.org/users/", contentLines ); + assertPresent( "http://maven.apache.org/plugins/", contentLines ); + } + + public void test_handleBuildFailureException_ShowAdviceMessageForInvalidTaskException() + { + Plugin plugin = new Plugin(); + plugin.setGroupId( "org.apache.maven.plugins" ); + plugin.setArtifactId( "maven-something-plugin" ); + plugin.setVersion( "[1.0" ); + + TaskValidationResult tvr = new TaskValidationResult( + "something-dumb", + "test message.", + new LifecycleLoaderException( + "No such lifecycle phase: something-dumb" ) ); + + InvalidTaskException e = tvr.generateInvalidTaskException(); + + StringWriter writer = new StringWriter(); + CLIReportingUtils.buildErrorMessage( e, false, writer ); + + toConsole( writer ); + + String[] contentLines = writer.toString().split( "\r?\n" ); + assertPresent( "test message", contentLines ); + assertPresent( "something-dumb", contentLines ); + assertPresent( "No such lifecycle phase: something-dumb", contentLines ); + } + + public void test_handleBuildFailureException_ShowLongMessageForMojoFailureException() + { + String longMessage = "This is a longer message."; + + MojoFailureException e = new MojoFailureException( "test-id", "Short Message", longMessage ); + + MojoBinding binding = new MojoBinding(); + binding.setGroupId( "plugin.group" ); + binding.setArtifactId( "plugin-artifact" ); + binding.setVersion( "10" ); + + BuildFailureException buildError = new ProjectBuildFailureException( "test:project:1", + binding, e ); + + StringWriter writer = new StringWriter(); + CLIReportingUtils.buildErrorMessage( buildError, false, writer ); + + toConsole( writer ); + + String[] contentLines = writer.toString().split( "\r?\n" ); + assertPresent( longMessage, contentLines ); + } + + public void test_handleBuildFailureException_ShowLongMessageForAggregatedMojoFailureException() + { + String longMessage = "This is a longer message."; + + MojoFailureException e = new MojoFailureException( "test-id", "Short Message", longMessage ); + + MojoBinding binding = new MojoBinding(); + binding.setGroupId( "plugin.group" ); + binding.setArtifactId( "plugin-artifact" ); + binding.setVersion( "10" ); + + BuildFailureException buildError = new AggregatedBuildFailureException( + "/path/to/project/dir", + binding, e ); + + StringWriter writer = new StringWriter(); + CLIReportingUtils.buildErrorMessage( buildError, false, writer ); + + toConsole( writer ); + + String[] contentLines = writer.toString().split( "\r?\n" ); + assertPresent( longMessage, contentLines ); } private void assertPresent( String message, - List messages ) + String[] contentLines ) { - for ( Iterator it = messages.iterator(); it.hasNext(); ) + for ( int i = 0; i < contentLines.length; i++ ) { - String entry = (String) it.next(); - - if ( entry.indexOf( message ) > -1 ) + if ( contentLines[i].indexOf( message ) > -1 ) { return; } } fail( "Message not found in output: \'" + message + "\'" ); - assertTrue( "Message: \'" + message + "\' is missing in output.", - messages.contains( message ) ); + } + + private void toConsole( StringWriter writer ) + { + System.out.println( new Throwable().getStackTrace()[1].getMethodName() + ":" ); + System.out.println( "==========================" ); + System.out.println( writer.toString() ); + System.out.println( "==========================" ); + System.out.println( "\n\n" ); } } diff --git a/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java b/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java index fcfbeb8f23..853777f236 100644 --- a/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java +++ b/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java @@ -69,8 +69,8 @@ import org.apache.maven.project.validation.ModelValidator; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; import org.codehaus.plexus.util.IOUtil; -import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import java.io.File; @@ -78,8 +78,6 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; import java.io.StringReader; -import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; @@ -378,8 +376,7 @@ public class DefaultMavenProjectBuilder } catch ( InvalidVersionSpecificationException e ) { - throw new ProjectBuildingException( projectId, "Unable to parse version '" + d.getVersion() + - "' for dependency '" + d.getManagementKey() + "': " + e.getMessage(), pomFile, e ); + throw new InvalidDependencyVersionException( projectId, d, pomFile, e ); } } } @@ -1006,7 +1003,22 @@ public class DefaultMavenProjectBuilder try { reader = ReaderFactory.newXmlReader( file ); - return readModel( projectId, file.toURI(), reader, strict ); + + String modelSource = IOUtil.toString( reader ); + + checkModelVersion( modelSource, projectId, file ); + + StringReader sReader = new StringReader( modelSource ); + + try + { + return modelReader.read( sReader, strict ); + } + catch ( XmlPullParserException e ) + { + throw new InvalidProjectModelException( projectId, "Parse error reading POM. Reason: " + e.getMessage(), + file, e ); + } } catch ( FileNotFoundException e ) { @@ -1024,58 +1036,14 @@ public class DefaultMavenProjectBuilder } } - private Model readModel( String projectId, - URI pomLocation, - Reader reader, - boolean strict ) - throws IOException, InvalidProjectModelException + private void checkModelVersion( String modelSource, + String projectId, + File file ) + throws InvalidProjectModelException { - String modelSource = IOUtil.toString( reader ); - if ( modelSource.indexOf( "" + MAVEN_MODEL_VERSION ) < 0 ) { - throw new InvalidProjectModelException( projectId, "Not a v" + MAVEN_MODEL_VERSION + " POM.", pomLocation ); - } - - StringReader sReader = new StringReader( modelSource ); - - try - { - return modelReader.read( sReader, strict ); - } - catch ( XmlPullParserException e ) - { - throw new InvalidProjectModelException( projectId, "Parse error reading POM. Reason: " + e.getMessage(), - pomLocation, e ); - } - } - - private Model readModel( String projectId, - URL url, - boolean strict ) - throws ProjectBuildingException - { - Reader reader = null; - URI uri = null; - try - { - uri = new URI( url.toString().replaceAll( " ", "%20" ) ); - reader = ReaderFactory.newXmlReader( url.openStream() ); - return readModel( projectId, uri, reader, strict ); - } - catch ( IOException e ) - { - throw new ProjectBuildingException( projectId, "Failed build model from URL \'" + url.toExternalForm() + - "\'\nError: \'" + e.getLocalizedMessage() + "\'", uri, e ); - } - catch ( URISyntaxException e ) - { - throw new ProjectBuildingException( projectId, "Failed build model from URL \'" + url.toExternalForm() - + "\'\nError: \'" + e.getLocalizedMessage() + "\'", e ); - } - finally - { - IOUtil.close( reader ); + throw new InvalidProjectModelException( projectId, "Not a v" + MAVEN_MODEL_VERSION + " POM.", file ); } } @@ -1222,7 +1190,7 @@ public class DefaultMavenProjectBuilder // TODO: share with createPluginArtifacts? protected Set createExtensionArtifacts( String projectId, - List extensions, File pomLocation ) + List extensions, File pomFile ) throws ProjectBuildingException { Set extensionArtifacts = new HashSet(); @@ -1252,9 +1220,9 @@ public class DefaultMavenProjectBuilder } catch ( InvalidVersionSpecificationException e ) { - throw new ProjectBuildingException( projectId, "Unable to parse version '" + version + - "' for extension '" + ArtifactUtils.versionlessKey( ext.getGroupId(), ext.getArtifactId() ) + - "': " + e.getMessage(), pomLocation, e ); + String key = ArtifactUtils.versionlessKey( ext.getGroupId(), ext.getArtifactId() ); + throw new InvalidProjectVersionException( projectId, "extension '" + key, + version, pomFile, e ); } if ( artifact != null ) @@ -1278,6 +1246,30 @@ public class DefaultMavenProjectBuilder String projectId = safeVersionlessKey( STANDALONE_SUPERPOM_GROUPID, STANDALONE_SUPERPOM_ARTIFACTID ); - return readModel( projectId, url, STRICT_MODEL_PARSING ); + Reader reader = null; + try + { + reader = ReaderFactory.newXmlReader( url.openStream() ); + String modelSource = IOUtil.toString( reader ); + + checkModelVersion( modelSource, projectId, null ); + + StringReader sReader = new StringReader( modelSource ); + + return modelReader.read( sReader, STRICT_MODEL_PARSING ); + } + catch ( XmlPullParserException e ) + { + throw new InvalidProjectModelException( projectId, "Parse error reading POM. Reason: " + e.getMessage(), e ); + } + catch ( IOException e ) + { + throw new ProjectBuildingException( projectId, "Failed build model from URL \'" + url.toExternalForm() + + "\'\nError: \'" + e.getLocalizedMessage() + "\'", e ); + } + finally + { + IOUtil.close( reader ); + } } } diff --git a/maven-project/src/main/java/org/apache/maven/project/InvalidProjectModelException.java b/maven-project/src/main/java/org/apache/maven/project/InvalidProjectModelException.java index 91109aec11..fb55891f19 100644 --- a/maven-project/src/main/java/org/apache/maven/project/InvalidProjectModelException.java +++ b/maven-project/src/main/java/org/apache/maven/project/InvalidProjectModelException.java @@ -19,37 +19,25 @@ package org.apache.maven.project; * under the License. */ -import java.io.File; -import java.net.URI; - import org.apache.maven.artifact.InvalidRepositoryException; import org.apache.maven.project.interpolation.ModelInterpolationException; import org.apache.maven.project.validation.ModelValidationResult; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import java.io.File; + public class InvalidProjectModelException extends ProjectBuildingException { private ModelValidationResult validationResult; - /** - * - * @param projectId - * @param message - * @param pomLocation pom location - */ - public InvalidProjectModelException( String projectId, String message, URI pomLocation ) - { - super( projectId, message, pomLocation ); - } - public InvalidProjectModelException( String projectId, String message, File pomLocation ) { super( projectId, message, pomLocation ); } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation * @param projectId * @param pomLocation absolute path of the pom file * @param message @@ -70,7 +58,7 @@ public class InvalidProjectModelException } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation * @param projectId * @param pomLocation absolute path of the pom file * @param message @@ -81,7 +69,7 @@ public class InvalidProjectModelException } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public InvalidProjectModelException( String projectId, String pomLocation, String message, ModelInterpolationException cause ) @@ -96,7 +84,7 @@ public class InvalidProjectModelException } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public InvalidProjectModelException( String projectId, String pomLocation, String message, InvalidRepositoryException cause ) @@ -111,17 +99,23 @@ public class InvalidProjectModelException } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public InvalidProjectModelException( String projectId, String pomLocation, String message, XmlPullParserException cause ) { - this( projectId, message, new File( pomLocation ).toURI(), cause ); + this( projectId, message, new File( pomLocation ), cause ); } - public InvalidProjectModelException( String projectId, String message, URI pomLocation, XmlPullParserException cause ) + public InvalidProjectModelException( String projectId, String message, File pomFile, XmlPullParserException cause ) { - super( projectId, message, pomLocation, cause ); + super( projectId, message, pomFile, cause ); + } + + // for super-POM building. + public InvalidProjectModelException( String projectId, String message, XmlPullParserException cause ) + { + super( projectId, message, cause ); } public final ModelValidationResult getValidationResult() diff --git a/maven-project/src/main/java/org/apache/maven/project/InvalidProjectVersionException.java b/maven-project/src/main/java/org/apache/maven/project/InvalidProjectVersionException.java new file mode 100644 index 0000000000..e8e8979171 --- /dev/null +++ b/maven-project/src/main/java/org/apache/maven/project/InvalidProjectVersionException.java @@ -0,0 +1,39 @@ +package org.apache.maven.project; + +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; + +import java.io.File; + +public class InvalidProjectVersionException + extends ProjectBuildingException +{ + + private final String locationInPom; + private final String offendingVersion; + + public InvalidProjectVersionException( String projectId, String locationInPom, String offendingVersion, File pomFile, InvalidVersionSpecificationException cause ) + { + super( projectId, formatMessage( projectId, locationInPom, offendingVersion, cause ), pomFile, cause ); + this.locationInPom = locationInPom; + this.offendingVersion = offendingVersion; + } + + private static String formatMessage( String projectId, + String locationInPom, + String offendingVersion, + InvalidVersionSpecificationException cause ) + { + return "Invalid version: " + offendingVersion + " found for: " + locationInPom + " in project: " + projectId + ". Reason: " + cause.getMessage(); + } + + public String getOffendingVersion() + { + return offendingVersion; + } + + public String getLocationInPom() + { + return locationInPom; + } + +} diff --git a/maven-project/src/main/java/org/apache/maven/project/ProjectBuildingException.java b/maven-project/src/main/java/org/apache/maven/project/ProjectBuildingException.java index 14441192bf..71367f58ff 100644 --- a/maven-project/src/main/java/org/apache/maven/project/ProjectBuildingException.java +++ b/maven-project/src/main/java/org/apache/maven/project/ProjectBuildingException.java @@ -1,10 +1,5 @@ package org.apache.maven.project; -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; - import org.apache.maven.artifact.InvalidRepositoryException; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; @@ -14,6 +9,9 @@ import org.apache.maven.project.artifact.InvalidDependencyVersionException; import org.apache.maven.project.interpolation.ModelInterpolationException; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import java.io.File; +import java.io.IOException; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -42,61 +40,38 @@ public class ProjectBuildingException { private final String projectId; - private URI pomUri; + private File pomFile; public ProjectBuildingException( String projectId, String message ) { - this( projectId, message, (URI) null ); + super( message ); + this.projectId = projectId; } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation * @param projectId * @param message * @param pomLocation absolute path of the pom file */ protected ProjectBuildingException( String projectId, String message, String pomLocation ) { - this( projectId, message, pomLocation, (Throwable) null ); + super( message ); + this.projectId = projectId; + pomFile = new File( pomLocation ); } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation - * @param projectId - * @param message - * @param pomLocation absolute path of the pom file - * @param cause - */ - private ProjectBuildingException( String projectId, String message, String pomLocation, Throwable cause ) - { - this( projectId, message, new File( pomLocation ), cause ); - } - - /** - * + * * @param projectId * @param message * @param pomFile pom file location */ public ProjectBuildingException( String projectId, String message, File pomFile ) { - this( projectId, message, pomFile, (Throwable) null ); - } - - /** - * - * @param projectId - * @param message - * @param cause - */ - private ProjectBuildingException( String projectId, String message, Throwable cause ) - { - this( projectId, message, (URI) null, cause ); - } - - public ProjectBuildingException( String projectId, String message, URISyntaxException cause ) - { - this( projectId, message, (Throwable) cause ); + super( message ); + this.projectId = projectId; + this.pomFile = pomFile; } /** @@ -105,186 +80,211 @@ public class ProjectBuildingException * @param pomFile pom file location * @param cause */ - public ProjectBuildingException( String projectId, String message, File pomFile, Throwable cause ) + protected ProjectBuildingException( String projectId, String message, File pomFile, Throwable cause ) { - this( projectId, message, pomFile.toURI(), cause ); + super( message, cause ); + this.projectId = projectId; + this.pomFile = pomFile; } /** - * Equivalent to new ProjectBuildingException(projectId, message, pomUri, null) - * - * @see #ProjectBuildingException(String, String, URI, Throwable) - */ - public ProjectBuildingException( String projectId, String message, URI pomUri ) - { - this( projectId, message, pomUri, (Throwable) null ); - } - - /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public ProjectBuildingException( String projectId, String message, String pomLocation, ProfileActivationException cause ) { - this( projectId, message, new File( pomLocation ), cause ); + super( message, cause ); + this.projectId = projectId; + pomFile = new File( pomLocation ); } - public ProjectBuildingException( String projectId, String message, File pomLocation, + public ProjectBuildingException( String projectId, String message, File pomFile, ProfileActivationException cause ) - { - this( projectId, message, pomLocation, (Throwable) cause ); - } - - /** - * @param projectId - * @param message - * @param pomUri location of the pom - * @param cause - */ - private ProjectBuildingException( String projectId, String message, URI pomUri, Throwable cause ) { super( message, cause ); this.projectId = projectId; - this.pomUri = pomUri; + this.pomFile = pomFile; } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public ProjectBuildingException( String projectId, String message, String pomLocation, IOException cause ) { - this( projectId, message, new File( pomLocation ), cause ); + super( message, cause ); + this.projectId = projectId; + pomFile = new File( pomLocation ); } - public ProjectBuildingException( String projectId, String message, URI pomLocation, IOException cause ) + public ProjectBuildingException( String projectId, String message, File pomFile, IOException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + this.pomFile = pomFile; + } + + // for super-POM building. + public ProjectBuildingException( String projectId, String message, IOException cause ) + { + super( message, cause ); + this.projectId = projectId; } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public ProjectBuildingException( String projectId, String message, String pomLocation, XmlPullParserException cause ) { - this( projectId, message, new File( pomLocation ), cause ); + super( message, cause ); + this.projectId = projectId; + pomFile = new File( pomLocation ); } - public ProjectBuildingException( String projectId, String message, URI pomLocation, XmlPullParserException cause ) + public ProjectBuildingException( String projectId, String message, File pomFile, XmlPullParserException cause ) { - this( message, projectId, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + this.pomFile = pomFile; } protected ProjectBuildingException( String projectId, String message, XmlPullParserException cause ) { - this( message, projectId, (URI) null, cause ); + super( message, cause ); + this.projectId = projectId; } public ProjectBuildingException( String projectId, String message, ArtifactResolutionException cause ) { - this( projectId, message, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; } public ProjectBuildingException( String projectId, String message, InvalidRepositoryException cause ) { - this( projectId, message, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + } + + public ProjectBuildingException( String projectId, String message, File pomFile, InvalidRepositoryException cause ) + { + super( message, cause ); + this.projectId = projectId; + this.pomFile = pomFile; } public ProjectBuildingException( String projectId, String message, ArtifactNotFoundException cause ) { - this( projectId, message, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; } - public ProjectBuildingException( String projectId, String message, File pomLocation, + public ProjectBuildingException( String projectId, String message, File pomFile, ArtifactResolutionException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + this.pomFile = pomFile; } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public ProjectBuildingException( String projectId, String message, String pomLocation, ArtifactResolutionException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + pomFile = new File( pomLocation ); } - public ProjectBuildingException( String projectId, String message, File pomLocation, ArtifactNotFoundException cause ) + public ProjectBuildingException( String projectId, String message, File pomFile, ArtifactNotFoundException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + this.pomFile = pomFile; } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public ProjectBuildingException( String projectId, String message, String pomLocation, ArtifactNotFoundException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + pomFile = new File( pomLocation ); } - public ProjectBuildingException( String projectId, String message, File pomLocation, + public ProjectBuildingException( String projectId, String message, File pomFile, InvalidVersionSpecificationException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + this.pomFile = pomFile; } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public ProjectBuildingException( String projectId, String message, String pomLocation, InvalidVersionSpecificationException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + pomFile = new File( pomLocation ); } - public ProjectBuildingException( String projectId, String message, File pomLocation, + public ProjectBuildingException( String projectId, String message, File pomFile, InvalidDependencyVersionException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + this.pomFile = pomFile; } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ public ProjectBuildingException( String projectId, String message, String pomLocation, InvalidDependencyVersionException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + pomFile = new File( pomLocation ); } - protected ProjectBuildingException( String projectId, String message, File pomLocation, + protected ProjectBuildingException( String projectId, String message, File pomFile, ModelInterpolationException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + this.pomFile = pomFile; } /** - * @deprecated use {@link File} or {@link URI} constructors for pomLocation + * @deprecated use {@link File} constructor for pomLocation */ protected ProjectBuildingException( String projectId, String message, String pomLocation, ModelInterpolationException cause ) { - this( projectId, message, pomLocation, (Throwable) cause ); + super( message, cause ); + this.projectId = projectId; + pomFile = new File ( pomLocation ); } - public URI getPomUri() + public File getPomFile() { - return pomUri; + return pomFile; } /** - * @deprecated use {@link #getPomUri()} + * @deprecated use {@link #getPomFile()} */ public String getPomLocation () { - if ( getPomUri() != null ) + if ( getPomFile() != null ) { - if ( "file".equals( getPomUri().getScheme() ) ) - { - return new File( getPomUri() ).getAbsolutePath(); - } - return getPomUri().toString(); + return getPomFile().getAbsolutePath(); } else { @@ -300,6 +300,6 @@ public class ProjectBuildingException public String getMessage() { return super.getMessage() + " for project " + projectId - + ( ( getPomUri() == null ? "" : " at " + getPomLocation() ) ); + + ( ( getPomFile() == null ? "" : " at " + getPomFile().getAbsolutePath() ) ); } } diff --git a/maven-project/src/main/java/org/apache/maven/project/artifact/InvalidDependencyVersionException.java b/maven-project/src/main/java/org/apache/maven/project/artifact/InvalidDependencyVersionException.java index 08983736f9..6c1ab050b8 100644 --- a/maven-project/src/main/java/org/apache/maven/project/artifact/InvalidDependencyVersionException.java +++ b/maven-project/src/main/java/org/apache/maven/project/artifact/InvalidDependencyVersionException.java @@ -1,6 +1,11 @@ package org.apache.maven.project.artifact; +import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.model.Dependency; +import org.apache.maven.project.InvalidProjectVersionException; + +import java.io.File; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -28,18 +33,23 @@ import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException * @version $Id$ */ public class InvalidDependencyVersionException - extends Exception + extends InvalidProjectVersionException { - public InvalidDependencyVersionException( String message, InvalidVersionSpecificationException cause ) + private Dependency dependency; + + public InvalidDependencyVersionException( String projectId, Dependency dependency, File pomFile, InvalidVersionSpecificationException cause ) { - super( message, cause ); + super( projectId, formatLocationInPom( dependency ), dependency.getVersion(), pomFile, cause ); + this.dependency = dependency; } - /** - * @deprecated use {@link #InvalidDependencyVersionException(String, InvalidVersionSpecificationException)} - */ - public InvalidDependencyVersionException( String message, Exception cause ) + private static String formatLocationInPom( Dependency dependency ) { - super( message, cause ); + return "dependency: " + ArtifactUtils.versionlessKey( dependency.getGroupId(), dependency.getArtifactId() ); + } + + public Dependency getDependency() + { + return dependency; } } diff --git a/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java b/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java index 601dd25d00..3a63f8f62c 100644 --- a/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java +++ b/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java @@ -371,8 +371,7 @@ public class MavenMetadataSource } catch ( InvalidVersionSpecificationException e ) { - throw new InvalidDependencyVersionException( "Unable to parse version '" + d.getVersion() + - "' for dependency '" + d.getManagementKey() + "': " + e.getMessage(), e ); + throw new InvalidDependencyVersionException( project.getId(), d, project.getFile(), e ); } Artifact artifact = artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange, d.getType(), d.getClassifier(), diff --git a/maven-project/src/main/java/org/apache/maven/project/build/model/DefaultModelLineageBuilder.java b/maven-project/src/main/java/org/apache/maven/project/build/model/DefaultModelLineageBuilder.java index c9f8a0cc27..7d3143ebf9 100644 --- a/maven-project/src/main/java/org/apache/maven/project/build/model/DefaultModelLineageBuilder.java +++ b/maven-project/src/main/java/org/apache/maven/project/build/model/DefaultModelLineageBuilder.java @@ -323,7 +323,7 @@ public class DefaultModelLineageBuilder { try { - parentPomFile = resolveParentFromRepositories( modelParent, localRepository, remoteRepositories, model.getId() ); + parentPomFile = resolveParentFromRepositories( modelParent, localRepository, remoteRepositories, model.getId(), modelPomFile ); isResolved = true; } catch( ProjectBuildingException e ) @@ -396,29 +396,23 @@ public class DefaultModelLineageBuilder } private File resolveParentFromRepositories( Parent modelParent, ArtifactRepository localRepository, - List remoteRepositories, String childId ) + List remoteRepositories, String childId, File childPomFile ) throws ProjectBuildingException { Artifact parentPomArtifact = artifactFactory.createBuildArtifact( modelParent.getGroupId(), modelParent .getArtifactId(), modelParent.getVersion(), "pom" ); -// getLogger().debug( "Looking for parent: " + modelParent.getId() + " using artifact: " + parentPomArtifact ); -// getLogger().debug( "\tLocal repository: " + localRepository.getBasedir() + "\n" ); -// getLogger().debug( "\tRemote repositories:\n" + remoteRepositories.toString().replace( ',', '\n' ) + "\n" ); - try { artifactResolver.resolve( parentPomArtifact, remoteRepositories, localRepository ); } catch ( ArtifactResolutionException e ) { - throw new ProjectBuildingException( "Parent: " + modelParent.getId(), - "Failed to resolve POM for parent of: " + childId, e ); + throw new ProjectBuildingException( childId, "Failed to resolve parent POM: " + modelParent.getId(), childPomFile, e ); } catch ( ArtifactNotFoundException e ) { - throw new ProjectBuildingException( "Parent: " + modelParent.getId(), "Cannot find parent: " - + parentPomArtifact.getId() + " of: " + childId, e ); + throw new ProjectBuildingException( childId, "Cannot find artifact for parent POM: " + modelParent.getId(), childPomFile, e ); } if ( parentPomArtifact.isResolved() )