[MNG-5222] Improvement in deprecated params detection

This commit is contained in:
Slawomir Jaranowski 2022-04-15 20:52:02 +02:00
parent bdfd8de968
commit 9ac2d08dc7
4 changed files with 180 additions and 118 deletions

View File

@ -143,6 +143,7 @@ public class DefaultMavenPluginManager
private PluginVersionResolver pluginVersionResolver;
private PluginArtifactsCache pluginArtifactsCache;
private MavenPluginValidator pluginValidator;
private MavenPluginConfigurationValidator configurationValidator;
private final ExtensionDescriptorBuilder extensionDescriptorBuilder = new ExtensionDescriptorBuilder();
private final PluginDescriptorBuilder builder = new PluginDescriptorBuilder();
@ -158,7 +159,8 @@ public DefaultMavenPluginManager(
ExtensionRealmCache extensionRealmCache,
PluginVersionResolver pluginVersionResolver,
PluginArtifactsCache pluginArtifactsCache,
MavenPluginValidator pluginValidator )
MavenPluginValidator pluginValidator,
MavenPluginConfigurationValidator configurationValidator )
{
this.container = container;
this.classRealmManager = classRealmManager;
@ -170,6 +172,7 @@ public DefaultMavenPluginManager(
this.pluginVersionResolver = pluginVersionResolver;
this.pluginArtifactsCache = pluginArtifactsCache;
this.pluginValidator = pluginValidator;
this.configurationValidator = configurationValidator;
}
public synchronized PluginDescriptor getPluginDescriptor( Plugin plugin, List<RemoteRepository> repositories,
@ -603,6 +606,8 @@ else if ( cause instanceof LinkageError )
ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution );
configurationValidator.validate( mojoDescriptor, pomConfiguration, expressionEvaluator );
populateMojoExecutionFields( mojo, mojoExecution.getExecutionId(), mojoDescriptor, pluginRealm,
pomConfiguration, expressionEvaluator );
@ -638,7 +643,7 @@ private void populateMojoExecutionFields( Object mojo, String executionId, MojoD
ConfigurationListener listener = new DebugConfigurationListener( logger );
ValidatingConfigurationListener validator =
new ValidatingConfigurationListener( mojo, mojoDescriptor, listener, expressionEvaluator );
new ValidatingConfigurationListener( mojo, mojoDescriptor, listener );
logger.debug( "Configuring mojo execution '" + mojoDescriptor.getId() + ':' + executionId + "' with "
+ configuratorId + " configurator -->" );

View File

@ -0,0 +1,133 @@
package org.apache.maven.plugin.internal;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Print warnings if deprecated params of plugin are used in configuration.
*
* @author Slawomir Jaranowski
*/
@Named
@Singleton
class DeprecatedPluginValidator implements MavenPluginConfigurationValidator
{
private static final Logger LOGGER = LoggerFactory.getLogger( DeprecatedPluginValidator.class );
@Override
public void validate( MojoDescriptor mojoDescriptor,
PlexusConfiguration pomConfiguration,
ExpressionEvaluator expressionEvaluator )
{
if ( !LOGGER.isWarnEnabled() )
{
return;
}
if ( mojoDescriptor.getParameters() == null )
{
return;
}
mojoDescriptor.getParameters().stream()
.filter( parameter -> parameter.getDeprecated() != null )
.filter( Parameter::isEditable )
.forEach( parameter -> checkParameter( parameter, pomConfiguration, expressionEvaluator ) );
}
private static void checkParameter( Parameter parameter,
PlexusConfiguration pomConfiguration,
ExpressionEvaluator expressionEvaluator )
{
PlexusConfiguration config = pomConfiguration.getChild( parameter.getName(), false );
if ( isValueSet( config, expressionEvaluator ) )
{
logDeprecateWarn( parameter );
}
}
private static boolean isValueSet( PlexusConfiguration config,
ExpressionEvaluator expressionEvaluator )
{
if ( config == null )
{
return false;
}
// there are sub items ... so configuration is declared
if ( config.getChildCount() > 0 )
{
return true;
}
String strValue = config.getValue();
if ( strValue == null || strValue.isEmpty() )
{
return false;
}
// for declaration like @Parameter( property = "config.property" )
// the value will contains ${config.property}
try
{
return expressionEvaluator.evaluate( strValue ) != null;
}
catch ( ExpressionEvaluationException e )
{
// not important
// will be reported during Mojo fields populate
}
// fallback - in case of error in expressionEvaluator
return false;
}
private static void logDeprecateWarn( Parameter parameter )
{
StringBuilder sb = new StringBuilder();
sb.append( "Parameter '" );
sb.append( parameter.getName() );
sb.append( '\'' );
if ( parameter.getExpression() != null )
{
String userProperty = parameter.getExpression().replace( "${", "'" ).replace( '}', '\'' );
sb.append( " (user property " );
sb.append( userProperty );
sb.append( ")" );
}
sb.append( " is deprecated: " );
sb.append( parameter.getDeprecated() );
LOGGER.warn( MessageUtils.buffer().warning( sb.toString() ).toString() );
}
}

View File

@ -0,0 +1,39 @@
package org.apache.maven.plugin.internal;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.configuration.PlexusConfiguration;
/**
* Service responsible for validating plugin configuration.
*
* @author Slawomir Jaranowski
*/
interface MavenPluginConfigurationValidator
{
/**
* Check mojo configuration.
*/
void validate( MojoDescriptor mojoDescriptor,
PlexusConfiguration pomConfiguration,
ExpressionEvaluator expressionEvaluator );
}

View File

@ -19,22 +19,13 @@
* under the License.
*/
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.codehaus.plexus.component.configurator.ConfigurationListener;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A configuration listener to help validate the plugin configuration. For instance, check for required but missing
@ -45,25 +36,16 @@
class ValidatingConfigurationListener
implements ConfigurationListener
{
private static final Logger LOGGER = LoggerFactory.getLogger( ValidatingConfigurationListener.class );
private final Object mojo;
private final ConfigurationListener delegate;
private final MojoDescriptor mojoDescriptor;
private final ExpressionEvaluator expressionEvaluator;
private final Map<String, Parameter> missingParameters;
ValidatingConfigurationListener( Object mojo, MojoDescriptor mojoDescriptor, ConfigurationListener delegate,
ExpressionEvaluator expressionEvaluator )
ValidatingConfigurationListener( Object mojo, MojoDescriptor mojoDescriptor, ConfigurationListener delegate )
{
this.mojo = mojo;
this.delegate = delegate;
this.mojoDescriptor = mojoDescriptor;
this.expressionEvaluator = expressionEvaluator;
this.missingParameters = new HashMap<>();
if ( mojoDescriptor.getParameters() != null )
@ -109,102 +91,5 @@ private void notify( String fieldName, Object value )
{
missingParameters.remove( fieldName );
}
if ( LOGGER.isWarnEnabled() )
{
warnDeprecated( fieldName, value );
}
}
private void warnDeprecated( String fieldName, Object value )
{
Parameter parameter = mojoDescriptor.getParameterMap().get( fieldName );
String deprecated = parameter.getDeprecated();
if ( deprecated != null )
{
Object defaultValue = evaluateValue( parameter.getDefaultValue() );
if ( !Objects.equals( toString( value ), defaultValue ) )
{
StringBuilder sb = new StringBuilder();
sb.append( " Parameter '" );
sb.append( fieldName );
sb.append( '\'' );
if ( parameter.getExpression() != null )
{
String userProperty = parameter.getExpression().replace( "${", "'" ).replace( '}', '\'' );
sb.append( " (user property " );
sb.append( userProperty );
sb.append( ")" );
}
sb.append( " is deprecated: " );
sb.append( deprecated );
LOGGER.warn( MessageUtils.buffer().warning( sb.toString() ).toString() );
}
}
}
private Object evaluateValue( String value )
{
try
{
return expressionEvaluator.evaluate( value );
}
catch ( ExpressionEvaluationException e )
{
// should not happen here
}
return value;
}
/**
* Creates a string representation of the specified object for comparing with default values.
*
* @param obj The object to create a string representation for, may be <code>null</code>.
* @return The string representation, null for empty arrays / collections.
*/
private static String toString( Object obj )
{
String str;
if ( obj != null && obj.getClass().isArray() )
{
int n = Array.getLength( obj );
if ( n == 0 )
{
str = null;
}
else
{
StringJoiner sj = new StringJoiner( "," );
for ( int i = 0; i < n; i++ )
{
sj.add( String.valueOf( Array.get( obj, i ) ) );
}
str = sj.toString();
}
}
else if ( obj instanceof Collection )
{
Collection<?> collection = (Collection<?>) obj;
if ( collection.isEmpty() )
{
str = null;
}
else
{
Iterator<?> it = collection.iterator();
StringJoiner sj = new StringJoiner( "," );
while ( it.hasNext() )
{
sj.add( String.valueOf( it.next() ) );
}
str = sj.toString();
}
}
else
{
str = String.valueOf( obj );
}
return str;
}
}