View Javadoc

1   package org.apache.maven.plugin;
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   * Display help information on maven-compiler-plugin.<br/> Call <pre>  mvn compiler:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</pre> to display parameter details.
12   *
13   * @version generated on Fri Apr 27 23:02:48 CEST 2012
14   * @author org.apache.maven.tools.plugin.generator.PluginHelpGenerator (version 2.8)
15   * @goal help
16   * @requiresProject false
17   * @threadSafe
18   */
19  @SuppressWarnings( "all" )
20  public class HelpMojo
21      extends AbstractMojo
22  {
23      /**
24       * If <code>true</code>, display all settable properties for each goal.
25       * 
26       * @parameter expression="${detail}" default-value="false"
27       */
28      private boolean detail;
29  
30      /**
31       * The name of the goal for which to show help. If unspecified, all goals will be displayed.
32       * 
33       * @parameter expression="${goal}"
34       */
35      private java.lang.String goal;
36  
37      /**
38       * The maximum length of a display line, should be positive.
39       * 
40       * @parameter expression="${lineLength}" default-value="80"
41       */
42      private int lineLength;
43  
44      /**
45       * The number of spaces per indentation level, should be positive.
46       * 
47       * @parameter expression="${indentSize}" default-value="2"
48       */
49      private int indentSize;
50  
51  
52      /** {@inheritDoc} */
53      public void execute()
54          throws MojoExecutionException
55      {
56          if ( lineLength <= 0 )
57          {
58              getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
59              lineLength = 80;
60          }
61          if ( indentSize <= 0 )
62          {
63              getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
64              indentSize = 2;
65          }
66  
67          StringBuffer sb = new StringBuffer();
68  
69          append( sb, "org.apache.maven.plugins:maven-compiler-plugin:2.4", 0 );
70          append( sb, "", 0 );
71  
72          append( sb, "Maven Compiler Plugin", 0 );
73          append( sb, "The Compiler Plugin is used to compile the sources of your project.", 1 );
74          append( sb, "", 0 );
75  
76          if ( goal == null || goal.length() <= 0 )
77          {
78              append( sb, "This plugin has 3 goals:", 0 );
79              append( sb, "", 0 );
80          }
81  
82          if ( goal == null || goal.length() <= 0 || "compile".equals( goal ) )
83          {
84              append( sb, "compiler:compile", 0 );
85              append( sb, "Compiles application sources", 1 );
86              append( sb, "", 0 );
87              if ( detail )
88              {
89                  append( sb, "Available parameters:", 1 );
90                  append( sb, "", 0 );
91  
92                  append( sb, "annotationProcessors", 2 );
93                  append( sb, "Names of annotation processors to run. Only applies to JDK 1.6+ If not set, the default annotation processors discovery process applies.\n", 3 );
94                  append( sb, "", 0 );
95  
96                  append( sb, "compilerArgument", 2 );
97                  append( sb, "Sets the unformatted single argument string to be passed to the compiler if fork is set to true. To pass multiple arguments such as -Xmaxerrs 1000 (which are actually two arguments) you have to use compilerArguments.\n\nThis is because the list of valid arguments passed to a Java compiler varies based on the compiler version.\n", 3 );
98                  append( sb, "", 0 );
99  
100                 append( sb, "compilerArguments", 2 );
101                 append( sb, "Sets the arguments to be passed to the compiler (prepending a dash) if fork is set to true.\n\nThis is because the list of valid arguments passed to a Java compiler varies based on the compiler version.\n\nTo pass -Xmaxerrs 1000 -Xlint -Xlint:-path -Averbose=true you should include the following:\n\n<compilerArguments>\n\u00a0\u00a0<Xmaxerrs>1000</Xmaxerrs>\n\u00a0\u00a0<Xlint/>\n\u00a0\u00a0<Xlint:-path/>\n\u00a0\u00a0<Averbose>true</Averbose>\n</compilerArguments>\n", 3 );
102                 append( sb, "", 0 );
103 
104                 append( sb, "compilerId (Default: javac)", 2 );
105                 append( sb, "The compiler id of the compiler to use. See this guide for more information.", 3 );
106                 append( sb, "Expression: ${maven.compiler.compilerId}", 3 );
107                 append( sb, "", 0 );
108 
109                 append( sb, "compilerVersion", 2 );
110                 append( sb, "Version of the compiler to use, ex. \'1.3\', \'1.5\', if fork is set to true.", 3 );
111                 append( sb, "Expression: ${maven.compiler.compilerVersion}", 3 );
112                 append( sb, "", 0 );
113 
114                 append( sb, "debug (Default: true)", 2 );
115                 append( sb, "Set to true to include debugging information in the compiled class files.", 3 );
116                 append( sb, "Expression: ${maven.compiler.debug}", 3 );
117                 append( sb, "", 0 );
118 
119                 append( sb, "debuglevel", 2 );
120                 append( sb, "Keyword list to be appended to the -g command-line switch. Legal values are none or a comma-separated list of the following keywords: lines, vars, and source. If debuglevel is not specified, by default, nothing will be appended to -g. If debug is not turned on, this attribute will be ignored.", 3 );
121                 append( sb, "Expression: ${maven.compiler.debuglevel}", 3 );
122                 append( sb, "", 0 );
123 
124                 append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
125                 append( sb, "The -encoding argument for the Java compiler.", 3 );
126                 append( sb, "Expression: ${encoding}", 3 );
127                 append( sb, "", 0 );
128 
129                 append( sb, "excludes", 2 );
130                 append( sb, "A list of exclusion filters for the compiler.", 3 );
131                 append( sb, "", 0 );
132 
133                 append( sb, "executable", 2 );
134                 append( sb, "Sets the executable of the compiler to use when fork is true.", 3 );
135                 append( sb, "Expression: ${maven.compiler.executable}", 3 );
136                 append( sb, "", 0 );
137 
138                 append( sb, "failOnError (Default: true)", 2 );
139                 append( sb, "Indicates whether the build will continue even if there are compilation errors.", 3 );
140                 append( sb, "Expression: ${maven.compiler.failOnError}", 3 );
141                 append( sb, "", 0 );
142 
143                 append( sb, "fork (Default: false)", 2 );
144                 append( sb, "Allows running the compiler in a separate process. If false it uses the built in compiler, while if true it will use an executable.", 3 );
145                 append( sb, "Expression: ${maven.compiler.fork}", 3 );
146                 append( sb, "", 0 );
147 
148                 append( sb, "generatedSourcesDirectory (Default: ${project.build.directory}/generated-sources/annotations)", 2 );
149                 append( sb, "Specify where to place generated source files created by annotation processing. Only applies to JDK 1.6+\n", 3 );
150                 append( sb, "", 0 );
151 
152                 append( sb, "includes", 2 );
153                 append( sb, "A list of inclusion filters for the compiler.", 3 );
154                 append( sb, "", 0 );
155 
156                 append( sb, "maxmem", 2 );
157                 append( sb, "Sets the maximum size, in megabytes, of the memory allocation pool, ex. \'128\', \'128m\' if fork is set to true.", 3 );
158                 append( sb, "Expression: ${maven.compiler.maxmem}", 3 );
159                 append( sb, "", 0 );
160 
161                 append( sb, "meminitial", 2 );
162                 append( sb, "Initial size, in megabytes, of the memory allocation pool, ex. \'64\', \'64m\' if fork is set to true.", 3 );
163                 append( sb, "Expression: ${maven.compiler.meminitial}", 3 );
164                 append( sb, "", 0 );
165 
166                 append( sb, "optimize (Default: false)", 2 );
167                 append( sb, "Set to true to optimize the compiled code using the compiler\'s optimization methods.", 3 );
168                 append( sb, "Expression: ${maven.compiler.optimize}", 3 );
169                 append( sb, "", 0 );
170 
171                 append( sb, "outputFileName", 2 );
172                 append( sb, "Sets the name of the output file when compiling a set of sources to a single file.", 3 );
173                 append( sb, "Expression: ${project.build.finalName}", 3 );
174                 append( sb, "", 0 );
175 
176                 append( sb, "proc", 2 );
177                 append( sb, "Sets whether annotation processing is performed or not. Only applies to JDK 1.6+ If not set, both compilation and annotation processing are performed at the same time.\n\nAllowed values are: none - no annotation processing is performed. only - only annotation processing is done, no compilation.\n", 3 );
178                 append( sb, "", 0 );
179 
180                 append( sb, "showDeprecation (Default: false)", 2 );
181                 append( sb, "Sets whether to show source locations where deprecated APIs are used.", 3 );
182                 append( sb, "Expression: ${maven.compiler.showDeprecation}", 3 );
183                 append( sb, "", 0 );
184 
185                 append( sb, "showWarnings (Default: false)", 2 );
186                 append( sb, "Set to true to show compilation warnings.", 3 );
187                 append( sb, "Expression: ${maven.compiler.showWarnings}", 3 );
188                 append( sb, "", 0 );
189 
190                 append( sb, "source (Default: 1.5)", 2 );
191                 append( sb, "The -source argument for the Java compiler.", 3 );
192                 append( sb, "Expression: ${maven.compiler.source}", 3 );
193                 append( sb, "", 0 );
194 
195                 append( sb, "staleMillis (Default: 0)", 2 );
196                 append( sb, "Sets the granularity in milliseconds of the last modification date for testing whether a source needs recompilation.", 3 );
197                 append( sb, "Expression: ${lastModGranularityMs}", 3 );
198                 append( sb, "", 0 );
199 
200                 append( sb, "target (Default: 1.5)", 2 );
201                 append( sb, "The -target argument for the Java compiler.", 3 );
202                 append( sb, "Expression: ${maven.compiler.target}", 3 );
203                 append( sb, "", 0 );
204 
205                 append( sb, "verbose (Default: false)", 2 );
206                 append( sb, "Set to true to show messages about what the compiler is doing.", 3 );
207                 append( sb, "Expression: ${maven.compiler.verbose}", 3 );
208                 append( sb, "", 0 );
209             }
210         }
211 
212         if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
213         {
214             append( sb, "compiler:help", 0 );
215             append( sb, "Display help information on maven-compiler-plugin.\nCall\n\u00a0\u00a0mvn\u00a0compiler:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
216             append( sb, "", 0 );
217             if ( detail )
218             {
219                 append( sb, "Available parameters:", 1 );
220                 append( sb, "", 0 );
221 
222                 append( sb, "detail (Default: false)", 2 );
223                 append( sb, "If true, display all settable properties for each goal.", 3 );
224                 append( sb, "Expression: ${detail}", 3 );
225                 append( sb, "", 0 );
226 
227                 append( sb, "goal", 2 );
228                 append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
229                 append( sb, "Expression: ${goal}", 3 );
230                 append( sb, "", 0 );
231 
232                 append( sb, "indentSize (Default: 2)", 2 );
233                 append( sb, "The number of spaces per indentation level, should be positive.", 3 );
234                 append( sb, "Expression: ${indentSize}", 3 );
235                 append( sb, "", 0 );
236 
237                 append( sb, "lineLength (Default: 80)", 2 );
238                 append( sb, "The maximum length of a display line, should be positive.", 3 );
239                 append( sb, "Expression: ${lineLength}", 3 );
240                 append( sb, "", 0 );
241             }
242         }
243 
244         if ( goal == null || goal.length() <= 0 || "testCompile".equals( goal ) )
245         {
246             append( sb, "compiler:testCompile", 0 );
247             append( sb, "Compiles application test sources.", 1 );
248             append( sb, "", 0 );
249             if ( detail )
250             {
251                 append( sb, "Available parameters:", 1 );
252                 append( sb, "", 0 );
253 
254                 append( sb, "annotationProcessors", 2 );
255                 append( sb, "Names of annotation processors to run. Only applies to JDK 1.6+ If not set, the default annotation processors discovery process applies.\n", 3 );
256                 append( sb, "", 0 );
257 
258                 append( sb, "compilerArgument", 2 );
259                 append( sb, "Sets the unformatted single argument string to be passed to the compiler if fork is set to true. To pass multiple arguments such as -Xmaxerrs 1000 (which are actually two arguments) you have to use compilerArguments.\n\nThis is because the list of valid arguments passed to a Java compiler varies based on the compiler version.\n", 3 );
260                 append( sb, "", 0 );
261 
262                 append( sb, "compilerArguments", 2 );
263                 append( sb, "Sets the arguments to be passed to the compiler (prepending a dash) if fork is set to true.\n\nThis is because the list of valid arguments passed to a Java compiler varies based on the compiler version.\n\nTo pass -Xmaxerrs 1000 -Xlint -Xlint:-path -Averbose=true you should include the following:\n\n<compilerArguments>\n\u00a0\u00a0<Xmaxerrs>1000</Xmaxerrs>\n\u00a0\u00a0<Xlint/>\n\u00a0\u00a0<Xlint:-path/>\n\u00a0\u00a0<Averbose>true</Averbose>\n</compilerArguments>\n", 3 );
264                 append( sb, "", 0 );
265 
266                 append( sb, "compilerId (Default: javac)", 2 );
267                 append( sb, "The compiler id of the compiler to use. See this guide for more information.", 3 );
268                 append( sb, "Expression: ${maven.compiler.compilerId}", 3 );
269                 append( sb, "", 0 );
270 
271                 append( sb, "compilerVersion", 2 );
272                 append( sb, "Version of the compiler to use, ex. \'1.3\', \'1.5\', if fork is set to true.", 3 );
273                 append( sb, "Expression: ${maven.compiler.compilerVersion}", 3 );
274                 append( sb, "", 0 );
275 
276                 append( sb, "debug (Default: true)", 2 );
277                 append( sb, "Set to true to include debugging information in the compiled class files.", 3 );
278                 append( sb, "Expression: ${maven.compiler.debug}", 3 );
279                 append( sb, "", 0 );
280 
281                 append( sb, "debuglevel", 2 );
282                 append( sb, "Keyword list to be appended to the -g command-line switch. Legal values are none or a comma-separated list of the following keywords: lines, vars, and source. If debuglevel is not specified, by default, nothing will be appended to -g. If debug is not turned on, this attribute will be ignored.", 3 );
283                 append( sb, "Expression: ${maven.compiler.debuglevel}", 3 );
284                 append( sb, "", 0 );
285 
286                 append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
287                 append( sb, "The -encoding argument for the Java compiler.", 3 );
288                 append( sb, "Expression: ${encoding}", 3 );
289                 append( sb, "", 0 );
290 
291                 append( sb, "executable", 2 );
292                 append( sb, "Sets the executable of the compiler to use when fork is true.", 3 );
293                 append( sb, "Expression: ${maven.compiler.executable}", 3 );
294                 append( sb, "", 0 );
295 
296                 append( sb, "failOnError (Default: true)", 2 );
297                 append( sb, "Indicates whether the build will continue even if there are compilation errors.", 3 );
298                 append( sb, "Expression: ${maven.compiler.failOnError}", 3 );
299                 append( sb, "", 0 );
300 
301                 append( sb, "fork (Default: false)", 2 );
302                 append( sb, "Allows running the compiler in a separate process. If false it uses the built in compiler, while if true it will use an executable.", 3 );
303                 append( sb, "Expression: ${maven.compiler.fork}", 3 );
304                 append( sb, "", 0 );
305 
306                 append( sb, "generatedTestSourcesDirectory (Default: ${project.build.directory}/generated-test-sources/test-annotations)", 2 );
307                 append( sb, "Specify where to place generated source files created by annotation processing. Only applies to JDK 1.6+\n", 3 );
308                 append( sb, "", 0 );
309 
310                 append( sb, "maxmem", 2 );
311                 append( sb, "Sets the maximum size, in megabytes, of the memory allocation pool, ex. \'128\', \'128m\' if fork is set to true.", 3 );
312                 append( sb, "Expression: ${maven.compiler.maxmem}", 3 );
313                 append( sb, "", 0 );
314 
315                 append( sb, "meminitial", 2 );
316                 append( sb, "Initial size, in megabytes, of the memory allocation pool, ex. \'64\', \'64m\' if fork is set to true.", 3 );
317                 append( sb, "Expression: ${maven.compiler.meminitial}", 3 );
318                 append( sb, "", 0 );
319 
320                 append( sb, "optimize (Default: false)", 2 );
321                 append( sb, "Set to true to optimize the compiled code using the compiler\'s optimization methods.", 3 );
322                 append( sb, "Expression: ${maven.compiler.optimize}", 3 );
323                 append( sb, "", 0 );
324 
325                 append( sb, "outputFileName", 2 );
326                 append( sb, "Sets the name of the output file when compiling a set of sources to a single file.", 3 );
327                 append( sb, "Expression: ${project.build.finalName}", 3 );
328                 append( sb, "", 0 );
329 
330                 append( sb, "proc", 2 );
331                 append( sb, "Sets whether annotation processing is performed or not. Only applies to JDK 1.6+ If not set, both compilation and annotation processing are performed at the same time.\n\nAllowed values are: none - no annotation processing is performed. only - only annotation processing is done, no compilation.\n", 3 );
332                 append( sb, "", 0 );
333 
334                 append( sb, "showDeprecation (Default: false)", 2 );
335                 append( sb, "Sets whether to show source locations where deprecated APIs are used.", 3 );
336                 append( sb, "Expression: ${maven.compiler.showDeprecation}", 3 );
337                 append( sb, "", 0 );
338 
339                 append( sb, "showWarnings (Default: false)", 2 );
340                 append( sb, "Set to true to show compilation warnings.", 3 );
341                 append( sb, "Expression: ${maven.compiler.showWarnings}", 3 );
342                 append( sb, "", 0 );
343 
344                 append( sb, "skip", 2 );
345                 append( sb, "Set this to \'true\' to bypass compilation of test sources. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
346                 append( sb, "Expression: ${maven.test.skip}", 3 );
347                 append( sb, "", 0 );
348 
349                 append( sb, "source (Default: 1.5)", 2 );
350                 append( sb, "The -source argument for the Java compiler.", 3 );
351                 append( sb, "Expression: ${maven.compiler.source}", 3 );
352                 append( sb, "", 0 );
353 
354                 append( sb, "staleMillis (Default: 0)", 2 );
355                 append( sb, "Sets the granularity in milliseconds of the last modification date for testing whether a source needs recompilation.", 3 );
356                 append( sb, "Expression: ${lastModGranularityMs}", 3 );
357                 append( sb, "", 0 );
358 
359                 append( sb, "target (Default: 1.5)", 2 );
360                 append( sb, "The -target argument for the Java compiler.", 3 );
361                 append( sb, "Expression: ${maven.compiler.target}", 3 );
362                 append( sb, "", 0 );
363 
364                 append( sb, "testCompilerArgument", 2 );
365                 append( sb, "Sets the unformatted argument string to be passed to test compiler if fork is set to true.\n\nThis is because the list of valid arguments passed to a Java compiler varies based on the compiler version.\n", 3 );
366                 append( sb, "", 0 );
367 
368                 append( sb, "testCompilerArguments", 2 );
369                 append( sb, "Sets the arguments to be passed to test compiler (prepending a dash) if fork is set to true.\n\nThis is because the list of valid arguments passed to a Java compiler varies based on the compiler version.\n", 3 );
370                 append( sb, "", 0 );
371 
372                 append( sb, "testExcludes", 2 );
373                 append( sb, "A list of exclusion filters for the compiler.", 3 );
374                 append( sb, "", 0 );
375 
376                 append( sb, "testIncludes", 2 );
377                 append( sb, "A list of inclusion filters for the compiler.", 3 );
378                 append( sb, "", 0 );
379 
380                 append( sb, "testSource", 2 );
381                 append( sb, "The -source argument for the test Java compiler.", 3 );
382                 append( sb, "Expression: ${maven.compiler.testSource}", 3 );
383                 append( sb, "", 0 );
384 
385                 append( sb, "testTarget", 2 );
386                 append( sb, "The -target argument for the test Java compiler.", 3 );
387                 append( sb, "Expression: ${maven.compiler.testTarget}", 3 );
388                 append( sb, "", 0 );
389 
390                 append( sb, "verbose (Default: false)", 2 );
391                 append( sb, "Set to true to show messages about what the compiler is doing.", 3 );
392                 append( sb, "Expression: ${maven.compiler.verbose}", 3 );
393                 append( sb, "", 0 );
394             }
395         }
396 
397         if ( getLog().isInfoEnabled() )
398         {
399             getLog().info( sb.toString() );
400         }
401     }
402 
403     /**
404      * <p>Repeat a String <code>n</code> times to form a new string.</p>
405      *
406      * @param str String to repeat
407      * @param repeat number of times to repeat str
408      * @return String with repeated String
409      * @throws NegativeArraySizeException if <code>repeat < 0</code>
410      * @throws NullPointerException if str is <code>null</code>
411      */
412     private static String repeat( String str, int repeat )
413     {
414         StringBuffer buffer = new StringBuffer( repeat * str.length() );
415 
416         for ( int i = 0; i < repeat; i++ )
417         {
418             buffer.append( str );
419         }
420 
421         return buffer.toString();
422     }
423 
424     /** 
425      * Append a description to the buffer by respecting the indentSize and lineLength parameters.
426      * <b>Note</b>: The last character is always a new line.
427      * 
428      * @param sb The buffer to append the description, not <code>null</code>.
429      * @param description The description, not <code>null</code>.
430      * @param indent The base indentation level of each line, must not be negative.
431      */
432     private void append( StringBuffer sb, String description, int indent )
433     {
434         for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
435         {
436             sb.append( it.next().toString() ).append( '\n' );
437         }
438     }
439 
440     /** 
441      * Splits the specified text into lines of convenient display length.
442      * 
443      * @param text The text to split into lines, must not be <code>null</code>.
444      * @param indent The base indentation level of each line, must not be negative.
445      * @param indentSize The size of each indentation, must not be negative.
446      * @param lineLength The length of the line, must not be negative.
447      * @return The sequence of display lines, never <code>null</code>.
448      * @throws NegativeArraySizeException if <code>indent < 0</code>
449      */
450     private static List toLines( String text, int indent, int indentSize, int lineLength )
451     {
452         List<String> lines = new ArrayList<String>();
453 
454         String ind = repeat( "\t", indent );
455         String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
456         for ( int i = 0; i < plainLines.length; i++ )
457         {
458             toLines( lines, ind + plainLines[i], indentSize, lineLength );
459         }
460 
461         return lines;
462     }
463 
464     /** 
465      * Adds the specified line to the output sequence, performing line wrapping if necessary.
466      * 
467      * @param lines The sequence of display lines, must not be <code>null</code>.
468      * @param line The line to add, must not be <code>null</code>.
469      * @param indentSize The size of each indentation, must not be negative.
470      * @param lineLength The length of the line, must not be negative.
471      */
472     private static void toLines( List<String> lines, String line, int indentSize, int lineLength )
473     {
474         int lineIndent = getIndentLevel( line );
475         StringBuffer buf = new StringBuffer( 256 );
476         String[] tokens = line.split( " +" );
477         for ( int i = 0; i < tokens.length; i++ )
478         {
479             String token = tokens[i];
480             if ( i > 0 )
481             {
482                 if ( buf.length() + token.length() >= lineLength )
483                 {
484                     lines.add( buf.toString() );
485                     buf.setLength( 0 );
486                     buf.append( repeat( " ", lineIndent * indentSize ) );
487                 }
488                 else
489                 {
490                     buf.append( ' ' );
491                 }
492             }
493             for ( int j = 0; j < token.length(); j++ )
494             {
495                 char c = token.charAt( j );
496                 if ( c == '\t' )
497                 {
498                     buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
499                 }
500                 else if ( c == '\u00A0' )
501                 {
502                     buf.append( ' ' );
503                 }
504                 else
505                 {
506                     buf.append( c );
507                 }
508             }
509         }
510         lines.add( buf.toString() );
511     }
512 
513     /** 
514      * Gets the indentation level of the specified line.
515      * 
516      * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
517      * @return The indentation level of the line.
518      */
519     private static int getIndentLevel( String line )
520     {
521         int level = 0;
522         for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
523         {
524             level++;
525         }
526         for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
527         {
528             if ( line.charAt( i ) == '\t' )
529             {
530                 level++;
531                 break;
532             }
533         }
534         return level;
535     }
536 }