Working on issue: MNG-379

Added specified stop-gap patch for issue: MNG-473 (affects settings-builder and registry-builder)

Today I've made the following progress on this so far:

- Added a new project, called maven-plugin-registry, to house the model for this new file.

- Developed/debugged/tested PluginVersionManager/DefaultPluginVersionManager to isolate the plugin-version checks/management code away from the PluginManager

- Added interactiveMode (<interactiveMode>true|false</interactiveMode> directly under the root element of settings.xml, or -B short CLI option or --batch-mode CLI option, where the CLI options turn OFF interactiveMode). This will allow things like the maven-plugins build to register new plugins (and, for now, new versions of plugins) automatically.

- Added user input handler for when interactiveMode = true, to get a yes/no on whether to use the discovered version over the installed version and/or no version at all. If there is no installed version, and the user selects 'n', then the discovered version is used FOR THAT SESSION ONLY, and won't be recorded in the registry.

- Added checks/recording rejected versions against the registry, before attempting to use the discovered version.

Pending:

- Still need to add update-policies, to determine two things:

  1. how often to check for updates
  2. what to do when updates are found (autoUpdate, etc.)



git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@190854 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
John Dennis Casey 2005-06-16 01:50:28 +00:00
parent d15513bd60
commit b813c3d430
29 changed files with 1289 additions and 187 deletions

View File

@ -115,7 +115,7 @@ cd ..
echo Rebuilding maven2 plugins
cd maven-plugins
call m2 -DupdateReleaseInfo=true -e %MAVEN_CMD_LINE_ARGS% clean:clean install
call m2 --batch-mode -DupdateReleaseInfo=true -e %MAVEN_CMD_LINE_ARGS% clean:clean install
cd ..
echo Running integration tests

View File

@ -51,7 +51,7 @@ ret=$?; if [ $ret != 0 ]; then exit $ret; fi
cd maven-plugins
# update the release info to ensure these versions get used in the integration tests
m2 -DupdateReleaseInfo=true -e $ARGS clean:clean install
m2 --batch-mode -DupdateReleaseInfo=true -e $ARGS clean:clean install
ret=$?; if [ $ret != 0 ]; then exit $ret; fi
)
ret=$?; if [ $ret != 0 ]; then exit $ret; fi
@ -61,7 +61,7 @@ ret=$?; if [ $ret != 0 ]; then exit $ret; fi
echo
echo "Running maven-core integration tests ..."
echo
./maven-core-it.sh "$HOME_ARGS" $ARGS
./maven-core-it.sh --batch-mode "$HOME_ARGS" $ARGS
ret=$?; if [ $ret != 0 ]; then exit $ret; fi
)
ret=$?; if [ $ret != 0 ]; then exit $ret; fi

View File

@ -23,6 +23,8 @@ package org.apache.maven.artifact.handler;
public class PluginHandler
extends AbstractArtifactHandler
{
public static final String PLUGIN_TYPE = "maven-plugin";
public String directory()
{

View File

@ -464,6 +464,8 @@ public class Verifier
cli.setExecutable( executable );
cli.createArgument().setValue( "-e" );
cli.createArgument().setValue( "--batch-mode" );
for ( Iterator i = properties.keySet().iterator(); i.hasNext(); )
{

View File

@ -85,6 +85,17 @@ it0026: Test merging of global- and user-level settings.xml files.
-------------------------------------------------------------------------------
==============================
NOTE: About it0023 and it0026
==============================
I am disabling these for now, because they depend on locally-supplied settings
files, and need to know the location of the local repository where the plugin
builds were deposited in order to work. This is why they will result in
ArtifactResolutionException's...they literally cannot find the plugins in the
local repository, because they wind up using the default local repository.
=============================
- generated sources
- generated resources from sources
- generated resources from generated sources

View File

@ -21,7 +21,7 @@ it0019
it0020
it0021
it0022
it0023
#it0023
it0024
it0025
it0026
#it0026

View File

@ -34,6 +34,11 @@
<artifactId>maven-settings</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-registry</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-profile</artifactId>
@ -81,6 +86,13 @@
<version>1.0-alpha-3</version>
<scope>runtime</scope>
</dependency>
<!-- used to prompt the user to add plugin versions to the plugin-registry. -->
<dependency>
<groupId>plexus</groupId>
<artifactId>plexus-input-handler</artifactId>
<version>1.0-alpha-2</version>
</dependency>
</dependencies>
<reports>
<plugins>

View File

@ -188,6 +188,11 @@ public class MavenCli
showFatalError( "Unable to read settings.xml", e, showErrors );
return 1;
}
if ( commandLine.hasOption( CLIManager.BATCH_MODE ) )
{
settings.setInteractiveMode( false );
}
List projectFiles = null;
try
@ -463,6 +468,8 @@ public class MavenCli
static class CLIManager
{
public static final char BATCH_MODE = 'B';
public static final char SET_SYSTEM_PROPERTY = 'D';
public static final char OFFLINE = 'o';
@ -513,6 +520,7 @@ public class MavenCli
"Update all snapshots regardless of repository policies" ).create( UPDATE_SNAPSHOTS ) );
options.addOption( OptionBuilder.withLongOpt( "activate-profiles" ).withDescription(
"Comma-delimited list of profiles to activate").hasArg().create( ACTIVATE_PROFILES ) );
options.addOption( OptionBuilder.withLongOpt( "batch-mode" ).withDescription( "Run in non-interactive (batch) mode" ).create( BATCH_MODE ) );
}
public CommandLine parse( String[] args )

View File

