Migration to Maven 3: because of an API change in ModelProblemCollector between 3.0.x and 3.1.x, that interface cannot be used as-is for compatibility for both in order to determine if the coordinate information passed by the user is valid. The plugins are compiled with 3.0 core and are currently linked to a specific ModelProblemCollector, but starting with 3.1.0-alpha-1, Maven core calls a different method than the one the plugins were compiled with. This results in AbstractMethodError at run-time. (this was not detected by the ITs because, although they tested that the build failed with missing parameters, it didn't test the cause of the failure.)

Since the plugins are now using a new MavenProject instance, and attaching things to it in order to deploy or install them, it is possible to rely on the validation performed during the building of that project to catch model errors.

git-svn-id: https://svn.apache.org/repos/asf/maven/plugins/trunk@1770497 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/it/gav-validation/invoker.properties b/src/it/gav-validation/invoker.properties
index a6e8266..07e1b13 100644
--- a/src/it/gav-validation/invoker.properties
+++ b/src/it/gav-validation/invoker.properties
@@ -17,3 +17,6 @@
 
 invoker.goals = org.apache.maven.plugins:maven-install-plugin:${project.version}:install-file
 invoker.buildResult = failure
+
+invoker.systemPropertiesFile.1 = test-invalid.properties
+invoker.systemPropertiesFile.2 = test-missing.properties
diff --git a/src/it/gav-validation/test.properties b/src/it/gav-validation/test-invalid.properties
similarity index 100%
rename from src/it/gav-validation/test.properties
rename to src/it/gav-validation/test-invalid.properties
diff --git a/src/it/gav-validation/test-missing.properties b/src/it/gav-validation/test-missing.properties
new file mode 100644
index 0000000..6efaf08
--- /dev/null
+++ b/src/it/gav-validation/test-missing.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+file = test.jar
+packaging = jar
+
+# missing coordinates should have install-file bail out
+groupId = groupId
diff --git a/src/it/gav-validation/verify.bsh b/src/it/gav-validation/verify.groovy
similarity index 75%
rename from src/it/gav-validation/verify.bsh
rename to src/it/gav-validation/verify.groovy
index cde34fb..f006b22 100644
--- a/src/it/gav-validation/verify.bsh
+++ b/src/it/gav-validation/verify.groovy
@@ -17,22 +17,19 @@
  * under the License.
  */
 
-import java.io.*;
-import java.util.*;
-
 String[] paths =
-{
+[
     "org/apache/maven/its/install/gv",
-};
+];
 
 for ( String path : paths )
 {
-    File file = new File( localRepositoryPath, path );
-    System.out.println( "Checking for absence of " + file );
-    if ( file.exists() )
-    {
-        throw new FileNotFoundException( "Existing: " + file.getAbsolutePath() );
-    }
+    assert !new File( localRepositoryPath, path ).exists();
 }
 
+File buildLog = new File( basedir, 'build.log' )
+assert buildLog.exists()
+assert buildLog.text.contains( "The artifact information is incomplete" )
+assert buildLog.text.contains( "The artifact information is not valid" )
+
 return true;
diff --git a/src/main/java/org/apache/maven/plugin/install/InstallFileMojo.java b/src/main/java/org/apache/maven/plugin/install/InstallFileMojo.java
index efff979..40ae515 100644
--- a/src/main/java/org/apache/maven/plugin/install/InstallFileMojo.java
+++ b/src/main/java/org/apache/maven/plugin/install/InstallFileMojo.java
@@ -27,26 +27,19 @@
 import java.io.OutputStream;
 import java.io.Reader;
 import java.io.Writer;
-import java.util.ArrayList;
 import java.util.Enumeration;
-import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.regex.Pattern;
 
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.model.InputLocation;
 import org.apache.maven.model.Model;
 import org.apache.maven.model.Parent;
-import org.apache.maven.model.building.DefaultModelBuildingRequest;
-import org.apache.maven.model.building.ModelBuildingRequest;
-import org.apache.maven.model.building.ModelProblem.Severity;
-import org.apache.maven.model.building.ModelProblemCollector;
+import org.apache.maven.model.building.ModelBuildingException;
 import org.apache.maven.model.building.ModelSource;
 import org.apache.maven.model.building.StringModelSource;
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
-import org.apache.maven.model.validation.ModelValidator;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugins.annotations.Component;
@@ -61,6 +54,7 @@
 import org.apache.maven.project.artifact.ProjectArtifactMetadata;
 import org.apache.maven.shared.project.install.ProjectInstaller;
 import org.apache.maven.shared.project.install.ProjectInstallerRequest;
+import org.apache.maven.shared.utils.Os;
 import org.apache.maven.shared.utils.ReaderFactory;
 import org.apache.maven.shared.utils.WriterFactory;
 import org.apache.maven.shared.utils.io.IOUtil;
@@ -164,12 +158,6 @@
     private File localRepositoryPath;
 
     /**
-    * The component used to validate the user-supplied artifact coordinates.
-    */
-    @Component
-    private ModelValidator modelValidator;
-    
-    /**
      * Used for attaching the artifacts to install to the project.
      */
     @Component
@@ -180,13 +168,13 @@
      */
     @Component
     private ProjectBuilder projectBuilder;
-    
+
     /**
      * Used to install the project created.
      */
     @Component
     private ProjectInstaller installer;
-    
+
     /**
      * @see org.apache.maven.plugin.Mojo#execute()
      */
@@ -202,14 +190,14 @@
         }
 
         ProjectBuildingRequest buildingRequest = session.getProjectBuildingRequest();
