1 | |
package org.apache.maven.plugin.invoker; |
2 | |
|
3 | |
import java.util.ArrayList; |
4 | |
import java.util.Iterator; |
5 | |
import java.util.List; |
6 | |
|
7 | |
import org.apache.maven.plugin.AbstractMojo; |
8 | |
import org.apache.maven.plugin.MojoExecutionException; |
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | 0 | public class HelpMojo |
18 | |
extends AbstractMojo |
19 | |
{ |
20 | |
|
21 | |
|
22 | |
|
23 | |
|
24 | |
|
25 | |
private boolean detail; |
26 | |
|
27 | |
|
28 | |
|
29 | |
|
30 | |
|
31 | |
|
32 | |
private java.lang.String goal; |
33 | |
|
34 | |
|
35 | |
|
36 | |
|
37 | |
|
38 | |
|
39 | |
private int lineLength; |
40 | |
|
41 | |
|
42 | |
|
43 | |
|
44 | |
|
45 | |
|
46 | |
private int indentSize; |
47 | |
|
48 | |
|
49 | |
|
50 | |
public void execute() |
51 | |
throws MojoExecutionException |
52 | |
{ |
53 | 0 | StringBuffer sb = new StringBuffer(); |
54 | |
|
55 | 0 | append( sb, "org.apache.maven.plugins:maven-invoker-plugin:1.2.1", 0 ); |
56 | 0 | append( sb, "", 0 ); |
57 | |
|
58 | 0 | append( sb, "Maven Invoker Plugin 1.2.1", 0 ); |
59 | 0 | append( sb, "The Maven Invoker Plugin is used to run a set of Maven projects. The plugin can determine whether each project execution is successful, and optionally can verify the output generated from a given project execution.", 1 ); |
60 | 0 | append( sb, "", 0 ); |
61 | |
|
62 | 0 | if ( goal == null || goal.length() <= 0 ) |
63 | |
{ |
64 | 0 | append( sb, "This plugin has 3 goals:", 0 ); |
65 | 0 | append( sb, "", 0 ); |
66 | |
} |
67 | |
|
68 | 0 | if ( goal == null || goal.length() <= 0 || "help".equals( goal ) ) |
69 | |
{ |
70 | 0 | append( sb, "invoker:help", 0 ); |
71 | 0 | append( sb, "Display help information on maven-invoker-plugin. Call\n\u00a0\u00a0mvn\u00a0invoker:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 ); |
72 | 0 | append( sb, "", 0 ); |
73 | 0 | if ( detail ) |
74 | |
{ |
75 | 0 | append( sb, "Available parameters:", 1 ); |
76 | 0 | append( sb, "", 0 ); |
77 | |
|
78 | 0 | append( sb, "detail (Default: false)", 2 ); |
79 | 0 | append( sb, "If true, display all settable properties for each goal.", 3 ); |
80 | 0 | append( sb, "", 0 ); |
81 | |
|
82 | 0 | append( sb, "goal", 2 ); |
83 | 0 | append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 ); |
84 | 0 | append( sb, "", 0 ); |
85 | |
|
86 | 0 | append( sb, "lineLength (Default: 80)", 2 ); |
87 | 0 | append( sb, "The maximum length of a display line.", 3 ); |
88 | 0 | append( sb, "", 0 ); |
89 | |
|
90 | 0 | append( sb, "indentSize (Default: 2)", 2 ); |
91 | 0 | append( sb, "The number of spaces per indentation level.", 3 ); |
92 | 0 | append( sb, "", 0 ); |
93 | |
} |
94 | |
} |
95 | |
|
96 | 0 | if ( goal == null || goal.length() <= 0 || "install".equals( goal ) ) |
97 | |
{ |
98 | 0 | append( sb, "invoker:install", 0 ); |
99 | 0 | append( sb, "Installs the project artifacts into the local repository as a preparation to run the integration tests. More precisely, all artifacts of the project itself, all its locally reachable parent POMs and all its dependencies from the reactor will be installed to the local repository.", 1 ); |
100 | 0 | append( sb, "", 0 ); |
101 | 0 | if ( detail ) |
102 | |
{ |
103 | 0 | append( sb, "Available parameters:", 1 ); |
104 | 0 | append( sb, "", 0 ); |
105 | |
|
106 | 0 | append( sb, "localRepositoryPath", 2 ); |
107 | 0 | append( sb, "The path to the local repository into which the project artifacts should be installed for the integration tests. If not set, the regular local repository will be used. To prevent soiling of your regular local repository with possibly broken artifacts, it is strongly recommended to use an isolated repository for the integration tests (e.g. ${project.build.directory}/it-repo).", 3 ); |
108 | 0 | append( sb, "", 0 ); |
109 | |
} |
110 | |
} |
111 | |
|
112 | 0 | if ( goal == null || goal.length() <= 0 || "run".equals( goal ) ) |
113 | |
{ |
114 | 0 | append( sb, "invoker:run", 0 ); |
115 | 0 | append( sb, "Searches for integration test Maven projects, and executes each, collecting a log in the project directory, and outputting the results to the command line.", 1 ); |
116 | 0 | append( sb, "", 0 ); |
117 | 0 | if ( detail ) |
118 | |
{ |
119 | 0 | append( sb, "Available parameters:", 1 ); |
120 | 0 | append( sb, "", 0 ); |
121 | |
|
122 | 0 | append( sb, "addTestClassPath (Default: false)", 2 ); |
123 | 0 | append( sb, "A flag whether the test class path of the project under test should be included in the class path of the pre-/post-build scripts. If set to false, the class path of script interpreter consists only of the runtime dependencies of the Maven Invoker Plugin. If set the true, the project\'s test class path will be prepended to the interpreter class path. Among others, this feature allows the scripts to access utility classes from the test sources of your project.", 3 ); |
124 | 0 | append( sb, "", 0 ); |
125 | |
|
126 | 0 | append( sb, "cloneAllFiles (Default: false)", 2 ); |
127 | 0 | append( sb, "Some files are normally excluded when copying the IT projects from the directory specified by the parameter projectsDirectory to the directory given by cloneProjectsTo (e.g. .svn, CVS, *~, etc). Setting this parameter to true will cause all files to be copied to the cloneProjectsTo directory.", 3 ); |
128 | 0 | append( sb, "", 0 ); |
129 | |
|
130 | 0 | append( sb, "cloneProjectsTo", 2 ); |
131 | 0 | append( sb, "Directory to which projects should be cloned prior to execution. If not specified, each integration test will be run in the directory in which the corresponding IT POM was found. In this case, you most likely want to configure your SCM to ignore target and build.log in the test\'s base directory.", 3 ); |
132 | 0 | append( sb, "", 0 ); |
133 | |
|
134 | 0 | append( sb, "debug (Default: false)", 2 ); |
135 | 0 | append( sb, "Whether to show debug statements in the build output.", 3 ); |
136 | 0 | append( sb, "", 0 ); |
137 | |
|
138 | 0 | append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 ); |
139 | 0 | append( sb, "The file encoding for the pre-/post-build scripts and the list files for goals and profiles.", 3 ); |
140 | 0 | append( sb, "", 0 ); |
141 | |
|
142 | 0 | append( sb, "goals", 2 ); |
143 | 0 | append( sb, "The list of goals to execute on each project. Default value is: package.", 3 ); |
144 | 0 | append( sb, "", 0 ); |
145 | |
|
146 | 0 | append( sb, "goalsFile (Default: goals.txt)", 2 ); |
147 | 0 | append( sb, "The name of the project-specific file that contains the enumeration of goals to execute for that test.", 3 ); |
148 | 0 | append( sb, "", 0 ); |
149 | |
|
150 | 0 | append( sb, "interpolationsProperties", 2 ); |
151 | 0 | append( sb, "List of properties which will be used to interpolate goal files.", 3 ); |
152 | 0 | append( sb, "", 0 ); |
153 | |
|
154 | 0 | append( sb, "invokerPropertiesFile (Default: invoker.properties)", 2 ); |
155 | 0 | append( sb, "The name of an optional test-specific file that contains properties used to configure the invocation of an integration test. This properties file may be used to specify settings for an individual test invocation. Any property present in the file will override the corresponding setting from the plugin configuration. The values of the properties are filtered and may use expressions like ${project.version} to reference project properties or values from the parameter interpolationsProperties. The snippet below describes the supported properties:\n#\u00a0A\u00a0comma\u00a0or\u00a0space\u00a0separated\u00a0list\u00a0of\u00a0goals/phases\u00a0to\u00a0execute,\u00a0may\n#\u00a0specify\u00a0an\u00a0empty\u00a0list\u00a0to\u00a0execute\u00a0the\u00a0default\u00a0goal\u00a0of\u00a0the\u00a0IT\u00a0project\ninvoker.goals=clean\u00a0package\u00a0site\n\n#\u00a0A\u00a0comma\u00a0or\u00a0space\u00a0separated\u00a0list\u00a0of\u00a0profiles\u00a0to\u00a0activate\ninvoker.profiles=its,jdk15\n\n#\u00a0The\u00a0value\u00a0for\u00a0the\u00a0environment\u00a0variable\u00a0MAVEN_OPTS\ninvoker.mavenOpts=-Dfile.encoding=UTF-16\u00a0-Xms32m\u00a0-Xmx256m\n\n#\u00a0Possible\u00a0values\u00a0are\u00a0\'fail-fast\'\u00a0(default),\u00a0\'fail-at-end\'\u00a0and\u00a0\'fail-never\'\ninvoker.failureBehavior=fail-never\n\n#\u00a0The\u00a0expected\u00a0result\u00a0of\u00a0the\u00a0build,\u00a0possible\u00a0values\u00a0are\u00a0\'success\'\u00a0(default)\u00a0and\u00a0\'failure\'\ninvoker.buildResult=failure\n\n#\u00a0A\u00a0boolean\u00a0value\u00a0controlling\u00a0the\u00a0-N\u00a0flag,\u00a0defaults\u00a0to\u00a0\'false\'\ninvoker.nonRecursive=false\n", 3 ); |
156 | 0 | append( sb, "", 0 ); |
157 | |
|
158 | 0 | append( sb, "invokerTest", 2 ); |
159 | 0 | append( sb, "Specify this parameter to run individual tests by file name, overriding the pomIncludes and pomExcludes parameters. Each pattern you specify here will be used to create an include pattern formatted like ${projectsDirectory}/${invoker.test}, so you can just type \'-Dinvoker.test=MyTest\' to run a single it in ${projectsDirectory}/${invoker.test}\'.", 3 ); |
160 | 0 | append( sb, "", 0 ); |
161 | |
|
162 | 0 | append( sb, "localRepositoryPath", 2 ); |
163 | 0 | append( sb, "The local repository for caching artifacts.", 3 ); |
164 | 0 | append( sb, "", 0 ); |
165 | |
|
166 | 0 | append( sb, "mavenOpts", 2 ); |
167 | 0 | append( sb, "The MAVEN_OPTS environment variable to use when invoking Maven. This value can be overridden for individual integration tests by using invokerPropertiesFile.", 3 ); |
168 | 0 | append( sb, "", 0 ); |
169 | |
|
170 | 0 | append( sb, "noLog (Default: false)", 2 ); |
171 | 0 | append( sb, "Suppress logging to the build.log file.", 3 ); |
172 | 0 | append( sb, "", 0 ); |
173 | |
|
174 | 0 | append( sb, "pom", 2 ); |
175 | 0 | append( sb, "A single POM to build, skipping any scanning parameters and behavior.", 3 ); |
176 | 0 | append( sb, "", 0 ); |
177 | |
|
178 | 0 | append( sb, "pomExcludes", 2 ); |
179 | 0 | append( sb, "Excludes for searching the integration test directory. This parameter is meant to be set from the POM. By default, no POM files are excluded.", 3 ); |
180 | 0 | append( sb, "", 0 ); |
181 | |
|
182 | 0 | append( sb, "pomIncludes", 2 ); |
183 | 0 | append( sb, "Includes for searching the integration test directory. This parameter is meant to be set from the POM. If this parameter is not set, the plugin will search for all pom.xml files one directory below projectsDirectory (*/pom.xml).", 3 ); |
184 | 0 | append( sb, "", 0 ); |
185 | |
|
186 | 0 | append( sb, "postBuildHookScript (Default: postbuild.bsh)", 2 ); |
187 | 0 | append( sb, "Relative path of a cleanup/verification BeanShell script to run after executing the build.", 3 ); |
188 | 0 | append( sb, "", 0 ); |
189 | |
|
190 | 0 | append( sb, "preBuildHookScript (Default: prebuild.bsh)", 2 ); |
191 | 0 | append( sb, "Relative path of a pre-build hook BeanShell script to run prior to executing the build.", 3 ); |
192 | 0 | append( sb, "", 0 ); |
193 | |
|
194 | 0 | append( sb, "profiles", 2 ); |
195 | 0 | append( sb, "List of profile identifiers to explicitly trigger in the build.", 3 ); |
196 | 0 | append( sb, "", 0 ); |
197 | |
|
198 | 0 | append( sb, "profilesFile (Default: profiles.txt)", 2 ); |
199 | 0 | append( sb, "The name of the project-specific file that contains the enumeration of profiles to use for that test. If the file exists and empty no profiles will be used even if the profiles is set", 3 ); |
200 | 0 | append( sb, "", 0 ); |
201 | |
|
202 | 0 | append( sb, "projectsDirectory (Default: ${basedir}/src/projects/)", 2 ); |
203 | 0 | append( sb, "Directory to search for integration tests.", 3 ); |
204 | 0 | append( sb, "", 0 ); |
205 | |
|
206 | 0 | append( sb, "properties", 2 ); |
207 | 0 | append( sb, "Common set of properties to pass in on each project\'s command line, via -D parameters.", 3 ); |
208 | 0 | append( sb, "", 0 ); |
209 | |
|
210 | 0 | append( sb, "settingsFile", 2 ); |
211 | 0 | append( sb, "Path to an alternate settings.xml to use for Maven invocation with all ITs.", 3 ); |
212 | 0 | append( sb, "", 0 ); |
213 | |
|
214 | 0 | append( sb, "showErrors (Default: false)", 2 ); |
215 | 0 | append( sb, "Whether to show errors in the build output.", 3 ); |
216 | 0 | append( sb, "", 0 ); |
217 | |
|
218 | 0 | append( sb, "skipInvocation (Default: false)", 2 ); |
219 | 0 | append( sb, "Flag used to suppress certain invocations. This is useful in tailoring the build using profiles.", 3 ); |
220 | 0 | append( sb, "", 0 ); |
221 | |
|
222 | 0 | append( sb, "streamLogs (Default: false)", 2 ); |
223 | 0 | append( sb, "Flag used to determine whether the build logs should be output to the normal mojo log.", 3 ); |
224 | 0 | append( sb, "", 0 ); |
225 | |
|
226 | 0 | append( sb, "suppressSummaries (Default: false)", 2 ); |
227 | 0 | append( sb, "Flag used to suppress the summary output notifying of successes and failures. If set to true, the only indication of the build\'s success or failure will be the effect it has on the main build (if it fails, the main build should fail as well). If streamLogs is enabled, the sub-build summary will also provide an indication.", 3 ); |
228 | 0 | append( sb, "", 0 ); |
229 | |
|
230 | 0 | append( sb, "testProperties", 2 ); |
231 | 0 | append( sb, "Common set of test properties to pass in on each IT\'s command line, via -D parameters.", 3 ); |
232 | 0 | append( sb, "", 0 ); |
233 | |
|
234 | 0 | append( sb, "testPropertiesFile (Default: test.properties)", 2 ); |
235 | 0 | append( sb, "Location of a properties file that defines CLI properties for the test.", 3 ); |
236 | 0 | append( sb, "", 0 ); |
237 | |
} |
238 | |
} |
239 | |
|
240 | 0 | if ( getLog().isInfoEnabled() ) |
241 | |
{ |
242 | 0 | getLog().info( sb.toString() ); |
243 | |
} |
244 | 0 | } |
245 | |
|
246 | |
|
247 | |
|
248 | |
|
249 | |
|
250 | |
|
251 | |
|
252 | |
|
253 | |
|
254 | |
|
255 | |
private static String repeat( String str, int repeat ) |
256 | |
{ |
257 | 0 | StringBuffer buffer = new StringBuffer( repeat * str.length() ); |
258 | |
|
259 | 0 | for ( int i = 0; i < repeat; i++ ) |
260 | |
{ |
261 | 0 | buffer.append( str ); |
262 | |
} |
263 | |
|
264 | 0 | return buffer.toString(); |
265 | |
} |
266 | |
|
267 | |
private void append( StringBuffer sb, String description, int indent ) |
268 | |
{ |
269 | 0 | for ( Iterator it = toLines( description, indent ).iterator(); it.hasNext(); ) |
270 | |
{ |
271 | 0 | sb.append( it.next().toString() ).append( '\n' ); |
272 | |
} |
273 | 0 | } |
274 | |
|
275 | |
|
276 | |
|
277 | |
|
278 | |
|
279 | |
|
280 | |
|
281 | |
|
282 | |
private List toLines( String text, int indent ) |
283 | |
{ |
284 | 0 | List lines = new ArrayList(); |
285 | |
|
286 | 0 | String ind = repeat( "\t", indent ); |
287 | 0 | String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" ); |
288 | 0 | for ( int i = 0; i < plainLines.length; i++ ) |
289 | |
{ |
290 | 0 | toLines( lines, ind + plainLines[i] ); |
291 | |
} |
292 | |
|
293 | 0 | return lines; |
294 | |
} |
295 | |
|
296 | |
|
297 | |
|
298 | |
|
299 | |
|
300 | |
|
301 | |
|
302 | |
private void toLines( List lines, String line ) |
303 | |
{ |
304 | 0 | int lineIndent = getIndentLevel( line ); |
305 | 0 | StringBuffer buf = new StringBuffer( 256 ); |
306 | 0 | String[] tokens = line.split( " +" ); |
307 | 0 | for ( int i = 0; i < tokens.length; i++ ) |
308 | |
{ |
309 | 0 | String token = tokens[i]; |
310 | 0 | if ( i > 0 ) |
311 | |
{ |
312 | 0 | if ( buf.length() + token.length() >= lineLength ) |
313 | |
{ |
314 | 0 | lines.add( buf.toString() ); |
315 | 0 | buf.setLength( 0 ); |
316 | 0 | buf.append( repeat( " ", lineIndent * indentSize ) ); |
317 | |
} |
318 | |
else |
319 | |
{ |
320 | 0 | buf.append( ' ' ); |
321 | |
} |
322 | |
} |
323 | 0 | for ( int j = 0; j < token.length(); j++ ) |
324 | |
{ |
325 | 0 | char c = token.charAt( j ); |
326 | 0 | if ( c == '\t' ) |
327 | |
{ |
328 | 0 | buf.append( repeat( " ", indentSize - buf.length() % indentSize ) ); |
329 | |
} |
330 | 0 | else if ( c == '\u00A0' ) |
331 | |
{ |
332 | 0 | buf.append( ' ' ); |
333 | |
} |
334 | |
else |
335 | |
{ |
336 | 0 | buf.append( c ); |
337 | |
} |
338 | |
} |
339 | |
} |
340 | 0 | lines.add( buf.toString() ); |
341 | 0 | } |
342 | |
|
343 | |
|
344 | |
|
345 | |
|
346 | |
|
347 | |
|
348 | |
|
349 | |
private static int getIndentLevel( String line ) |
350 | |
{ |
351 | 0 | int level = 0; |
352 | 0 | for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ ) |
353 | |
{ |
354 | 0 | level++; |
355 | |
} |
356 | 0 | for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ ) |
357 | |
{ |
358 | 0 | if ( line.charAt( i ) == '\t' ) |
359 | |
{ |
360 | 0 | level++; |
361 | 0 | break; |
362 | |
} |
363 | |
} |
364 | 0 | return level; |
365 | |
} |
366 | |
} |