@ -31,6 +31,7 @@ import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.injection.ModelDefaultsInjector;
import org.apache.maven.settings.Settings;
@ -195,7 +196,7 @@ public class DefaultLifecycleExecutor
for ( Iterator instanceIterator = instances.iterator(); instanceIterator.hasNext(); )
{
GoalInstance instance = (GoalInstance) instanceIterator.next();
String executePhase = mojoDescriptor.getExecutePhase();
if ( executePhase != null )
@ -241,7 +242,7 @@ public class DefaultLifecycleExecutor
if ( idx > -1 )
{
GoalInstance cached = (GoalInstance) instances.get( idx );
cached.incorporate( goalInstance );
}
else
@ -310,12 +311,16 @@ public class DefaultLifecycleExecutor
try
{
pluginDescriptor = pluginManager.verifyPlugin( groupId, artifactId, version, session.getProject(), session
.getLocalRepository() );
.getLocalRepository(), session.getSettings().isInteractiveMode() );
}
catch ( PluginManagerException e )
{
throw new LifecycleExecutionException( "Internal error in the plugin manager", e );
}
catch ( PluginVersionResolutionException e )
{
throw new LifecycleExecutionException( "Error resolving plugin version", e );
}
if ( plugin.isInheritanceApplied() || pluginDescriptor.isInheritedByDefault() )
{
@ -574,12 +579,17 @@ public class DefaultLifecycleExecutor
injectHandlerPluginConfiguration( session.getProject(), groupId, artifactId, version );
pluginDescriptor = pluginManager.verifyPlugin( groupId, artifactId, version, session.getProject(),
session.getLocalRepository() );
session.getLocalRepository(), session.getSettings()
.isInteractiveMode() );
}
catch ( PluginManagerException e )
{
throw new LifecycleExecutionException( "Internal error in the plugin manager", e );
}
catch ( PluginVersionResolutionException e )
{
throw new LifecycleExecutionException( "Error resolving plugin version", e );
}
}
else
{

View File

@ -26,9 +26,7 @@ import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter;
import org.apache.maven.artifact.resolver.filter.InversionArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.artifact.transform.ReleaseArtifactTransformation;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Plugin;
import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.monitor.event.MavenEvents;
import org.apache.maven.monitor.logging.DefaultLog;
@ -37,6 +35,8 @@ import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugin.version.PluginVersionManager;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.artifact.MavenMetadataSource;
@ -177,54 +177,33 @@ public class DefaultPluginManager
}
public PluginDescriptor verifyPlugin( String groupId, String artifactId, String version, MavenProject project,
ArtifactRepository localRepository )
throws ArtifactResolutionException, PluginManagerException
ArtifactRepository localRepository, boolean interactiveMode )
throws ArtifactResolutionException, PluginManagerException, PluginVersionResolutionException
{
String pluginKey = groupId + ":" + artifactId;
// TODO: this should be possibly outside
// [HTTP-301] All version-resolution logic has been moved to DefaultPluginVersionManager. :)
if ( version == null )
{
Plugin pluginConfig = null;
PluginVersionManager pluginVersionManager = null;
for ( Iterator it = project.getBuildPlugins().iterator(); it.hasNext(); )
try
{
Plugin plugin = (Plugin) it.next();
pluginVersionManager = (PluginVersionManager) container.lookup( PluginVersionManager.ROLE );
if ( groupId.equals( plugin.getGroupId() ) && artifactId.equals( plugin.getArtifactId() ) )
{
pluginConfig = plugin;
break;
}
version = pluginVersionManager.resolvePluginVersion( groupId, artifactId, project, localRepository,
interactiveMode );
}
if ( project.getReports() != null )
catch ( ComponentLookupException e )
{
for ( Iterator it = project.getReports().getPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
if ( groupId.equals( plugin.getGroupId() ) && artifactId.equals( plugin.getArtifactId() ) )
{
pluginConfig = plugin;
break;
}
}
throw new PluginVersionResolutionException( groupId, artifactId,
"Cannot retrieve an instance of the PluginVersionManager",
e );
}
if ( pluginConfig != null )
finally
{
if ( StringUtils.isEmpty( pluginConfig.getVersion() ) )
{
version = ReleaseArtifactTransformation.RELEASE_VERSION;
}
else
{
version = pluginConfig.getVersion();
}
releaseComponent( pluginVersionManager );
}
}
@ -249,8 +228,9 @@ public class DefaultPluginManager
}
catch ( ArtifactResolutionException e )
{
if ( groupId.equals( e.getGroupId() ) && artifactId.equals( e.getArtifactId() )
&& version.equals( e.getVersion() ) && "maven-plugin".equals( e.getType() ) )
if ( ( groupId == null || artifactId == null || version == null || ( groupId.equals( e.getGroupId() )
&& artifactId.equals( e.getArtifactId() ) && version.equals( e.getVersion() ) ) )
&& "maven-plugin".equals( e.getType() ) )
{
throw new PluginNotFoundException( e );
}
@ -299,7 +279,7 @@ public class DefaultPluginManager
}
container.createChildContainer( pluginKey, files, Collections.EMPTY_MAP, Collections.singletonList( this ) );
// this plugin's descriptor should have been discovered by now, so we should be able to circle
// around and set the artifacts.
PluginDescriptor addedPlugin = (PluginDescriptor) pluginDescriptors.get( pluginKey );
@ -436,7 +416,7 @@ public class DefaultPluginManager
pluginDescriptor,
pathTranslator,
getLogger() );
checkRequiredParameters( mojoDescriptor, mergedConfiguration, expressionEvaluator, plugin );
populatePluginFields( plugin, mojoDescriptor, mergedConfiguration, pluginContainer, expressionEvaluator );
@ -445,9 +425,9 @@ public class DefaultPluginManager
// Event monitoring.
String event = MavenEvents.MOJO_EXECUTION;
EventDispatcher dispatcher = session.getEventDispatcher();
String goalExecId = goalName;
if ( goalInstance.getExecutionId() != null )
{
goalExecId += " {execution: " + goalInstance.getExecutionId() + "}";
@ -463,7 +443,7 @@ public class DefaultPluginManager
catch ( MojoExecutionException e )
{
session.getEventDispatcher().dispatchError( event, goalExecId, e );
throw e;
}
// End event monitoring.
@ -728,6 +708,7 @@ public class DefaultPluginManager
}
catch ( ComponentLifecycleException e )
{
getLogger().debug( "Failed to release plugin container - ignoring." );
}
}
}

View File