-        
+
         // ----------------------------------------------------------------------
         // Override the default localRepository variable
         // ----------------------------------------------------------------------
         if ( localRepositoryPath != null )
         {
             buildingRequest = repositoryManager.setLocalRepositoryBasedir( buildingRequest, localRepositoryPath );
-            
+
             getLog().debug( "localRepoPath: " + repositoryManager.getLocalRepositoryBasedir( buildingRequest ) );
         }
 
@@ -225,17 +213,15 @@
             pomFile = temporaryPom;
         }
 
-        validateArtifactInformation();
-        
         MavenProject project = createMavenProject();
         Artifact artifact = project.getArtifact();
-        
+
         if ( file.equals( getLocalRepoFile( buildingRequest, artifact ) ) )
         {
             throw new MojoFailureException( "Cannot install artifact. "
                 + "Artifact is already in the local repository.\n\nFile in question is: " + file + "\n" );
         }
-        
+
         if ( classifier == null )
         {
             artifact.setFile( file );
@@ -295,7 +281,7 @@
         {
             projectHelper.attachArtifact( project, "jar", "javadoc", javadoc );
         }
-        
+
         try
         {
             // CHECKSTYLE_OFF: LineLength
@@ -318,32 +304,41 @@
             }
         }
     }
-    
+
     /**
      * Creates a Maven project in-memory from the user-supplied groupId, artifactId and version. When a classifier is
      * supplied, the packaging must be POM because the project with only have attachments. This project serves as basis
      * to attach the artifacts to install to.
      * 
      * @return The created Maven project, never <code>null</code>.
+     * @throws MojoExecutionException When the model of the project could not be built.
      * @throws MojoFailureException When building the project failed.
      */
     private MavenProject createMavenProject()
