Repository: maven Updated Branches: refs/heads/MNG-6056 1c4f3b25e -> bf6aa97a6 (forced update)
[MNG-6056] Implement Feature Toggle Module to handle Feature Toggles o Implemented feature toggle module plus command line options etc. to activate feature and list available feature toggles. o Added example feature locations which should be removed before really using it. Project: http://git-wip-us.apache.org/repos/asf/maven/repo Commit: http://git-wip-us.apache.org/repos/asf/maven/commit/bf6aa97a Tree: http://git-wip-us.apache.org/repos/asf/maven/tree/bf6aa97a Diff: http://git-wip-us.apache.org/repos/asf/maven/diff/bf6aa97a Branch: refs/heads/MNG-6056 Commit: bf6aa97a61a345a9187229e3af25ff3f3bc231ba Parents: c2018a4 Author: Karl Heinz Marbaise <khmarba...@apache.org> Authored: Sat Jul 2 22:47:46 2016 +0200 Committer: Karl Heinz Marbaise <khmarba...@apache.org> Committed: Sat Jul 2 23:00:06 2016 +0200 ---------------------------------------------------------------------- maven-core/pom.xml | 4 + .../java/org/apache/maven/DefaultMaven.java | 16 ++ .../apache/maven/graph/DefaultGraphBuilder.java | 10 + maven-embedder/pom.xml | 4 + .../java/org/apache/maven/cli/CLIManager.java | 6 + .../java/org/apache/maven/cli/MavenCli.java | 221 ++++++++++++------- .../java/org/apache/maven/cli/MavenCliTest.java | 2 + maven-feature/pom.xml | 62 ++++++ .../apache/maven/feature/AvailableFeatures.java | 62 ++++++ .../maven/feature/DefaultSelectedFeatures.java | 75 +++++++ .../apache/maven/feature/SelectedFeatures.java | 56 +++++ .../feature/DefaultSelectedFeaturesTest.java | 58 +++++ pom.xml | 6 + 13 files changed, 508 insertions(+), 74 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-core/pom.xml ---------------------------------------------------------------------- diff --git a/maven-core/pom.xml b/maven-core/pom.xml index adf63a6..ec35f98 100644 --- a/maven-core/pom.xml +++ b/maven-core/pom.xml @@ -38,6 +38,10 @@ under the License. </properties> <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-feature</artifactId> + </dependency> <!-- Maven --> <dependency> <groupId>org.apache.maven</groupId> http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java ---------------------------------------------------------------------- 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 da17830..d2cabac 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -38,6 +38,8 @@ import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenExecutionResult; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.ProjectDependencyGraph; +import org.apache.maven.feature.AvailableFeatures; +import org.apache.maven.feature.SelectedFeatures; import org.apache.maven.graph.GraphBuilder; import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory; import org.apache.maven.lifecycle.internal.ExecutionEventCatapult; @@ -92,6 +94,9 @@ public class DefaultMaven @Requirement private DefaultRepositorySystemSessionFactory repositorySessionFactory; + + @Requirement + private SelectedFeatures selectedFeatures; @Requirement( hint = GraphBuilder.HINT ) private GraphBuilder graphBuilder; @@ -101,6 +106,17 @@ public class DefaultMaven { MavenExecutionResult result; + List<AvailableFeatures> activatedFeatures = selectedFeatures.getActiveFeatures(); + if ( !activatedFeatures.isEmpty() ) + { + logger.debug( "-------------------------------------------" ); + for ( AvailableFeatures feature : activatedFeatures ) + { + logger.debug( "Feature: " + feature.name() + " activated."); + } + logger.debug( "-------------------------------------------" ); + } + try { result = doExecute( request ); http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java ---------------------------------------------------------------------- diff --git a/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java b/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java index 680d584..fc78f78 100644 --- a/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java @@ -36,6 +36,8 @@ import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenExecutionResult; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.ProjectDependencyGraph; +import org.apache.maven.feature.AvailableFeatures; +import org.apache.maven.feature.SelectedFeatures; import org.apache.maven.model.Plugin; import org.apache.maven.model.building.DefaultModelProblem; import org.apache.maven.model.building.ModelProblem; @@ -65,6 +67,10 @@ public class DefaultGraphBuilder @Requirement protected ProjectBuilder projectBuilder; + + @Requirement + private SelectedFeatures selectedFeatures; + @Override public Result<ProjectDependencyGraph> build( MavenSession session ) @@ -74,6 +80,10 @@ public class DefaultGraphBuilder return dependencyGraph( session, session.getProjects(), false ); } + if (selectedFeatures.isFeatureActive( AvailableFeatures.MNG10000 )) { + logger.info( " -> Features MNG 10000 is activated." ); + } + List<MavenProject> projects = session.getProjects(); if ( projects == null ) http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-embedder/pom.xml ---------------------------------------------------------------------- diff --git a/maven-embedder/pom.xml b/maven-embedder/pom.xml index f9973c5..12fb613 100644 --- a/maven-embedder/pom.xml +++ b/maven-embedder/pom.xml @@ -36,6 +36,10 @@ under the License. <dependencies> <dependency> <groupId>org.apache.maven</groupId> + <artifactId>maven-feature</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> <artifactId>maven-builder-support</artifactId> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java ---------------------------------------------------------------------- diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java index f461835..59c7446 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java @@ -100,6 +100,10 @@ public class CLIManager public static final String LEGACY_LOCAL_REPOSITORY = "llr"; public static final String BUILDER = "b"; + + public static final String LIST_FEATURES = "lf"; + + public static final String ACTIVATE_FEATURES = "af"; protected Options options; @@ -140,6 +144,8 @@ public class CLIManager options.addOption( OptionBuilder.withLongOpt( "threads" ).hasArg().withDescription( "Thread count, for instance 2.0C where C is core multiplied" ).create( THREADS ) ); options.addOption( OptionBuilder.withLongOpt( "legacy-local-repository" ).withDescription( "Use Maven 2 Legacy Local Repository behaviour, ie no use of _remote.repositories. Can also be activated by using -Dmaven.legacyLocalRepo=true" ).create( LEGACY_LOCAL_REPOSITORY ) ); options.addOption( OptionBuilder.withLongOpt( "builder" ).hasArg().withDescription( "The id of the build strategy to use." ).create( BUILDER ) ); + options.addOption( OptionBuilder.withLongOpt( "list-features" ).withDescription( "List the exiting features which can be activated." ).create( LIST_FEATURES) ); + options.addOption( OptionBuilder.withLongOpt( "activate-features" ).withDescription( "Comma-delimited list of features to be actived." ).hasArg().create( ACTIVATE_FEATURES ) ); // Adding this back in for compatibility with the verifier that hard codes this option. options.addOption( OptionBuilder.withLongOpt( "no-plugin-registry" ).withDescription( "Ineffective, only kept for backward compatibility" ).create( "npr" ) ); http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java ---------------------------------------------------------------------- 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 3e1194b..ec8c2c9 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 @@ -41,9 +41,11 @@ import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; + import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.UnrecognizedOptionException; +import org.apache.commons.lang3.text.WordUtils; import org.apache.maven.BuildAbort; import org.apache.maven.InternalErrorException; import org.apache.maven.Maven; @@ -78,6 +80,8 @@ import org.apache.maven.execution.MavenExecutionRequestPopulator; import org.apache.maven.execution.MavenExecutionResult; import org.apache.maven.extension.internal.CoreExports; import org.apache.maven.extension.internal.CoreExtensionEntry; +import org.apache.maven.feature.AvailableFeatures; +import org.apache.maven.feature.SelectedFeatures; import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.model.Profile; import org.apache.maven.model.Repository; @@ -103,13 +107,11 @@ import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.classworlds.ClassWorld; import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.classworlds.realm.NoSuchRealmException; +import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.logging.LoggerManager; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import com.google.common.base.Charsets; -import com.google.common.io.Files; -import com.google.inject.AbstractModule; import org.eclipse.aether.transfer.TransferListener; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; @@ -120,6 +122,11 @@ import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; import org.sonatype.plexus.components.sec.dispatcher.SecUtil; import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity; +import com.google.common.base.Charsets; +import com.google.common.base.Splitter; +import com.google.common.io.Files; +import com.google.inject.AbstractModule; + // TODO: push all common bits back to plexus cli and prepare for transition to Guice. We don't need 50 ways to make CLIs /** @@ -185,6 +192,9 @@ public class MavenCli private Map<String, ConfigurationProcessor> configurationProcessors; private ProfileSelector profileSelector; + + @Requirement + private SelectedFeatures selectedFeatures; public MavenCli() { @@ -226,8 +236,8 @@ public class MavenCli } /** - * This supports painless invocation by the Verifier during embedded execution of the core ITs. - * See <a href="http://maven.apache.org/shared/maven-verifier/xref/org/apache/maven/it/Embedded3xLauncher.html"> + * This supports painless invocation by the Verifier during embedded execution of the core ITs. See + * <a href="http://maven.apache.org/shared/maven-verifier/xref/org/apache/maven/it/Embedded3xLauncher.html"> * <code>Embedded3xLauncher</code> in <code>maven-verifier</code></a> */ public int doMain( String[] args, String workingDirectory, PrintStream stdout, PrintStream stderr ) @@ -354,8 +364,7 @@ public class MavenCli String basedirProperty = System.getProperty( MULTIMODULE_PROJECT_DIRECTORY ); if ( basedirProperty == null ) { - System.err.format( - "-D%s system property is not set.", MULTIMODULE_PROJECT_DIRECTORY ); + System.err.format( "-D%s system property is not set.", MULTIMODULE_PROJECT_DIRECTORY ); throw new ExitException( 1 ); } File basedir = basedirProperty != null ? new File( basedirProperty ) : new File( "" ); @@ -446,6 +455,35 @@ public class MavenCli System.out.println( CLIReportingUtils.showVersion() ); throw new ExitException( 0 ); } + + if ( cliRequest.commandLine.hasOption( CLIManager.LIST_FEATURES ) ) + { + AvailableFeatures[] availableFeatures = AvailableFeatures.values(); + + System.out.println( "" ); + System.out.println( "Currently existing feature toggles which you can enable:" ); + System.out.println( "" ); + System.out.println( "Issue Option Description" ); + System.out.println( "--------- ------- ----------------------------------------------------" ); + for ( AvailableFeatures feature : availableFeatures ) + { + String wrappedString = WordUtils.wrap( feature.getDescription(), 60); + List<String> splitToList = Splitter.on( System.lineSeparator() ).splitToList( wrappedString ); + for ( int i = 0; i < splitToList.size(); i++ ) + { + if (i == 0) { + System.out.print (String.format( "%-9s %-8s", feature.getIssue(), feature.name()) + " "); + } else { + System.out.print (String.format( "%-9s %-8s", "", "" ) + " "); + } + System.out.println( splitToList.get( i )); + } + } + + System.out.println( "" ); + System.out.println( "If you like to know more about a particular issue please visit: issues.apache.org/jira/browse/[ISSUE]" ); + throw new ExitException( 0 ); + } } /** @@ -558,9 +596,8 @@ public class MavenCli ClassRealm containerRealm = setupContainerRealm( cliRequest.classWorld, coreRealm, extClassPath, extensions ); - ContainerConfiguration cc = new DefaultContainerConfiguration().setClassWorld( cliRequest.classWorld ).setRealm( - containerRealm ).setClassPathScanning( PlexusConstants.SCANNING_INDEX ).setAutoWiring( true ).setName( - "maven" ); + ContainerConfiguration cc = + new DefaultContainerConfiguration().setClassWorld( cliRequest.classWorld ).setRealm( containerRealm ).setClassPathScanning( PlexusConstants.SCANNING_INDEX ).setAutoWiring( true ).setName( "maven" ); Set<String> exportedArtifacts = new HashSet<>( coreEntry.getExportedArtifacts() ); Set<String> exportedPackages = new HashSet<>( coreEntry.getExportedPackages() ); @@ -598,6 +635,10 @@ public class MavenCli Thread.currentThread().setContextClassLoader( container.getContainerRealm() ); + //Explicitly startup lookup for the component, cause it's used during command line + //parsing etc. + selectedFeatures = container.lookup( SelectedFeatures.class ); + eventSpyDispatcher = container.lookup( EventSpyDispatcher.class ); DefaultEventSpyContext eventSpyContext = new DefaultEventSpyContext(); @@ -652,11 +693,11 @@ public class MavenCli } ContainerConfiguration cc = new DefaultContainerConfiguration() // - .setClassWorld( cliRequest.classWorld ) // - .setRealm( containerRealm ) // - .setClassPathScanning( PlexusConstants.SCANNING_INDEX ) // - .setAutoWiring( true ) // - .setName( "maven" ); + .setClassWorld( cliRequest.classWorld ) // + .setRealm( containerRealm ) // + .setClassPathScanning( PlexusConstants.SCANNING_INDEX ) // + .setAutoWiring( true ) // + .setName( "maven" ); DefaultPlexusContainer container = new DefaultPlexusContainer( cc, new AbstractModule() { @@ -722,7 +763,7 @@ public class MavenCli { CoreExtensionsXpp3Reader parser = new CoreExtensionsXpp3Reader(); - try ( InputStream is = new BufferedInputStream( new FileInputStream( extensionsFile ) ) ) + try (InputStream is = new BufferedInputStream( new FileInputStream( extensionsFile ) )) { return parser.read( is ).getExtensions(); @@ -732,7 +773,7 @@ public class MavenCli private ClassRealm setupContainerRealm( ClassWorld classWorld, ClassRealm coreRealm, List<File> extClassPath, List<CoreExtensionEntry> extensions ) - throws Exception + throws Exception { if ( !extClassPath.isEmpty() || !extensions.isEmpty() ) { @@ -828,8 +869,8 @@ public class MavenCli DefaultPlexusCipher cipher = new DefaultPlexusCipher(); - System.out.println( - cipher.encryptAndDecorate( passwd, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION ) ); + System.out.println( cipher.encryptAndDecorate( passwd, + DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION ) ); throw new ExitException( 0 ); } @@ -885,7 +926,7 @@ public class MavenCli throws Exception { if ( cliRequest.commandLine.hasOption( CLIManager.LEGACY_LOCAL_REPOSITORY ) - || Boolean.getBoolean( "maven.legacyLocalRepo" ) ) + || Boolean.getBoolean( "maven.legacyLocalRepo" ) ) { cliRequest.request.setUseLegacyLocalRepository( true ); } @@ -904,9 +945,8 @@ public class MavenCli profileActivationContext.setInactiveProfileIds( request.getInactiveProfiles() ); profileActivationContext.setSystemProperties( request.getSystemProperties() ); profileActivationContext.setUserProperties( request.getUserProperties() ); - profileActivationContext.setProjectDirectory( request.getPom() != null - ? request.getPom().getParentFile() - : null ); + profileActivationContext.setProjectDirectory( request.getPom() != null ? request.getPom().getParentFile() + : null ); final List<ModelProblem> modelProblems = new ArrayList<>(); final List<Profile> activeProfiles = @@ -917,10 +957,12 @@ public class MavenCli @Override public void add( final ModelProblemCollectorRequest req ) { - modelProblems.add( new DefaultModelProblem( - req.getMessage(), req.getSeverity(), - req.getVersion(), Profile.SOURCE_SETTINGS, -1, -1, - null, req.getException() ) ); + modelProblems.add( new DefaultModelProblem( req.getMessage(), + req.getSeverity(), + req.getVersion(), + Profile.SOURCE_SETTINGS, + -1, -1, null, + req.getException() ) ); } @@ -949,14 +991,14 @@ public class MavenCli { try { - request.addRemoteRepository( - MavenRepositorySystem.buildArtifactRepository( remoteRepository ) ); + request.addRemoteRepository( MavenRepositorySystem.buildArtifactRepository( remoteRepository ) ); } catch ( final InvalidRepositoryException e ) { slf4jLogger.warn( String.format( "Failure adding repository '%s' from profile '%s'.", - remoteRepository.getId(), profile.getId() ), e ); + remoteRepository.getId(), profile.getId() ), + e ); } } @@ -967,14 +1009,14 @@ public class MavenCli { try { - request.addPluginArtifactRepository( - MavenRepositorySystem.buildArtifactRepository( pluginRepository ) ); + request.addPluginArtifactRepository( MavenRepositorySystem.buildArtifactRepository( pluginRepository ) ); } catch ( InvalidRepositoryException e ) { slf4jLogger.warn( String.format( "Failure adding plugin repository '%s' from profile '%s'.", - pluginRepository.getId(), profile.getId() ), e ); + pluginRepository.getId(), profile.getId() ), + e ); } } @@ -1032,7 +1074,7 @@ public class MavenCli { slf4jLogger.error( "" ); slf4jLogger.error( "For more information about the errors and possible solutions" - + ", please read the following articles:" ); + + ", please read the following articles:" ); for ( Map.Entry<String, String> entry : references.entrySet() ) { @@ -1044,8 +1086,7 @@ public class MavenCli { slf4jLogger.error( "" ); slf4jLogger.error( "After correcting the problems, you can resume the build with the command" ); - slf4jLogger.error( buffer().strong().a( " mvn <goals> -rf :" ) - .a( project.getArtifactId() ).reset().toString() ); + slf4jLogger.error( buffer().strong().a( " mvn <goals> -rf :" ).a( project.getArtifactId() ).reset().toString() ); } if ( MavenExecutionRequest.REACTOR_FAIL_NEVER.equals( cliRequest.request.getReactorFailureBehavior() ) ) @@ -1100,8 +1141,8 @@ public class MavenCli { String line = indent + lines[i].trim(); - if ( ( i == lines.length - 1 ) && ( showErrors - || ( summary.getException() instanceof InternalErrorException ) ) ) + if ( ( i == lines.length - 1 ) + && ( showErrors || ( summary.getException() instanceof InternalErrorException ) ) ) { slf4jLogger.error( line, summary.getException() ); } @@ -1168,9 +1209,9 @@ public class MavenCli // // There are too many ConfigurationProcessors so we don't know which one to run so report the error. // - StringBuilder sb = new StringBuilder( - String.format( "\nThere can only be one user supplied ConfigurationProcessor, there are %s:\n\n", - userSuppliedConfigurationProcessorCount ) ); + StringBuilder sb = + new StringBuilder( String.format( "\nThere can only be one user supplied ConfigurationProcessor, there are %s:\n\n", + userSuppliedConfigurationProcessorCount ) ); for ( Entry<String, ConfigurationProcessor> entry : configurationProcessors.entrySet() ) { String hint = entry.getKey(); @@ -1199,8 +1240,8 @@ public class MavenCli if ( !userToolchainsFile.isFile() ) { - throw new FileNotFoundException( - "The specified user toolchains file does not exist: " + userToolchainsFile ); + throw new FileNotFoundException( "The specified user toolchains file does not exist: " + + userToolchainsFile ); } } else @@ -1218,8 +1259,8 @@ public class MavenCli if ( !globalToolchainsFile.isFile() ) { - throw new FileNotFoundException( - "The specified global toolchains file does not exist: " + globalToolchainsFile ); + throw new FileNotFoundException( "The specified global toolchains file does not exist: " + + globalToolchainsFile ); } } else @@ -1242,11 +1283,10 @@ public class MavenCli eventSpyDispatcher.onEvent( toolchainsRequest ); - slf4jLogger.debug( - "Reading global toolchains from " + getLocation( toolchainsRequest.getGlobalToolchainsSource(), - globalToolchainsFile ) ); - slf4jLogger.debug( "Reading user toolchains from " + getLocation( toolchainsRequest.getUserToolchainsSource(), - userToolchainsFile ) ); + slf4jLogger.debug( "Reading global toolchains from " + + getLocation( toolchainsRequest.getGlobalToolchainsSource(), globalToolchainsFile ) ); + slf4jLogger.debug( "Reading user toolchains from " + + getLocation( toolchainsRequest.getUserToolchainsSource(), userToolchainsFile ) ); ToolchainsBuildingResult toolchainsResult = toolchainsBuilder.build( toolchainsRequest ); @@ -1296,7 +1336,7 @@ public class MavenCli if ( commandLine.hasOption( deprecatedOption ) ) { slf4jLogger.warn( "Command line option -" + deprecatedOption - + " is deprecated and will be removed in future Maven versions." ); + + " is deprecated and will be removed in future Maven versions." ); } } @@ -1450,19 +1490,20 @@ public class MavenCli userToolchainsFile = MavenCli.DEFAULT_USER_TOOLCHAINS_FILE; } - request.setBaseDirectory( baseDirectory ).setGoals( goals ).setSystemProperties( - cliRequest.systemProperties ).setUserProperties( cliRequest.userProperties ).setReactorFailureBehavior( - reactorFailureBehaviour ) // default: fail fast - .setRecursive( recursive ) // default: true - .setShowErrors( showErrors ) // default: false - .addActiveProfiles( activeProfiles ) // optional - .addInactiveProfiles( inactiveProfiles ) // optional - .setExecutionListener( executionListener ).setTransferListener( - transferListener ) // default: batch mode which goes along with interactive - .setUpdateSnapshots( updateSnapshots ) // default: false - .setNoSnapshotUpdates( noSnapshotUpdates ) // default: false - .setGlobalChecksumPolicy( globalChecksumPolicy ) // default: warn - .setMultiModuleProjectDirectory( cliRequest.multiModuleProjectDirectory ); + request.setBaseDirectory( baseDirectory ).setGoals( goals ).setSystemProperties( cliRequest.systemProperties ).setUserProperties( cliRequest.userProperties ).setReactorFailureBehavior( reactorFailureBehaviour ) // default: + // fail + // fast + .setRecursive( recursive ) // default: true + .setShowErrors( showErrors ) // default: false + .addActiveProfiles( activeProfiles ) // optional + .addInactiveProfiles( inactiveProfiles ) // optional + .setExecutionListener( executionListener ).setTransferListener( transferListener ) // default: batch mode which + // goes along with + // interactive + .setUpdateSnapshots( updateSnapshots ) // default: false + .setNoSnapshotUpdates( noSnapshotUpdates ) // default: false + .setGlobalChecksumPolicy( globalChecksumPolicy ) // default: warn + .setMultiModuleProjectDirectory( cliRequest.multiModuleProjectDirectory ); if ( alternatePomFile != null ) { @@ -1531,18 +1572,18 @@ public class MavenCli request.setExcludedProjects( exclProjects ); } - if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && !commandLine.hasOption( - CLIManager.ALSO_MAKE_DEPENDENTS ) ) + if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) + && !commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) ) { request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM ); } - else if ( !commandLine.hasOption( CLIManager.ALSO_MAKE ) && commandLine.hasOption( - CLIManager.ALSO_MAKE_DEPENDENTS ) ) + else if ( !commandLine.hasOption( CLIManager.ALSO_MAKE ) + && commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) ) { request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM ); } - else if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && commandLine.hasOption( - CLIManager.ALSO_MAKE_DEPENDENTS ) ) + else if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) + && commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) ) { request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_BOTH ); } @@ -1570,10 +1611,13 @@ public class MavenCli // parameters but this is sufficient for now. Ultimately we want components like Builders to provide a way to // extend the command line to accept its own configuration parameters. // - final String threadConfiguration = commandLine.hasOption( CLIManager.THREADS ) - ? commandLine.getOptionValue( CLIManager.THREADS ) - : request.getSystemProperties().getProperty( - MavenCli.THREADS_DEPRECATED ); // TODO: Remove this setting. Note that the int-tests use it + final String threadConfiguration = + commandLine.hasOption( CLIManager.THREADS ) ? commandLine.getOptionValue( CLIManager.THREADS ) + : request.getSystemProperties().getProperty( MavenCli.THREADS_DEPRECATED ); // TODO: Remove + // this setting. + // Note that the + // int-tests use + // it if ( threadConfiguration != null ) { @@ -1600,6 +1644,35 @@ public class MavenCli request.setBuilderId( commandLine.getOptionValue( CLIManager.BUILDER ) ); } + if ( commandLine.hasOption( CLIManager.ACTIVATE_FEATURES ) ) + { + String activateFeaturesOptionValue = commandLine.getOptionValue( CLIManager.ACTIVATE_FEATURES ); + + List<AvailableFeatures> activatedFeatures = new ArrayList<>(); + + if ( activateFeaturesOptionValue != null ) + { + StringTokenizer featureTokens = new StringTokenizer( activateFeaturesOptionValue, "," ); + + while ( featureTokens.hasMoreTokens() ) + { + String featureToken = featureTokens.nextToken().trim(); + + try + { + AvailableFeatures resultingFeature = AvailableFeatures.valueOf( featureToken.toUpperCase() ); + activatedFeatures.add( resultingFeature ); + } + catch ( java.lang.IllegalArgumentException e ) + { + slf4jLogger.warn( "The requested feature '" + featureToken + "' Does not exist." ); + } + } + } + + selectedFeatures.setActivatedFeatures( activatedFeatures ); + } + return request; } http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java ---------------------------------------------------------------------- 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 c8d75b1..6bd5f5b 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,6 +24,7 @@ import java.io.File; import junit.framework.TestCase; import org.apache.commons.cli.ParseException; +import org.apache.maven.feature.AvailableFeatures; public class MavenCliTest extends TestCase @@ -107,4 +108,5 @@ public class MavenCliTest } } + } http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-feature/pom.xml ---------------------------------------------------------------------- diff --git a/maven-feature/pom.xml b/maven-feature/pom.xml new file mode 100644 index 0000000..0ddd5fc --- /dev/null +++ b/maven-feature/pom.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + 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. +--> + +<project + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.maven</groupId> + <artifactId>maven</artifactId> + <version>3.4.0-SNAPSHOT</version> + </parent> + + <artifactId>maven-feature</artifactId> + + <name>Maven Feature</name> + <description>Feature Toggle Module. Can be used in any other module.</description> + + <dependencies> + <dependency> + <groupId>org.eclipse.sisu</groupId> + <artifactId>org.eclipse.sisu.plexus</artifactId> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-component-annotations</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-component-metadata</artifactId> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-feature/src/main/java/org/apache/maven/feature/AvailableFeatures.java ---------------------------------------------------------------------- diff --git a/maven-feature/src/main/java/org/apache/maven/feature/AvailableFeatures.java b/maven-feature/src/main/java/org/apache/maven/feature/AvailableFeatures.java new file mode 100644 index 0000000..473a40c --- /dev/null +++ b/maven-feature/src/main/java/org/apache/maven/feature/AvailableFeatures.java @@ -0,0 +1,62 @@ +package org.apache.maven.feature; + +/* + * 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. + */ + +/** + * @author Karl Heinz Marbaise <a href="mailto:khmarba...@apache.org">khmarba...@apache.org</a> + * + * @since 3.4.0 + */ +public enum AvailableFeatures +{ + + //FIXME: Only some examples given. Nothing which exists in reality. + + MNG9991( "MNG-9991", "First Feature to be toggable via command line option. " + + "First Feature to be toggable via command line option." ), + MNG9992( "MNG-9992", "First Feature to be toggable via command line option. " + + "First Feature to be toggable via command line option. XX asdfa. asdf dsf." ), + MNG9993( "MNG-9993", "First Feature to be toggable via command line option. " + + "More text than you think." ), + MNG10000( "MNG-10000", "First Feature to be toggable via command line option. " + + "Here much more than you thing." ); + +// UNKNONW ("UNKNOWN", "The unknown feature."); + + private String issue; + + private String description; + + private AvailableFeatures( String issue, String description ) + { + this.issue = issue; + this.description = description; + } + + public String getDescription() + { + return this.description; + } + + public String getIssue() + { + return this.issue; + } +} http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-feature/src/main/java/org/apache/maven/feature/DefaultSelectedFeatures.java ---------------------------------------------------------------------- diff --git a/maven-feature/src/main/java/org/apache/maven/feature/DefaultSelectedFeatures.java b/maven-feature/src/main/java/org/apache/maven/feature/DefaultSelectedFeatures.java new file mode 100644 index 0000000..cc11462 --- /dev/null +++ b/maven-feature/src/main/java/org/apache/maven/feature/DefaultSelectedFeatures.java @@ -0,0 +1,75 @@ +package org.apache.maven.feature; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.codehaus.plexus.logging.Logger; + +@Component( instantiationStrategy = "singleton", role = SelectedFeatures.class ) +public class DefaultSelectedFeatures + implements SelectedFeatures +{ + @Requirement + private Logger logger; + + private List<AvailableFeatures> activatedFeatures; + + @Override + public void setActivatedFeatures( List<AvailableFeatures> featuresToBeActivated ) + { + if ( featuresToBeActivated == null ) + { + this.activatedFeatures = new ArrayList<>(); + } + else + { + this.activatedFeatures = featuresToBeActivated; + } + } + + @Override + public boolean isFeatureActive( AvailableFeatures feature ) + { + if ( activatedFeatures != null ) + { + return activatedFeatures.contains( feature ); + } + return false; + } + + @Override + public List<AvailableFeatures> getActiveFeatures() + { + if ( activatedFeatures == null ) + { + return Collections.emptyList(); + } + else + { + return activatedFeatures; + } + } + +} http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-feature/src/main/java/org/apache/maven/feature/SelectedFeatures.java ---------------------------------------------------------------------- diff --git a/maven-feature/src/main/java/org/apache/maven/feature/SelectedFeatures.java b/maven-feature/src/main/java/org/apache/maven/feature/SelectedFeatures.java new file mode 100644 index 0000000..6f6007a --- /dev/null +++ b/maven-feature/src/main/java/org/apache/maven/feature/SelectedFeatures.java @@ -0,0 +1,56 @@ +package org.apache.maven.feature; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.List; + +/** + * This gives access to the feature storage which can be used during the + * run of Maven to access information about the activated features. + * + * @author Karl Heinz Marbaise <a href="mailto:khmarba...@apache.org">khmarba...@apache.org</a> + * + * @since 3.4.0 + */ +public interface SelectedFeatures +{ + + /** + * @since 3.4.0 + * @return The list of features which will be activated. + */ + void setActivatedFeatures(List<AvailableFeatures> activatedFeatures); + + /** + * @param feature The feature to check for if it is activated or not. + * @return <code>true</code> in case of feature has been activated via command line. + * <code>--activate-feature FEATURE</code> <code>false</code> otherwise. + * @since 3.4.0 + */ + boolean isFeatureActive(AvailableFeatures feature); + + /** + * @return The list of features which are activated. + * @since 3.4.0 + */ + List<AvailableFeatures> getActiveFeatures(); + + +} http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/maven-feature/src/test/java/org/apache/maven/feature/DefaultSelectedFeaturesTest.java ---------------------------------------------------------------------- diff --git a/maven-feature/src/test/java/org/apache/maven/feature/DefaultSelectedFeaturesTest.java b/maven-feature/src/test/java/org/apache/maven/feature/DefaultSelectedFeaturesTest.java new file mode 100644 index 0000000..0790134 --- /dev/null +++ b/maven-feature/src/test/java/org/apache/maven/feature/DefaultSelectedFeaturesTest.java @@ -0,0 +1,58 @@ +package org.apache.maven.feature; + +/* + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.junit.Test; + +public class DefaultSelectedFeaturesTest +{ + + @Test + public void getActiveFeaturesShouldNotReturnNull() + { + DefaultSelectedFeatures sf = new DefaultSelectedFeatures(); + assertNotNull( sf.getActiveFeatures() ); + assertEquals( sf.getActiveFeatures().size(), 0 ); + } + + @Test + public void isFeatureActiveShouldReturnFalse() + { + DefaultSelectedFeatures sf = new DefaultSelectedFeatures(); + assertFalse( sf.isFeatureActive( AvailableFeatures.MNG10000 ) ); + } + + @Test + public void isFeatureActiveShouldReturnFalseIfNotTheCorrectFeatureIsActivated() + { + DefaultSelectedFeatures sf = new DefaultSelectedFeatures(); + + sf.setActivatedFeatures( Arrays.asList( AvailableFeatures.MNG9991, AvailableFeatures.MNG9992 ) ); + assertFalse( sf.isFeatureActive( AvailableFeatures.MNG10000 ) ); + assertTrue( sf.isFeatureActive( AvailableFeatures.MNG9991 ) ); + } +} http://git-wip-us.apache.org/repos/asf/maven/blob/bf6aa97a/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index c447507..4e4ec05 100644 --- a/pom.xml +++ b/pom.xml @@ -81,6 +81,7 @@ under the License. </properties> <modules> + <module>maven-feature</module> <module>maven-plugin-api</module> <module>maven-builder-support</module> <module>maven-model</module> @@ -165,6 +166,11 @@ under the License. <dependencyManagement> <!--bootstrap-end-comment--> <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-feature</artifactId> + <version>${project.version}</version> + </dependency> <!-- Maven Modules --> <!--bootstrap-start-comment--> <dependency>