@ -20,6 +20,7 @@ import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
/**
@ -36,6 +37,6 @@ public interface PluginManager
PluginDescriptor verifyPlugin( String prefix );
PluginDescriptor verifyPlugin( String groupId, String artifactId, String version, MavenProject project,
ArtifactRepository localRepository )
throws ArtifactResolutionException, PluginManagerException;
ArtifactRepository localRepository, boolean interactiveMode )
throws ArtifactResolutionException, PluginManagerException, PluginVersionResolutionException;
}

View File

@ -140,6 +140,30 @@ public class PluginParameterExpressionEvaluator
{
value = context.getSettings();
}
else if ( expression.startsWith( "settings" ) )
{
try
{
int pathSeparator = expression.indexOf( "/" );
if ( pathSeparator > 0 )
{
String pathExpression = expression.substring( 1, pathSeparator );
value = ReflectionValueExtractor.evaluate( pathExpression, context.getSettings() );
value = value + expression.substring( pathSeparator );
}
else
{
value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), context.getSettings() );
}
}
catch ( Exception e )
{
// TODO: don't catch exception
throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression,
e );
}
}
else if ( expression.equals( "basedir" ) )
{
value = context.getProject().getBasedir().getAbsolutePath();

View File

@ -0,0 +1,454 @@
package org.apache.maven.plugin.version;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.handler.PluginHandler;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.registry.MavenPluginRegistryBuilder;
import org.apache.maven.plugin.registry.PluginRegistry;
import org.apache.maven.plugin.registry.PluginRegistryUtils;
import org.apache.maven.plugin.registry.TrackableBase;
import org.apache.maven.plugin.registry.io.xpp3.PluginRegistryXpp3Writer;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.components.inputhandler.InputHandler;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed 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.
*/
public class DefaultPluginVersionManager
extends AbstractLogEnabled
implements PluginVersionManager
{
private MavenPluginRegistryBuilder mavenPluginRegistryBuilder;
private ArtifactResolver artifactResolver;
private ArtifactFactory artifactFactory;
private InputHandler inputHandler;
public String resolvePluginVersion( String groupId, String artifactId, MavenProject project,
ArtifactRepository localRepository, boolean interactiveMode )
throws PluginVersionResolutionException
{
// first pass...if the plugin is specified in the pom, try to retrieve the version from there.
String version = getVersionFromPluginConfig( groupId, artifactId, project );
// TODO: we're NEVER going to persist POM-derived plugin versions...dunno if this is 'right' or not.
String updatedVersion = null;
boolean promptToPersistUpdatedVersion = false;
// second pass...if the plugin is listed in the settings.xml, use the version from <useVersion/>.
if ( StringUtils.isEmpty( version ) )
{
// 1. resolve existing useVersion.
version = resolveExistingFromPluginRegistry( groupId, artifactId );
if ( StringUtils.isNotEmpty( version ) )
{
// TODO: 2. check for updates. Determine whether this is the right time to attempt to update the version.
boolean checkForUpdates = true;
if ( checkForUpdates )
{
updatedVersion = resolveReleaseVersion( groupId, artifactId, project
.getRemoteArtifactRepositories(), localRepository );
if ( StringUtils.isNotEmpty( updatedVersion ) && !updatedVersion.equals( version ) )
{
boolean isRejected = checkForRejectedStatus( groupId, artifactId, updatedVersion );
// we should only prompt to use this version if the user has not previously rejected it.
promptToPersistUpdatedVersion = !isRejected;
if ( isRejected )
{
updatedVersion = null;
}
else
{
getLogger()
.info( "Plugin {" + constructPluginKey( groupId, artifactId ) + "} has updates." );
}
}
else
{
// let's be very careful about making this code resistant to change...
promptToPersistUpdatedVersion = false;
}
}
else
{
// let's be very careful about making this code resistant to change...
promptToPersistUpdatedVersion = false;
}
}
else
{
// let's be very careful about making this code resistant to change...
promptToPersistUpdatedVersion = false;
}
}
// final pass...retrieve the version for RELEASE and also set that resolved version as the <useVersion/>
// in settings.xml.
if ( StringUtils.isEmpty( version ) )
{
// 1. resolve the version to be used THIS TIME
version = resolveReleaseVersion( groupId, artifactId, project.getRemoteArtifactRepositories(),
localRepository );
// 2. Set the updatedVersion so the user will be prompted whether to make this version permanent.
updatedVersion = version;
promptToPersistUpdatedVersion = true;
}
// if we still haven't found a version, then fail early before we get into the update goop.
if ( StringUtils.isEmpty( version ) )
{
throw new PluginVersionResolutionException( groupId, artifactId,
"Failed to resolve a valid version for this plugin" );
}
// if we're not in interactive mode, then the default is to update and NOT prompt.
// TODO: replace this with proper update policy-based determination related to batch mode.
boolean persistUpdatedVersion = promptToPersistUpdatedVersion && !interactiveMode;
// don't prompt if not in interactive mode.
if ( promptToPersistUpdatedVersion && interactiveMode )
{
persistUpdatedVersion = promptToPersistPluginUpdate( version, updatedVersion, groupId, artifactId );
}
// if it is determined that we should use this version, persist it as useVersion.
if ( persistUpdatedVersion )
{
updatePluginVersionInRegistry( groupId, artifactId, updatedVersion );
}
// otherwise, if we prompted the user to update, we should treat this as a rejectedVersion, and
// persist it iff the plugin pre-exists and is in the user-level registry.
else if ( promptToPersistUpdatedVersion && interactiveMode )
{
addNewVersionToRejectedListInExisting( groupId, artifactId, updatedVersion );
}
return version;
}
private boolean checkForRejectedStatus( String groupId, String artifactId, String version )
throws PluginVersionResolutionException
{
PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId );
org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry );
return plugin.getRejectedVersions().contains( version );
}
private boolean promptToPersistPluginUpdate( String version, String updatedVersion, String groupId,
String artifactId )
throws PluginVersionResolutionException
{
try
{
StringBuffer message = new StringBuffer();
// this means that the plugin is not registered.
if ( version != null && version.equals( updatedVersion ) )
{
message.append( "Unregistered plugin detected.\n\n" );
}
else
{
message.append( "New plugin version detected.\n\n" );
}
message.append( "Group ID: " ).append( groupId ).append( "\n" );
message.append( "Artifact ID: " ).append( artifactId ).append( "\n" );
message.append( "\n" );
// this means that we've detected a new, non-rejected plugin version.
if ( version != null && !version.equals( updatedVersion ) )
{
message.append( "Registered Version: " ).append( version ).append( "\n" );
}
message.append( "Detected (NEW) Version: " ).append( updatedVersion ).append( "\n" );
message.append( "\n" );
message.append( "Would you like to use this new version from now on? [Y/n] " );
// TODO: check the GUI-friendliness of this approach to collecting input.
// If we can't port this prompt into a GUI, IDE-integration will not work well.
getLogger().info( message.toString() );
String persistAnswer = inputHandler.readLine();
return StringUtils.isEmpty( persistAnswer ) || "y".equalsIgnoreCase( persistAnswer );
}
catch ( Exception e )
{
throw new PluginVersionResolutionException( groupId, artifactId, "Can't read user input.", e );
}
}
private void addNewVersionToRejectedListInExisting( String groupId, String artifactId, String rejectedVersion )
throws PluginVersionResolutionException
{
PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId );
org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry );
String pluginKey = constructPluginKey( groupId, artifactId );
if ( plugin != null && !TrackableBase.GLOBAL_LEVEL.equals( plugin.getSourceLevel() ) )
{
plugin.addRejectedVersion( rejectedVersion );
writeUserRegistry( groupId, artifactId, pluginRegistry );
getLogger().warn(
"Plugin version: " + rejectedVersion + " added to your rejectedVersions list.\n"
+ "You will not be prompted for this version again.\n\nPlugin: " + pluginKey );
}
else
{
getLogger().warn( "Cannot add rejectedVersion entry for: " + rejectedVersion + ".\n\nPlugin: " + pluginKey );
}
}
private String resolveExistingFromPluginRegistry( String groupId, String artifactId )
throws PluginVersionResolutionException
{
PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId );
org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry );
String version = null;
if ( plugin != null )
{
version = plugin.getUseVersion();
}
return version;
}
private org.apache.maven.plugin.registry.Plugin getPlugin( String groupId, String artifactId,
PluginRegistry pluginRegistry )
{
Map pluginsByKey = null;
if ( pluginRegistry != null )
{
pluginsByKey = pluginRegistry.getPluginsByKey();
}
else
{
pluginsByKey = new HashMap();
}
String pluginKey = constructPluginKey( groupId, artifactId );
return (org.apache.maven.plugin.registry.Plugin) pluginsByKey.get( pluginKey );
}
private String constructPluginKey( String groupId, String artifactId )
{
return groupId + ":" + artifactId;
}
private String getVersionFromPluginConfig( String groupId, String artifactId, MavenProject project )
{
String version = null;
Plugin pluginConfig = null;
for ( Iterator it = project.getBuildPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
if ( groupId.equals( plugin.getGroupId() ) && artifactId.equals( plugin.getArtifactId() ) )
{
pluginConfig = plugin;
break;
}
}
// won't this overwrite the above loop if it exists in both places (unlikely, I know)??
// maybe that's the idea...?
if ( project.getReports() != null )
{
for ( Iterator it = project.getReports().getPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
if ( groupId.equals( plugin.getGroupId() ) && artifactId.equals( plugin.getArtifactId() ) )
{
pluginConfig = plugin;
break;
}
}
}
if ( pluginConfig != null )
{
version = pluginConfig.getVersion();
}
return version;
}
private void updatePluginVersionInRegistry( String groupId, String artifactId, String version )
throws PluginVersionResolutionException
{
PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId );
org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry );
// if we can find the plugin, but we've gotten here, the useVersion must be missing; fill it in.
if ( plugin != null )
{
if ( PluginRegistry.GLOBAL_LEVEL.equals( plugin.getSourceLevel() ) )
{
// do nothing. We don't rewrite the globals, under any circumstances.
getLogger().warn(
"Cannot update registered version for plugin {" + groupId + ":" + artifactId
+ "}; it is specified in the global registry." );
}
else
{
plugin.setUseVersion( version );
}
}
else
{
plugin = new org.apache.maven.plugin.registry.Plugin();
plugin.setGroupId( groupId );
plugin.setArtifactId( artifactId );
plugin.setUseVersion( version );
plugin.setAutoUpdate( false );
pluginRegistry.addPlugin( plugin );
}
writeUserRegistry( groupId, artifactId, pluginRegistry );
}
private void writeUserRegistry( String groupId, String artifactId, PluginRegistry pluginRegistry )
throws PluginVersionResolutionException
{
File pluginRegistryFile = pluginRegistry.getFile();
PluginRegistry extractedUserRegistry = PluginRegistryUtils.extractUserPluginRegistry( pluginRegistry );
// only rewrite the user-level registry if one existed before, or if we've created user-level data here.
if ( extractedUserRegistry != null )
{
FileWriter fWriter = null;
try
{
fWriter = new FileWriter( pluginRegistryFile );
PluginRegistryXpp3Writer writer = new PluginRegistryXpp3Writer();
writer.write( fWriter, PluginRegistryUtils.extractUserPluginRegistry( pluginRegistry ) );
}
catch ( IOException e )
{
// TODO: should we soften this to a warning??
throw new PluginVersionResolutionException(
groupId,
artifactId,
"Cannot rewrite user-level plugin-registry.xml with new plugin version.",
e );
}
finally
{
IOUtil.close( fWriter );
}
}
}
private PluginRegistry getPluginRegistry( String groupId, String artifactId )
throws PluginVersionResolutionException
{
PluginRegistry pluginRegistry = null;
try
{
pluginRegistry = mavenPluginRegistryBuilder.buildPluginRegistry();
}
catch ( IOException e )
{
throw new PluginVersionResolutionException( groupId, artifactId, "Cannot read plugin registry", e );
}
catch ( XmlPullParserException e )
{
throw new PluginVersionResolutionException( groupId, artifactId, "Cannot parse plugin registry", e );
}
if ( pluginRegistry == null )
{
pluginRegistry = mavenPluginRegistryBuilder.createUserPluginRegistry();
}
return pluginRegistry;
}
private String resolveReleaseVersion( String groupId, String artifactId, List remoteRepositories,
ArtifactRepository localRepository )
throws PluginVersionResolutionException
{
Artifact releaseArtifact = artifactFactory.createArtifact( groupId, artifactId, "RELEASE",
Artifact.SCOPE_RUNTIME, PluginHandler.PLUGIN_TYPE );
try
{
artifactResolver.resolve( releaseArtifact, remoteRepositories, localRepository );
}
catch ( ArtifactResolutionException e )
{
throw new PluginVersionResolutionException( groupId, artifactId,
"Cannot resolve RELEASE version of this plugin.", e );
}
return releaseArtifact.getVersion();
}
}