-        throws MojoFailureException
+        throws MojoExecutionException, MojoFailureException
     {
-        ModelSource modelSource =
-            new StringModelSource( "<project>" + "<modelVersion>4.0.0</modelVersion>" + "<groupId>" + groupId
-                + "</groupId>" + "<artifactId>" + artifactId + "</artifactId>" + "<version>" + version + "</version>"
-                + "<packaging>" + ( classifier == null ? packaging : "pom" ) + "</packaging>" + "</project>" );
-        DefaultProjectBuildingRequest buildingRequest =
-            new DefaultProjectBuildingRequest( session.getProjectBuildingRequest() );
-        buildingRequest.setProcessPlugins( false );
+        if ( groupId == null || artifactId == null || version == null || packaging == null )
+        {
+            throw new MojoExecutionException( "The artifact information is incomplete: 'groupId', 'artifactId', "
+                + "'version' and 'packaging' are required." );
+        }
+        ModelSource modelSource = new StringModelSource( "<project><modelVersion>4.0.0</modelVersion><groupId>"
+            + groupId + "</groupId><artifactId>" + artifactId + "</artifactId><version>" + version
+            + "</version><packaging>" + ( classifier == null ? packaging : "pom" ) + "</packaging></project>" );
+        ProjectBuildingRequest pbr = new DefaultProjectBuildingRequest( session.getProjectBuildingRequest() );
+        pbr.setProcessPlugins( false );
         try
         {
-            return projectBuilder.build( modelSource, buildingRequest ).getProject();
+            return projectBuilder.build( modelSource, pbr ).getProject();
         }
         catch ( ProjectBuildingException e )
         {
-            throw new MojoFailureException( e.getMessage(), e );
+            if ( e.getCause() instanceof ModelBuildingException )
+            {
+                throw new MojoExecutionException( "The artifact information is not valid:" + Os.LINE_SEP
+                    + e.getCause().getMessage() );
+            }
+            throw new MojoFailureException( "Unable to create the project.", e );
         }
     }
 
@@ -375,16 +370,16 @@
                     try
                     {
                         pomInputStream = jarFile.getInputStream( entry );
-                        
+
                         String base = file.getName();
                         if ( base.indexOf( '.' ) > 0 )
                         {
                             base = base.substring( 0, base.lastIndexOf( '.' ) );
                         }
                         pomFile = File.createTempFile( base, ".pom" );
-                        
+
                         pomOutputStream = new FileOutputStream( pomFile );
-                        
+
                         IOUtil.copy( pomInputStream, pomOutputStream );
 
                         pomOutputStream.close();
@@ -504,29 +499,6 @@
     }
 
     /**
-     * Validates the user-supplied artifact information.
-     * 
-     * @throws MojoExecutionException If any artifact coordinate is invalid.
-     */
-    private void validateArtifactInformation()
-        throws MojoExecutionException
-    {
-        Model model = generateModel();
-
-        ModelBuildingRequest buildingRequest = new DefaultModelBuildingRequest();
-        
-        InstallModelProblemCollector problemCollector = new InstallModelProblemCollector();
-        
-        modelValidator.validateEffectiveModel( model, buildingRequest , problemCollector );
-
-        if ( problemCollector.getMessageCount() > 0 )
-        {
-            throw new MojoExecutionException( "The artifact information is incomplete or not valid:\n"
-                + problemCollector.render( "  " ) );
-        }
-    }
-    
-    /**
      * Generates a minimal model from the user-supplied artifact information.
      * 
      * @return The generated model, never <code>null</code>.
@@ -581,40 +553,4 @@
         }
     }
 
-    private static class InstallModelProblemCollector implements ModelProblemCollector
-    {
-        /** */
-        private static final String NEWLINE = System.getProperty( "line.separator" );
-
-        /** */
-        private List<String> messages = new ArrayList<String>();
-        
-        @Override
-        public void add( Severity severity, String message, InputLocation location, Exception cause )
-        {
-            messages.add( message );
-        }
-
-        public int getMessageCount()
-        {
-            return messages.size();
-        }
-
-        public String render( String indentation )
-        {
-            if ( messages.size() == 0 )
-            {
-                return indentation + "There were no validation errors.";
-            }
-
-            StringBuilder message = new StringBuilder();
-
-            for ( int i = 0; i < messages.size(); i++ )
-            {
-                message.append( indentation + "[" + i + "]  " + messages.get( i ).toString() + NEWLINE );
-            }
-
-            return message.toString();
-        }
-    };
 }