blob: d4b8947a02885e7a650fd112ce07322b9de5ac01 [file] [log] [blame]
/*
* 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 bsh.*;
import java.util.regex.Pattern;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import org.codehaus.plexus.util.StringUtils;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
// only on start of line
this.tag = "\\r?\\n\\s*\\*?\\s*@(\\w+)";
// zero width lookahead to next tag or end of comment
this.tagOrEndComment = "(?=" + tag + "|\\*/)";
this.commentTextPattern = Pattern.compile( "(?s)/\\*\\*(.*?)" + tagOrEndComment );
this.tagsPattern = Pattern.compile( "(?s)" + tag + "\\s*(.*?)" + tagOrEndComment );
this.descriptionPattern = Pattern.compile( "(?s)\\r?\\n\\s*\\*" );
this.typePattern = Pattern.compile( "type\\s*=\\s*\"(.*?)\"" );
this.expressionPattern = Pattern.compile( "expression\\s*=\\s*\"(.*?)\"" );
this.defaultValuePattern = Pattern.compile( "default-value\\s*=\\s*\"(.*?)\"" );
this.phasePattern = Pattern.compile( "phase\\s*=\\s*\"(.*?)\"" );
this.goalPattern = Pattern.compile( "goal\\s*=\\s*\"(.*?)\"" );
this.lifecyclePattern = Pattern.compile( "lifecycle\\s*=\\s*\"(.*?)\"" );
this.rolePattern = Pattern.compile( "role\\s*=\\s*\"(.*?)\"" );
this.roleHintPattern = Pattern.compile( "roleHint\\s*=\\s*\"(.*?)\"" );
setAccessibility( true );
createParameter( text, method )
{
if ( method.startsWith( "set" ) )
{
this.name = StringUtils.uncapitalise( method.substring( 3 ) );
this.desc = getDescription( text );
this.tags = getTags( text );
this.parameter = new Parameter();
parameter.setName( name );
parameter.setDescription( desc );
parameter.setRequired( tags.containsKey( "required" ) );
parameter.setEditable( !tags.containsKey( "readonly" ) );
this.deprecation = tags.get( "deprecated" );
if ( deprecation != null )
{
parameter.setDeprecated( deprecation );
}
this.alias = tags.get( "alias" );
if ( alias != null )
{
parameter.setAlias( alias );
}
this.value = tags.get( "parameter" );
if ( value != null )
{
m = typePattern.matcher( value );
if ( m.find() )
{
parameter.setType( m.group( 1 ) );
}
else
{
parameter.setType( "java.lang.Object" );
}
m = expressionPattern.matcher( value );
if ( m.find() )
{
parameter.setExpression( m.group( 1 ) );
}
m = defaultValuePattern.matcher( value );
if ( m.find() )
{
parameter.setDefaultValue( m.group( 1 ) );
}
}
value = tags.get( "component" );
if ( value != null )
{
m = rolePattern.matcher( value );
if ( m.find() )
{
role = m.group( 1 );
}
m = roleHintPattern.matcher( value );
if ( m.find() )
{
roleHint = m.group( 1 );
}
else
{
roleHint = null;
}
parameter.setRequirement( new Requirement( role, roleHint ) );
}
return parameter;
}
return null;
}
getTags( text )
{
this.matcher = tagsPattern.matcher( text );
this.tags = new HashMap();
while ( matcher.find() )
{
this.tagname = matcher.group( 1 );
this.tagvalue = matcher.group( 2 );
tags.put( tagname, tagvalue.trim() );
}
return tags;
}
getDescription( text )
{
this.matcher = commentTextPattern.matcher( text );
if ( matcher.find() )
{
this.input = matcher.group( 1 );
return descriptionPattern.matcher( input ).replaceAll( "" ).trim();
}
else
{
return "";
}
}
extract( file, encoding, mojoDescriptor )
{
this.parser = new Parser( new InputStreamReader( new FileInputStream( file ), encoding ) );
parser.setRetainComments( true );
this.lastNode = null;
this.firstComment = null;
while ( !parser.Line() )
{
this.node = parser.popNode();
if ( node instanceof BSHFormalComment && firstComment == null )
{
firstComment = node;
}
if ( node instanceof BSHMethodDeclaration )
{
if ( lastNode instanceof BSHFormalComment )
{
this.text = lastNode.text;
this.method = node.name;
this.parameter = createParameter( text, method );
if ( parameter != null )
{
if ( "${reports}".equals( parameter.getExpression() ) )
{
mojoDescriptor.setRequiresReports( true );
}
mojoDescriptor.addParameter( parameter );
}
if ( firstComment == lastNode )
{
firstComment = null;
}
}
}
lastNode = node;
}
if ( firstComment != null )
{
this.text = firstComment.text;
mojoDescriptor.setDescription( getDescription( text ) );
this.tags = getTags( text );
mojoDescriptor.setGoal( tags.get( "goal" ) );
mojoDescriptor.setPhase( tags.get( "phase" ) );
this.value = tags.get( "requiresDependencyResolution" );
// TODO: share with java extractor
if ( value == null || value.length() == 0 )
{
value = "runtime";
}
mojoDescriptor.setDependencyResolutionRequired( value );
mojoDescriptor.setProjectRequired( tags.containsKey( "requiresProject" ) );
mojoDescriptor.setOnlineRequired( tags.containsKey( "requiresOnline" ) );
this.value = tags.get( "execute" );
if ( value != null )
{
m = phasePattern.matcher( value );
if ( m.find() )
{
mojoDescriptor.setExecutePhase( m.group( 1 ) );
}
m = goalPattern.matcher( value );
if ( m.find() )
{
mojoDescriptor.setExecuteGoal( m.group( 1 ) );
}
if ( mojoDescriptor.getExecutePhase() == null || mojoDescriptor.getExecuteGoal() == null )
{
throw new InvalidPluginDescriptorException( "@execute must have a phase or goal" );
}
if ( mojoDescriptor.getExecutePhase() != null && mojoDescriptor.getExecuteGoal() != null )
{
throw new InvalidPluginDescriptorException( "@execute must have only one of a phase or goal" );
}
m = lifecyclePattern.matcher( value );
if ( m.find() )
{
mojoDescriptor.setExecuteLifecycle( m.group( 1 ) );
if ( mojoDescriptor.getExecuteGoal() != null )
{
throw new InvalidPluginDescriptorException( "@execute lifecycle requires a phase instead of a goal" );
}
}
}
}
}
extract( file, encoding, mojoDescriptor );