View File

@ -0,0 +1,31 @@
package org.apache.maven.plugin.version;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.project.MavenProject;
/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed 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.
*/
public interface PluginVersionManager
{
String ROLE = PluginVersionManager.class.getName();
String resolvePluginVersion( String groupId, String artifactId, MavenProject project,
ArtifactRepository localRepository, boolean interactiveMode )
throws PluginVersionResolutionException;
}

View File

@ -0,0 +1,62 @@
package org.apache.maven.plugin.version;
/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed 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.
*/
public class PluginVersionResolutionException
extends Exception
{
private final String groupId;
private final String artifactId;
private final String baseMessage;
public PluginVersionResolutionException( String groupId, String artifactId, String baseMessage, Throwable cause )
{
super( "Error resolving version for \'" + groupId + ":" + artifactId + "\': " + baseMessage, cause );
this.groupId = groupId;
this.artifactId = artifactId;
this.baseMessage = baseMessage;
}
public PluginVersionResolutionException( String groupId, String artifactId, String baseMessage )
{
super( "Error resolving version for \'" + groupId + ":" + artifactId + "\': " + baseMessage );
this.groupId = groupId;
this.artifactId = artifactId;
this.baseMessage = baseMessage;
}
public String getGroupId()
{
return groupId;
}
public String getArtifactId()
{
return artifactId;
}
public String getBaseMessage()
{
return baseMessage;
}
}

