From 7997634209cf2e666aa94ece24e089da179d8aa3 Mon Sep 17 00:00:00 2001 From: Jason van Zyl Date: Sat, 24 Jan 2015 17:37:00 -0500 Subject: [PATCH] MNG-5774 Provide an extension point for alternate CLI configuration source --- maven-core/pom.xml | 1 + .../java/org/apache/maven/DefaultMaven.java | 2 +- .../maven/bridge/MavenRepositorySystem.java | 2 +- .../DefaultMavenExecutionRequest.java | 132 ++++++++ .../execution/MavenExecutionRequest.java | 16 + .../MavenExecutionRequestPopulator.java | 1 + .../java/org/apache/maven/cli/CliRequest.java | 120 +++++++ .../java/org/apache/maven/cli/MavenCli.java | 195 ++++------- .../configuration/ConfigurationProcessor.java | 28 ++ .../SettingsXmlConfigurationProcessor.java | 308 ++++++++++++++++++ .../org/apache/maven/cli/MavenCliTest.java | 1 - 11 files changed, 680 insertions(+), 126 deletions(-) create mode 100644 maven-embedder/src/main/java/org/apache/maven/cli/CliRequest.java create mode 100644 maven-embedder/src/main/java/org/apache/maven/cli/configuration/ConfigurationProcessor.java create mode 100644 maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java diff --git a/maven-core/pom.xml b/maven-core/pom.xml index f6158d49d0..75285a08a0 100644 --- a/maven-core/pom.xml +++ b/maven-core/pom.xml @@ -40,6 +40,7 @@ org.apache.maven maven-model + org.apache.maven maven-settings 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 385ff74c1d..20d37586ba 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -156,7 +156,7 @@ public class DefaultMaven // @SuppressWarnings( "checkstyle:methodlength" ) private MavenExecutionResult doExecute( MavenExecutionRequest request ) - { + { request.setStartTime( new Date() ); MavenExecutionResult result = new DefaultMavenExecutionResult(); diff --git a/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java b/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java index ad937856c1..c0f682ed05 100644 --- a/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java +++ b/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java @@ -351,7 +351,7 @@ public class MavenRepositorySystem return modelRepositoryPolicy; } - public ArtifactRepository buildArtifactRepository( org.apache.maven.settings.Repository repo ) + public static ArtifactRepository buildArtifactRepository( org.apache.maven.settings.Repository repo ) throws InvalidRepositoryException { return buildArtifactRepository( fromSettingsRepository( repo ) ); 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 9daba38ffa..21a63a126b 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 @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Properties; import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.eventspy.internal.EventSpyDispatcher; import org.apache.maven.model.Profile; import org.apache.maven.project.DefaultProjectBuildingRequest; import org.apache.maven.project.ProjectBuildingRequest; @@ -40,6 +41,8 @@ import org.eclipse.aether.RepositoryCache; import org.eclipse.aether.repository.WorkspaceReader; import org.eclipse.aether.transfer.TransferListener; +import com.google.common.collect.Maps; + /** * @author Jason van Zyl */ @@ -53,6 +56,8 @@ public class DefaultMavenExecutionRequest private ArtifactRepository localRepository; + private EventSpyDispatcher eventSpyDispatcher; + private File localRepositoryPath; private boolean offline = false; @@ -156,6 +161,8 @@ public class DefaultMavenExecutionRequest private boolean useLegacyLocalRepositoryManager = false; + private Map data; + public DefaultMavenExecutionRequest() { } @@ -203,6 +210,7 @@ public class DefaultMavenExecutionRequest return copy; } + @Override public String getBaseDirectory() { if ( basedir == null ) @@ -213,16 +221,19 @@ public class DefaultMavenExecutionRequest return basedir.getAbsolutePath(); } + @Override public ArtifactRepository getLocalRepository() { return localRepository; } + @Override public File getLocalRepositoryPath() { return localRepositoryPath; } + @Override public List getGoals() { if ( goals == null ) @@ -232,6 +243,7 @@ public class DefaultMavenExecutionRequest return goals; } + @Override public Properties getSystemProperties() { if ( systemProperties == null ) @@ -242,6 +254,7 @@ public class DefaultMavenExecutionRequest return systemProperties; } + @Override public Properties getUserProperties() { if ( userProperties == null ) @@ -252,16 +265,19 @@ public class DefaultMavenExecutionRequest return userProperties; } + @Override public File getPom() { return pom; } + @Override public String getReactorFailureBehavior() { return reactorFailureBehavior; } + @Override public List getSelectedProjects() { if ( selectedProjects == null ) @@ -272,6 +288,7 @@ public class DefaultMavenExecutionRequest return selectedProjects; } + @Override public List getExcludedProjects() { if ( excludedProjects == null ) @@ -282,31 +299,37 @@ public class DefaultMavenExecutionRequest return excludedProjects; } + @Override public String getResumeFrom() { return resumeFrom; } + @Override public String getMakeBehavior() { return makeBehavior; } + @Override public Date getStartTime() { return startTime; } + @Override public boolean isShowErrors() { return showErrors; } + @Override public boolean isInteractiveMode() { return interactiveMode; } + @Override public MavenExecutionRequest setActiveProfiles( List activeProfiles ) { if ( activeProfiles != null ) @@ -321,6 +344,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setInactiveProfiles( List inactiveProfiles ) { if ( inactiveProfiles != null ) @@ -335,6 +359,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setRemoteRepositories( List remoteRepositories ) { if ( remoteRepositories != null ) @@ -349,6 +374,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setPluginArtifactRepositories( List pluginArtifactRepositories ) { if ( pluginArtifactRepositories != null ) @@ -368,6 +394,7 @@ public class DefaultMavenExecutionRequest this.projectBuildingRequest = projectBuildingConfiguration; } + @Override public List getActiveProfiles() { if ( activeProfiles == null ) @@ -377,6 +404,7 @@ public class DefaultMavenExecutionRequest return activeProfiles; } + @Override public List getInactiveProfiles() { if ( inactiveProfiles == null ) @@ -386,36 +414,43 @@ public class DefaultMavenExecutionRequest return inactiveProfiles; } + @Override public TransferListener getTransferListener() { return transferListener; } + @Override public int getLoggingLevel() { return loggingLevel; } + @Override public boolean isOffline() { return offline; } + @Override public boolean isUpdateSnapshots() { return updateSnapshots; } + @Override public boolean isNoSnapshotUpdates() { return noSnapshotUpdates; } + @Override public String getGlobalChecksumPolicy() { return globalChecksumPolicy; } + @Override public boolean isRecursive() { return recursive; @@ -425,6 +460,7 @@ public class DefaultMavenExecutionRequest // // ---------------------------------------------------------------------- + @Override public MavenExecutionRequest setBaseDirectory( File basedir ) { this.basedir = basedir; @@ -432,6 +468,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setStartTime( Date startTime ) { this.startTime = startTime; @@ -439,6 +476,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setShowErrors( boolean showErrors ) { this.showErrors = showErrors; @@ -446,6 +484,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setGoals( List goals ) { if ( goals != null ) @@ -460,6 +499,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setLocalRepository( ArtifactRepository localRepository ) { this.localRepository = localRepository; @@ -472,6 +512,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setLocalRepositoryPath( File localRepository ) { localRepositoryPath = localRepository; @@ -479,6 +520,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setLocalRepositoryPath( String localRepository ) { localRepositoryPath = ( localRepository != null ) ? new File( localRepository ) : null; @@ -486,6 +528,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setSystemProperties( Properties properties ) { if ( properties != null ) @@ -501,6 +544,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setUserProperties( Properties userProperties ) { if ( userProperties != null ) @@ -516,6 +560,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setReactorFailureBehavior( String failureBehavior ) { reactorFailureBehavior = failureBehavior; @@ -523,6 +568,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setSelectedProjects( List selectedProjects ) { if ( selectedProjects != null ) @@ -537,6 +583,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setExcludedProjects( List excludedProjects ) { if ( excludedProjects != null ) @@ -551,6 +598,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setResumeFrom( String project ) { this.resumeFrom = project; @@ -558,6 +606,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setMakeBehavior( String makeBehavior ) { this.makeBehavior = makeBehavior; @@ -565,6 +614,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addActiveProfile( String profile ) { if ( !getActiveProfiles().contains( profile ) ) @@ -575,6 +625,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addInactiveProfile( String profile ) { if ( !getInactiveProfiles().contains( profile ) ) @@ -585,6 +636,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addActiveProfiles( List profiles ) { for ( String profile : profiles ) @@ -595,6 +647,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addInactiveProfiles( List profiles ) { for ( String profile : profiles ) @@ -618,6 +671,7 @@ public class DefaultMavenExecutionRequest } /** @deprecated use {@link #setPom(File)} */ + @Deprecated public MavenExecutionRequest setPomFile( String pomFilename ) { if ( pomFilename != null ) @@ -628,6 +682,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setPom( File pom ) { this.pom = pom; @@ -635,6 +690,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setInteractiveMode( boolean interactive ) { interactiveMode = interactive; @@ -642,6 +698,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setTransferListener( TransferListener transferListener ) { this.transferListener = transferListener; @@ -649,6 +706,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setLoggingLevel( int loggingLevel ) { this.loggingLevel = loggingLevel; @@ -656,6 +714,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setOffline( boolean offline ) { this.offline = offline; @@ -663,6 +722,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setUpdateSnapshots( boolean updateSnapshots ) { this.updateSnapshots = updateSnapshots; @@ -670,6 +730,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setNoSnapshotUpdates( boolean noSnapshotUpdates ) { this.noSnapshotUpdates = noSnapshotUpdates; @@ -677,6 +738,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setGlobalChecksumPolicy( String globalChecksumPolicy ) { this.globalChecksumPolicy = globalChecksumPolicy; @@ -688,6 +750,7 @@ public class DefaultMavenExecutionRequest // Settings equivalents // ---------------------------------------------------------------------------- + @Override public List getProxies() { if ( proxies == null ) @@ -697,6 +760,7 @@ public class DefaultMavenExecutionRequest return proxies; } + @Override public MavenExecutionRequest setProxies( List proxies ) { if ( proxies != null ) @@ -711,6 +775,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addProxy( Proxy proxy ) { if ( proxy == null ) @@ -731,6 +796,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public List getServers() { if ( servers == null ) @@ -740,6 +806,7 @@ public class DefaultMavenExecutionRequest return servers; } + @Override public MavenExecutionRequest setServers( List servers ) { if ( servers != null ) @@ -754,6 +821,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addServer( Server server ) { if ( server == null ) @@ -774,6 +842,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public List getMirrors() { if ( mirrors == null ) @@ -783,6 +852,7 @@ public class DefaultMavenExecutionRequest return mirrors; } + @Override public MavenExecutionRequest setMirrors( List mirrors ) { if ( mirrors != null ) @@ -797,6 +867,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addMirror( Mirror mirror ) { if ( mirror == null ) @@ -817,6 +888,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public List getProfiles() { if ( profiles == null ) @@ -826,6 +898,7 @@ public class DefaultMavenExecutionRequest return profiles; } + @Override public MavenExecutionRequest setProfiles( List profiles ) { if ( profiles != null ) @@ -840,6 +913,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public List getPluginGroups() { if ( pluginGroups == null ) @@ -850,6 +924,7 @@ public class DefaultMavenExecutionRequest return pluginGroups; } + @Override public MavenExecutionRequest setPluginGroups( List pluginGroups ) { if ( pluginGroups != null ) @@ -864,6 +939,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addPluginGroup( String pluginGroup ) { if ( !getPluginGroups().contains( pluginGroup ) ) @@ -874,6 +950,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addPluginGroups( List pluginGroups ) { for ( String pluginGroup : pluginGroups ) @@ -884,6 +961,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest setRecursive( boolean recursive ) { this.recursive = recursive; @@ -894,11 +972,13 @@ public class DefaultMavenExecutionRequest // calculated from request attributes. private ProjectBuildingRequest projectBuildingRequest; + @Override public boolean isProjectPresent() { return isProjectPresent; } + @Override public MavenExecutionRequest setProjectPresent( boolean projectPresent ) { isProjectPresent = projectPresent; @@ -908,11 +988,13 @@ public class DefaultMavenExecutionRequest // Settings files + @Override public File getUserSettingsFile() { return userSettingsFile; } + @Override public MavenExecutionRequest setUserSettingsFile( File userSettingsFile ) { this.userSettingsFile = userSettingsFile; @@ -920,11 +1002,13 @@ public class DefaultMavenExecutionRequest return this; } + @Override public File getGlobalSettingsFile() { return globalSettingsFile; } + @Override public MavenExecutionRequest setGlobalSettingsFile( File globalSettingsFile ) { this.globalSettingsFile = globalSettingsFile; @@ -932,11 +1016,13 @@ public class DefaultMavenExecutionRequest return this; } + @Override public File getUserToolchainsFile() { return userToolchainsFile; } + @Override public MavenExecutionRequest setUserToolchainsFile( File userToolchainsFile ) { this.userToolchainsFile = userToolchainsFile; @@ -957,6 +1043,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public MavenExecutionRequest addRemoteRepository( ArtifactRepository repository ) { for ( ArtifactRepository repo : getRemoteRepositories() ) @@ -972,6 +1059,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public List getRemoteRepositories() { if ( remoteRepositories == null ) @@ -981,6 +1069,7 @@ public class DefaultMavenExecutionRequest return remoteRepositories; } + @Override public MavenExecutionRequest addPluginArtifactRepository( ArtifactRepository repository ) { for ( ArtifactRepository repo : getPluginArtifactRepositories() ) @@ -996,6 +1085,7 @@ public class DefaultMavenExecutionRequest return this; } + @Override public List getPluginArtifactRepositories() { if ( pluginArtifactRepositories == null ) @@ -1006,6 +1096,7 @@ public class DefaultMavenExecutionRequest } // TODO: this does not belong here. + @Override public ProjectBuildingRequest getProjectBuildingRequest() { if ( projectBuildingRequest == null ) @@ -1026,6 +1117,7 @@ public class DefaultMavenExecutionRequest return projectBuildingRequest; } + @Override public MavenExecutionRequest addProfile( Profile profile ) { if ( profile == null ) @@ -1046,11 +1138,13 @@ public class DefaultMavenExecutionRequest return this; } + @Override public RepositoryCache getRepositoryCache() { return repositoryCache; } + @Override public MavenExecutionRequest setRepositoryCache( RepositoryCache repositoryCache ) { this.repositoryCache = repositoryCache; @@ -1058,11 +1152,13 @@ public class DefaultMavenExecutionRequest return this; } + @Override public ExecutionListener getExecutionListener() { return executionListener; } + @Override public MavenExecutionRequest setExecutionListener( ExecutionListener executionListener ) { this.executionListener = executionListener; @@ -1070,66 +1166,78 @@ public class DefaultMavenExecutionRequest return this; } + @Override public void setDegreeOfConcurrency( final int degreeOfConcurrency ) { this.degreeOfConcurrency = degreeOfConcurrency; } + @Override public int getDegreeOfConcurrency() { return degreeOfConcurrency; } + @Override public WorkspaceReader getWorkspaceReader() { return workspaceReader; } + @Override public MavenExecutionRequest setWorkspaceReader( WorkspaceReader workspaceReader ) { this.workspaceReader = workspaceReader; return this; } + @Override public boolean isCacheTransferError() { return cacheTransferError; } + @Override public MavenExecutionRequest setCacheTransferError( boolean cacheTransferError ) { this.cacheTransferError = cacheTransferError; return this; } + @Override public boolean isCacheNotFound() { return cacheNotFound; } + @Override public MavenExecutionRequest setCacheNotFound( boolean cacheNotFound ) { this.cacheNotFound = cacheNotFound; return this; } + @Override public boolean isUseLegacyLocalRepository() { return this.useLegacyLocalRepositoryManager; } + @Override public MavenExecutionRequest setUseLegacyLocalRepository( boolean useLegacyLocalRepositoryManager ) { this.useLegacyLocalRepositoryManager = useLegacyLocalRepositoryManager; return this; } + @Override public MavenExecutionRequest setBuilderId( String builderId ) { this.builderId = builderId; return this; } + @Override public String getBuilderId() { return builderId; @@ -1163,4 +1271,28 @@ public class DefaultMavenExecutionRequest { return multiModuleProjectDirectory; } + + @Override + public MavenExecutionRequest setEventSpyDispatcher( EventSpyDispatcher eventSpyDispatcher ) + { + this.eventSpyDispatcher = eventSpyDispatcher; + return this; + } + + @Override + public EventSpyDispatcher getEventSpyDispatcher() + { + return eventSpyDispatcher; + } + + @Override + public Map getData() + { + if ( data == null ) + { + data = Maps.newHashMap(); + } + + return data; + } } diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java index bb4a49a4d8..b88f72883c 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java +++ b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java @@ -27,6 +27,7 @@ import java.util.Properties; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; +import org.apache.maven.eventspy.internal.EventSpyDispatcher; import org.apache.maven.model.Profile; import org.apache.maven.project.ProjectBuildingRequest; // @@ -424,4 +425,19 @@ public interface MavenExecutionRequest * @since 3.2.6 */ File getMultiModuleProjectDirectory(); + + /** + * @since 3.2.6 + */ + MavenExecutionRequest setEventSpyDispatcher( EventSpyDispatcher eventSpyDispatcher ); + + /** + * @since 3.2.6 + */ + EventSpyDispatcher getEventSpyDispatcher(); + + /** + * @since 3.2.6 + */ + Map getData(); } diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequestPopulator.java b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequestPopulator.java index 8eb805c87a..677e8c20b8 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequestPopulator.java +++ b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequestPopulator.java @@ -40,6 +40,7 @@ public interface MavenExecutionRequestPopulator * @return The populated execution request, never {@code null}. * @throws MavenExecutionRequestPopulationException If the execution request could not be populated. */ + @Deprecated MavenExecutionRequest populateFromSettings( MavenExecutionRequest request, Settings settings ) throws MavenExecutionRequestPopulationException; diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CliRequest.java b/maven-embedder/src/main/java/org/apache/maven/cli/CliRequest.java new file mode 100644 index 0000000000..4656dd3776 --- /dev/null +++ b/maven-embedder/src/main/java/org/apache/maven/cli/CliRequest.java @@ -0,0 +1,120 @@ +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.io.File; +import java.util.Properties; + +import org.apache.commons.cli.CommandLine; +import org.apache.maven.execution.DefaultMavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionRequest; +import org.codehaus.plexus.classworlds.ClassWorld; + +public class CliRequest +{ + String[] args; + + CommandLine commandLine; + + ClassWorld classWorld; + + String workingDirectory; + + File multiModuleProjectDirectory; + + boolean debug; + + boolean quiet; + + boolean showErrors = true; + + Properties userProperties = new Properties(); + + Properties systemProperties = new Properties(); + + MavenExecutionRequest request; + + CliRequest( String[] args, ClassWorld classWorld ) + { + this.args = args; + this.classWorld = classWorld; + this.request = new DefaultMavenExecutionRequest(); + } + + public String[] getArgs() + { + return args; + } + + public CommandLine getCommandLine() + { + return commandLine; + } + + public ClassWorld getClassWorld() + { + return classWorld; + } + + public String getWorkingDirectory() + { + return workingDirectory; + } + + public File getMultiModuleProjectDirectory() + { + return multiModuleProjectDirectory; + } + + public boolean isDebug() + { + return debug; + } + + public boolean isQuiet() + { + return quiet; + } + + public boolean isShowErrors() + { + return showErrors; + } + + public Properties getUserProperties() + { + return userProperties; + } + + public Properties getSystemProperties() + { + return systemProperties; + } + + public MavenExecutionRequest getRequest() + { + return request; + } + + public void setUserProperties( Properties properties ) + { + this.userProperties.putAll( properties ); + } +} \ No newline at end of file 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 4e7e072065..ced883c235 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 @@ -35,6 +35,7 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; @@ -48,6 +49,8 @@ import org.apache.maven.Maven; import org.apache.maven.building.FileSource; import org.apache.maven.building.Problem; import org.apache.maven.building.Source; +import org.apache.maven.cli.configuration.ConfigurationProcessor; +import org.apache.maven.cli.configuration.SettingsXmlConfigurationProcessor; import org.apache.maven.cli.event.DefaultEventSpyContext; import org.apache.maven.cli.event.ExecutionEventLogger; import org.apache.maven.cli.internal.BootstrapCoreExtensionManager; @@ -77,11 +80,6 @@ import org.apache.maven.model.building.ModelProcessor; import org.apache.maven.project.MavenProject; import org.apache.maven.properties.internal.EnvironmentUtils; import org.apache.maven.properties.internal.SystemProperties; -import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; -import org.apache.maven.settings.building.SettingsBuilder; -import org.apache.maven.settings.building.SettingsBuildingRequest; -import org.apache.maven.settings.building.SettingsBuildingResult; -import org.apache.maven.settings.building.SettingsProblem; import org.apache.maven.toolchain.building.DefaultToolchainsBuildingRequest; import org.apache.maven.toolchain.building.ToolchainsBuilder; import org.apache.maven.toolchain.building.ToolchainsBuildingResult; @@ -132,11 +130,6 @@ public class MavenCli @SuppressWarnings( "checkstyle:constantname" ) public static final File userMavenConfigurationHome = new File( userHome, ".m2" ); - public static final File DEFAULT_USER_SETTINGS_FILE = new File( userMavenConfigurationHome, "settings.xml" ); - - public static final File DEFAULT_GLOBAL_SETTINGS_FILE = - new File( System.getProperty( "maven.home", System.getProperty( "user.dir", "" ) ), "conf/settings.xml" ); - public static final File DEFAULT_USER_TOOLCHAINS_FILE = new File( userMavenConfigurationHome, "toolchains.xml" ); public static final File DEFAULT_GLOBAL_TOOLCHAINS_FILE = @@ -162,12 +155,12 @@ public class MavenCli private MavenExecutionRequestPopulator executionRequestPopulator; - private SettingsBuilder settingsBuilder; - private ToolchainsBuilder toolchainsBuilder; private DefaultSecDispatcher dispatcher; + private Map configurationProcessors; + public MavenCli() { this( null ); @@ -274,7 +267,7 @@ public class MavenCli properties( cliRequest ); localContainer = container( cliRequest ); commands( cliRequest ); - settings( cliRequest ); + configure( cliRequest ); toolchains( cliRequest ); populateRequest( cliRequest ); encryption( cliRequest ); @@ -581,8 +574,8 @@ public class MavenCli modelProcessor = createModelProcessor( container ); - settingsBuilder = container.lookup( SettingsBuilder.class ); - + configurationProcessors = container.lookupMap( ConfigurationProcessor.class ); + toolchainsBuilder = container.lookup( ToolchainsBuilder.class ); dispatcher = (DefaultSecDispatcher) container.lookup( SecDispatcher.class, "maven" ); @@ -639,20 +632,24 @@ public class MavenCli Thread.currentThread().setContextClassLoader( container.getContainerRealm() ); executionRequestPopulator = container.lookup( MavenExecutionRequestPopulator.class ); - settingsBuilder = container.lookup( SettingsBuilder.class ); - + + configurationProcessors = container.lookupMap( ConfigurationProcessor.class ); + + configure( cliRequest ); + MavenExecutionRequest request = DefaultMavenExecutionRequest.copy( cliRequest.request ); - settings( cliRequest, request ); + request = populateRequest( cliRequest, request ); + request = executionRequestPopulator.populateDefaults( request ); BootstrapCoreExtensionManager resolver = container.lookup( BootstrapCoreExtensionManager.class ); + return resolver.loadCoreExtensions( request, providedArtifacts, extensions ); } finally { executionRequestPopulator = null; - settingsBuilder = null; container.dispose(); } } @@ -979,93 +976,69 @@ public class MavenCli } @SuppressWarnings( "checkstyle:methodlength" ) - private void settings( CliRequest cliRequest ) + private void configure( CliRequest cliRequest ) throws Exception { - settings( cliRequest, cliRequest.request ); - } - - private void settings( CliRequest cliRequest, MavenExecutionRequest request ) - throws Exception - { - File userSettingsFile; - - if ( cliRequest.commandLine.hasOption( CLIManager.ALTERNATE_USER_SETTINGS ) ) + // + // This is not ideal but there are events specifically for configuration from the CLI which I don't + // believe are really valid but there are ITs which assert the right events are published so this + // needs to be supported so the EventSpyDispatcher needs to be put in the CliRequest so that + // it can be accessed by configuration processors. + // + cliRequest.request.setEventSpyDispatcher( eventSpyDispatcher ); + + // + // We expect at most 2 implementations to be available. The SettingsXmlConfigurationProcessor implementation + // is always available in the core and likely always will be, but we may have another ConfigurationProcessor + // present supplied by the user. The rule is that we only allow the execution of one ConfigurationProcessor. + // If there is more than one then we execute the one supplied by the user, otherwise we execute the + // the default SettingsXmlConfigurationProcessor. + // + int userSuppliedConfigurationProcessorCount = configurationProcessors.size() - 1; + + if ( userSuppliedConfigurationProcessorCount == 0 ) { - userSettingsFile = new File( cliRequest.commandLine.getOptionValue( CLIManager.ALTERNATE_USER_SETTINGS ) ); - userSettingsFile = resolveFile( userSettingsFile, cliRequest.workingDirectory ); - - if ( !userSettingsFile.isFile() ) + // + // Our settings.xml source is historically how we have configured Maven from the CLI so we are going to + // have to honour its existence forever. So let's run it. + // + configurationProcessors.get( SettingsXmlConfigurationProcessor.HINT ).process( cliRequest ); + } + else if ( userSuppliedConfigurationProcessorCount == 1 ) + { + // + // Run the user supplied ConfigurationProcessor + // + for ( Entry entry : configurationProcessors.entrySet() ) { - throw new FileNotFoundException( "The specified user settings file does not exist: " - + userSettingsFile ); - } + String hint = entry.getKey(); + if ( !hint.equals( SettingsXmlConfigurationProcessor.HINT ) ) + { + ConfigurationProcessor configurationProcessor = entry.getValue(); + configurationProcessor.process( cliRequest ); + } + } } - else + else if ( userSuppliedConfigurationProcessorCount > 1 ) { - userSettingsFile = DEFAULT_USER_SETTINGS_FILE; - } - - File globalSettingsFile; - - if ( cliRequest.commandLine.hasOption( CLIManager.ALTERNATE_GLOBAL_SETTINGS ) ) - { - globalSettingsFile = - new File( cliRequest.commandLine.getOptionValue( CLIManager.ALTERNATE_GLOBAL_SETTINGS ) ); - globalSettingsFile = resolveFile( globalSettingsFile, cliRequest.workingDirectory ); - - if ( !globalSettingsFile.isFile() ) + // + // There are too many ConfigurationProcessors so we don't know which one to run so report the error. + // + StringBuffer sb = new StringBuffer( + String.format( "\nThere can only be one user supplied ConfigurationProcessor, there are %s:\n\n", + userSuppliedConfigurationProcessorCount ) ); + for ( Entry entry : configurationProcessors.entrySet() ) { - throw new FileNotFoundException( "The specified global settings file does not exist: " - + globalSettingsFile ); + String hint = entry.getKey(); + if ( !hint.equals( SettingsXmlConfigurationProcessor.HINT ) ) + { + ConfigurationProcessor configurationProcessor = entry.getValue(); + sb.append( String.format( "%s\n", configurationProcessor.getClass().getName() ) ); + } } - } - else - { - globalSettingsFile = DEFAULT_GLOBAL_SETTINGS_FILE; - } - - request.setGlobalSettingsFile( globalSettingsFile ); - request.setUserSettingsFile( userSettingsFile ); - - SettingsBuildingRequest settingsRequest = new DefaultSettingsBuildingRequest(); - settingsRequest.setGlobalSettingsFile( globalSettingsFile ); - settingsRequest.setUserSettingsFile( userSettingsFile ); - settingsRequest.setSystemProperties( cliRequest.systemProperties ); - settingsRequest.setUserProperties( cliRequest.userProperties ); - - if ( eventSpyDispatcher != null ) - { - eventSpyDispatcher.onEvent( settingsRequest ); - } - - slf4jLogger.debug( "Reading global settings from " - + getLocation( settingsRequest.getGlobalSettingsSource(), - settingsRequest.getGlobalSettingsFile() ) ); - slf4jLogger.debug( "Reading user settings from " - + getLocation( settingsRequest.getUserSettingsSource(), settingsRequest.getUserSettingsFile() ) ); - - SettingsBuildingResult settingsResult = settingsBuilder.build( settingsRequest ); - - if ( eventSpyDispatcher != null ) - { - eventSpyDispatcher.onEvent( settingsResult ); - } - - executionRequestPopulator.populateFromSettings( request, settingsResult.getEffectiveSettings() ); - - if ( !settingsResult.getProblems().isEmpty() && slf4jLogger.isWarnEnabled() ) - { - slf4jLogger.warn( "" ); - slf4jLogger.warn( "Some problems were encountered while building the effective settings" ); - - for ( SettingsProblem problem : settingsResult.getProblems() ) - { - slf4jLogger.warn( problem.getMessage() + " @ " + problem.getLocation() ); - } - - slf4jLogger.warn( "" ); - } + sb.append( String.format( "\n" ) ); + throw new Exception( sb.toString() ); + } } @SuppressWarnings( "checkstyle:methodlength" ) @@ -1346,8 +1319,7 @@ public class MavenCli .setUpdateSnapshots( updateSnapshots ) // default: false .setNoSnapshotUpdates( noSnapshotUpdates ) // default: false .setGlobalChecksumPolicy( globalChecksumPolicy ) // default: warn - .setMultiModuleProjectDirectory( cliRequest.multiModuleProjectDirectory ) - ; + .setMultiModuleProjectDirectory( cliRequest.multiModuleProjectDirectory ); if ( alternatePomFile != null ) { @@ -1589,28 +1561,6 @@ public class MavenCli System.setProperty( name, value ); } - static class CliRequest - { - String[] args; - CommandLine commandLine; - ClassWorld classWorld; - String workingDirectory; - File multiModuleProjectDirectory; - boolean debug; - boolean quiet; - boolean showErrors = true; - Properties userProperties = new Properties(); - Properties systemProperties = new Properties(); - MavenExecutionRequest request; - - CliRequest( String[] args, ClassWorld classWorld ) - { - this.args = args; - this.classWorld = classWorld; - this.request = new DefaultMavenExecutionRequest(); - } - } - static class ExitException extends Exception { @@ -1621,7 +1571,6 @@ public class MavenCli { this.exitCode = exitCode; } - } // diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/configuration/ConfigurationProcessor.java b/maven-embedder/src/main/java/org/apache/maven/cli/configuration/ConfigurationProcessor.java new file mode 100644 index 0000000000..75fb9b916d --- /dev/null +++ b/maven-embedder/src/main/java/org/apache/maven/cli/configuration/ConfigurationProcessor.java @@ -0,0 +1,28 @@ +package org.apache.maven.cli.configuration; + +/* + * 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.cli.CliRequest; + +public interface ConfigurationProcessor +{ + void process( CliRequest request ) + throws Exception; +} diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java b/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java new file mode 100644 index 0000000000..890a6581fd --- /dev/null +++ b/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java @@ -0,0 +1,308 @@ +package org.apache.maven.cli.configuration; + +/* + * 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.File; +import java.io.FileNotFoundException; +import java.util.List; + +import org.apache.commons.cli.CommandLine; +import org.apache.maven.artifact.InvalidRepositoryException; +import org.apache.maven.bridge.MavenRepositorySystem; +import org.apache.maven.building.Source; +import org.apache.maven.cli.CLIManager; +import org.apache.maven.cli.CliRequest; +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionRequestPopulationException; +import org.apache.maven.settings.Mirror; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Repository; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; +import org.apache.maven.settings.SettingsUtils; +import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; +import org.apache.maven.settings.building.SettingsBuilder; +import org.apache.maven.settings.building.SettingsBuildingRequest; +import org.apache.maven.settings.building.SettingsBuildingResult; +import org.apache.maven.settings.building.SettingsProblem; +import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; +import org.apache.maven.settings.crypto.SettingsDecrypter; +import org.apache.maven.settings.crypto.SettingsDecryptionResult; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.slf4j.Logger; + +@Component( role = ConfigurationProcessor.class, hint = SettingsXmlConfigurationProcessor.HINT ) +public class SettingsXmlConfigurationProcessor + implements ConfigurationProcessor +{ + public static final String HINT = "settings"; + + public static final String USER_HOME = System.getProperty( "user.home" ); + + public static final File USER_MAVEN_CONFIGURATION_HOME = new File( USER_HOME, ".m2" ); + + public static final File DEFAULT_USER_SETTINGS_FILE = new File( USER_MAVEN_CONFIGURATION_HOME, "settings.xml" ); + + public static final File DEFAULT_GLOBAL_SETTINGS_FILE = new File( System.getProperty( "maven.home", System + .getProperty( "user.dir", "" ) ), "conf/settings.xml" ); + + @Requirement + private Logger logger; + + @Requirement + private SettingsBuilder settingsBuilder; + + @Requirement + private SettingsDecrypter settingsDecrypter; + + @Override + public void process( CliRequest cliRequest ) + throws Exception + { + CommandLine commandLine = cliRequest.getCommandLine(); + String workingDirectory = cliRequest.getWorkingDirectory(); + MavenExecutionRequest request = cliRequest.getRequest(); + + File userSettingsFile; + + if ( commandLine.hasOption( CLIManager.ALTERNATE_USER_SETTINGS ) ) + { + userSettingsFile = new File( commandLine.getOptionValue( CLIManager.ALTERNATE_USER_SETTINGS ) ); + userSettingsFile = resolveFile( userSettingsFile, workingDirectory ); + + if ( !userSettingsFile.isFile() ) + { + throw new FileNotFoundException( "The specified user settings file does not exist: " + + userSettingsFile ); + } + } + else + { + userSettingsFile = DEFAULT_USER_SETTINGS_FILE; + } + + File globalSettingsFile; + + if ( commandLine.hasOption( CLIManager.ALTERNATE_GLOBAL_SETTINGS ) ) + { + globalSettingsFile = new File( commandLine.getOptionValue( CLIManager.ALTERNATE_GLOBAL_SETTINGS ) ); + globalSettingsFile = resolveFile( globalSettingsFile, workingDirectory ); + + if ( !globalSettingsFile.isFile() ) + { + throw new FileNotFoundException( "The specified global settings file does not exist: " + + globalSettingsFile ); + } + } + else + { + globalSettingsFile = DEFAULT_GLOBAL_SETTINGS_FILE; + } + + request.setGlobalSettingsFile( globalSettingsFile ); + request.setUserSettingsFile( userSettingsFile ); + + SettingsBuildingRequest settingsRequest = new DefaultSettingsBuildingRequest(); + settingsRequest.setGlobalSettingsFile( globalSettingsFile ); + settingsRequest.setUserSettingsFile( userSettingsFile ); + settingsRequest.setSystemProperties( cliRequest.getSystemProperties() ); + settingsRequest.setUserProperties( cliRequest.getUserProperties() ); + + if ( request.getEventSpyDispatcher() != null ) + { + request.getEventSpyDispatcher().onEvent( settingsRequest ); + } + + logger.debug( "Reading global settings from " + + getLocation( settingsRequest.getGlobalSettingsSource(), settingsRequest.getGlobalSettingsFile() ) ); + logger.debug( "Reading user settings from " + + getLocation( settingsRequest.getUserSettingsSource(), settingsRequest.getUserSettingsFile() ) ); + + SettingsBuildingResult settingsResult = settingsBuilder.build( settingsRequest ); + + if ( request.getEventSpyDispatcher() != null ) + { + request.getEventSpyDispatcher().onEvent( settingsResult ); + } + + populateFromSettings( request, settingsResult.getEffectiveSettings() ); + + if ( !settingsResult.getProblems().isEmpty() && logger.isWarnEnabled() ) + { + logger.warn( "" ); + logger.warn( "Some problems were encountered while building the effective settings" ); + + for ( SettingsProblem problem : settingsResult.getProblems() ) + { + logger.warn( problem.getMessage() + " @ " + problem.getLocation() ); + } + logger.warn( "" ); + } + + DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest(); + decrypt.setProxies( request.getProxies() ); + decrypt.setServers( request.getServers() ); + SettingsDecryptionResult decrypted = settingsDecrypter.decrypt( decrypt ); + + if ( logger.isDebugEnabled() ) + { + for ( SettingsProblem problem : decrypted.getProblems() ) + { + logger.debug( problem.getMessage(), problem.getException() ); + } + } + + request.setProxies( decrypt.getProxies() ); + request.setServers( decrypt.getServers() ); + } + + public MavenExecutionRequest populateFromSettings( MavenExecutionRequest request, Settings settings ) + throws MavenExecutionRequestPopulationException + { + if ( settings == null ) + { + return request; + } + + request.setOffline( settings.isOffline() ); + + request.setInteractiveMode( settings.isInteractiveMode() ); + + request.setPluginGroups( settings.getPluginGroups() ); + + request.setLocalRepositoryPath( settings.getLocalRepository() ); + + for ( Server server : settings.getServers() ) + { + server = server.clone(); + + request.addServer( server ); + } + + // + // + // true + // http + // proxy.somewhere.com + // 8080 + // proxyuser + // somepassword + // www.google.com|*.somewhere.com + // + // + + for ( Proxy proxy : settings.getProxies() ) + { + if ( !proxy.isActive() ) + { + continue; + } + + proxy = proxy.clone(); + + request.addProxy( proxy ); + } + + // + // + // nexus + // * + // http://repository.sonatype.org/content/groups/public + // + // + + for ( Mirror mirror : settings.getMirrors() ) + { + mirror = mirror.clone(); + + request.addMirror( mirror ); + } + + request.setActiveProfiles( settings.getActiveProfiles() ); + + for ( org.apache.maven.settings.Profile rawProfile : settings.getProfiles() ) + { + request.addProfile( SettingsUtils.convertFromSettingsProfile( rawProfile ) ); + + if ( settings.getActiveProfiles().contains( rawProfile.getId() ) ) + { + List remoteRepositories = rawProfile.getRepositories(); + for ( Repository remoteRepository : remoteRepositories ) + { + try + { + request.addRemoteRepository( + MavenRepositorySystem.buildArtifactRepository( remoteRepository ) ); + } + catch ( InvalidRepositoryException e ) + { + // do nothing for now + } + } + + List pluginRepositories = rawProfile.getPluginRepositories(); + for ( Repository pluginRepository : pluginRepositories ) + { + try + { + request.addPluginArtifactRepository( + MavenRepositorySystem.buildArtifactRepository( pluginRepository ) ); + } + catch ( InvalidRepositoryException e ) + { + // do nothing for now + } + } + } + } + return request; + } + + private Object getLocation( Source source, File defaultLocation ) + { + if ( source != null ) + { + return source.getLocation(); + } + return defaultLocation; + } + + static File resolveFile( File file, String workingDirectory ) + { + if ( file == null ) + { + return null; + } + else if ( file.isAbsolute() ) + { + return file; + } + else if ( file.getPath().startsWith( File.separator ) ) + { + // drive-relative Windows path + return file.getAbsoluteFile(); + } + else + { + return new File( workingDirectory, file.getPath() ).getAbsoluteFile(); + } + } +} diff --git a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java index 0c85dfb69c..c8d75b1040 100644 --- a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java +++ b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java @@ -24,7 +24,6 @@ import java.io.File; import junit.framework.TestCase; import org.apache.commons.cli.ParseException; -import org.apache.maven.cli.MavenCli.CliRequest; public class MavenCliTest extends TestCase