[MNG-4936] Allow to better monitor and adjust a Maven build during CI

git-svn-id: https://svn.apache.org/repos/asf/maven/maven-3/trunk@1050096 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Benjamin Bentmann 2010-12-16 18:58:54 +00:00
parent 625c0faa8e
commit 887c5b82b5
14 changed files with 762 additions and 7 deletions

View File

@ -0,0 +1,39 @@
package org.apache.maven;
/*
* 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.
*/
/**
* A special throwable used to signal a graceful abort of the build.
*/
public class BuildAbort
extends Error
{
public BuildAbort( String message )
{
super( message );
}
public BuildAbort( String message, Throwable cause )
{
super( message, cause );
}
}

View File

@ -33,6 +33,7 @@ import java.util.Properties;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
import org.apache.maven.execution.DefaultMavenExecutionResult;
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.execution.MavenExecutionRequest;
@ -143,6 +144,9 @@ public class DefaultMaven
@Requirement
private LegacySupport legacySupport;
@Requirement
private EventSpyDispatcher eventSpyDispatcher;
public MavenExecutionResult execute( MavenExecutionRequest request )
{
MavenExecutionResult result;
@ -437,7 +441,7 @@ public class DefaultMaven
session.setTransferListener( request.getTransferListener() );
session.setRepositoryListener( new LoggingRepositoryListener( logger ) );
session.setRepositoryListener( eventSpyDispatcher.chainListener( new LoggingRepositoryListener( logger ) ) );
session.setUserProps( request.getUserProperties() );
session.setSystemProps( request.getSystemProperties() );
@ -564,7 +568,7 @@ public class DefaultMaven
//
if ( request.getPom() == null )
{
ModelSource modelSource = new UrlModelSource( getClass().getResource( "project/standalone.xml" ) );
ModelSource modelSource = new UrlModelSource( DefaultMaven.class.getResource( "project/standalone.xml" ) );
MavenProject project =
projectBuilder.build( modelSource, request.getProjectBuildingRequest() ).getProject();
project.setExecutionRoot( true );

View File

@ -0,0 +1,44 @@
package org.apache.maven.eventspy;
/*
* 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.
*/
/**
* A skeleton eventspy that does nothing other than helping implementors.
*/
public abstract class AbstractEventSpy
implements EventSpy
{
public void init( Context context )
throws Exception
{
}
public void onEvent( Object event )
throws Exception
{
}
public void close()
throws Exception
{
}
}

View File

@ -0,0 +1,50 @@
package org.apache.maven.eventspy;
/*
* 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.util.Map;
/**
* A core extension to monitor Maven's execution. Typically, such an extension gets loaded into Maven by specifying the
* system property {@code maven.ext.class.path} on the command line. As soon as dependency injection is setup, Maven
* looks up all implementators of this interface and calls their {@link #init(Context)} method. <em>Note:</em>
* Implementors are strongly advised to inherit from {@link AbstractEventSpy} instead of directly implementing this
* interface.
*/
public interface EventSpy
{
interface Context
{
Map<String, Object> getData();
}
void init( Context context )
throws Exception;
void onEvent( Object event )
throws Exception;
void close()
throws Exception;
}

View File

@ -0,0 +1,155 @@
package org.apache.maven.eventspy.internal;
/*
* 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.util.ArrayList;
import java.util.List;
import org.apache.maven.eventspy.EventSpy;
import org.apache.maven.execution.ExecutionListener;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.sonatype.aether.RepositoryListener;
/**
* Dispatches callbacks to all registered eventspies.
*/
@Component( role = EventSpyDispatcher.class )
public class EventSpyDispatcher
{
@Requirement
private Logger logger;
@Requirement( role = EventSpy.class )
private List<EventSpy> eventSpies;
public void setEventSpies( List<EventSpy> eventSpies )
{
// make copy to get rid of needless overhead for dynamic lookups
this.eventSpies = new ArrayList<EventSpy>( eventSpies );
}
public List<EventSpy> getEventSpies()
{
return eventSpies;
}
public ExecutionListener chainListener( ExecutionListener listener )
{
if ( eventSpies.isEmpty() )
{
return listener;
}
return new EventSpyExecutionListener( this, listener );
}
public RepositoryListener chainListener( RepositoryListener listener )
{
if ( eventSpies.isEmpty() )
{
return listener;
}
return new EventSpyRepositoryListener( this, listener );
}
public void init( EventSpy.Context context )
{
if ( eventSpies.isEmpty() )
{
return;
}
for ( EventSpy eventSpy : eventSpies )
{
try
{
eventSpy.init( context );
}
catch ( Exception e )
{
String msg = "Failed to initialize spy " + eventSpy.getClass().getName() + ": " + e.getMessage();
if ( logger.isDebugEnabled() )
{
logger.warn( msg, e );
}
else
{
logger.warn( msg );
}
}
}
}
public void onEvent( Object event )
{
if ( eventSpies.isEmpty() )
{
return;
}
for ( EventSpy eventSpy : eventSpies )
{
try
{
eventSpy.onEvent( event );
}
catch ( Exception e )
{
String msg = "Failed to forward event to spy " + eventSpy.getClass().getName() + ": " + e.getMessage();
if ( logger.isDebugEnabled() )
{
logger.warn( msg, e );
}
else
{
logger.warn( msg );
}
}
}
}
public void close()
{
if ( eventSpies.isEmpty() )
{
return;
}
for ( EventSpy eventSpy : eventSpies )
{
try
{
eventSpy.close();
}
catch ( Exception e )
{
String msg = "Failed to close spy " + eventSpy.getClass().getName() + ": " + e.getMessage();
if ( logger.isDebugEnabled() )
{
logger.warn( msg, e );
}
else
{
logger.warn( msg );
}
}
}
}
}

View File

@ -0,0 +1,162 @@
package org.apache.maven.eventspy.internal;
/*
* 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 org.apache.maven.execution.AbstractExecutionListener;
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.execution.ExecutionListener;
/**
* Forwards execution events to eventspies.
*/
class EventSpyExecutionListener
extends AbstractExecutionListener
{
private final EventSpyDispatcher dispatcher;
private final ExecutionListener delegate;
public EventSpyExecutionListener( EventSpyDispatcher dispatcher, ExecutionListener delegate )
{
this.dispatcher = dispatcher;
this.delegate = delegate;
}
@Override
public void projectDiscoveryStarted( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.projectDiscoveryStarted( event );
}
@Override
public void sessionStarted( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.sessionStarted( event );
}
@Override
public void sessionEnded( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.sessionEnded( event );
}
@Override
public void projectSkipped( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.projectSkipped( event );
}
@Override
public void projectStarted( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.projectStarted( event );
}
@Override
public void projectSucceeded( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.projectSucceeded( event );
}
@Override
public void projectFailed( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.projectFailed( event );
}
@Override
public void forkStarted( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.forkStarted( event );
}
@Override
public void forkSucceeded( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.forkSucceeded( event );
}
@Override
public void forkFailed( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.forkFailed( event );
}
@Override
public void mojoSkipped( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.mojoSkipped( event );
}
@Override
public void mojoStarted( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.mojoStarted( event );
}
@Override
public void mojoSucceeded( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.mojoSucceeded( event );
}
@Override
public void mojoFailed( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.mojoFailed( event );
}
@Override
public void forkedProjectStarted( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.forkedProjectStarted( event );
}
@Override
public void forkedProjectSucceeded( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.forkedProjectSucceeded( event );
}
@Override
public void forkedProjectFailed( ExecutionEvent event )
{
dispatcher.onEvent( event );
delegate.forkedProjectFailed( event );
}
}

View File

@ -0,0 +1,175 @@
package org.apache.maven.eventspy.internal;
/*
* 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 org.sonatype.aether.AbstractRepositoryListener;
import org.sonatype.aether.RepositoryEvent;
import org.sonatype.aether.RepositoryListener;
/**
* Forwards repository events to eventspies.
*/
class EventSpyRepositoryListener
extends AbstractRepositoryListener
{
private final EventSpyDispatcher dispatcher;
private final RepositoryListener delegate;
public EventSpyRepositoryListener( EventSpyDispatcher dispatcher, RepositoryListener delegate )
{
this.dispatcher = dispatcher;
this.delegate = delegate;
}
@Override
public void artifactDeployed( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactDeployed( event );
}
@Override
public void artifactDeploying( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactDeploying( event );
}
@Override
public void artifactDescriptorInvalid( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactDescriptorInvalid( event );
}
@Override
public void artifactDescriptorMissing( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactDescriptorMissing( event );
}
@Override
public void artifactInstalled( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactInstalled( event );
}
@Override
public void artifactInstalling( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactInstalling( event );
}
@Override
public void artifactResolved( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactResolved( event );
}
@Override
public void artifactResolving( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactResolving( event );
}
@Override
public void metadataDeployed( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.metadataDeployed( event );
}
@Override
public void metadataDeploying( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.metadataDeploying( event );
}
@Override
public void metadataInstalled( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.metadataInstalled( event );
}
@Override
public void metadataInstalling( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.metadataInstalling( event );
}
@Override
public void metadataInvalid( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.metadataInvalid( event );
}
@Override
public void metadataResolved( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.metadataResolved( event );
}
@Override
public void metadataResolving( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.metadataResolving( event );
}
@Override
public void artifactDownloaded( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactDownloaded( event );
}
@Override
public void artifactDownloading( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.artifactDownloading( event );
}
@Override
public void metadataDownloaded( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.metadataDownloaded( event );
}
@Override
public void metadataDownloading( RepositoryEvent event )
{
dispatcher.onEvent( event );
delegate.metadataDownloading( event );
}
}

View File

@ -29,7 +29,7 @@ import org.sonatype.aether.transfer.TransferCancelledException;
import org.sonatype.aether.transfer.TransferEvent;
import org.sonatype.aether.transfer.TransferResource;
abstract class AbstractMavenTransferListener
public abstract class AbstractMavenTransferListener
extends AbstractTransferListener
{

View File

@ -21,7 +21,7 @@ package org.apache.maven.cli;
import java.io.PrintStream;
class BatchModeMavenTransferListener
public class BatchModeMavenTransferListener
extends AbstractMavenTransferListener
{
public BatchModeMavenTransferListener( PrintStream out )

View File

@ -32,7 +32,7 @@ import org.sonatype.aether.transfer.TransferResource;
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
class ConsoleMavenTransferListener
public class ConsoleMavenTransferListener
extends AbstractMavenTransferListener
{

View File

@ -0,0 +1,38 @@
package org.apache.maven.cli;
/*
* 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.util.HashMap;
import java.util.Map;
import org.apache.maven.eventspy.EventSpy;
public class DefaultEventSpyContext
implements EventSpy.Context
{
private final Map<String, Object> data = new HashMap<String, Object>();
public Map<String, Object> getData()
{
return data;
}
}

View File

@ -40,7 +40,7 @@ import org.codehaus.plexus.logging.Logger;
*
* @author Benjamin Bentmann
*/
class ExecutionEventLogger
public class ExecutionEventLogger
extends AbstractExecutionListener
{
private final Logger logger;

View File

@ -33,8 +33,10 @@ import java.util.StringTokenizer;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.UnrecognizedOptionException;
import org.apache.maven.BuildAbort;
import org.apache.maven.InternalErrorException;
import org.apache.maven.Maven;
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
import org.apache.maven.exception.DefaultExceptionHandler;
import org.apache.maven.exception.ExceptionHandler;
import org.apache.maven.exception.ExceptionSummary;
@ -59,6 +61,7 @@ import org.codehaus.plexus.DefaultContainerConfiguration;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.StringUtils;
@ -92,6 +95,8 @@ public class MavenCli
public static final File DEFAULT_USER_TOOLCHAINS_FILE = new File( userMavenConfigurationHome, "toolchains.xml" );
private static final String EXT_CLASS_PATH = "maven.ext.class.path";
private ClassWorld classWorld;
// Per-instance container supports fast embedded execution of core ITs
@ -99,6 +104,8 @@ public class MavenCli
private Logger logger;
private EventSpyDispatcher eventSpyDispatcher;
private ModelProcessor modelProcessor;
private Maven maven;
@ -196,6 +203,12 @@ public class MavenCli
// pure user error, suppress stack trace
return 1;
}
catch ( BuildAbort e )
{
CLIReportingUtils.showError( logger, "ABORTED", e, cliRequest.showErrors );
return 2;
}
catch ( Exception e )
{
CLIReportingUtils.showError( logger, "Error executing Maven.", e, cliRequest.showErrors );
@ -352,6 +365,7 @@ public class MavenCli
ContainerConfiguration cc = new DefaultContainerConfiguration()
.setClassWorld( cliRequest.classWorld )
.setRealm( setupContainerRealm( cliRequest ) )
.setName( "maven" );
container = new DefaultPlexusContainer( cc );
@ -368,6 +382,22 @@ public class MavenCli
container.getLoggerManager().setThresholds( cliRequest.request.getLoggingLevel() );
Thread.currentThread().setContextClassLoader( container.getContainerRealm() );
eventSpyDispatcher = container.lookup( EventSpyDispatcher.class );
DefaultEventSpyContext eventSpyContext = new DefaultEventSpyContext();
Map<String, Object> data = eventSpyContext.getData();
data.put( "plexus", container );
data.put( "workingDirectory", cliRequest.workingDirectory );
data.put( "systemProperties", cliRequest.systemProperties );
data.put( "userProperties", cliRequest.userProperties );
data.put( "versionProperties", CLIReportingUtils.getBuildProperties() );
eventSpyDispatcher.init( eventSpyContext );
// refresh logger in case container got customized by spy
logger = container.getLoggerManager().getLoggerForComponent( MavenCli.class.getName(), null );
maven = container.lookup( Maven.class );
executionRequestPopulator = container.lookup( MavenExecutionRequestPopulator.class );
@ -389,9 +419,56 @@ public class MavenCli
}
} );
logger.setThreshold( cliRequest.request.getLoggingLevel() );
return logger;
}
private ClassRealm setupContainerRealm( CliRequest cliRequest )
throws Exception
{
ClassRealm containerRealm = null;
String extClassPath = cliRequest.userProperties.getProperty( EXT_CLASS_PATH );
if ( extClassPath == null )
{
extClassPath = cliRequest.systemProperties.getProperty( EXT_CLASS_PATH );
}
if ( StringUtils.isNotEmpty( extClassPath ) )
{
String[] jars = StringUtils.split( extClassPath, File.pathSeparator );
if ( jars.length > 0 )
{
ClassRealm coreRealm = cliRequest.classWorld.getClassRealm( "plexus.core" );
if ( coreRealm == null )
{
coreRealm = (ClassRealm) cliRequest.classWorld.getRealms().iterator().next();
}
ClassRealm extRealm = cliRequest.classWorld.newRealm( "maven.ext", null );
logger.debug( "Populating class realm " + extRealm.getId() );
for ( String jar : jars )
{
File file = resolveFile( new File( jar ), cliRequest.workingDirectory );
logger.debug( " Included " + file );
extRealm.addURL( file.toURI().toURL() );
}
extRealm.setParentRealm( coreRealm );
containerRealm = extRealm;
}
}
return containerRealm;
}
protected void customizeContainer( PlexusContainer container )
{
}
@ -448,8 +525,14 @@ public class MavenCli
private int execute( CliRequest cliRequest )
{
eventSpyDispatcher.onEvent( cliRequest.request );
MavenExecutionResult result = maven.execute( cliRequest.request );
eventSpyDispatcher.onEvent( result );
eventSpyDispatcher.close();
if ( result.hasExceptions() )
{
ExceptionHandler handler = new DefaultExceptionHandler();
@ -625,6 +708,8 @@ public class MavenCli
settingsRequest.setSystemProperties( cliRequest.systemProperties );
settingsRequest.setUserProperties( cliRequest.userProperties );
eventSpyDispatcher.onEvent( settingsRequest );
logger.debug( "Reading global settings from "
+ getSettingsLocation( settingsRequest.getGlobalSettingsSource(), settingsRequest.getGlobalSettingsFile() ) );
logger.debug( "Reading user settings from "
@ -632,6 +717,8 @@ public class MavenCli
SettingsBuildingResult settingsResult = settingsBuilder.build( settingsRequest );
eventSpyDispatcher.onEvent( settingsResult );
executionRequestPopulator.populateFromSettings( cliRequest.request, settingsResult.getEffectiveSettings() );
if ( !settingsResult.getProblems().isEmpty() && logger.isWarnEnabled() )
@ -800,6 +887,7 @@ public class MavenCli
}
ExecutionListener executionListener = new ExecutionEventLogger( logger );
executionListener = eventSpyDispatcher.chainListener( executionListener );
String alternatePomFile = null;
if ( commandLine.hasOption( CLIManager.ALTERNATE_POM_FILE ) )

View File

@ -24,7 +24,7 @@ import org.sonatype.aether.transfer.AbstractTransferListener;
/**
* @author Benjamin Bentmann
*/
class QuietMavenTransferListener
public class QuietMavenTransferListener
extends AbstractTransferListener
{