Coverage Report - org.codehaus.plexus.classworlds.launcher.ConfigurationParser
 
Classes in this File Line Coverage Branch Coverage Complexity
ConfigurationParser
91 %
136/148
90 %
69/76
10,333
ConfigurationParser$1
83 %
5/6
75 %
3/4
10,333
 
 1  
 package org.codehaus.plexus.classworlds.launcher;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2006 Codehaus Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *      http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import java.io.BufferedReader;
 20  
 import java.io.File;
 21  
 import java.io.FileInputStream;
 22  
 import java.io.FileNotFoundException;
 23  
 import java.io.FilenameFilter;
 24  
 import java.io.IOException;
 25  
 import java.io.InputStream;
 26  
 import java.io.InputStreamReader;
 27  
 import java.net.MalformedURLException;
 28  
 import java.net.URL;
 29  
 import java.util.Properties;
 30  
 
 31  
 import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
 32  
 import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
 33  
 
 34  
 /**
 35  
  * Event based launcher configuration parser, delegating effective configuration handling to ConfigurationHandler.
 36  
  *
 37  
  * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
 38  
  * @author Jason van Zyl
 39  
  * @author Igor Fedorenko
 40  
  * @see ConfigurationHandler
 41  
  */
 42  
 public class ConfigurationParser
 43  
 {
 44  
     public static final String MAIN_PREFIX = "main is";
 45  
 
 46  
     public static final String SET_PREFIX = "set";
 47  
 
 48  
     public static final String IMPORT_PREFIX = "import";
 49  
 
 50  
     public static final String LOAD_PREFIX = "load";
 51  
 
 52  
     /**
 53  
      * Optionally spec prefix.
 54  
      */
 55  
     public static final String OPTIONALLY_PREFIX = "optionally";
 56  
 
 57  
     private ConfigurationHandler handler;
 58  
 
 59  
     private Properties systemProperties;
 60  
 
 61  
     public ConfigurationParser( ConfigurationHandler handler, Properties systemProperties )
 62  38
     {
 63  38
         this.handler = handler;
 64  38
         this.systemProperties = systemProperties;
 65  38
     }
 66  
 
 67  
     /**
 68  
      * Parse launcher configuration file and send events to the handler.
 69  
      */
 70  
     public void parse( InputStream is )
 71  
         throws IOException, ConfigurationException, DuplicateRealmException, NoSuchRealmException
 72  
     {
 73  24
         BufferedReader reader = new BufferedReader( new InputStreamReader( is, "UTF-8" ) );
 74  
 
 75  24
         String line = null;
 76  
 
 77  24
         int lineNo = 0;
 78  
 
 79  24
         boolean mainSet = false;
 80  
         
 81  24
         String curRealm = null;
 82  
 
 83  
         while ( true )
 84  
         {
 85  298
             line = reader.readLine();
 86  
 
 87  298
             if ( line == null )
 88  
             {
 89  19
                 break;
 90  
             }
 91  
 
 92  279
             ++lineNo;
 93  279
             line = line.trim();
 94  
 
 95  279
             if ( canIgnore( line ) )
 96  
             {
 97  191
                 continue;
 98  
             }
 99  
 
 100  88
             if ( line.startsWith( MAIN_PREFIX ) )
 101  
             {
 102  21
                 if ( mainSet )
 103  
                 {
 104  1
                     throw new ConfigurationException( "Duplicate main configuration", lineNo, line );
 105  
                 }
 106  
 
 107  20
                 String conf = line.substring( MAIN_PREFIX.length() ).trim();
 108  
 
 109  20
                 int fromLoc = conf.indexOf( "from" );
 110  
 
 111  20
                 if ( fromLoc < 0 )
 112  
                 {
 113  0
                     throw new ConfigurationException( "Missing from clause", lineNo, line );
 114  
                 }
 115  
 
 116  20
                 String mainClassName = filter( conf.substring( 0, fromLoc ).trim() );
 117  
 
 118  20
                 String mainRealmName = filter( conf.substring( fromLoc + 4 ).trim() );
 119  
 
 120  20
                 this.handler.setAppMain( mainClassName, mainRealmName );
 121  
 
 122  20
                 mainSet = true;
 123  20
             }
 124  67
             else if ( line.startsWith( SET_PREFIX ) )
 125  
             {
 126  18
                 String conf = line.substring( SET_PREFIX.length() ).trim();
 127  
 
 128  18
                 int usingLoc = conf.indexOf( " using" ) + 1;
 129  
 
 130  18
                 String property = null;
 131  
 
 132  18
                 String propertiesFileName = null;
 133  
 
 134  18
                 if ( usingLoc > 0 )
 135  
                 {
 136  12
                     property = conf.substring( 0, usingLoc ).trim();
 137  
 
 138  12
                     propertiesFileName = filter( conf.substring( usingLoc + 5 ).trim() );
 139  
 
 140  12
                     conf = propertiesFileName;
 141  
                 }
 142  
 
 143  18
                 String defaultValue = null;
 144  
 
 145  18
                 int defaultLoc = conf.indexOf( " default" ) + 1;
 146  
 
 147  18
                 if ( defaultLoc > 0 )
 148  
                 {
 149  12
                     defaultValue = filter( conf.substring( defaultLoc + 7 ).trim() );
 150  
 
 151  12
                     if ( property == null )
 152  
                     {
 153  6
                         property = conf.substring( 0, defaultLoc ).trim();
 154  
                     }
 155  
                     else
 156  
                     {
 157  6
                         propertiesFileName = conf.substring( 0, defaultLoc ).trim();
 158  
                     }
 159  
                 }
 160  
 
 161  18
                 String value = systemProperties.getProperty( property );
 162  
 
 163  18
                 if ( value != null )
 164  
                 {
 165  2
                     continue;
 166  
                 }
 167  
 
 168  16
                 if ( propertiesFileName != null )
 169  
                 {
 170  11
                     File propertiesFile = new File( propertiesFileName );
 171  
 
 172  11
                     if ( propertiesFile.exists() )
 173  
                     {
 174  5
                         Properties properties = new Properties();
 175  
 
 176  
                         try
 177  
                         {
 178  5
                             properties.load( new FileInputStream( propertiesFileName ) );
 179  
 
 180  5
                             value = properties.getProperty( property );
 181  
                         }
 182  0
                         catch ( Exception e )
 183  
                         {
 184  
                             // do nothing
 185  5
                         }
 186  
                     }
 187  
                 }
 188  
 
 189  16
                 if ( value == null && defaultValue != null )
 190  
                 {
 191  11
                     value = defaultValue;
 192  
                 }
 193  
 
 194  16
                 if ( value != null )
 195  
                 {
 196  13
                     value = filter( value );
 197  13
                     systemProperties.setProperty( property, value );
 198  
                 }
 199  16
             }
 200  49
             else if ( line.startsWith( "[" ) )
 201  
             {
 202  27
                 int rbrack = line.indexOf( "]" );
 203  
 
 204  27
                 if ( rbrack < 0 )
 205  
                 {
 206  1
                     throw new ConfigurationException( "Invalid realm specifier", lineNo, line );
 207  
                 }
 208  
 
 209  26
                 String realmName = line.substring( 1, rbrack );
 210  
 
 211  26
                 handler.addRealm( realmName );
 212  
 
 213  25
                 curRealm = realmName;
 214  25
             }
 215  22
             else if ( line.startsWith( IMPORT_PREFIX ) )
 216  
             {
 217  3
                 if ( curRealm == null )
 218  
                 {
 219  1
                     throw new ConfigurationException( "Unhandled import", lineNo, line );
 220  
                 }
 221  
 
 222  2
                 String conf = line.substring( IMPORT_PREFIX.length() ).trim();
 223  
 
 224  2
                 int fromLoc = conf.indexOf( "from" );
 225  
 
 226  2
                 if ( fromLoc < 0 )
 227  
                 {
 228  0
                     throw new ConfigurationException( "Missing from clause", lineNo, line );
 229  
                 }
 230  
 
 231  2
                 String importSpec = conf.substring( 0, fromLoc ).trim();
 232  
 
 233  2
                 String relamName = conf.substring( fromLoc + 4 ).trim();
 234  
 
 235  2
                 handler.addImportFrom( relamName, importSpec );
 236  
 
 237  2
             }
 238  19
             else if ( line.startsWith( LOAD_PREFIX ) )
 239  
             {
 240  16
                 String constituent = line.substring( LOAD_PREFIX.length() ).trim();
 241  
 
 242  16
                 constituent = filter( constituent );
 243  
 
 244  16
                 if ( constituent.indexOf( "*" ) >= 0 )
 245  
                 {
 246  1
                     loadGlob( constituent, false /*not optionally*/ );
 247  
                 }
 248  
                 else
 249  
                 {
 250  15
                     File file = new File( constituent );
 251  
 
 252  15
                     if ( file.exists() )
 253  
                     {
 254  15
                         handler.addLoadFile( file );
 255  
                     }
 256  
                     else
 257  
                     {
 258  
                         try
 259  
                         {
 260  0
                           handler.addLoadURL( new URL( constituent ) );
 261  
                         }
 262  0
                         catch ( MalformedURLException e )
 263  
                         {
 264  0
                             throw new FileNotFoundException( constituent );
 265  0
                         }
 266  
                     }
 267  
                 }
 268  16
             }
 269  3
             else if ( line.startsWith( OPTIONALLY_PREFIX ) )
 270  
             {
 271  2
                 String constituent = line.substring( OPTIONALLY_PREFIX.length() ).trim();
 272  
 
 273  2
                 constituent = filter( constituent );
 274  
 
 275  2
                 if ( constituent.indexOf( "*" ) >= 0 )
 276  
                 {
 277  1
                     loadGlob( constituent, true /*optionally*/ );
 278  
                 }
 279  
                 else
 280  
                 {
 281  1
                     File file = new File( constituent );
 282  
 
 283  1
                     if ( file.exists() )
 284  
                     {
 285  1
                         handler.addLoadFile( file );
 286  
                     }
 287  
                     else
 288  
                     {
 289  
                         try
 290  
                         {
 291  0
                             handler.addLoadURL( new URL( constituent ) );
 292  
                         }
 293  0
                         catch ( MalformedURLException e )
 294  
                         {
 295  
                             // swallow
 296  0
                         }
 297  
                     }
 298  
                 }
 299  2
             }
 300  
             else
 301  
             {
 302  1
                 throw new ConfigurationException( "Unhandled configuration", lineNo, line );
 303  
             }
 304  
         }
 305  
 
 306  19
         reader.close();
 307  19
     }
 308  
 
 309  
     /**
 310  
      * Load a glob into the specified classloader.
 311  
      *
 312  
      * @param line       The path configuration line.
 313  
      * @param optionally Whether the path is optional or required
 314  
      * @throws MalformedURLException If the line does not represent
 315  
      *                               a valid path element.
 316  
      * @throws FileNotFoundException If the line does not represent
 317  
      *                               a valid path element in the filesystem.
 318  
      * @throws ConfigurationException 
 319  
      */
 320  
     protected void loadGlob( String line,
 321  
                              boolean optionally )
 322  
         throws MalformedURLException, FileNotFoundException, ConfigurationException
 323  
     {
 324  2
         File globFile = new File( line );
 325  
 
 326  2
         File dir = globFile.getParentFile();
 327  2
         if ( !dir.exists() )
 328  
         {
 329  1
             if ( optionally )
 330  
             {
 331  1
                 return;
 332  
             }
 333  
             else
 334  
             {
 335  0
                 throw new FileNotFoundException( dir.toString() );
 336  
             }
 337  
         }
 338  
 
 339  1
         String localName = globFile.getName();
 340  
 
 341  1
         int starLoc = localName.indexOf( "*" );
 342  
 
 343  1
         final String prefix = localName.substring( 0, starLoc );
 344  
 
 345  1
         final String suffix = localName.substring( starLoc + 1 );
 346  
 
 347  1
         File[] matches = dir.listFiles( new FilenameFilter()
 348  1
         {
 349  
             public boolean accept( File dir,
 350  
                                    String name )
 351  
             {
 352  37
                 if ( !name.startsWith( prefix ) )
 353  
                 {
 354  0
                     return false;
 355  
                 }
 356  
 
 357  37
                 if ( !name.endsWith( suffix ) )
 358  
                 {
 359  22
                     return false;
 360  
                 }
 361  
 
 362  15
                 return true;
 363  
             }
 364  
         } );
 365  
 
 366  16
         for ( File match : matches )
 367  
         {
 368  15
             handler.addLoadFile( match );
 369  
         }
 370  1
     }
 371  
 
 372  
     /**
 373  
      * Filter a string for system properties.
 374  
      *
 375  
      * @param text The text to filter.
 376  
      * @return The filtered text.
 377  
      * @throws ConfigurationException If the property does not
 378  
      *                                exist or if there is a syntax error.
 379  
      */
 380  
     protected String filter( String text )
 381  
         throws ConfigurationException
 382  
     {
 383  102
         String result = "";
 384  
 
 385  102
         int cur = 0;
 386  102
         int textLen = text.length();
 387  
 
 388  102
         int propStart = -1;
 389  102
         int propStop = -1;
 390  
 
 391  102
         String propName = null;
 392  102
         String propValue = null;
 393  
 
 394  140
         while ( cur < textLen )
 395  
         {
 396  138
             propStart = text.indexOf( "${", cur );
 397  
 
 398  138
             if ( propStart < 0 )
 399  
             {
 400  98
                 break;
 401  
             }
 402  
 
 403  40
             result += text.substring( cur, propStart );
 404  
 
 405  40
             propStop = text.indexOf( "}", propStart );
 406  
 
 407  40
             if ( propStop < 0 )
 408  
             {
 409  1
                 throw new ConfigurationException( "Unterminated property: " + text.substring( propStart ) );
 410  
             }
 411  
 
 412  39
             propName = text.substring( propStart + 2, propStop );
 413  
 
 414  39
             propValue = systemProperties.getProperty( propName );
 415  
 
 416  
             /* do our best if we are not running from surefire */
 417  39
             if ( propName.equals( "basedir" ) && ( propValue == null || propValue.equals( "" ) ) )
 418  
             {
 419  0
                 propValue = ( new File( "" ) ).getAbsolutePath();
 420  
 
 421  
             }
 422  
 
 423  39
             if ( propValue == null )
 424  
             {
 425  1
                 throw new ConfigurationException( "No such property: " + propName );
 426  
             }
 427  38
             result += propValue;
 428  
 
 429  38
             cur = propStop + 1;
 430  
         }
 431  
 
 432  100
         result += text.substring( cur );
 433  
 
 434  100
         return result;
 435  
     }
 436  
 
 437  
     /**
 438  
      * Determine if a line can be ignored because it is
 439  
      * a comment or simply blank.
 440  
      *
 441  
      * @param line The line to test.
 442  
      * @return <code>true</code> if the line is ignorable,
 443  
      *         otherwise <code>false</code>.
 444  
      */
 445  
     private boolean canIgnore( String line )
 446  
     {
 447  279
         return ( line.length() == 0 || line.startsWith( "#" ) );
 448  
     }
 449  
 }