001    package org.codehaus.mojo.license;
002    
003    import java.util.ArrayList;
004    import java.util.Iterator;
005    import java.util.List;
006    
007    import org.apache.maven.plugin.AbstractMojo;
008    import org.apache.maven.plugin.MojoExecutionException;
009    
010    /**
011     * Display help information on license-maven-plugin.<br/> Call <pre>  mvn license:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</pre> to display parameter details.
012     *
013     * @version generated on Wed Jan 18 00:55:04 UTC 2012
014     * @author org.apache.maven.tools.plugin.generator.PluginHelpGenerator (version 2.7)
015     * @goal help
016     * @requiresProject false
017     * @threadSafe
018     */
019    public class HelpMojo
020        extends AbstractMojo
021    {
022        /**
023         * If <code>true</code>, display all settable properties for each goal.
024         * 
025         * @parameter expression="${detail}" default-value="false"
026         */
027        private boolean detail;
028    
029        /**
030         * The name of the goal for which to show help. If unspecified, all goals will be displayed.
031         * 
032         * @parameter expression="${goal}"
033         */
034        private java.lang.String goal;
035    
036        /**
037         * The maximum length of a display line, should be positive.
038         * 
039         * @parameter expression="${lineLength}" default-value="80"
040         */
041        private int lineLength;
042    
043        /**
044         * The number of spaces per indentation level, should be positive.
045         * 
046         * @parameter expression="${indentSize}" default-value="2"
047         */
048        private int indentSize;
049    
050    
051        /** {@inheritDoc} */
052        public void execute()
053            throws MojoExecutionException
054        {
055            if ( lineLength <= 0 )
056            {
057                getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
058                lineLength = 80;
059            }
060            if ( indentSize <= 0 )
061            {
062                getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
063                indentSize = 2;
064            }
065    
066            StringBuffer sb = new StringBuffer();
067    
068            append( sb, "org.kuali.maven.plugins:license-maven-plugin:1.0-kuali", 0 );
069            append( sb, "", 0 );
070    
071            append( sb, "License Maven Plugin", 0 );
072            append( sb, "Maven plugin to download and collect license files from project dependencies.", 1 );
073            append( sb, "", 0 );
074    
075            if ( goal == null || goal.length() <= 0 )
076            {
077                append( sb, "This plugin has 8 goals:", 0 );
078                append( sb, "", 0 );
079            }
080    
081            if ( goal == null || goal.length() <= 0 || "add-third-party".equals( goal ) )
082            {
083                append( sb, "license:add-third-party", 0 );
084                append( sb, "Goal to generate the third-party license file.\nThis file contains a list of the dependencies and their licenses. Each dependency and it\'s license is displayed on a single line in the format\n\n\n\u00a0\u00a0(<license-name>)\u00a0<project-name>\u00a0<groupId>:<artifactId>:<version>\u00a0-\u00a0<project-url>\nIt will also copy it in the class-path (says add the generated directory as a resource of the build).", 1 );
085                append( sb, "", 0 );
086                if ( detail )
087                {
088                    append( sb, "Available parameters:", 1 );
089                    append( sb, "", 0 );
090    
091                    append( sb, "artifactLicenseMapping (Default: THIRD-PARTY.properties)", 2 );
092                    append( sb, "Location of a properties file mapping artifacts that are published with no license to the license that should be used for them. This supports classpath notation and any other type of URL Spring 3.1 resource loading can understand.", 3 );
093                    append( sb, "Expression: ${license.artifactLicenseMapping}", 3 );
094                    append( sb, "", 0 );
095    
096                    append( sb, "bundleThirdPartyPath (Default: META-INF/${project.artifactId}-THIRD-PARTY.txt)", 2 );
097                    append( sb, "The path of the bundled third party file to produce when generateBundle is on.\nNote: This option is not available for pom module types.\n", 3 );
098                    append( sb, "Expression: ${license.bundleThirdPartyPath}", 3 );
099                    append( sb, "", 0 );
100    
101                    append( sb, "deployMissingFile (Default: true)", 2 );
102                    append( sb, "Deploy the third party missing file in maven repository.", 3 );
103                    append( sb, "Expression: ${license.deployMissingFile}", 3 );
104                    append( sb, "", 0 );
105    
106                    append( sb, "doGenerateMissing (Default: false)", 2 );
107                    append( sb, "Controls if THIRD-PARTY.properties gets created or not", 3 );
108                    append( sb, "Expression: ${license.doGenerateMissing}", 3 );
109                    append( sb, "", 0 );
110    
111                    append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
112                    append( sb, "Encoding used to read and writes files.\nNote: If nothing is filled here, we will use the system property file.encoding.\n", 3 );
113                    append( sb, "Expression: ${license.encoding}", 3 );
114                    append( sb, "", 0 );
115    
116                    append( sb, "excludedArtifacts", 2 );
117                    append( sb, "A filter to exclude some ArtifactsIds", 3 );
118                    append( sb, "Expression: ${license.excludedArtifacts}", 3 );
119                    append( sb, "", 0 );
120    
121                    append( sb, "excludedGroups", 2 );
122                    append( sb, "A filter to exclude some GroupIds", 3 );
123                    append( sb, "Expression: ${license.excludedGroups}", 3 );
124                    append( sb, "", 0 );
125    
126                    append( sb, "excludedScopes (Default: system)", 2 );
127                    append( sb, "A filter to exclude some scopes.", 3 );
128                    append( sb, "Expression: ${license.excludedScopes}", 3 );
129                    append( sb, "", 0 );
130    
131                    append( sb, "failIfWarning (Default: false)", 2 );
132                    append( sb, "A flag to fail the build if at least one dependency was detected without a license.", 3 );
133                    append( sb, "Expression: ${license.failIfWarning}", 3 );
134                    append( sb, "", 0 );
135    
136                    append( sb, "force (Default: false)", 2 );
137                    append( sb, "To force generation of the third-party file even if every thing is up to date.", 3 );
138                    append( sb, "Expression: ${license.force}", 3 );
139                    append( sb, "", 0 );
140    
141                    append( sb, "generateBundle (Default: false)", 2 );
142                    append( sb, "A flag to copy a bundled version of the third-party file. This is usefull to avoid for a final application collision name of third party file.\nThe file will be copied at the bundleThirdPartyPath location.\n", 3 );
143                    append( sb, "Expression: ${license.generateBundle}", 3 );
144                    append( sb, "", 0 );
145    
146                    append( sb, "groupByLicense (Default: false)", 2 );
147                    append( sb, "A flag to change the grouping of the generated THIRD-PARTY file.\nBy default, group by dependecies.\n\nIf sets to true, the it will group by license type.\n", 3 );
148                    append( sb, "Expression: ${license.groupByLicense}", 3 );
149                    append( sb, "", 0 );
150    
151                    append( sb, "includedArtifacts", 2 );
152                    append( sb, "A filter to include only some ArtifactsIds", 3 );
153                    append( sb, "Expression: ${license.includedArtifacts}", 3 );
154                    append( sb, "", 0 );
155    
156                    append( sb, "includedGroups", 2 );
157                    append( sb, "A filter to include only some GroupIds", 3 );
158                    append( sb, "Expression: ${license.includedGroups}", 3 );
159                    append( sb, "", 0 );
160    
161                    append( sb, "includedScopes", 2 );
162                    append( sb, "A filter to include only some scopes, if let empty then all scopes will be used (no filter).", 3 );
163                    append( sb, "Expression: ${license.includedScopes}", 3 );
164                    append( sb, "", 0 );
165    
166                    append( sb, "includeTransitiveDependencies (Default: true)", 2 );
167                    append( sb, "Include transitive dependencies when downloading license files.", 3 );
168                    append( sb, "", 0 );
169    
170                    append( sb, "licenseMerges", 2 );
171                    append( sb, "To merge licenses in final file.\nEach entry represents a merge (first license is main license to keep), licenses are separated by |.\n\nExample :\n\n\n<licenseMerges>\n<licenseMerge>The\u00a0Apache\u00a0Software\u00a0License|Version\u00a02.0,Apache\u00a0License,\u00a0Version\u00a02.0</licenseMerge>\n</licenseMerges>\n</pre>\n", 3 );
172                    append( sb, "", 0 );
173    
174                    append( sb, "missingFile (Default: src/license/THIRD-PARTY.properties)", 2 );
175                    append( sb, "The file where to fill the license for dependencies with unknown license.", 3 );
176                    append( sb, "Expression: ${license.missingFile}", 3 );
177                    append( sb, "", 0 );
178    
179                    append( sb, "outputDirectory (Default: ${project.build.directory}/generated-sources/license)", 2 );
180                    append( sb, "Directory where to generate files.", 3 );
181                    append( sb, "Required: Yes", 3 );
182                    append( sb, "Expression: ${license.outputDirectory}", 3 );
183                    append( sb, "", 0 );
184    
185                    append( sb, "project (Default: ${project})", 2 );
186                    append( sb, "The reacted project.", 3 );
187                    append( sb, "Required: Yes", 3 );
188                    append( sb, "", 0 );
189    
190                    append( sb, "thirdPartyFilename (Default: THIRD-PARTY.txt)", 2 );
191                    append( sb, "File where to wirte the third-party file.", 3 );
192                    append( sb, "Required: Yes", 3 );
193                    append( sb, "Expression: ${license.thirdPartyFilename}", 3 );
194                    append( sb, "", 0 );
195    
196                    append( sb, "useMissingFile (Default: false)", 2 );
197                    append( sb, "A flag to use the missing licenses file to consolidate the THID-PARTY file.", 3 );
198                    append( sb, "Expression: ${license.useMissingFile}", 3 );
199                    append( sb, "", 0 );
200    
201                    append( sb, "useRepositoryMissingFiles (Default: true)", 2 );
202                    append( sb, "Load from repositories third party missing files.", 3 );
203                    append( sb, "Expression: ${license.useRepositoryMissingFiles}", 3 );
204                    append( sb, "", 0 );
205    
206                    append( sb, "verbose (Default: ${maven.verbose})", 2 );
207                    append( sb, "Flag to activate verbose mode.\nNote: Verbose mode is always on if you starts a debug maven instance (says via -X).\n", 3 );
208                    append( sb, "Expression: ${license.verbose}", 3 );
209                    append( sb, "", 0 );
210                }
211            }
212    
213            if ( goal == null || goal.length() <= 0 || "aggregate-add-third-party".equals( goal ) )
214            {
215                append( sb, "license:aggregate-add-third-party", 0 );
216                append( sb, "This aggregator goal (will be executed only once and only on pom projects) executed the add-third-party on all his modules (in a parellel build cycle) then aggreates all the third-party files in final one in the pom project.", 1 );
217                append( sb, "", 0 );
218                if ( detail )
219                {
220                    append( sb, "Available parameters:", 1 );
221                    append( sb, "", 0 );
222    
223                    append( sb, "artifactLicenseMapping (Default: THIRD-PARTY.properties)", 2 );
224                    append( sb, "Location of a properties file mapping artifacts that are published with no license to the license that should be used for them. This supports classpath notation and any other type of URL Spring 3.1 resource loading can understand.", 3 );
225                    append( sb, "Expression: ${license.artifactLicenseMapping}", 3 );
226                    append( sb, "", 0 );
227    
228                    append( sb, "bundleThirdPartyPath (Default: META-INF/${project.artifactId}-THIRD-PARTY.txt)", 2 );
229                    append( sb, "The path of the bundled third party file to produce when generateBundle is on.\nNote: This option is not available for pom module types.\n", 3 );
230                    append( sb, "Expression: ${license.bundleThirdPartyPath}", 3 );
231                    append( sb, "", 0 );
232    
233                    append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
234                    append( sb, "Encoding used to read and writes files.\nNote: If nothing is filled here, we will use the system property file.encoding.\n", 3 );
235                    append( sb, "Expression: ${license.encoding}", 3 );
236                    append( sb, "", 0 );
237    
238                    append( sb, "excludedArtifacts", 2 );
239                    append( sb, "A filter to exclude some ArtifactsIds", 3 );
240                    append( sb, "Expression: ${license.excludedArtifacts}", 3 );
241                    append( sb, "", 0 );
242    
243                    append( sb, "excludedGroups", 2 );
244                    append( sb, "A filter to exclude some GroupIds", 3 );
245                    append( sb, "Expression: ${license.excludedGroups}", 3 );
246                    append( sb, "", 0 );
247    
248                    append( sb, "excludedScopes (Default: system)", 2 );
249                    append( sb, "A filter to exclude some scopes.", 3 );
250                    append( sb, "Expression: ${license.excludedScopes}", 3 );
251                    append( sb, "", 0 );
252    
253                    append( sb, "failIfWarning (Default: false)", 2 );
254                    append( sb, "A flag to fail the build if at least one dependency was detected without a license.", 3 );
255                    append( sb, "Expression: ${license.failIfWarning}", 3 );
256                    append( sb, "", 0 );
257    
258                    append( sb, "force (Default: false)", 2 );
259                    append( sb, "To force generation of the third-party file even if every thing is up to date.", 3 );
260                    append( sb, "Expression: ${license.force}", 3 );
261                    append( sb, "", 0 );
262    
263                    append( sb, "generateBundle (Default: false)", 2 );
264                    append( sb, "A flag to copy a bundled version of the third-party file. This is usefull to avoid for a final application collision name of third party file.\nThe file will be copied at the bundleThirdPartyPath location.\n", 3 );
265                    append( sb, "Expression: ${license.generateBundle}", 3 );
266                    append( sb, "", 0 );
267    
268                    append( sb, "groupByLicense (Default: false)", 2 );
269                    append( sb, "A flag to change the grouping of the generated THIRD-PARTY file.\nBy default, group by dependecies.\n\nIf sets to true, the it will group by license type.\n", 3 );
270                    append( sb, "Expression: ${license.groupByLicense}", 3 );
271                    append( sb, "", 0 );
272    
273                    append( sb, "includedArtifacts", 2 );
274                    append( sb, "A filter to include only some ArtifactsIds", 3 );
275                    append( sb, "Expression: ${license.includedArtifacts}", 3 );
276                    append( sb, "", 0 );
277    
278                    append( sb, "includedGroups", 2 );
279                    append( sb, "A filter to include only some GroupIds", 3 );
280                    append( sb, "Expression: ${license.includedGroups}", 3 );
281                    append( sb, "", 0 );
282    
283                    append( sb, "includedScopes", 2 );
284                    append( sb, "A filter to include only some scopes, if let empty then all scopes will be used (no filter).", 3 );
285                    append( sb, "Expression: ${license.includedScopes}", 3 );
286                    append( sb, "", 0 );
287    
288                    append( sb, "includeTransitiveDependencies (Default: true)", 2 );
289                    append( sb, "Include transitive dependencies when downloading license files.", 3 );
290                    append( sb, "", 0 );
291    
292                    append( sb, "licenseMerges", 2 );
293                    append( sb, "To merge licenses in final file.\nEach entry represents a merge (first license is main license to keep), licenses are separated by |.\n\nExample :\n\n\n<licenseMerges>\n<licenseMerge>The\u00a0Apache\u00a0Software\u00a0License|Version\u00a02.0,Apache\u00a0License,\u00a0Version\u00a02.0</licenseMerge>\n</licenseMerges>\n</pre>\n", 3 );
294                    append( sb, "", 0 );
295    
296                    append( sb, "missingFile (Default: src/license/THIRD-PARTY.properties)", 2 );
297                    append( sb, "The file where to fill the license for dependencies with unknown license.", 3 );
298                    append( sb, "Expression: ${license.missingFile}", 3 );
299                    append( sb, "", 0 );
300    
301                    append( sb, "outputDirectory (Default: ${project.build.directory}/generated-sources/license)", 2 );
302                    append( sb, "Directory where to generate files.", 3 );
303                    append( sb, "Required: Yes", 3 );
304                    append( sb, "Expression: ${license.outputDirectory}", 3 );
305                    append( sb, "", 0 );
306    
307                    append( sb, "project (Default: ${project})", 2 );
308                    append( sb, "The reacted project.", 3 );
309                    append( sb, "Required: Yes", 3 );
310                    append( sb, "", 0 );
311    
312                    append( sb, "thirdPartyFilename (Default: THIRD-PARTY.txt)", 2 );
313                    append( sb, "File where to wirte the third-party file.", 3 );
314                    append( sb, "Required: Yes", 3 );
315                    append( sb, "Expression: ${license.thirdPartyFilename}", 3 );
316                    append( sb, "", 0 );
317    
318                    append( sb, "useMissingFile (Default: false)", 2 );
319                    append( sb, "A flag to use the missing licenses file to consolidate the THID-PARTY file.", 3 );
320                    append( sb, "Expression: ${license.useMissingFile}", 3 );
321                    append( sb, "", 0 );
322    
323                    append( sb, "verbose (Default: ${maven.verbose})", 2 );
324                    append( sb, "Flag to activate verbose mode.\nNote: Verbose mode is always on if you starts a debug maven instance (says via -X).\n", 3 );
325                    append( sb, "Expression: ${license.verbose}", 3 );
326                    append( sb, "", 0 );
327                }
328            }
329    
330            if ( goal == null || goal.length() <= 0 || "comment-style-list".equals( goal ) )
331            {
332                append( sb, "license:comment-style-list", 0 );
333                append( sb, "Displays all the available comment style to box file headers.", 1 );
334                append( sb, "", 0 );
335                if ( detail )
336                {
337                    append( sb, "Available parameters:", 1 );
338                    append( sb, "", 0 );
339    
340                    append( sb, "detail", 2 );
341                    append( sb, "A flag to display also the content of each license.", 3 );
342                    append( sb, "Expression: ${detail}", 3 );
343                    append( sb, "", 0 );
344    
345                    append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
346                    append( sb, "Encoding used to read and writes files.\nNote: If nothing is filled here, we will use the system property file.encoding.\n", 3 );
347                    append( sb, "Expression: ${license.encoding}", 3 );
348                    append( sb, "", 0 );
349    
350                    append( sb, "project (Default: ${project})", 2 );
351                    append( sb, "The reacted project.", 3 );
352                    append( sb, "Required: Yes", 3 );
353                    append( sb, "", 0 );
354    
355                    append( sb, "verbose (Default: ${maven.verbose})", 2 );
356                    append( sb, "Flag to activate verbose mode.\nNote: Verbose mode is always on if you starts a debug maven instance (says via -X).\n", 3 );
357                    append( sb, "Expression: ${license.verbose}", 3 );
358                    append( sb, "", 0 );
359                }
360            }
361    
362            if ( goal == null || goal.length() <= 0 || "download-licenses".equals( goal ) )
363            {
364                append( sb, "license:download-licenses", 0 );
365                append( sb, "Download the license files of all the current project\'s dependencies, and generate a summary file containing a list of all dependencies and their licenses.", 1 );
366                append( sb, "", 0 );
367                if ( detail )
368                {
369                    append( sb, "Available parameters:", 1 );
370                    append( sb, "", 0 );
371    
372                    append( sb, "excludedScopes (Default: system)", 2 );
373                    append( sb, "A filter to exclude some scopes.", 3 );
374                    append( sb, "Expression: ${license.excludedScopes}", 3 );
375                    append( sb, "", 0 );
376    
377                    append( sb, "includedScopes", 2 );
378                    append( sb, "A filter to include only some scopes, if let empty then all scopes will be used (no filter).", 3 );
379                    append( sb, "Expression: ${license.includedScopes}", 3 );
380                    append( sb, "", 0 );
381    
382                    append( sb, "includeTransitiveDependencies (Default: true)", 2 );
383                    append( sb, "Include transitive dependencies when downloading license files.", 3 );
384                    append( sb, "", 0 );
385    
386                    append( sb, "licensesConfigFile (Default: ${project.basedir}/src/license/licenses.xml)", 2 );
387                    append( sb, "Input file containing a mapping between each dependency and it\'s license information.", 3 );
388                    append( sb, "Expression: ${licensesConfigFile}", 3 );
389                    append( sb, "", 0 );
390    
391                    append( sb, "licensesOutputDirectory (Default: ${project.build.directory}/generated-resources/licenses)", 2 );
392                    append( sb, "The directory to which the dependency licenses should be written.", 3 );
393                    append( sb, "Expression: ${licensesOutputDirectory}", 3 );
394                    append( sb, "", 0 );
395    
396                    append( sb, "licensesOutputFile (Default: ${project.build.directory}/generated-resources/licenses.xml)", 2 );
397                    append( sb, "The output file containing a mapping between each dependency and it\'s license information.", 3 );
398                    append( sb, "Expression: ${licensesOutputFile}", 3 );
399                    append( sb, "", 0 );
400    
401                    append( sb, "offline (Default: ${settings.offline})", 2 );
402                    append( sb, "Settings offline flag (will not download anything if setted to true).", 3 );
403                    append( sb, "", 0 );
404    
405                    append( sb, "quiet (Default: false)", 2 );
406                    append( sb, "Don\'t show warnings about bad or missing license files.", 3 );
407                    append( sb, "", 0 );
408                }
409            }
410    
411            if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
412            {
413                append( sb, "license:help", 0 );
414                append( sb, "Display help information on license-maven-plugin.\nCall\n\u00a0\u00a0mvn\u00a0license:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
415                append( sb, "", 0 );
416                if ( detail )
417                {
418                    append( sb, "Available parameters:", 1 );
419                    append( sb, "", 0 );
420    
421                    append( sb, "detail (Default: false)", 2 );
422                    append( sb, "If true, display all settable properties for each goal.", 3 );
423                    append( sb, "Expression: ${detail}", 3 );
424                    append( sb, "", 0 );
425    
426                    append( sb, "goal", 2 );
427                    append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
428                    append( sb, "Expression: ${goal}", 3 );
429                    append( sb, "", 0 );
430    
431                    append( sb, "indentSize (Default: 2)", 2 );
432                    append( sb, "The number of spaces per indentation level, should be positive.", 3 );
433                    append( sb, "Expression: ${indentSize}", 3 );
434                    append( sb, "", 0 );
435    
436                    append( sb, "lineLength (Default: 80)", 2 );
437                    append( sb, "The maximum length of a display line, should be positive.", 3 );
438                    append( sb, "Expression: ${lineLength}", 3 );
439                    append( sb, "", 0 );
440                }
441            }
442    
443            if ( goal == null || goal.length() <= 0 || "license-list".equals( goal ) )
444            {
445                append( sb, "license:license-list", 0 );
446                append( sb, "Display all available licenses.", 1 );
447                append( sb, "", 0 );
448                if ( detail )
449                {
450                    append( sb, "Available parameters:", 1 );
451                    append( sb, "", 0 );
452    
453                    append( sb, "detail", 2 );
454                    append( sb, "A flag to display also the content of each license.", 3 );
455                    append( sb, "Expression: ${detail}", 3 );
456                    append( sb, "", 0 );
457    
458                    append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
459                    append( sb, "Encoding used to read and writes files.\nNote: If nothing is filled here, we will use the system property file.encoding.\n", 3 );
460                    append( sb, "Expression: ${license.encoding}", 3 );
461                    append( sb, "", 0 );
462    
463                    append( sb, "extraResolver", 2 );
464                    append( sb, "the url of an extra license repository.", 3 );
465                    append( sb, "Expression: ${extraResolver}", 3 );
466                    append( sb, "", 0 );
467    
468                    append( sb, "project (Default: ${project})", 2 );
469                    append( sb, "The reacted project.", 3 );
470                    append( sb, "Required: Yes", 3 );
471                    append( sb, "", 0 );
472    
473                    append( sb, "verbose (Default: ${maven.verbose})", 2 );
474                    append( sb, "Flag to activate verbose mode.\nNote: Verbose mode is always on if you starts a debug maven instance (says via -X).\n", 3 );
475                    append( sb, "Expression: ${license.verbose}", 3 );
476                    append( sb, "", 0 );
477                }
478            }
479    
480            if ( goal == null || goal.length() <= 0 || "update-file-header".equals( goal ) )
481            {
482                append( sb, "license:update-file-header", 0 );
483                append( sb, "The goal to update (or add) the header on project source files.\nThis goal replace the update-header goal which can not deal with Copyright.\n\nThis goal use a specific project file descriptor project.xml to describe all files to update for a whole project.\n", 1 );
484                append( sb, "", 0 );
485                if ( detail )
486                {
487                    append( sb, "Available parameters:", 1 );
488                    append( sb, "", 0 );
489    
490                    append( sb, "addSvnKeyWords (Default: false)", 2 );
491                    append( sb, "A flag to add svn:keywords on new header.\nWill add svn keywords :\n\nAuthor,\u00a0Id,\u00a0Rev,\u00a0URL\u00a0and\u00a0Date\n", 3 );
492                    append( sb, "Expression: ${license.addSvnKeyWords}", 3 );
493                    append( sb, "", 0 );
494    
495                    append( sb, "canUpdateCopyright (Default: false)", 2 );
496                    append( sb, "A flag to authorize update of the copyright part of the header.\nNote: By default, do NOT authorize it since copyright part should be handled by developpers (holder can change on each file for example).\n", 3 );
497                    append( sb, "Expression: ${license.canUpdateCopyright}", 3 );
498                    append( sb, "", 0 );
499    
500                    append( sb, "canUpdateDescription (Default: false)", 2 );
501                    append( sb, "A flag to authorize update of the description part of the header.\nNote: By default, do NOT authorize it since description can change on each file).\n", 3 );
502                    append( sb, "Expression: ${license.canUpdateDescription}", 3 );
503                    append( sb, "", 0 );
504    
505                    append( sb, "canUpdateLicense (Default: true)", 2 );
506                    append( sb, "A flag to authorize update of the license part of the header.\nNote: By default, authorize it since license part should always be generated by the plugin.\n", 3 );
507                    append( sb, "Expression: ${license.canUpdateLicense}", 3 );
508                    append( sb, "", 0 );
509    
510                    append( sb, "clearAfterOperation (Default: true)", 2 );
511                    append( sb, "A flag to clear everything after execution.\nNote: This property should ONLY be used for test purpose.\n", 3 );
512                    append( sb, "Expression: ${license.clearAfterOperation}", 3 );
513                    append( sb, "", 0 );
514    
515                    append( sb, "dryRun (Default: false)", 2 );
516                    append( sb, "A flag to test plugin but modify no file.", 3 );
517                    append( sb, "Expression: ${dryRun}", 3 );
518                    append( sb, "", 0 );
519    
520                    append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
521                    append( sb, "Encoding used to read and writes files.\nNote: If nothing is filled here, we will use the system property file.encoding.\n", 3 );
522                    append( sb, "Expression: ${license.encoding}", 3 );
523                    append( sb, "", 0 );
524    
525                    append( sb, "excludes", 2 );
526                    append( sb, "Specific files to excludes, separated by a comma. By default, thoses file type are excluded:\n-\tmodelisation\n-\timages\n\nNote: This parameter is not useable if you are still using a project file descriptor.\n", 3 );
527                    append( sb, "Expression: ${license.excludes}", 3 );
528                    append( sb, "", 0 );
529    
530                    append( sb, "extraExtensions", 2 );
531                    append( sb, "To associate extra extension files to an existing comment style.\nKeys of the map are the extension of extra files to treate, and the value is the comment style you want to associate.\n\nFor example, to treate file with extensions java2 and jdata as java files (says using the java comment style, declare this in your plugin configuration :\n\n<extraExtensions>\n<java2>java</java2>\n<jdata>java</jdata>\n</extraExtensions>\n\nNote: This parameter is not useable if you are still using a project file descriptor.\n", 3 );
532                    append( sb, "", 0 );
533    
534                    append( sb, "ignoreTag", 2 );
535                    append( sb, "A tag to place on files that will be ignored by the plugin.\nSometimes, it is necessary to do this when file is under a specific license.\n\nNote: If no sets, will use the default tag %%Ignore-License\n", 3 );
536                    append( sb, "Expression: ${license.ignoreTag}", 3 );
537                    append( sb, "", 0 );
538    
539                    append( sb, "inceptionYear (Default: ${project.inceptionYear})", 2 );
540                    append( sb, "Inception year of the project.\nWill be used as first year of copyright section in new header.\n", 3 );
541                    append( sb, "Required: Yes", 3 );
542                    append( sb, "Expression: ${license.inceptionYear}", 3 );
543                    append( sb, "", 0 );
544    
545                    append( sb, "includes", 2 );
546                    append( sb, "Specific files to includes, separated by a comma. By default, it is \'** /*\'.\nNote: This parameter is not useable if you are still using a project file descriptor.\n", 3 );
547                    append( sb, "Expression: ${license.includes}", 3 );
548                    append( sb, "", 0 );
549    
550                    append( sb, "keepBackup (Default: false)", 2 );
551                    append( sb, "A flag to keep a backup of every modified file.", 3 );
552                    append( sb, "Expression: ${license.keepBackup}", 3 );
553                    append( sb, "", 0 );
554    
555                    append( sb, "licenseName", 2 );
556                    append( sb, "Name of the license to use in the project.", 3 );
557                    append( sb, "Expression: ${license.licenseName}", 3 );
558                    append( sb, "", 0 );
559    
560                    append( sb, "licenseResolver", 2 );
561                    append( sb, "To specify an external extra licenses repository resolver (says the base url of the repository where the license.properties is present).", 3 );
562                    append( sb, "Expression: ${license.licenseResolver}", 3 );
563                    append( sb, "", 0 );
564    
565                    append( sb, "organizationName (Default: ${project.organization.name})", 2 );
566                    append( sb, "Name of project\'s organization.\nWill be used as copyrigth\'s holder in new header.\n", 3 );
567                    append( sb, "Required: Yes", 3 );
568                    append( sb, "Expression: ${license.organizationName}", 3 );
569                    append( sb, "", 0 );
570    
571                    append( sb, "project (Default: ${project})", 2 );
572                    append( sb, "The reacted project.", 3 );
573                    append( sb, "Required: Yes", 3 );
574                    append( sb, "", 0 );
575    
576                    append( sb, "projectName (Default: ${project.name})", 2 );
577                    append( sb, "Name of project (or module).\nWill be used as description section of new header.\n", 3 );
578                    append( sb, "Required: Yes", 3 );
579                    append( sb, "Expression: ${license.projectName}", 3 );
580                    append( sb, "", 0 );
581    
582                    append( sb, "roots", 2 );
583                    append( sb, "To specify the base dir from which we apply the license.\nShould be on form \'root1,root2,rootn\'.\n\nBy default, the main roots are \'src, target\ngenerated-sources, target/processed-sources\'.\nNote: If some of these roots do not exist, they will be simply ignored.\n\nNote: This parameter is not useable if you are still using a project file descriptor.\n", 3 );
584                    append( sb, "Expression: ${license.roots}", 3 );
585                    append( sb, "", 0 );
586    
587                    append( sb, "skipUpdateLicense (Default: false)", 2 );
588                    append( sb, "A flag to skip the goal.", 3 );
589                    append( sb, "Expression: ${license.skipUpdateLicense}", 3 );
590                    append( sb, "", 0 );
591    
592                    append( sb, "updateCopyright (Default: false)", 2 );
593                    append( sb, "A flag to update copyright application time (change copyright last year if required) according to the last commit made on the processed file.\nNote that this functionnality is still not effective.\n", 3 );
594                    append( sb, "Expression: ${license.updateCopyright}", 3 );
595                    append( sb, "", 0 );
596    
597                    append( sb, "verbose (Default: ${maven.verbose})", 2 );
598                    append( sb, "Flag to activate verbose mode.\nNote: Verbose mode is always on if you starts a debug maven instance (says via -X).\n", 3 );
599                    append( sb, "Expression: ${license.verbose}", 3 );
600                    append( sb, "", 0 );
601                }
602            }
603    
604            if ( goal == null || goal.length() <= 0 || "update-project-license".equals( goal ) )
605            {
606                append( sb, "license:update-project-license", 0 );
607                append( sb, "Updates (or creates) the main project license file according to the given license defines as licenseName.\nCan also generate a bundled license file (to avoid collision names in class-path). This file is by default generated in META-INF class-path directory.\n", 1 );
608                append( sb, "", 0 );
609                if ( detail )
610                {
611                    append( sb, "Available parameters:", 1 );
612                    append( sb, "", 0 );
613    
614                    append( sb, "bundleLicensePath (Default: META-INF/${project.artifactId}-LICENSE.txt)", 2 );
615                    append( sb, "The path of the bundled license file to produce when generateBundle is on.\nNote: This option is not available for pom module types.\n", 3 );
616                    append( sb, "Expression: ${license.bundleLicensePath}", 3 );
617                    append( sb, "", 0 );
618    
619                    append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
620                    append( sb, "Encoding used to read and writes files.\nNote: If nothing is filled here, we will use the system property file.encoding.\n", 3 );
621                    append( sb, "Expression: ${license.encoding}", 3 );
622                    append( sb, "", 0 );
623    
624                    append( sb, "force (Default: false)", 2 );
625                    append( sb, "A flag to force to generate project license file even if it is up-to-date.", 3 );
626                    append( sb, "Expression: ${license.force}", 3 );
627                    append( sb, "", 0 );
628    
629                    append( sb, "generateBundle (Default: false)", 2 );
630                    append( sb, "A flag to copy the main license file in a bundled place.\nThis is usefull for final application to have a none confusing location to seek for the application license.\n\nIf Sets to true, will copy the license file to the bundleLicensePath to outputDirectory.\n\nNote: This option is not available for pom module types.\n", 3 );
631                    append( sb, "Expression: ${license.generateBundle}", 3 );
632                    append( sb, "", 0 );
633    
634                    append( sb, "keepBackup (Default: false)", 2 );
635                    append( sb, "A flag to keep a backup of every modified file.", 3 );
636                    append( sb, "Expression: ${license.keepBackup}", 3 );
637                    append( sb, "", 0 );
638    
639                    append( sb, "licenseFile (Default: ${basedir}/LICENSE.txt)", 2 );
640                    append( sb, "Project license file to synchronize with main license defined in descriptor file.", 3 );
641                    append( sb, "Required: Yes", 3 );
642                    append( sb, "Expression: ${license.licenceFile}", 3 );
643                    append( sb, "", 0 );
644    
645                    append( sb, "licenseName", 2 );
646                    append( sb, "Name of the license to use in the project.", 3 );
647                    append( sb, "Expression: ${license.licenseName}", 3 );
648                    append( sb, "", 0 );
649    
650                    append( sb, "licenseResolver", 2 );
651                    append( sb, "To specify an external extra licenses repository resolver (says the base url of the repository where the license.properties is present).", 3 );
652                    append( sb, "Expression: ${license.licenseResolver}", 3 );
653                    append( sb, "", 0 );
654    
655                    append( sb, "outputDirectory (Default: target/generated-sources/license)", 2 );
656                    append( sb, "The directory where to generate license resources.\nNote: This option is not available for pom module types.\n", 3 );
657                    append( sb, "Expression: ${license.outputDirectory}", 3 );
658                    append( sb, "", 0 );
659    
660                    append( sb, "project (Default: ${project})", 2 );
661                    append( sb, "The reacted project.", 3 );
662                    append( sb, "Required: Yes", 3 );
663                    append( sb, "", 0 );
664    
665                    append( sb, "skipUpdateProjectLicense (Default: false)", 2 );
666                    append( sb, "A flag to skip the goal.", 3 );
667                    append( sb, "Expression: ${license.skipUpdateProjectLicense}", 3 );
668                    append( sb, "", 0 );
669    
670                    append( sb, "verbose (Default: ${maven.verbose})", 2 );
671                    append( sb, "Flag to activate verbose mode.\nNote: Verbose mode is always on if you starts a debug maven instance (says via -X).\n", 3 );
672                    append( sb, "Expression: ${license.verbose}", 3 );
673                    append( sb, "", 0 );
674                }
675            }
676    
677            if ( getLog().isInfoEnabled() )
678            {
679                getLog().info( sb.toString() );
680            }
681        }
682    
683        /**
684         * <p>Repeat a String <code>n</code> times to form a new string.</p>
685         *
686         * @param str String to repeat
687         * @param repeat number of times to repeat str
688         * @return String with repeated String
689         * @throws NegativeArraySizeException if <code>repeat < 0</code>
690         * @throws NullPointerException if str is <code>null</code>
691         */
692        private static String repeat( String str, int repeat )
693        {
694            StringBuffer buffer = new StringBuffer( repeat * str.length() );
695    
696            for ( int i = 0; i < repeat; i++ )
697            {
698                buffer.append( str );
699            }
700    
701            return buffer.toString();
702        }
703    
704        /** 
705         * Append a description to the buffer by respecting the indentSize and lineLength parameters.
706         * <b>Note</b>: The last character is always a new line.
707         * 
708         * @param sb The buffer to append the description, not <code>null</code>.
709         * @param description The description, not <code>null</code>.
710         * @param indent The base indentation level of each line, must not be negative.
711         */
712        private void append( StringBuffer sb, String description, int indent )
713        {
714            for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
715            {
716                sb.append( it.next().toString() ).append( '\n' );
717            }
718        }
719    
720        /** 
721         * Splits the specified text into lines of convenient display length.
722         * 
723         * @param text The text to split into lines, must not be <code>null</code>.
724         * @param indent The base indentation level of each line, must not be negative.
725         * @param indentSize The size of each indentation, must not be negative.
726         * @param lineLength The length of the line, must not be negative.
727         * @return The sequence of display lines, never <code>null</code>.
728         * @throws NegativeArraySizeException if <code>indent < 0</code>
729         */
730        private static List toLines( String text, int indent, int indentSize, int lineLength )
731        {
732            List lines = new ArrayList();
733    
734            String ind = repeat( "\t", indent );
735            String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
736            for ( int i = 0; i < plainLines.length; i++ )
737            {
738                toLines( lines, ind + plainLines[i], indentSize, lineLength );
739            }
740    
741            return lines;
742        }
743    
744        /** 
745         * Adds the specified line to the output sequence, performing line wrapping if necessary.
746         * 
747         * @param lines The sequence of display lines, must not be <code>null</code>.
748         * @param line The line to add, must not be <code>null</code>.
749         * @param indentSize The size of each indentation, must not be negative.
750         * @param lineLength The length of the line, must not be negative.
751         */
752        private static void toLines( List lines, String line, int indentSize, int lineLength )
753        {
754            int lineIndent = getIndentLevel( line );
755            StringBuffer buf = new StringBuffer( 256 );
756            String[] tokens = line.split( " +" );
757            for ( int i = 0; i < tokens.length; i++ )
758            {
759                String token = tokens[i];
760                if ( i > 0 )
761                {
762                    if ( buf.length() + token.length() >= lineLength )
763                    {
764                        lines.add( buf.toString() );
765                        buf.setLength( 0 );
766                        buf.append( repeat( " ", lineIndent * indentSize ) );
767                    }
768                    else
769                    {
770                        buf.append( ' ' );
771                    }
772                }
773                for ( int j = 0; j < token.length(); j++ )
774                {
775                    char c = token.charAt( j );
776                    if ( c == '\t' )
777                    {
778                        buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
779                    }
780                    else if ( c == '\u00A0' )
781                    {
782                        buf.append( ' ' );
783                    }
784                    else
785                    {
786                        buf.append( c );
787                    }
788                }
789            }
790            lines.add( buf.toString() );
791        }
792    
793        /** 
794         * Gets the indentation level of the specified line.
795         * 
796         * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
797         * @return The indentation level of the line.
798         */
799        private static int getIndentLevel( String line )
800        {
801            int level = 0;
802            for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
803            {
804                level++;
805            }
806            for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
807            {
808                if ( line.charAt( i ) == '\t' )
809                {
810                    level++;
811                    break;
812                }
813            }
814            return level;
815        }
816    }