View File

@ -24,15 +24,6 @@
</requirement>
</requirements>
</component>
<!--
|
|
|
-->
<component>
<role>org.apache.maven.profiles.MavenProfilesBuilder</role>
<implementation>org.apache.maven.profiles.DefaultMavenProfilesBuilder</implementation>
</component>
<!--
|
|PluginConfigurationDiagnoser
@ -64,6 +55,15 @@
<implementation>org.apache.maven.usability.InvalidArtifactDiagnoser</implementation>
</component>
<!--
|
|
|
-->
<component>
<role>org.apache.maven.profiles.MavenProfilesBuilder</role>
<implementation>org.apache.maven.profiles.DefaultMavenProfilesBuilder</implementation>
</component>
<!--
|
| Lifecycle executor
@ -259,5 +259,26 @@
<!-- END SNIPPET: plexus-service-lifecycle -->
</configuration>
</component>
<component>
<role>org.apache.maven.plugin.version.PluginVersionManager</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.plugin.version.DefaultPluginVersionManager</implementation>
<instantiation-strategy>per-lookup</instantiation-strategy>
<requirements>
<requirement>
<role>org.apache.maven.plugin.registry.MavenPluginRegistryBuilder</role>
</requirement>
<requirement>
<role>org.apache.maven.artifact.resolver.ArtifactResolver</role>
</requirement>
<requirement>
<role>org.apache.maven.artifact.factory.ArtifactFactory</role>
</requirement>
<requirement>
<role>org.codehaus.plexus.components.inputhandler.InputHandler</role>
</requirement>
</requirements>
</component>
</components>
</component-set>

View File

@ -38,7 +38,7 @@ public class MBoot
String[] builds = new String[]{"maven-model", "maven-monitor", "maven-plugin-api",
"maven-plugin-descriptor", "maven-artifact", "maven-script/maven-script-marmalade",
"maven-script/maven-script-beanshell", "maven-project",
"maven-settings", "maven-profile",
"maven-settings", "maven-profile", "maven-plugin-registry",
"maven-reporting/maven-reporting-api", "maven-core", "maven-archiver",
"maven-plugin-tools/maven-plugin-tools-api",
"maven-plugin-tools/maven-plugin-tools-java",
@ -61,6 +61,7 @@ public class MBoot
targetVersions.put( "maven-model", "4.0.0" );
targetVersions.put( "maven-settings", "1.0.0" );
targetVersions.put( "maven-profile", "1.0.0" );
targetVersions.put( "maven-plugin-registry", "1.0.0" );
MODELLO_TARGET_VERSIONS = Collections.unmodifiableMap( targetVersions );
@ -68,6 +69,7 @@ public class MBoot
modelFiles.put( "maven-model", "maven.mdo" );
modelFiles.put( "maven-settings", "settings.mdo" );
modelFiles.put( "maven-profile", "profiles.mdo" );
modelFiles.put( "maven-plugin-registry", "plugin-registry.mdo" );
MODELLO_MODEL_FILES = Collections.unmodifiableMap( modelFiles );
}

View File

@ -0,0 +1,168 @@
<model>
<id>plugin-registry</id>
<name>PluginRegistry</name>
<description><![CDATA[
Contains plugin version information related to which version of a particular plugin to use,
when and how to update plugins, and which versions of a plugin have already been declined for
update.
]]></description>
<defaults>
<default>
<key>package</key>
<value>org.apache.maven.plugin.registry</value>
</default>
</defaults>
<classes>
<class>
<name>TrackableBase</name>
<version>1.0.0</version>
<description>common base class that contains code to track the source for this instance (USER|GLOBAL)</description>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
public static final String USER_LEVEL = "user-level";
public static final String GLOBAL_LEVEL = "global-level";
private String sourceLevel = USER_LEVEL;
private boolean sourceLevelSet = false;
public void setSourceLevel( String sourceLevel )
{
if ( sourceLevelSet )
{
throw new IllegalStateException( "Cannot reset sourceLevel attribute; it is already set to: " + sourceLevel );
}
else if ( !( USER_LEVEL.equals( sourceLevel ) || GLOBAL_LEVEL.equals( sourceLevel ) ) )
{
throw new IllegalArgumentException( "sourceLevel must be one of: {" + USER_LEVEL + "," + GLOBAL_LEVEL + "}" );
}
else
{
this.sourceLevel = sourceLevel;
this.sourceLevelSet = true;
}
}
public String getSourceLevel()
{
return sourceLevel;
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class rootElement="true" xml.tagName="pluginRegistry">
<name>PluginRegistry</name>
<version>1.0.0</version>
<superClass>TrackableBase</superClass>
<description>Root element of the plugin registry file.</description>
<fields>
<field>
<name>plugins</name>
<version>1.0.0</version>
<description>Specified plugin update policy information.</description>
<association>
<type>Plugin</type>
<multiplicity>*</multiplicity>
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
private Map pluginsByKey;
public Map getPluginsByKey()
{
if ( pluginsByKey == null )
{
pluginsByKey = new HashMap();
for ( Iterator it = getPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
pluginsByKey.put( plugin.getKey(), plugin );
}
}
return pluginsByKey;
}
public void flushPluginsByKey()
{
this.pluginsByKey = null;
}
private java.io.File file;
public void setFile( java.io.File file )
{
this.file = file;
}
public java.io.File getFile()
{
return file;
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class>
<name>Plugin</name>
<version>1.0.0</version>
<superClass>TrackableBase</superClass>
<description>Policy for updating a single plugin.</description>
<fields>
<field>
<name>groupId</name>
<version>1.0.0</version>
<required>true</required>
<type>String</type>
</field>
<field>
<name>artifactId</name>
<version>1.0.0</version>
<required>true</required>
<type>String</type>
</field>
<field>
<name>autoUpdate</name>
<version>1.0.0</version>
<type>boolean</type>
<default>false</default>
<description>Whether to automatically update this plugin - false means prompt the user.</description>
</field>
<field>
<name>useVersion</name>
<version>1.0.0</version>
<type>String</type>
<description>The current version of this plugin, to be used until the appropriate update actions happen.</description>
</field>
<field>
<name>rejectedVersions</name>
<version>1.0.0</version>
<description>The list of versions for this plugin that the user declined to "install"</description>
<association>
<type>String</type>
<multiplicity>*</multiplicity>
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
public String getKey()
{
return getGroupId() + ":" + getArtifactId();
}
]]></code>
</codeSegment>
</codeSegments>
</class>
</classes>
</model>

