From 504f5bca65c4a9edee050c62cedb3857d4cc875c Mon Sep 17 00:00:00 2001 From: Benjamin Bentmann Date: Tue, 20 Oct 2009 21:08:08 +0000 Subject: [PATCH] [MNG-4186] Provide an exact pointer to documentation specific to each known exception that can occur git-svn-id: https://svn.apache.org/repos/asf/maven/maven-3/trunk@827792 13f79535-47bb-0310-9956-ffa450edef68 --- .../AbstractArtifactResolutionException.java | 81 ++++--- ...LocalRepositoryNotAccessibleException.java | 44 ++++ .../legacy/DefaultWagonManager.java | 19 +- .../java/org/apache/maven/DefaultMaven.java | 46 ++-- .../exception/DefaultExceptionHandler.java | 224 ++++++++++++------ .../maven/exception/ExceptionSummary.java | 28 ++- .../DefaultMavenExecutionRequest.java | 5 + .../DefaultMavenExecutionResult.java | 15 -- .../maven/execution/MavenExecutionResult.java | 3 - .../maven/plugin/BuildPluginManager.java | 2 +- .../plugin/DefaultBuildPluginManager.java | 53 +++-- .../maven/plugin/MavenPluginManager.java | 2 +- .../plugin/PluginContainerException.java | 14 ++ .../plugin/PluginResolutionException.java | 5 +- .../internal/DefaultMavenPluginManager.java | 91 ++++--- .../project/DefaultModelBuildingListener.java | 4 +- .../java/org/apache/maven/cli/MavenCli.java | 138 +++++++---- 17 files changed, 507 insertions(+), 267 deletions(-) create mode 100644 maven-compat/src/main/java/org/apache/maven/repository/LocalRepositoryNotAccessibleException.java diff --git a/maven-compat/src/main/java/org/apache/maven/artifact/resolver/AbstractArtifactResolutionException.java b/maven-compat/src/main/java/org/apache/maven/artifact/resolver/AbstractArtifactResolutionException.java index aa1bb3511e..ce8a54cbd4 100644 --- a/maven-compat/src/main/java/org/apache/maven/artifact/resolver/AbstractArtifactResolutionException.java +++ b/maven-compat/src/main/java/org/apache/maven/artifact/resolver/AbstractArtifactResolutionException.java @@ -78,7 +78,7 @@ public class AbstractArtifactResolutionException Throwable t ) { super( constructMessageBase( message, groupId, artifactId, version, type, remoteRepositories, path ), t ); - + this.originalMessage = message; this.groupId = groupId; this.artifactId = artifactId; @@ -196,50 +196,55 @@ public class AbstractArtifactResolutionException StringBuilder sb = new StringBuilder(); sb.append( message ); - sb.append( LS ); - sb.append( " " + groupId + ":" + artifactId + ":" + type + ":" + version ); - sb.append( LS ); - if ( remoteRepositories != null ) + + if ( message == null || !message.contains( "from the specified remote repositories:" ) ) { sb.append( LS ); - sb.append( "from the specified remote repositories:" ); - sb.append( LS + " " ); - - if ( remoteRepositories.isEmpty() ) + sb.append( " " + groupId + ":" + artifactId + ":" + type + ":" + version ); + sb.append( LS ); + if ( remoteRepositories != null ) { - sb.append( "(none)" ); + sb.append( LS ); + sb.append( "from the specified remote repositories:" ); + sb.append( LS + " " ); + + if ( remoteRepositories.isEmpty() ) + { + sb.append( "(none)" ); + } + + for ( Iterator i = remoteRepositories.iterator(); i.hasNext(); ) + { + ArtifactRepository remoteRepository = i.next(); + + sb.append( remoteRepository.getId() ); + sb.append( " (" ); + sb.append( remoteRepository.getUrl() ); + + ArtifactRepositoryPolicy releases = remoteRepository.getReleases(); + if ( releases != null ) + { + sb.append( ", releases=" ).append( releases.isEnabled() ); + } + + ArtifactRepositoryPolicy snapshots = remoteRepository.getSnapshots(); + if ( snapshots != null ) + { + sb.append( ", snapshots=" ).append( snapshots.isEnabled() ); + } + + sb.append( ")" ); + if ( i.hasNext() ) + { + sb.append( "," ).append( LS ).append( " " ); + } + } } - for ( Iterator i = remoteRepositories.iterator(); i.hasNext(); ) - { - ArtifactRepository remoteRepository = i.next(); - - sb.append( remoteRepository.getId() ); - sb.append( " (" ); - sb.append( remoteRepository.getUrl() ); - - ArtifactRepositoryPolicy releases = remoteRepository.getReleases(); - if ( releases != null ) - { - sb.append( ", releases=" ).append( releases.isEnabled() ); - } - - ArtifactRepositoryPolicy snapshots = remoteRepository.getSnapshots(); - if ( snapshots != null ) - { - sb.append( ", snapshots=" ).append( snapshots.isEnabled() ); - } - - sb.append( ")" ); - if ( i.hasNext() ) - { - sb.append( "," ).append( LS ).append( " " ); - } - } + sb.append( constructArtifactPath( path, "" ) ); + sb.append( LS ); } - sb.append( constructArtifactPath( path, "" ) ); - sb.append( LS ); return sb.toString(); } diff --git a/maven-compat/src/main/java/org/apache/maven/repository/LocalRepositoryNotAccessibleException.java b/maven-compat/src/main/java/org/apache/maven/repository/LocalRepositoryNotAccessibleException.java new file mode 100644 index 0000000000..72c2311adc --- /dev/null +++ b/maven-compat/src/main/java/org/apache/maven/repository/LocalRepositoryNotAccessibleException.java @@ -0,0 +1,44 @@ +package org.apache.maven.repository; + +/* + * 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. + */ + +import java.io.IOException; + +/** + * Signals a failure to store files within the local repository. + * + * @author Benjamin Bentmann + */ +public class LocalRepositoryNotAccessibleException + extends IOException +{ + + public LocalRepositoryNotAccessibleException( String message, Throwable cause ) + { + super( message ); + initCause( cause ); + } + + public LocalRepositoryNotAccessibleException( String message ) + { + super( message ); + } + +} diff --git a/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultWagonManager.java b/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultWagonManager.java index c65e4b9858..f84a097a16 100644 --- a/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultWagonManager.java +++ b/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultWagonManager.java @@ -122,6 +122,8 @@ public class DefaultWagonManager public void getArtifact( Artifact artifact, List remoteRepositories, TransferListener downloadMonitor, boolean force ) throws TransferFailedException, ResourceDoesNotExistException { + TransferFailedException tfe = null; + for ( ArtifactRepository repository : remoteRepositories ) { try @@ -139,18 +141,29 @@ public class DefaultWagonManager // This one we will eat when looking through remote repositories // because we want to cycle through them all before squawking. - logger.debug( "Unable to find resource '" + artifact.getId() + "' in repository " + repository.getId() + " (" + repository.getUrl() + ")", e ); + logger.debug( "Unable to find resource '" + artifact.getId() + "' in repository " + repository.getId() + + " (" + repository.getUrl() + ")", e ); } catch ( TransferFailedException e ) { - logger.debug( "Unable to get resource '" + artifact.getId() + "' from repository " + repository.getId() + " (" + repository.getUrl() + ")", e ); + tfe = e; + + logger.debug( "Unable to get resource '" + artifact.getId() + "' from repository " + repository.getId() + + " (" + repository.getUrl() + ")", e ); } } // if it already exists locally we were just trying to force it - ignore the update if ( !artifact.getFile().exists() ) { - throw new ResourceDoesNotExistException( "Unable to download the artifact from any repository" ); + if ( tfe != null ) + { + throw tfe; + } + else + { + throw new ResourceDoesNotExistException( "Unable to download the artifact from any repository" ); + } } } 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 a00cf57247..12f3e5ef4b 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -29,9 +29,6 @@ import java.util.List; import java.util.Map; import org.apache.maven.artifact.ArtifactUtils; -import org.apache.maven.exception.DefaultExceptionHandler; -import org.apache.maven.exception.ExceptionHandler; -import org.apache.maven.exception.ExceptionSummary; import org.apache.maven.execution.DefaultLifecycleEvent; import org.apache.maven.execution.DefaultMavenExecutionResult; import org.apache.maven.execution.DuplicateProjectException; @@ -50,6 +47,7 @@ import org.apache.maven.project.ProjectBuildingException; import org.apache.maven.project.ProjectBuildingRequest; import org.apache.maven.project.ProjectBuildingResult; import org.apache.maven.repository.DelegatingLocalArtifactRepository; +import org.apache.maven.repository.LocalRepositoryNotAccessibleException; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; @@ -92,14 +90,18 @@ public class DefaultMaven public MavenExecutionResult execute( MavenExecutionRequest request ) { + MavenExecutionResult result; + try { - return doExecute( request ); + result = doExecute( request ); } catch ( OutOfMemoryError e ) { - return processResult( new DefaultMavenExecutionResult(), e ); + result = processResult( new DefaultMavenExecutionResult(), e ); } + + return result; } private MavenExecutionResult doExecute( MavenExecutionRequest request ) @@ -113,8 +115,18 @@ public class DefaultMaven request.setStartTime( new Date() ); MavenExecutionResult result = new DefaultMavenExecutionResult(); - - DelegatingLocalArtifactRepository delegatingLocalArtifactRepository = new DelegatingLocalArtifactRepository( request.getLocalRepository() ); + + try + { + validateLocalRepository( request ); + } + catch ( LocalRepositoryNotAccessibleException e ) + { + return processResult( result, e ); + } + + DelegatingLocalArtifactRepository delegatingLocalArtifactRepository = + new DelegatingLocalArtifactRepository( request.getLocalRepository() ); request.setLocalRepository( delegatingLocalArtifactRepository ); @@ -229,6 +241,18 @@ public class DefaultMaven return result; } + private void validateLocalRepository( MavenExecutionRequest request ) + throws LocalRepositoryNotAccessibleException + { + File localRepoDir = request.getLocalRepositoryPath(); + localRepoDir.mkdirs(); + + if ( !localRepoDir.isDirectory() ) + { + throw new LocalRepositoryNotAccessibleException( "Could not create local repository at " + localRepoDir ); + } + } + private Collection getLifecycleParticipants( Collection projects ) { Collection lifecycleListeners = @@ -279,17 +303,11 @@ public class DefaultMaven private MavenExecutionResult processResult( MavenExecutionResult result, Throwable e ) { - ExceptionHandler handler = new DefaultExceptionHandler(); - - ExceptionSummary es = handler.handleException( e ); - if ( !result.getExceptions().contains( e ) ) { result.addException( e ); } - - result.setExceptionSummary( es ); - + return result; } diff --git a/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java b/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java index 4dcb880683..ed8aa16d1d 100644 --- a/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java +++ b/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java @@ -19,16 +19,17 @@ package org.apache.maven.exception; * under the License. */ -import org.apache.maven.artifact.resolver.ArtifactNotFoundException; -import org.apache.maven.artifact.resolver.ArtifactResolutionException; -import org.apache.maven.plugin.CycleDetectedInPluginGraphException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.maven.model.building.ModelProblem; +import org.apache.maven.plugin.AbstractMojoExecutionException; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugin.MojoNotFoundException; -import org.apache.maven.plugin.PluginDescriptorParsingException; -import org.apache.maven.plugin.PluginNotFoundException; -import org.apache.maven.plugin.PluginResolutionException; -import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException; +import org.apache.maven.plugin.PluginExecutionException; +import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.ProjectBuildingResult; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.util.StringUtils; @@ -79,73 +80,162 @@ Plugins: public class DefaultExceptionHandler implements ExceptionHandler { + public ExceptionSummary handleException( Throwable exception ) { - String message; - - String reference = "http://"; - - // Plugin problems - if ( exception instanceof PluginNotFoundException ) - { - message = exception.getMessage(); - } - else if ( exception instanceof PluginResolutionException ) - { - message = exception.getMessage(); - } - else if ( exception instanceof PluginDescriptorParsingException ) - { - message = exception.getMessage(); - } - else if ( exception instanceof CycleDetectedInPluginGraphException ) - { - message = exception.getMessage(); - } - else if ( exception instanceof NoPluginFoundForPrefixException ) - { - message = exception.getMessage(); - } - - // Project dependency downloading problems. - else if ( exception instanceof ArtifactNotFoundException ) - { - message = exception.getMessage(); - } - else if ( exception instanceof ArtifactResolutionException ) - { - message = exception.getMessage(); - } - - // Mojo problems - else if ( exception instanceof MojoNotFoundException ) - { - message = exception.getMessage(); - } - else if ( exception instanceof MojoFailureException ) - { - message = ((MojoFailureException)exception).getLongMessage(); + return handle( "", exception ); + } - if ( StringUtils.isEmpty( message ) ) - { - message = exception.getMessage(); - } - } - else if ( exception instanceof MojoExecutionException ) - { - message = ((MojoExecutionException)exception).getLongMessage(); + private ExceptionSummary handle( String message, Throwable exception ) + { + String reference = getReference( exception ); - if ( StringUtils.isEmpty( message ) ) + List children = null; + + if ( exception instanceof ProjectBuildingException ) + { + List results = ( (ProjectBuildingException) exception ).getResults(); + + children = new ArrayList(); + + for ( ProjectBuildingResult result : results ) { - message = exception.getMessage(); + ExceptionSummary child = handle( result ); + if ( child != null ) + { + children.add( child ); + } } + + message = "The build could not read " + children.size() + " project" + ( children.size() == 1 ? "" : "s" ); } - else { - message = exception.getMessage(); - } - - return new ExceptionSummary( exception, message, reference ); + message = getMessage( message, exception ); + } + + return new ExceptionSummary( exception, message, reference, children ); } + + private ExceptionSummary handle( ProjectBuildingResult result ) + { + List children = new ArrayList(); + + for ( ModelProblem problem : result.getProblems() ) + { + ExceptionSummary child = handle( problem ); + if ( child != null ) + { + children.add( child ); + } + } + + if ( children.isEmpty() ) + { + return null; + } + + String message = + "The project " + result.getProjectId() + " (" + result.getPomFile() + ") has " + children.size() + " error" + + ( children.size() == 1 ? "" : "s" ); + + return new ExceptionSummary( null, message, null, children ); + } + + private ExceptionSummary handle( ModelProblem problem ) + { + if ( ModelProblem.Severity.ERROR.compareTo( problem.getSeverity() ) >= 0 ) + { + return handle( problem.getMessage(), problem.getException() ); + } + else + { + return null; + } + } + + private String getReference( Throwable exception ) + { + String reference = ""; + + if ( exception != null ) + { + if ( exception instanceof MojoExecutionException ) + { + reference = MojoExecutionException.class.getSimpleName(); + } + else if ( exception instanceof MojoFailureException ) + { + reference = MojoFailureException.class.getSimpleName(); + } + else if ( exception instanceof LinkageError ) + { + reference = LinkageError.class.getSimpleName(); + } + else if ( exception instanceof PluginExecutionException ) + { + reference = getReference( exception.getCause() ); + + if ( StringUtils.isEmpty( reference ) ) + { + reference = exception.getClass().getSimpleName(); + } + } + else if ( !( exception instanceof RuntimeException ) ) + { + reference = exception.getClass().getSimpleName(); + } + } + + if ( StringUtils.isNotEmpty( reference ) && !reference.startsWith( "http:" ) ) + { + reference = "http://cwiki.apache.org/confluence/display/MAVEN/" + reference; + } + + return reference; + } + + private String getMessage( String message, Throwable exception ) + { + String fullMessage = ( message != null ) ? message : ""; + + for ( Throwable t = exception; t != null; t = t.getCause() ) + { + String exceptionMessage = t.getMessage(); + + if ( t instanceof AbstractMojoExecutionException ) + { + String longMessage = ( (AbstractMojoExecutionException) t ).getLongMessage(); + if ( StringUtils.isNotEmpty( longMessage ) ) + { + exceptionMessage = longMessage; + } + } + + if ( t instanceof UnknownHostException && !fullMessage.contains( "host" ) ) + { + if ( fullMessage.length() > 0 ) + { + fullMessage += ": "; + } + fullMessage += "Unknown host " + exceptionMessage; + } + else if ( !fullMessage.contains( exceptionMessage ) ) + { + if ( fullMessage.length() > 0 ) + { + fullMessage += ": "; + } + fullMessage += exceptionMessage; + } + } + + if ( StringUtils.isEmpty( fullMessage ) && exception != null ) + { + fullMessage = exception.toString(); + } + + return fullMessage.trim(); + } + } diff --git a/maven-core/src/main/java/org/apache/maven/exception/ExceptionSummary.java b/maven-core/src/main/java/org/apache/maven/exception/ExceptionSummary.java index 1325e04366..048698ea28 100644 --- a/maven-core/src/main/java/org/apache/maven/exception/ExceptionSummary.java +++ b/maven-core/src/main/java/org/apache/maven/exception/ExceptionSummary.java @@ -19,6 +19,9 @@ package org.apache.maven.exception; * under the License. */ +import java.util.Collections; +import java.util.List; + // provide a // - the exception // - useful message @@ -28,17 +31,26 @@ package org.apache.maven.exception; public class ExceptionSummary { + private Throwable exception; - + private String message; - + private String reference; + private List children; + public ExceptionSummary( Throwable exception, String message, String reference ) + { + this( exception, message, reference, null ); + } + + public ExceptionSummary( Throwable exception, String message, String reference, List children ) { this.exception = exception; - this.message = message; - this.reference = reference; + this.message = ( message != null ) ? message : ""; + this.reference = ( reference != null ) ? reference : ""; + this.children = ( children != null ) ? children : Collections. emptyList(); } public Throwable getException() @@ -54,5 +66,11 @@ public class ExceptionSummary public String getReference() { return reference; - } + } + + public List getChildren() + { + return children; + } + } diff --git a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java index 3891636099..be98482d64 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java +++ b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java @@ -426,6 +426,11 @@ public class DefaultMavenExecutionRequest { this.localRepository = localRepository; + if ( localRepository != null ) + { + setLocalRepositoryPath( new File( localRepository.getBasedir() ).getAbsoluteFile() ); + } + return this; } diff --git a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionResult.java b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionResult.java index ccb8d6a4d8..24e2b0f18e 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionResult.java +++ b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionResult.java @@ -26,7 +26,6 @@ import java.util.List; import java.util.Map; import org.apache.maven.artifact.resolver.ArtifactResolutionResult; -import org.apache.maven.exception.ExceptionSummary; import org.apache.maven.project.MavenProject; /** @author Jason van Zyl */ @@ -41,8 +40,6 @@ public class DefaultMavenExecutionResult private List exceptions; - private ExceptionSummary exceptionSummary; - private Map buildSummaries; public MavenExecutionResult setProject( MavenProject project ) @@ -103,18 +100,6 @@ public class DefaultMavenExecutionResult return !getExceptions().isEmpty(); } - public MavenExecutionResult setExceptionSummary( ExceptionSummary exceptionSummary ) - { - this.exceptionSummary = exceptionSummary; - - return this; - } - - public ExceptionSummary getExceptionSummary() - { - return exceptionSummary; - } - public BuildSummary getBuildSummary( MavenProject project ) { return ( buildSummaries != null ) ? buildSummaries.get( project ) : null; diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionResult.java b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionResult.java index be725c991a..a431dfa9fe 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionResult.java +++ b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionResult.java @@ -49,9 +49,6 @@ public interface MavenExecutionResult MavenExecutionResult addException( Throwable e ); boolean hasExceptions(); - - MavenExecutionResult setExceptionSummary( ExceptionSummary exceptionSummary ); - ExceptionSummary getExceptionSummary(); /** * Gets the build summary for the specified project. diff --git a/maven-core/src/main/java/org/apache/maven/plugin/BuildPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/BuildPluginManager.java index 3fd0425e1e..6b61396097 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/BuildPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/BuildPluginManager.java @@ -36,7 +36,7 @@ public interface BuildPluginManager throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException; ClassRealm getPluginRealm( MavenSession session, PluginDescriptor pluginDescriptor ) - throws PluginManagerException; + throws PluginResolutionException, PluginManagerException; void executeMojo( MavenSession session, MojoExecution execution ) throws MojoFailureException, MojoExecutionException, PluginConfigurationException, PluginManagerException; diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java index ad4e0f8832..805d34d02f 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java @@ -19,7 +19,6 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; import org.apache.maven.artifact.repository.RepositoryRequest; -import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.descriptor.MojoDescriptor; @@ -75,7 +74,16 @@ public class DefaultBuildPluginManager Mojo mojo = null; - ClassRealm pluginRealm = getPluginRealm( session, mojoDescriptor.getPluginDescriptor() ); + ClassRealm pluginRealm; + try + { + pluginRealm = getPluginRealm( session, mojoDescriptor.getPluginDescriptor() ); + } + catch ( PluginResolutionException e ) + { + throw new PluginExecutionException( mojoExecution, project, e ); + } + ClassRealm oldLookupRealm = container.getLookupRealm(); ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); @@ -110,22 +118,36 @@ public class DefaultBuildPluginManager { throw new PluginExecutionException( mojoExecution, project, e ); } + catch ( NoClassDefFoundError e ) + { + ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); + PrintStream ps = new PrintStream( os ); + ps.println( "A required class was missing while executing " + mojoDescriptor.getId() + ": " + + e.getMessage() ); + pluginRealm.display( ps ); + + Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); + + throw new PluginExecutionException( mojoExecution, project, wrapper ); + } catch ( LinkageError e ) { ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); PrintStream ps = new PrintStream( os ); - ps.println( "A linkage error occured while executing " + mojoDescriptor.getId() ); - ps.println( e ); + ps.println( "An API incompatibility was encountered while executing " + mojoDescriptor.getId() + ": " + + e.getClass().getName() + ": " + e.getMessage() ); pluginRealm.display( ps ); - throw new PluginExecutionException( mojoExecution, project, os.toString(), e ); + Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); + + throw new PluginExecutionException( mojoExecution, project, wrapper ); } catch ( ClassCastException e ) { ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); PrintStream ps = new PrintStream( os ); - ps.println( "A type incompatibility occured while executing " + mojoDescriptor.getId() ); - ps.println( e ); + ps.println( "A type incompatibility occured while executing " + mojoDescriptor.getId() + ": " + + e.getMessage() ); pluginRealm.display( ps ); throw new PluginExecutionException( mojoExecution, project, os.toString(), e ); @@ -148,10 +170,10 @@ public class DefaultBuildPluginManager /** * TODO pluginDescriptor classRealm and artifacts are set as a side effect of this * call, which is not nice. - * @throws ArtifactResolutionException + * @throws PluginResolutionException */ public ClassRealm getPluginRealm( MavenSession session, PluginDescriptor pluginDescriptor ) - throws PluginManagerException + throws PluginResolutionException, PluginManagerException { ClassRealm pluginRealm = pluginDescriptor.getClassRealm(); if ( pluginRealm != null ) @@ -159,17 +181,8 @@ public class DefaultBuildPluginManager return pluginRealm; } - Plugin plugin = pluginDescriptor.getPlugin(); - - try - { - mavenPluginManager.setupPluginRealm( pluginDescriptor, session, - session.getCurrentProject().getClassRealm(), null ); - } - catch ( PluginResolutionException e ) - { - throw new PluginManagerException( plugin, e.getMessage(), e ); - } + mavenPluginManager.setupPluginRealm( pluginDescriptor, session, session.getCurrentProject().getClassRealm(), + null ); return pluginDescriptor.getClassRealm(); } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginManager.java index 8b8fc38eb8..51019c3766 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginManager.java @@ -74,7 +74,7 @@ public interface MavenPluginManager */ void setupPluginRealm( PluginDescriptor pluginDescriptor, MavenSession session, ClassLoader parent, List imports ) - throws PluginResolutionException, PluginManagerException; + throws PluginResolutionException, PluginContainerException; /** * Looks up the mojo for the specified mojo execution and populates its parameters from the configuration given by diff --git a/maven-core/src/main/java/org/apache/maven/plugin/PluginContainerException.java b/maven-core/src/main/java/org/apache/maven/plugin/PluginContainerException.java index 326d3507ae..f6122ee433 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/PluginContainerException.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/PluginContainerException.java @@ -42,6 +42,13 @@ public class PluginContainerException private ClassRealm pluginRealm; + public PluginContainerException( MojoDescriptor mojoDescriptor, ClassRealm pluginRealm, String message, Throwable e ) + { + super( mojoDescriptor, message, e ); + + this.pluginRealm = pluginRealm; + } + public PluginContainerException( MojoDescriptor mojoDescriptor, ClassRealm pluginRealm, String message, ComponentLookupException e ) { super( mojoDescriptor, message, e ); @@ -49,6 +56,13 @@ public class PluginContainerException this.pluginRealm = pluginRealm; } + public PluginContainerException( Plugin plugin, ClassRealm pluginRealm, String message, Throwable e ) + { + super( plugin, message, e ); + + this.pluginRealm = pluginRealm; + } + public PluginContainerException( Plugin plugin, ClassRealm pluginRealm, String message, PlexusConfigurationException e ) { super( plugin, message, e ); diff --git a/maven-core/src/main/java/org/apache/maven/plugin/PluginResolutionException.java b/maven-core/src/main/java/org/apache/maven/plugin/PluginResolutionException.java index 98b445bc53..b5e10da728 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/PluginResolutionException.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/PluginResolutionException.java @@ -36,8 +36,9 @@ public class PluginResolutionException public PluginResolutionException( Plugin plugin, ArtifactResolutionException e ) { - super( "Plugin or one of its dependencies could not be resolved: " + e.getMessage(), e.getGroupId(), - e.getArtifactId(), e.getVersion(), e.getType(), null, e.getRemoteRepositories(), null, e.getCause() ); + super( "Plugin " + plugin.getId() + " or one of its dependencies could not be resolved: " + e.getMessage(), + e.getGroupId(), e.getArtifactId(), e.getVersion(), e.getType(), null, e.getRemoteRepositories(), null, + e ); this.plugin = plugin; } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index 9ee241ef14..e407886925 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -20,10 +20,12 @@ package org.apache.maven.plugin.internal; */ import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.PrintStream; import java.io.Reader; import java.net.MalformedURLException; import java.util.ArrayList; @@ -63,7 +65,6 @@ import org.apache.maven.plugin.PluginConfigurationException; import org.apache.maven.plugin.PluginContainerException; import org.apache.maven.plugin.PluginDescriptorCache; import org.apache.maven.plugin.PluginDescriptorParsingException; -import org.apache.maven.plugin.PluginManagerException; import org.apache.maven.plugin.PluginParameterExpressionEvaluator; import org.apache.maven.plugin.PluginRealmCache; import org.apache.maven.plugin.PluginResolutionException; @@ -290,7 +291,7 @@ public class DefaultMavenPluginManager public synchronized void setupPluginRealm( PluginDescriptor pluginDescriptor, MavenSession session, ClassLoader parent, List imports ) - throws PluginResolutionException, PluginManagerException + throws PluginResolutionException, PluginContainerException { Plugin plugin = pluginDescriptor.getPlugin(); @@ -319,8 +320,8 @@ public class DefaultMavenPluginManager } private void createPluginRealm( PluginDescriptor pluginDescriptor, MavenSession session, ClassLoader parent, - List imports ) - throws PluginResolutionException, PluginManagerException + List imports ) + throws PluginResolutionException, PluginContainerException { Plugin plugin = pluginDescriptor.getPlugin(); @@ -401,13 +402,13 @@ public class DefaultMavenPluginManager } catch ( PlexusConfigurationException e ) { - throw new PluginManagerException( plugin, "Error in component graph of plugin " + plugin.getId() + ": " - + e.getMessage(), e ); + throw new PluginContainerException( plugin, pluginRealm, "Error in component graph of plugin " + + plugin.getId() + ": " + e.getMessage(), e ); } catch ( CycleDetectedInComponentGraphException e ) { - throw new PluginManagerException( plugin, "Error in component graph of plugin " + plugin.getId() + ": " - + e.getMessage(), e ); + throw new PluginContainerException( plugin, pluginRealm, "Error in component graph of plugin " + + plugin.getId() + ": " + e.getMessage(), e ); } } @@ -497,13 +498,28 @@ public class DefaultMavenPluginManager if ( ( cause instanceof NoClassDefFoundError ) || ( cause instanceof ClassNotFoundException ) ) { - throw new PluginContainerException( mojoDescriptor, pluginRealm, "Unable to load the mojo '" - + mojoDescriptor.getGoal() + "' in the plugin '" + pluginDescriptor.getId() - + "'. A required class is missing: " + cause.getMessage(), e ); + ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); + PrintStream ps = new PrintStream( os ); + ps.println( "Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '" + + pluginDescriptor.getId() + "'. A required class is missing: " + cause.getMessage() ); + pluginRealm.display( ps ); + + throw new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), cause ); + } + else if ( cause instanceof LinkageError ) + { + ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); + PrintStream ps = new PrintStream( os ); + ps.println( "Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '" + + pluginDescriptor.getId() + "' due to an API incompatibility: " + e.getClass().getName() + + ": " + cause.getMessage() ); + pluginRealm.display( ps ); + + throw new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), cause ); } - throw new PluginContainerException( mojoDescriptor, pluginRealm, "Unable to find the mojo '" - + mojoDescriptor.getGoal() + "' (or one of its required components) in the plugin '" + throw new PluginContainerException( mojoDescriptor, pluginRealm, "Unable to load the mojo '" + + mojoDescriptor.getGoal() + "' (or one of its required components) from the plugin '" + pluginDescriptor.getId() + "'", e ); } @@ -596,46 +612,23 @@ public class DefaultMavenPluginManager } catch ( NoClassDefFoundError e ) { - throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), - "A required class was missing during configuration of mojo " - + mojoDescriptor.getId() + ": " + e.getMessage(), e ); + ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); + PrintStream ps = new PrintStream( os ); + ps.println( "A required class was missing during configuration of mojo " + mojoDescriptor.getId() + ": " + + e.getMessage() ); + pluginRealm.display( ps ); + + throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), os.toString(), e ); } catch ( LinkageError e ) { - if ( logger.isFatalErrorEnabled() ) - { - logger.fatalError( configurator.getClass().getName() - + "#configureComponent(...) caused a linkage error (" + e.getClass().getName() - + ") and may be out-of-date. Check the realms:" ); + ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); + PrintStream ps = new PrintStream( os ); + ps.println( "An API incompatibility was encountered during configuration of mojo " + mojoDescriptor.getId() + + ": " + e.getClass().getName() + ": " + e.getMessage() ); + pluginRealm.display( ps ); - StringBuilder sb = new StringBuilder(); - sb.append( "Plugin realm = " + pluginRealm.getId() ).append( '\n' ); - for ( int i = 0; i < pluginRealm.getURLs().length; i++ ) - { - sb.append( "urls[" + i + "] = " + pluginRealm.getURLs()[i] ); - if ( i != ( pluginRealm.getURLs().length - 1 ) ) - { - sb.append( '\n' ); - } - } - logger.fatalError( sb.toString() ); - - ClassRealm containerRealm = container.getContainerRealm(); - sb = new StringBuilder(); - sb.append( "Container realm = " + containerRealm.getId() ).append( '\n' ); - for ( int i = 0; i < containerRealm.getURLs().length; i++ ) - { - sb.append( "urls[" + i + "] = " + containerRealm.getURLs()[i] ); - if ( i != ( containerRealm.getURLs().length - 1 ) ) - { - sb.append( '\n' ); - } - } - logger.fatalError( sb.toString() ); - } - - throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), e.getClass().getName() + ": " - + e.getMessage(), new ComponentConfigurationException( e ) ); + throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), os.toString(), e ); } finally { diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java b/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java index 6fadb20bf2..91078a63e2 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java @@ -118,11 +118,11 @@ class DefaultModelBuildingListener } catch ( PluginResolutionException e ) { - event.getProblems().addError( "Unresolveable build extensions: " + e.getMessage(), e ); + event.getProblems().addError( "Unresolveable build extension: " + e.getMessage(), e ); } catch ( PluginVersionResolutionException e ) { - event.getProblems().addError( "Unresolveable build extensions: " + e.getMessage(), e ); + event.getProblems().addError( "Unresolveable build extension: " + e.getMessage(), e ); } if ( project.getClassRealm() != null ) diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java index 66493e9815..ba619c1017 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java @@ -21,7 +21,9 @@ import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import java.util.Map.Entry; @@ -29,6 +31,8 @@ import java.util.Map.Entry; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.ParseException; import org.apache.maven.Maven; +import org.apache.maven.exception.DefaultExceptionHandler; +import org.apache.maven.exception.ExceptionHandler; import org.apache.maven.exception.ExceptionSummary; import org.apache.maven.execution.DefaultMavenExecutionRequest; import org.apache.maven.execution.DefaultMavenExecutionResult; @@ -37,7 +41,6 @@ import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenExecutionRequestPopulator; import org.apache.maven.execution.MavenExecutionResult; import org.apache.maven.model.building.ModelProcessor; -import org.apache.maven.model.locator.ModelLocator; import org.apache.maven.repository.ArtifactTransferListener; import org.apache.maven.settings.Settings; import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; @@ -453,52 +456,7 @@ public class MavenCli try { - if ( result.hasExceptions() ) - { - ExceptionSummary es = result.getExceptionSummary(); - - if ( es == null ) - { - logger.error( "", result.getExceptions().get( 0 ) ); - } - else - { - if ( showErrors ) - { - logger.error( es.getMessage(), es.getException() ); - } - else - { - logger.error( es.getMessage() ); - logger.error( "To see the full stack trace of the error, re-run Maven with the -e switch." ); - } - - logger.error( "Re-run Maven using the -X switch to enable full debug logging." ); - - if ( StringUtils.isNotEmpty( es.getReference() ) ) - { - logger.error( "" ); - logger.error( "For more information about the error and possible solutions" - + ", please try the following article:" ); - logger.error( " " + es.getReference() ); - } - } - - if ( MavenExecutionRequest.REACTOR_FAIL_NEVER.equals( request.getReactorFailureBehavior() ) ) - { - logger.info( "Build failures were ignored." ); - - return 0; - } - else - { - return 1; - } - } - else - { - return 0; - } + return processResult( request, result, showErrors ); } finally { @@ -509,6 +467,92 @@ public class MavenCli } } + private int processResult( MavenExecutionRequest request, MavenExecutionResult result, boolean showErrors ) + { + if ( result.hasExceptions() ) + { + ExceptionHandler handler = new DefaultExceptionHandler(); + + Map references = new LinkedHashMap(); + + for ( Throwable exception : result.getExceptions() ) + { + ExceptionSummary summary = handler.handleException( exception ); + + logSummary( summary, references, "", showErrors ); + } + + logger.error( "" ); + + if ( !showErrors ) + { + logger.error( "To see the full stack trace of the errors, re-run Maven with the -e switch." ); + } + if ( !logger.isDebugEnabled() ) + { + logger.error( "Re-run Maven using the -X switch to enable full debug logging." ); + } + + if ( !references.isEmpty() ) + { + logger.error( "" ); + logger.error( "For more information about the errors and possible solutions" + + ", please read the following articles:" ); + + for ( Map.Entry entry : references.entrySet() ) + { + logger.error( entry.getValue() + " " + entry.getKey() ); + } + } + + if ( MavenExecutionRequest.REACTOR_FAIL_NEVER.equals( request.getReactorFailureBehavior() ) ) + { + logger.info( "Build failures were ignored." ); + + return 0; + } + else + { + return 1; + } + } + else + { + return 0; + } + } + + private void logSummary( ExceptionSummary summary, Map references, String indent, boolean showErrors ) + { + String referenceKey = ""; + + if ( StringUtils.isNotEmpty( summary.getReference() ) ) + { + referenceKey = references.get( summary.getReference() ); + if ( referenceKey == null ) + { + referenceKey = "[" + references.size() + "]"; + references.put( summary.getReference(), referenceKey ); + } + } + + if ( showErrors ) + { + logger.error( indent + referenceKey, summary.getException() ); + } + else + { + logger.error( indent + summary.getMessage() + " " + referenceKey ); + } + + indent += " "; + + for ( ExceptionSummary child : summary.getChildren() ) + { + logSummary( child, references, indent, showErrors ); + } + } + protected ModelProcessor createModelProcessor( PlexusContainer container ) throws ComponentLookupException {