001package org.apache.maven.tools.plugin.generator;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.io.IOException;
024import java.io.InputStream;
025import java.io.InputStreamReader;
026import java.io.OutputStreamWriter;
027import java.io.StringWriter;
028import java.io.Writer;
029
030import org.apache.maven.project.MavenProject;
031import org.apache.velocity.VelocityContext;
032import org.codehaus.plexus.logging.AbstractLogEnabled;
033import org.codehaus.plexus.logging.Logger;
034import org.codehaus.plexus.logging.console.ConsoleLogger;
035import org.codehaus.plexus.util.StringUtils;
036import org.codehaus.plexus.util.io.CachingOutputStream;
037import org.codehaus.plexus.velocity.VelocityComponent;
038
039import static java.nio.charset.StandardCharsets.UTF_8;
040
041/**
042 * Generates an <code>HelpMojo</code> class from <code>help-class-source.vm</code> template.
043 * The generated mojo reads help content from <code>META-INF/maven/${groupId}/${artifactId}/plugin-help.xml</code>
044 * resource, which is generated by this {@link PluginDescriptorFilesGenerator}.
045 *
046 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
047 * @since 2.4
048 */
049public class PluginHelpGenerator
050    extends AbstractLogEnabled
051{
052    /**
053     * Default generated class name
054     */
055    private static final String HELP_MOJO_CLASS_NAME = "HelpMojo";
056
057    private String helpPackageName;
058    private String goalPrefix;
059    private MavenProject mavenProject;
060    private VelocityComponent velocityComponent;
061
062    /**
063     * Default constructor
064     */
065    public PluginHelpGenerator()
066    {
067        this.enableLogging( new ConsoleLogger( Logger.LEVEL_INFO, "PluginHelpGenerator" ) );
068    }
069
070    // ----------------------------------------------------------------------
071    // Public methods
072    // ----------------------------------------------------------------------
073
074    public void execute( File destinationDirectory )
075        throws GeneratorException
076    {
077        String helpImplementation = getImplementation();
078
079        try
080        {
081            String sourcePath = helpImplementation.replace( '.', File.separatorChar ) + ".java";
082
083            File helpClass = new File( destinationDirectory, sourcePath );
084            helpClass.getParentFile().mkdirs();
085
086            String helpClassSources =
087                getHelpClassSources( getPluginHelpPath( mavenProject ) );
088
089            try ( Writer w = new OutputStreamWriter( new CachingOutputStream( helpClass ), UTF_8 ) )
090            {
091                w.write( helpClassSources );
092            }
093        }
094        catch ( IOException e )
095        {
096            throw new GeneratorException( e.getMessage(), e );
097        }
098    }
099
100    public PluginHelpGenerator setHelpPackageName( String helpPackageName )
101    {
102        this.helpPackageName = helpPackageName;
103        return this;
104    }
105
106    public PluginHelpGenerator setVelocityComponent( VelocityComponent velocityComponent )
107    {
108        this.velocityComponent = velocityComponent;
109        return this;
110    }
111
112    public PluginHelpGenerator setGoalPrefix( String goalPrefix )
113    {
114        this.goalPrefix = goalPrefix;
115        return this;
116    }
117
118    public PluginHelpGenerator setMavenProject( MavenProject mavenProject )
119    {
120        this.mavenProject = mavenProject;
121        return this;
122    }
123
124    // ----------------------------------------------------------------------
125    // Private methods
126    // ----------------------------------------------------------------------
127
128    private String getHelpClassSources( String pluginHelpPath )
129        throws IOException
130    {
131        VelocityContext context = new VelocityContext();
132        boolean useAnnotations = mavenProject.getArtifactMap().containsKey(
133            "org.apache.maven.plugin-tools:maven-plugin-annotations" );
134
135        context.put( "helpPackageName", helpPackageName );
136        context.put( "pluginHelpPath", pluginHelpPath );
137        context.put( "artifactId", mavenProject.getArtifactId() );
138        // TODO: evaluate prefix from deserialized plugin
139        context.put( "goalPrefix", goalPrefix );
140        context.put( "useAnnotations", useAnnotations );
141
142        StringWriter stringWriter = new StringWriter();
143
144        // plugin-tools sources are UTF-8 (and even ASCII in this case))
145        try ( InputStream is = //
146                 Thread.currentThread().getContextClassLoader().getResourceAsStream( "help-class-source.vm" ); //
147             InputStreamReader isReader = new InputStreamReader( is, UTF_8 ) )
148        {
149            //isReader =
150            velocityComponent.getEngine().evaluate( context, stringWriter, "", isReader );
151        }
152        // Apply OS lineSeparator instead of template's lineSeparator to have consistent separators for
153        // all source files.
154        return stringWriter.toString().replaceAll( "(\r\n|\n|\r)", System.lineSeparator() );
155    }
156
157    /**
158     * @return The implementation.
159     */
160    private String getImplementation( )
161    {
162        return StringUtils.isEmpty( helpPackageName )
163            ? HELP_MOJO_CLASS_NAME
164            : helpPackageName + '.' + HELP_MOJO_CLASS_NAME;
165    }
166
167    static String getPluginHelpPath( MavenProject mavenProject )
168    {
169        return mavenProject.getGroupId() + "/" + mavenProject.getArtifactId() + "/plugin-help.xml";
170    }
171}