Coverage Report - org.apache.maven.plugin.jar.HelpMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
HelpMojo
0%
0/276
0%
0/82
7.833
 
 1  
 package org.apache.maven.plugin.jar;
 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-jar-plugin.<br/> Call <pre>  mvn jar:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</pre> to display parameter details.
 12  
  *
 13  
  * @version generated on Thu Jan 26 21:38:23 CET 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  0
 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  0
         if ( lineLength <= 0 )
 57  
         {
 58  0
             getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
 59  0
             lineLength = 80;
 60  
         }
 61  0
         if ( indentSize <= 0 )
 62  
         {
 63  0
             getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
 64  0
             indentSize = 2;
 65  
         }
 66  
 
 67  0
         StringBuffer sb = new StringBuffer();
 68  
 
 69  0
         append( sb, "org.apache.maven.plugins:maven-jar-plugin:2.4", 0 );
 70  0
         append( sb, "", 0 );
 71  
 
 72  0
         append( sb, "Maven JAR Plugin", 0 );
 73  0
         append( sb, "Builds a Java Archive (JAR) file from the compiled project classes and resources.", 1 );
 74  0
         append( sb, "", 0 );
 75  
 
 76  0
         if ( goal == null || goal.length() <= 0 )
 77  
         {
 78  0
             append( sb, "This plugin has 5 goals:", 0 );
 79  0
             append( sb, "", 0 );
 80  
         }
 81  
 
 82  0
         if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
 83  
         {
 84  0
             append( sb, "jar:help", 0 );
 85  0
             append( sb, "Display help information on maven-jar-plugin.\nCall\n\u00a0\u00a0mvn\u00a0jar:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
 86  0
             append( sb, "", 0 );
 87  0
             if ( detail )
 88  
             {
 89  0
                 append( sb, "Available parameters:", 1 );
 90  0
                 append( sb, "", 0 );
 91  
 
 92  0
                 append( sb, "detail (Default: false)", 2 );
 93  0
                 append( sb, "If true, display all settable properties for each goal.", 3 );
 94  0
                 append( sb, "Expression: ${detail}", 3 );
 95  0
                 append( sb, "", 0 );
 96  
 
 97  0
                 append( sb, "goal", 2 );
 98  0
                 append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
 99  0
                 append( sb, "Expression: ${goal}", 3 );
 100  0
                 append( sb, "", 0 );
 101  
 
 102  0
                 append( sb, "indentSize (Default: 2)", 2 );
 103  0
                 append( sb, "The number of spaces per indentation level, should be positive.", 3 );
 104  0
                 append( sb, "Expression: ${indentSize}", 3 );
 105  0
                 append( sb, "", 0 );
 106  
 
 107  0
                 append( sb, "lineLength (Default: 80)", 2 );
 108  0
                 append( sb, "The maximum length of a display line, should be positive.", 3 );
 109  0
                 append( sb, "Expression: ${lineLength}", 3 );
 110  0
                 append( sb, "", 0 );
 111  
             }
 112  
         }
 113  
 
 114  0
         if ( goal == null || goal.length() <= 0 || "jar".equals( goal ) )
 115  
         {
 116  0
             append( sb, "jar:jar", 0 );
 117  0
             append( sb, "Build a JAR from the current project.", 1 );
 118  0
             append( sb, "", 0 );
 119  0
             if ( detail )
 120  
             {
 121  0
                 append( sb, "Available parameters:", 1 );
 122  0
                 append( sb, "", 0 );
 123  
 
 124  0
                 append( sb, "archive", 2 );
 125  0
                 append( sb, "The archive configuration to use. See Maven Archiver Reference.", 3 );
 126  0
                 append( sb, "", 0 );
 127  
 
 128  0
                 append( sb, "classesDirectory (Default: ${project.build.outputDirectory})", 2 );
 129  0
                 append( sb, "Directory containing the classes and resource files that should be packaged into the JAR.", 3 );
 130  0
                 append( sb, "Required: Yes", 3 );
 131  0
                 append( sb, "", 0 );
 132  
 
 133  0
                 append( sb, "classifier", 2 );
 134  0
                 append( sb, "Classifier to add to the artifact generated. If given, the artifact will be attached. If this is not given,it will merely be written to the output directory according to the finalName.", 3 );
 135  0
                 append( sb, "", 0 );
 136  
 
 137  0
                 append( sb, "excludes", 2 );
 138  0
                 append( sb, "List of files to exclude. Specified as fileset patterns which are relative to the input directory whose contents is being packaged into the JAR.", 3 );
 139  0
                 append( sb, "", 0 );
 140  
 
 141  0
                 append( sb, "finalName (Default: ${project.build.finalName})", 2 );
 142  0
                 append( sb, "Name of the generated JAR.", 3 );
 143  0
                 append( sb, "Required: Yes", 3 );
 144  0
                 append( sb, "Expression: ${jar.finalName}", 3 );
 145  0
                 append( sb, "", 0 );
 146  
 
 147  0
                 append( sb, "forceCreation (Default: false)", 2 );
 148  0
                 append( sb, "Whether creating the archive should be forced.", 3 );
 149  0
                 append( sb, "Expression: ${jar.forceCreation}", 3 );
 150  0
                 append( sb, "", 0 );
 151  
 
 152  0
                 append( sb, "includes", 2 );
 153  0
                 append( sb, "List of files to include. Specified as fileset patterns which are relative to the input directory whose contents is being packaged into the JAR.", 3 );
 154  0
                 append( sb, "", 0 );
 155  
 
 156  0
                 append( sb, "outputDirectory (Default: ${project.build.directory})", 2 );
 157  0
                 append( sb, "Directory containing the generated JAR.", 3 );
 158  0
                 append( sb, "Required: Yes", 3 );
 159  0
                 append( sb, "", 0 );
 160  
 
 161  0
                 append( sb, "skipIfEmpty (Default: false)", 2 );
 162  0
                 append( sb, "Skip creating empty archives", 3 );
 163  0
                 append( sb, "Expression: ${jar.skipIfEmpty}", 3 );
 164  0
                 append( sb, "", 0 );
 165  
 
 166  0
                 append( sb, "useDefaultManifestFile (Default: false)", 2 );
 167  0
                 append( sb, "Set this to true to enable the use of the defaultManifestFile.", 3 );
 168  0
                 append( sb, "Expression: ${jar.useDefaultManifestFile}", 3 );
 169  0
                 append( sb, "", 0 );
 170  
             }
 171  
         }
 172  
 
 173  0
         if ( goal == null || goal.length() <= 0 || "sign".equals( goal ) )
 174  
         {
 175  0
             append( sb, "jar:sign", 0 );
 176  0
             append( sb, "Deprecated. As of version 2.3, this goal is no longer supported in favor of the dedicated maven-jarsigner-plugin.", 1 );
 177  0
             if ( detail )
 178  
             {
 179  0
                 append( sb, "", 0 );
 180  0
                 append( sb, "Signs a JAR using jarsigner.", 1 );
 181  
             }
 182  0
             append( sb, "", 0 );
 183  0
             if ( detail )
 184  
             {
 185  0
                 append( sb, "Available parameters:", 1 );
 186  0
                 append( sb, "", 0 );
 187  
 
 188  0
                 append( sb, "alias", 2 );
 189  0
                 append( sb, "See options.", 3 );
 190  0
                 append( sb, "Required: Yes", 3 );
 191  0
                 append( sb, "Expression: ${alias}", 3 );
 192  0
                 append( sb, "", 0 );
 193  
 
 194  0
                 append( sb, "classifier", 2 );
 195  0
                 append( sb, "Classifier to use for the generated artifact. If not specified, the generated artifact becomes the primary artifact.", 3 );
 196  0
                 append( sb, "Expression: ${classifier}", 3 );
 197  0
                 append( sb, "", 0 );
 198  
 
 199  0
                 append( sb, "finalName", 2 );
 200  0
                 append( sb, "Name of the generated JAR (without classifier and extension).", 3 );
 201  0
                 append( sb, "Required: Yes", 3 );
 202  0
                 append( sb, "Expression: ${project.build.finalName}", 3 );
 203  0
                 append( sb, "", 0 );
 204  
 
 205  0
                 append( sb, "jarPath (Default: ${project.build.directory}/${project.build.finalName}.${project.packaging})", 2 );
 206  0
                 append( sb, "Path of the jar to sign. When specified, the finalName is ignored.", 3 );
 207  0
                 append( sb, "", 0 );
 208  
 
 209  0
                 append( sb, "keypass", 2 );
 210  0
                 append( sb, "See options.", 3 );
 211  0
                 append( sb, "Expression: ${keypass}", 3 );
 212  0
                 append( sb, "", 0 );
 213  
 
 214  0
                 append( sb, "keystore", 2 );
 215  0
                 append( sb, "See options.", 3 );
 216  0
                 append( sb, "Expression: ${keystore}", 3 );
 217  0
                 append( sb, "", 0 );
 218  
 
 219  0
                 append( sb, "sigfile", 2 );
 220  0
                 append( sb, "See options.", 3 );
 221  0
                 append( sb, "Expression: ${sigfile}", 3 );
 222  0
                 append( sb, "", 0 );
 223  
 
 224  0
                 append( sb, "signedjar", 2 );
 225  0
                 append( sb, "See options. Not specifying this argument will sign the jar in-place (your original jar is going to be overwritten).", 3 );
 226  0
                 append( sb, "Expression: ${signedjar}", 3 );
 227  0
                 append( sb, "", 0 );
 228  
 
 229  0
                 append( sb, "skip (Default: false)", 2 );
 230  0
                 append( sb, "Set this to true to disable signing. Useful to speed up build process in development environment.", 3 );
 231  0
                 append( sb, "Expression: ${maven.jar.sign.skip}", 3 );
 232  0
                 append( sb, "", 0 );
 233  
 
 234  0
                 append( sb, "storepass", 2 );
 235  0
                 append( sb, "See options.", 3 );
 236  0
                 append( sb, "Expression: ${storepass}", 3 );
 237  0
                 append( sb, "", 0 );
 238  
 
 239  0
                 append( sb, "type", 2 );
 240  0
                 append( sb, "See options. The corresponding option in the command line is -storetype.", 3 );
 241  0
                 append( sb, "Expression: ${type}", 3 );
 242  0
                 append( sb, "", 0 );
 243  
 
 244  0
                 append( sb, "verbose (Default: false)", 2 );
 245  0
                 append( sb, "Enable verbose. See options.", 3 );
 246  0
                 append( sb, "Expression: ${verbose}", 3 );
 247  0
                 append( sb, "", 0 );
 248  
 
 249  0
                 append( sb, "verify (Default: false)", 2 );
 250  0
                 append( sb, "Automatically verify a jar after signing it. See options.", 3 );
 251  0
                 append( sb, "Expression: ${verify}", 3 );
 252  0
                 append( sb, "", 0 );
 253  
 
 254  0
                 append( sb, "workingDirectory (Default: ${basedir})", 2 );
 255  0
                 append( sb, "The working directory in which the jarsigner executable will be run.", 3 );
 256  0
                 append( sb, "Required: Yes", 3 );
 257  0
                 append( sb, "Expression: ${workingdir}", 3 );
 258  0
                 append( sb, "", 0 );
 259  
             }
 260  
         }
 261  
 
 262  0
         if ( goal == null || goal.length() <= 0 || "sign-verify".equals( goal ) )
 263  
         {
 264  0
             append( sb, "jar:sign-verify", 0 );
 265  0
             append( sb, "Deprecated. As of version 2.3, this goal is no longer supported in favor of the dedicated maven-jarsigner-plugin.", 1 );
 266  0
             if ( detail )
 267  
             {
 268  0
                 append( sb, "", 0 );
 269  0
                 append( sb, "Checks the signature of a signed jar using jarsigner.", 1 );
 270  
             }
 271  0
             append( sb, "", 0 );
 272  0
             if ( detail )
 273  
             {
 274  0
                 append( sb, "Available parameters:", 1 );
 275  0
                 append( sb, "", 0 );
 276  
 
 277  0
                 append( sb, "checkCerts (Default: false)", 2 );
 278  0
                 append( sb, "Check certificates. Requires setVerbose(). See options.", 3 );
 279  0
                 append( sb, "Expression: ${checkcerts}", 3 );
 280  0
                 append( sb, "", 0 );
 281  
 
 282  0
                 append( sb, "errorWhenNotSigned (Default: true)", 2 );
 283  0
                 append( sb, "When true this will make the execute() operation fail, throwing an exception, when verifying a non signed jar. Primarily to keep backwards compatibility with existing code, and allow reusing the bean in unattended operations when set to false.", 3 );
 284  0
                 append( sb, "Expression: ${errorWhenNotSigned}", 3 );
 285  0
                 append( sb, "", 0 );
 286  
 
 287  0
                 append( sb, "finalName", 2 );
 288  0
                 append( sb, "Name of the generated JAR (without classifier and extension).", 3 );
 289  0
                 append( sb, "Required: Yes", 3 );
 290  0
                 append( sb, "Expression: ${project.build.finalName}", 3 );
 291  0
                 append( sb, "", 0 );
 292  
 
 293  0
                 append( sb, "jarPath", 2 );
 294  0
                 append( sb, "Path of the signed jar. When specified, the finalName is ignored.", 3 );
 295  0
                 append( sb, "Expression: ${jarpath}", 3 );
 296  0
                 append( sb, "", 0 );
 297  
 
 298  0
                 append( sb, "verbose (Default: false)", 2 );
 299  0
                 append( sb, "Enable verbose See options.", 3 );
 300  0
                 append( sb, "Expression: ${verbose}", 3 );
 301  0
                 append( sb, "", 0 );
 302  
 
 303  0
                 append( sb, "workingDirectory (Default: ${basedir})", 2 );
 304  0
                 append( sb, "The working directory in which the jarsigner executable will be run.", 3 );
 305  0
                 append( sb, "Required: Yes", 3 );
 306  0
                 append( sb, "Expression: ${workingdir}", 3 );
 307  0
                 append( sb, "", 0 );
 308  
             }
 309  
         }
 310  
 
 311  0
         if ( goal == null || goal.length() <= 0 || "test-jar".equals( goal ) )
 312  
         {
 313  0
             append( sb, "jar:test-jar", 0 );
 314  0
             append( sb, "Build a JAR of the test classes for the current project.", 1 );
 315  0
             append( sb, "", 0 );
 316  0
             if ( detail )
 317  
             {
 318  0
                 append( sb, "Available parameters:", 1 );
 319  0
                 append( sb, "", 0 );
 320  
 
 321  0
                 append( sb, "archive", 2 );
 322  0
                 append( sb, "The archive configuration to use. See Maven Archiver Reference.", 3 );
 323  0
                 append( sb, "", 0 );
 324  
 
 325  0
                 append( sb, "excludes", 2 );
 326  0
                 append( sb, "List of files to exclude. Specified as fileset patterns which are relative to the input directory whose contents is being packaged into the JAR.", 3 );
 327  0
                 append( sb, "", 0 );
 328  
 
 329  0
                 append( sb, "finalName (Default: ${project.build.finalName})", 2 );
 330  0
                 append( sb, "Name of the generated JAR.", 3 );
 331  0
                 append( sb, "Required: Yes", 3 );
 332  0
                 append( sb, "Expression: ${jar.finalName}", 3 );
 333  0
                 append( sb, "", 0 );
 334  
 
 335  0
                 append( sb, "forceCreation (Default: false)", 2 );
 336  0
                 append( sb, "Whether creating the archive should be forced.", 3 );
 337  0
                 append( sb, "Expression: ${jar.forceCreation}", 3 );
 338  0
                 append( sb, "", 0 );
 339  
 
 340  0
                 append( sb, "includes", 2 );
 341  0
                 append( sb, "List of files to include. Specified as fileset patterns which are relative to the input directory whose contents is being packaged into the JAR.", 3 );
 342  0
                 append( sb, "", 0 );
 343  
 
 344  0
                 append( sb, "outputDirectory (Default: ${project.build.directory})", 2 );
 345  0
                 append( sb, "Directory containing the generated JAR.", 3 );
 346  0
                 append( sb, "Required: Yes", 3 );
 347  0
                 append( sb, "", 0 );
 348  
 
 349  0
                 append( sb, "skip", 2 );
 350  0
                 append( sb, "Set this to true to bypass unit tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
 351  0
                 append( sb, "Expression: ${maven.test.skip}", 3 );
 352  0
                 append( sb, "", 0 );
 353  
 
 354  0
                 append( sb, "skipIfEmpty (Default: false)", 2 );
 355  0
                 append( sb, "Skip creating empty archives", 3 );
 356  0
                 append( sb, "Expression: ${jar.skipIfEmpty}", 3 );
 357  0
                 append( sb, "", 0 );
 358  
 
 359  0
                 append( sb, "testClassesDirectory (Default: ${project.build.testOutputDirectory})", 2 );
 360  0
                 append( sb, "Directory containing the test classes and resource files that should be packaged into the JAR.", 3 );
 361  0
                 append( sb, "Required: Yes", 3 );
 362  0
                 append( sb, "", 0 );
 363  
 
 364  0
                 append( sb, "useDefaultManifestFile (Default: false)", 2 );
 365  0
                 append( sb, "Set this to true to enable the use of the defaultManifestFile.", 3 );
 366  0
                 append( sb, "Expression: ${jar.useDefaultManifestFile}", 3 );
 367  0
                 append( sb, "", 0 );
 368  
             }
 369  
         }
 370  
 
 371  0
         if ( getLog().isInfoEnabled() )
 372  
         {
 373  0
             getLog().info( sb.toString() );
 374  
         }
 375  0
     }
 376  
 
 377  
     /**
 378  
      * <p>Repeat a String <code>n</code> times to form a new string.</p>
 379  
      *
 380  
      * @param str String to repeat
 381  
      * @param repeat number of times to repeat str
 382  
      * @return String with repeated String
 383  
      * @throws NegativeArraySizeException if <code>repeat < 0</code>
 384  
      * @throws NullPointerException if str is <code>null</code>
 385  
      */
 386  
     private static String repeat( String str, int repeat )
 387  
     {
 388  0
         StringBuffer buffer = new StringBuffer( repeat * str.length() );
 389  
 
 390  0
         for ( int i = 0; i < repeat; i++ )
 391  
         {
 392  0
             buffer.append( str );
 393  
         }
 394  
 
 395  0
         return buffer.toString();
 396  
     }
 397  
 
 398  
     /** 
 399  
      * Append a description to the buffer by respecting the indentSize and lineLength parameters.
 400  
      * <b>Note</b>: The last character is always a new line.
 401  
      * 
 402  
      * @param sb The buffer to append the description, not <code>null</code>.
 403  
      * @param description The description, not <code>null</code>.
 404  
      * @param indent The base indentation level of each line, must not be negative.
 405  
      */
 406  
     private void append( StringBuffer sb, String description, int indent )
 407  
     {
 408  0
         for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
 409  
         {
 410  0
             sb.append( it.next().toString() ).append( '\n' );
 411  
         }
 412  0
     }
 413  
 
 414  
     /** 
 415  
      * Splits the specified text into lines of convenient display length.
 416  
      * 
 417  
      * @param text The text to split into lines, must not be <code>null</code>.
 418  
      * @param indent The base indentation level of each line, must not be negative.
 419  
      * @param indentSize The size of each indentation, must not be negative.
 420  
      * @param lineLength The length of the line, must not be negative.
 421  
      * @return The sequence of display lines, never <code>null</code>.
 422  
      * @throws NegativeArraySizeException if <code>indent < 0</code>
 423  
      */
 424  
     private static List toLines( String text, int indent, int indentSize, int lineLength )
 425  
     {
 426  0
         List<String> lines = new ArrayList<String>();
 427  
 
 428  0
         String ind = repeat( "\t", indent );
 429  0
         String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
 430  0
         for ( int i = 0; i < plainLines.length; i++ )
 431  
         {
 432  0
             toLines( lines, ind + plainLines[i], indentSize, lineLength );
 433  
         }
 434  
 
 435  0
         return lines;
 436  
     }
 437  
 
 438  
     /** 
 439  
      * Adds the specified line to the output sequence, performing line wrapping if necessary.
 440  
      * 
 441  
      * @param lines The sequence of display lines, must not be <code>null</code>.
 442  
      * @param line The line to add, must not be <code>null</code>.
 443  
      * @param indentSize The size of each indentation, must not be negative.
 444  
      * @param lineLength The length of the line, must not be negative.
 445  
      */
 446  
     private static void toLines( List<String> lines, String line, int indentSize, int lineLength )
 447  
     {
 448  0
         int lineIndent = getIndentLevel( line );
 449  0
         StringBuffer buf = new StringBuffer( 256 );
 450  0
         String[] tokens = line.split( " +" );
 451  0
         for ( int i = 0; i < tokens.length; i++ )
 452  
         {
 453  0
             String token = tokens[i];
 454  0
             if ( i > 0 )
 455  
             {
 456  0
                 if ( buf.length() + token.length() >= lineLength )
 457  
                 {
 458  0
                     lines.add( buf.toString() );
 459  0
                     buf.setLength( 0 );
 460  0
                     buf.append( repeat( " ", lineIndent * indentSize ) );
 461  
                 }
 462  
                 else
 463  
                 {
 464  0
                     buf.append( ' ' );
 465  
                 }
 466  
             }
 467  0
             for ( int j = 0; j < token.length(); j++ )
 468  
             {
 469  0
                 char c = token.charAt( j );
 470  0
                 if ( c == '\t' )
 471  
                 {
 472  0
                     buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
 473  
                 }
 474  0
                 else if ( c == '\u00A0' )
 475  
                 {
 476  0
                     buf.append( ' ' );
 477  
                 }
 478  
                 else
 479  
                 {
 480  0
                     buf.append( c );
 481  
                 }
 482  
             }
 483  
         }
 484  0
         lines.add( buf.toString() );
 485  0
     }
 486  
 
 487  
     /** 
 488  
      * Gets the indentation level of the specified line.
 489  
      * 
 490  
      * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
 491  
      * @return The indentation level of the line.
 492  
      */
 493  
     private static int getIndentLevel( String line )
 494  
     {
 495  0
         int level = 0;
 496  0
         for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
 497  
         {
 498  0
             level++;
 499  
         }
 500  0
         for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
 501  
         {
 502  0
             if ( line.charAt( i ) == '\t' )
 503  
             {
 504  0
                 level++;
 505  0
                 break;
 506  
             }
 507  
         }
 508  0
         return level;
 509  
     }
 510  
 }