View File

@ -0,0 +1,46 @@
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>maven</artifactId>
<groupId>org.apache.maven</groupId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>maven-plugin-registry</artifactId>
<name>Maven Plugin Registry Model</name>
<dependencies>
<dependency>
<groupId>plexus</groupId>
<artifactId>plexus-container-default</artifactId>
<version>1.0-alpha-4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>1.0-alpha-3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.modello</groupId>
<artifactId>modello-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<goals>
<goal>
<id>xpp3-writer</id>
</goal>
<goal>
<id>java</id>
</goal>
<goal>
<id>xpp3-reader</id>
</goal>
</goals>
<configuration>
<version>1.0.0</version>
<model>plugin-registry.mdo</model>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,163 @@
package org.apache.maven.plugin.registry;
import org.apache.maven.plugin.registry.io.xpp3.PluginRegistryXpp3Reader;
import org.apache.maven.plugin.registry.TrackableBase;
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.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed 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.
*/
public class DefaultPluginRegistryBuilder
extends AbstractLogEnabled
implements MavenPluginRegistryBuilder, Initializable
{
public static final String userHome = System.getProperty( "user.home" );
/**
* @configuration
*/
private String userRegistryPath;
/**
* @configuration
*/
private String globalRegistryPath;
private File userRegistryFile;
private File globalRegistryFile;
// ----------------------------------------------------------------------
// Component Lifecycle
// ----------------------------------------------------------------------
public void initialize()
{
userRegistryFile = getFile( userRegistryPath, "user.home", MavenPluginRegistryBuilder.ALT_USER_PLUGIN_REG_LOCATION );
globalRegistryFile = getFile( globalRegistryPath, "maven.home", MavenPluginRegistryBuilder.ALT_GLOBAL_PLUGIN_REG_LOCATION );
getLogger().debug( "Building Maven global-level settings from: '" + globalRegistryFile.getAbsolutePath() + "'" );
getLogger().debug( "Building Maven user-level settings from: '" + userRegistryFile.getAbsolutePath() + "'" );
}
public PluginRegistry buildPluginRegistry()
throws IOException, XmlPullParserException
{
PluginRegistry global = readPluginRegistry( globalRegistryFile );
PluginRegistry user = readPluginRegistry( userRegistryFile );
if ( user == null && global != null )
{
// we'll use the globals, but first we have to recursively mark them as global...
PluginRegistryUtils.recursivelySetSourceLevel( global, PluginRegistry.GLOBAL_LEVEL );
user = global;
}
else
{
// merge non-colliding plugins into the user registry.
PluginRegistryUtils.merge( user, global, TrackableBase.GLOBAL_LEVEL );
}
return user;
}
private PluginRegistry readPluginRegistry( File registryFile )
throws IOException, XmlPullParserException
{
PluginRegistry registry = null;
if ( registryFile.exists() && registryFile.isFile() )
{
FileReader reader = null;
try
{
reader = new FileReader( registryFile );
PluginRegistryXpp3Reader modelReader = new PluginRegistryXpp3Reader();
registry = modelReader.read( reader );
registry.setFile( registryFile );
}
finally
{
IOUtil.close( reader );
}
}
return registry;
}
private File getFile( String pathPattern, String basedirSysProp, String altLocationSysProp )
{
// -------------------------------------------------------------------------------------
// Alright, here's the justification for all the regexp wizardry below...
//
// Continuum and other server-like apps may need to locate the user-level and
// global-level settings somewhere other than ${user.home} and ${maven.home},
// respectively. Using a simple replacement of these patterns will allow them
// to specify the absolute path to these files in a customized components.xml
// file. Ideally, we'd do full pattern-evaluation against the sysprops, but this
// is a first step. There are several replacements below, in order to normalize
// the path character before we operate on the string as a regex input, and
// in order to avoid surprises with the File construction...
// -------------------------------------------------------------------------------------
String path = System.getProperty( altLocationSysProp );
if ( StringUtils.isEmpty( path ) )
{
// TODO: This replacing shouldn't be necessary as user.home should be in the
// context of the container and thus the value would be interpolated by Plexus
String basedir = System.getProperty( basedirSysProp );
basedir = basedir.replaceAll( "\\\\", "/" );
basedir = basedir.replaceAll("\\$", "\\\\\\$");
path = pathPattern.replaceAll( "\\$\\{" + basedirSysProp + "\\}", basedir );
path = path.replaceAll( "\\\\", "/" );
path = path.replaceAll( "//", "/" );
return new File( path ).getAbsoluteFile();
}
else
{
return new File( path ).getAbsoluteFile();
}
}
public PluginRegistry createUserPluginRegistry()
{
PluginRegistry registry = new PluginRegistry();
registry.setFile( userRegistryFile );
return registry;
}
}

View File

@ -0,0 +1,35 @@
package org.apache.maven.plugin.registry;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.IOException;
/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed 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.
*/
public interface MavenPluginRegistryBuilder
{
String ROLE = MavenPluginRegistryBuilder.class.getName();
String ALT_USER_PLUGIN_REG_LOCATION = "org.apache.maven.user-plugin-registry";
String ALT_GLOBAL_PLUGIN_REG_LOCATION = "org.apache.maven.global-plugin-registry";
PluginRegistry buildPluginRegistry()
throws IOException, XmlPullParserException;
PluginRegistry createUserPluginRegistry();
}

View File

@ -0,0 +1,122 @@
package org.apache.maven.plugin.registry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed 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.
*/
public final class PluginRegistryUtils
{
private PluginRegistryUtils()
{
// don't allow construction.
}
public static void merge( PluginRegistry dominant, PluginRegistry recessive, String recessiveSourceLevel )
{
// can't merge into something that doesn't exist...
if ( dominant == null )
{
return;
}
List recessivePlugins = null;
if(recessive != null)
{
recessivePlugins = recessive.getPlugins();
}
else
{
recessivePlugins = Collections.EMPTY_LIST;
}
shallowMergePlugins( dominant, recessivePlugins, recessiveSourceLevel );
}
public static void recursivelySetSourceLevel( PluginRegistry pluginRegistry, String sourceLevel )
{
if ( pluginRegistry == null )
{
return;
}
pluginRegistry.setSourceLevel( sourceLevel );
for ( Iterator it = pluginRegistry.getPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
plugin.setSourceLevel( sourceLevel );
}
}
private static void shallowMergePlugins( PluginRegistry dominant, List recessive, String recessiveSourceLevel )
{
Map dominantByKey = dominant.getPluginsByKey();
List dominantPlugins = dominant.getPlugins();
for ( Iterator it = recessive.iterator(); it.hasNext(); )
{
Plugin recessivePlugin = (Plugin) it.next();
if ( !dominantByKey.containsKey( recessivePlugin.getKey() ) )
{
recessivePlugin.setSourceLevel( recessiveSourceLevel );
dominantPlugins.add( recessivePlugin );
}
}
dominant.flushPluginsByKey();
}
public static PluginRegistry extractUserPluginRegistry( PluginRegistry pluginRegistry )
{
PluginRegistry userRegistry = null;
// check if this registry is entirely made up of global settings
if ( pluginRegistry != null && !PluginRegistry.GLOBAL_LEVEL.equals( pluginRegistry.getSourceLevel() ) )
{
userRegistry = new PluginRegistry();
List plugins = new ArrayList();
for ( Iterator it = pluginRegistry.getPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
if ( TrackableBase.USER_LEVEL.equals( plugin.getSourceLevel() ) )
{
plugins.add( plugin );
}
}
userRegistry.setPlugins( plugins );
userRegistry.setFile( pluginRegistry.getFile() );
}
return userRegistry;
}
}

View File

@ -0,0 +1,14 @@
<component-set>
<components>
<component>
<role>org.apache.maven.plugin.registry.MavenPluginRegistryBuilder</role>
<implementation>org.apache.maven.plugin.registry.DefaultPluginRegistryBuilder</implementation>
<configuration>
<globalRegistryPath>${maven.home}/conf/plugin-registry.xml</globalRegistryPath>
<userRegistryPath>${user.home}/.m2/plugin-registry.xml</userRegistryPath>
</configuration>
</component>
</components>
</component-set>

View File

@ -58,6 +58,12 @@ public class PrepareReleaseMojo
* @readonly
*/
private String basedir;
/**
* @parameter expression="${settings.interactiveMode}"
* @readonly
*/
private boolean interactive = true;
private static final String SNAPSHOT = "-SNAPSHOT";
@ -490,7 +496,7 @@ public class PrepareReleaseMojo
{
ScmBean scm = getScm();
if ( scm.getTag() == null )
if ( scm.getTag() == null && interactive )
{
getLog().info( "What tag name should be used? [ " + tag + " ]" );

View File

@ -22,6 +22,7 @@ import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.PluginManager;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.reporting.MavenReportConfiguration;
@ -77,6 +78,12 @@ public class DoxiaMojo
private static final String RESOURCE_DIR = "org/apache/maven/doxia";
private static final String DEFAULT_TEMPLATE = RESOURCE_DIR + "/maven-site.vm";
/**
* @parameter expression="${settings.interactiveMode}"
* @readonly
*/
private boolean interactive = true;
/**
* @parameter expression="${basedir}/src/site"
@ -717,12 +724,16 @@ public class DoxiaMojo
try
{
pluginManager.verifyPlugin( plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion(),
project, localRepository );
project, localRepository, interactive );
}
catch ( ArtifactResolutionException e )
{
throw new MojoExecutionException( "Cannot find report plugin", e );
}
catch ( PluginVersionResolutionException e )
{
throw new MojoExecutionException( "Cannot resolve version for report plugin", e );
}
catch ( PluginManagerException e )
{
throw new MojoExecutionException( "Cannot find report plugin", e );

View File

@ -78,6 +78,13 @@
<description><![CDATA[The local repository.]]></description>
<type>String</type>
</field>
<field>
<name>interactiveMode</name>
<version>1.0.0</version>
<description><![CDATA[Whether Maven should attempt to interact with the user for input.]]></description>
<type>boolean</type>
<defaultValue>true</defaultValue>
</field>
<!-- [JC] Not ready to use yet, so I'm making if unavailable for now. -->
<!-- field>
<name>passwordStore</name>
@ -173,15 +180,6 @@
<multiplicity>*</multiplicity>
</association>
</field>
<field>
<name>pluginUpdates</name>
<version>1.0.0</version>
<description>Specified plugin update policy information.</description>
<association>
<type>PluginUpdate</type>
<multiplicity>*</multiplicity>
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
@ -299,28 +297,16 @@
return localRepositorySourceLevel;
}
private Map pluginUpdatesByKey;
private java.io.File file;
public Map getPluginUpdatesByKey()
public void setFile( java.io.File file )
{
if ( pluginUpdatesByKey == null )
{
pluginUpdatesByKey = new HashMap();
for ( Iterator it = getPluginUpdates().iterator(); it.hasNext(); )
{
PluginUpdate pluginUpdate = (PluginUpdate) it.next();
pluginUpdatesByKey.put( pluginUpdate.getKey(), pluginUpdate );
}
}
return pluginUpdatesByKey;
this.file = file;
}
public void flushPluginUpdatesByKey()
public java.io.File getFile()
{
this.pluginUpdatesByKey = null;
return file;
}
]]></code>
</codeSegment>
@ -672,58 +658,5 @@
</fields>
</class>
<!-- /BuildProfile support -->
<class>
<name>PluginUpdate</name>
<version>1.0.0</version>
<superClass>TrackableBase</superClass>
<description>Policy for updating a single plugin.</description>
<fields>
<field>
<name>groupId</name>
<version>1.0.0</version>
<required>true</required>
<type>String</type>
</field>
<field>
<name>artifactId</name>
<version>1.0.0</version>
<required>true</required>
<type>String</type>
</field>
<field>
<name>autoUpdate</name>
<version>1.0.0</version>
<type>boolean</type>
<default>false</default>
<description>Whether to automatically update this plugin - false means prompt the user.</description>
</field>
<field>
<name>useVersion</name>
<version>1.0.0</version>
<type>String</type>
<description>The current version of this plugin, to be used until the appropriate update actions happen.</description>
</field>
<field>
<name>rejectedVersions</name>
<version>1.0.0</version>
<description>The list of versions for this plugin that the user declined to "install"</description>
<association>
<type>String</type>
<multiplicity>*</multiplicity>
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
public String getKey()
{
return getGroupId() + ":" + getArtifactId();
}
]]></code>
</codeSegment>
</codeSegments>
</class>
</classes>
</model>

View File

@ -58,8 +58,9 @@ public class DefaultMavenSettingsBuilder
public void initialize()
{
userSettingsFile = getFile( userSettingsPath, "user.home", MavenSettingsBuilder.ALT_USER_SETTINGS_XML_LOCATION );
globalSettingsFile = getFile( globalSettingsPath, "maven.home", MavenSettingsBuilder.ALT_GLOBAL_SETTINGS_XML_LOCATION );
globalSettingsFile = getFile( globalSettingsPath, "maven.home",
MavenSettingsBuilder.ALT_GLOBAL_SETTINGS_XML_LOCATION );
getLogger().debug( "Building Maven global-level settings from: '" + globalSettingsFile.getAbsolutePath() + "'" );
getLogger().debug( "Building Maven user-level settings from: '" + userSettingsFile.getAbsolutePath() + "'" );
@ -84,6 +85,8 @@ public class DefaultMavenSettingsBuilder
SettingsXpp3Reader modelReader = new SettingsXpp3Reader();
settings = modelReader.read( reader );
settings.setFile( settingsFile );
}
finally
{
@ -125,7 +128,7 @@ public class DefaultMavenSettingsBuilder
return userSettings;
}
private File getFile( String pathPattern, String basedirSysProp, String altLocationSysProp )
{
// -------------------------------------------------------------------------------------
@ -140,7 +143,7 @@ public class DefaultMavenSettingsBuilder
// the path character before we operate on the string as a regex input, and
// in order to avoid surprises with the File construction...
// -------------------------------------------------------------------------------------
String path = System.getProperty( altLocationSysProp );
if ( StringUtils.isEmpty( path ) )
@ -150,7 +153,8 @@ public class DefaultMavenSettingsBuilder
String basedir = System.getProperty( basedirSysProp );
basedir = basedir.replaceAll( "\\\\", "/" );
basedir = basedir.replaceAll( "\\$", "\\\\\\$" );
path = pathPattern.replaceAll( "\\$\\{" + basedirSysProp + "\\}", basedir );
path = path.replaceAll( "\\\\", "/" );
path = path.replaceAll( "//", "/" );
@ -162,5 +166,5 @@ public class DefaultMavenSettingsBuilder
return new File( path ).getAbsoluteFile();
}
}
}

View File

@ -28,15 +28,16 @@ public final class SettingsUtils
private SettingsUtils()
{
// don't allow construction.
}
public static void merge( Settings dominant, Settings recessive, String recessiveSourceLevel )
{
if ( dominant == null || recessive == null )
{
return;
}
recessive.setSourceLevel( recessiveSourceLevel );
List dominantActiveProfiles = dominant.getActiveProfiles();
@ -49,7 +50,7 @@ public final class SettingsUtils
if ( !dominantActiveProfiles.contains( profileId ) )
{
dominantActiveProfiles.add( profileId );
dominant.setActiveProfileSourceLevel( profileId, recessiveSourceLevel );
}
}
@ -57,7 +58,7 @@ public final class SettingsUtils
if ( StringUtils.isEmpty( dominant.getLocalRepository() ) )
{
dominant.setLocalRepository( recessive.getLocalRepository() );
dominant.setLocalRepositorySourceLevel( recessiveSourceLevel );
}
@ -66,58 +67,36 @@ public final class SettingsUtils
shallowMergeById( dominant.getProxies(), recessive.getProxies(), recessiveSourceLevel );
shallowMergeById( dominant.getProfiles(), recessive.getProfiles(), recessiveSourceLevel );
shallowMergePluginUpdates( dominant, recessive.getPluginUpdates(), recessiveSourceLevel );
}
private static void shallowMergePluginUpdates( Settings dominant, List recessive, String recessiveSourceLevel )
{
Map dominantByKey = dominant.getPluginUpdatesByKey();
List dominantPluginUpdates = dominant.getPluginUpdates();
for ( Iterator it = recessive.iterator(); it.hasNext(); )
{
PluginUpdate recessivePluginUpdate = (PluginUpdate) it.next();
if( !dominantByKey.containsKey( recessivePluginUpdate.getKey() ) )
{
recessivePluginUpdate.setSourceLevel( recessiveSourceLevel );
dominantPluginUpdates.add( recessivePluginUpdate );
}
}
dominant.flushPluginUpdatesByKey();
}
private static void shallowMergeById( List dominant, List recessive, String recessiveSourceLevel )
{
Map dominantById = mapById( dominant );
for ( Iterator it = recessive.iterator(); it.hasNext(); )
{
IdentifiableBase identifiable = (IdentifiableBase) it.next();
if( !dominantById.containsKey(identifiable.getId()))
if ( !dominantById.containsKey( identifiable.getId() ) )
{
identifiable.setSourceLevel( recessiveSourceLevel );
dominant.add( identifiable );
}
}
}
private static Map mapById( List identifiables )
{
Map byId = new HashMap();
for ( Iterator it = identifiables.iterator(); it.hasNext(); )
{
IdentifiableBase identifiable = (IdentifiableBase) it.next();
byId.put( identifiable.getId(), identifiable );
}
return byId;
}

View File

@ -5,7 +5,7 @@
<role>org.apache.maven.settings.MavenSettingsBuilder</role>
<implementation>org.apache.maven.settings.DefaultMavenSettingsBuilder</implementation>
<configuration>
<globalSettingsPath>${maven.home}/settings.xml</globalSettingsPath>
<globalSettingsPath>${maven.home}/conf/settings.xml</globalSettingsPath>
<userSettingsPath>${user.home}/.m2/settings.xml</userSettingsPath>
</configuration>
</component>