Clover coverage report - classworlds - 1.1-alpha-1
Coverage timestamp: Sun Sep 19 2004 14:08:44 EDT
file stats: LOC: 593   Methods: 11
NCLOC: 352   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
Configurator.java 87.5% 92.7% 81.8% 90.6%
coverage coverage
 1   
 package org.codehaus.classworlds;
 2   
 
 3   
 /*
 4   
  $Id: Configurator.java,v 1.3 2004/09/07 13:17:42 brett Exp $
 5   
 
 6   
  Copyright 2002 (C) The Werken Company. All Rights Reserved.
 7   
 
 8   
  Redistribution and use of this software and associated documentation
 9   
  ("Software"), with or without modification, are permitted provided
 10   
  that the following conditions are met:
 11   
 
 12   
  1. Redistributions of source code must retain copyright
 13   
     statements and notices.  Redistributions must also contain a
 14   
     copy of this document.
 15   
 
 16   
  2. Redistributions in binary form must reproduce the
 17   
     above copyright notice, this list of conditions and the
 18   
     following disclaimer in the documentation and/or other
 19   
     materials provided with the distribution.
 20   
 
 21   
  3. The name "classworlds" must not be used to endorse or promote
 22   
     products derived from this Software without prior written
 23   
     permission of The Werken Company.  For written permission,
 24   
     please contact bob@werken.com.
 25   
 
 26   
  4. Products derived from this Software may not be called "classworlds"
 27   
     nor may "classworlds" appear in their names without prior written
 28   
     permission of The Werken Company. "classworlds" is a registered
 29   
     trademark of The Werken Company.
 30   
 
 31   
  5. Due credit should be given to The Werken Company.
 32   
     (http://classworlds.werken.com/).
 33   
 
 34   
  THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
 35   
  ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 36   
  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 37   
  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 38   
  THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 39   
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 40   
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 41   
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 42   
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 43   
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 44   
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 45   
  OF THE POSSIBILITY OF SUCH DAMAGE.
 46   
 
 47   
  */
 48   
 
 49   
 import java.io.BufferedReader;
 50   
 import java.io.File;
 51   
 import java.io.FileNotFoundException;
 52   
 import java.io.FilenameFilter;
 53   
 import java.io.IOException;
 54   
 import java.io.InputStream;
 55   
 import java.io.InputStreamReader;
 56   
 import java.io.FileInputStream;
 57   
 import java.net.MalformedURLException;
 58   
 import java.net.URL;
 59   
 import java.util.ArrayList;
 60   
 import java.util.Collections;
 61   
 import java.util.Comparator;
 62   
 import java.util.HashMap;
 63   
 import java.util.Iterator;
 64   
 import java.util.List;
 65   
 import java.util.Map;
 66   
 import java.util.Properties;
 67   
 
 68   
 /**
 69   
  * <code>Launcher</code> configurator.
 70   
  *
 71   
  * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
 72   
  * @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
 73   
  * @version $Id: Configurator.java,v 1.3 2004/09/07 13:17:42 brett Exp $
 74   
  */
 75   
 public class Configurator
 76   
 {
 77   
     public static final String MAIN_PREFIX = "main is";
 78   
 
 79   
     public static final String SET_PREFIX = "set";
 80   
 
 81   
     public static final String IMPORT_PREFIX = "import";
 82   
 
 83   
     public static final String LOAD_PREFIX = "load";
 84   
 
 85   
     /** Optionally spec prefix. */
 86   
     public static final String OPTIONALLY_PREFIX = "optionally";
 87   
 
 88   
     /** The launcher to configure. */
 89   
     private Launcher launcher;
 90   
 
 91   
     private ClassWorld world;
 92   
 
 93   
     /** Processed Realms. */
 94   
     private Map configuredRealms;
 95   
 
 96   
     /** Construct.
 97   
      *
 98   
      *  @param launcher The launcher to configure.
 99   
      */
 100  68
     public Configurator( Launcher launcher )
 101   
     {
 102  68
         this.launcher = launcher;
 103   
 
 104  68
         configuredRealms = new HashMap();
 105   
     }
 106   
 
 107   
     /** Construct.
 108   
      *
 109   
      *  @param classWorld The classWorld to configure.
 110   
      */
 111  0
     public Configurator( ClassWorld world )
 112   
     {
 113  0
         setClassWorld( world );
 114   
     }
 115   
 
 116   
     /** set world.
 117   
      *  this setter is provided so you can use the same configurator to configure several "worlds"
 118   
      *
 119   
      *  @param classWorld The classWorld to configure.
 120   
      */
 121  0
     public void setClassWorld( ClassWorld world )
 122   
     {
 123  0
         this.world = world;
 124   
 
 125  0
         configuredRealms = new HashMap();
 126   
     }
 127   
 
 128   
     /**
 129   
      * Configure from a file.
 130   
      *
 131   
      * @param is The config input stream
 132   
      * @throws IOException             If an error occurs reading the config file.
 133   
      * @throws MalformedURLException   If the config file contains invalid URLs.
 134   
      * @throws ConfigurationException  If the config file is corrupt.
 135   
      * @throws DuplicateRealmException If the config file defines two realms with the same id.
 136   
      * @throws NoSuchRealmException    If the config file defines a main entry point in
 137   
      *                                 a non-existent realm.
 138   
      */
 139  52
     public void configure( InputStream is )
 140   
         throws IOException, MalformedURLException, ConfigurationException, DuplicateRealmException, NoSuchRealmException
 141   
     {
 142  52
         BufferedReader reader = new BufferedReader( new InputStreamReader( is ) );
 143   
 
 144  52
         if ( world == null )
 145   
         {
 146  52
             world = new ClassWorld();
 147   
         }
 148   
 
 149  52
         ClassRealm curRealm = null;
 150   
 
 151  52
         String line = null;
 152   
 
 153  52
         int lineNo = 0;
 154   
 
 155  52
         boolean mainSet = false;
 156   
 
 157  52
         while ( true )
 158   
         {
 159  660
             line = reader.readLine();
 160   
 
 161  660
             if ( line == null )
 162   
             {
 163  42
                 break;
 164   
             }
 165   
 
 166  618
             ++lineNo;
 167  618
             line = line.trim();
 168   
 
 169  618
             if ( canIgnore( line ) )
 170   
             {
 171  422
                 continue;
 172   
             }
 173   
 
 174  196
             if ( line.startsWith( MAIN_PREFIX ) )
 175   
             {
 176  46
                 if ( mainSet )
 177   
                 {
 178  2
                     throw new ConfigurationException( "Duplicate main configuration", lineNo, line );
 179   
                 }
 180   
 
 181  44
                 String conf = line.substring( MAIN_PREFIX.length() ).trim();
 182   
 
 183  44
                 int fromLoc = conf.indexOf( "from" );
 184   
 
 185  44
                 if ( fromLoc < 0 )
 186   
                 {
 187  0
                     throw new ConfigurationException( "Missing from clause", lineNo, line );
 188   
                 }
 189   
 
 190  44
                 String mainClassName = conf.substring( 0, fromLoc ).trim();
 191   
 
 192  44
                 String mainRealmName = conf.substring( fromLoc + 4 ).trim();
 193   
 
 194  44
                 if ( this.launcher != null )
 195   
                 {
 196  44
                     this.launcher.setAppMain( mainClassName, mainRealmName );
 197   
                 }
 198   
 
 199  44
                 mainSet = true;
 200   
             }
 201  150
             else if ( line.startsWith( SET_PREFIX ) )
 202   
             {
 203  36
                 String conf = line.substring( SET_PREFIX.length() ).trim();
 204   
 
 205  36
                 int usingLoc = conf.indexOf( " using" ) + 1;
 206   
 
 207  36
                 String property = null;
 208  36
                 String propertiesFileName = null;
 209  36
                 if ( usingLoc > 0 )
 210   
                 {
 211  24
                     property = conf.substring( 0, usingLoc ).trim();
 212   
 
 213  24
                     propertiesFileName = filter( conf.substring( usingLoc + 5 ).trim() );
 214   
 
 215  24
                     conf = propertiesFileName;
 216   
                 }
 217   
 
 218  36
                 String defaultValue = null;
 219   
 
 220  36
                 int defaultLoc = conf.indexOf( " default" ) + 1;
 221   
 
 222  36
                 if ( defaultLoc > 0 )
 223   
                 {
 224  24
                     defaultValue = conf.substring( defaultLoc + 7 ).trim();
 225   
 
 226  24
                     if ( property == null )
 227   
                     {
 228  12
                         property = conf.substring( 0, defaultLoc ).trim();
 229   
                     }
 230   
                     else
 231   
                     {
 232  12
                         propertiesFileName = conf.substring( 0, defaultLoc ).trim();
 233   
                     }
 234   
                 }
 235   
 
 236  36
                 String value = System.getProperty( property );
 237   
                 
 238  36
                 if ( value != null )
 239   
                 {
 240  4
                     continue;
 241   
                 }
 242   
 
 243  32
                 if ( propertiesFileName != null )
 244   
                 {
 245  22
                     File propertiesFile = new File( propertiesFileName );
 246   
 
 247  22
                     if ( propertiesFile.exists() )
 248   
                     {
 249  10
                         Properties properties = new Properties();
 250   
 
 251  10
                         try
 252   
                         {
 253  10
                             properties.load( new FileInputStream( propertiesFileName ) );
 254   
     
 255  10
                             value = properties.getProperty( property );
 256   
                         }
 257   
                         catch ( Exception e )
 258   
                         {
 259   
                             // do nothing
 260   
                         }
 261   
                     }
 262   
                 }
 263   
 
 264  32
                 if ( value == null && defaultValue != null )
 265   
                 {
 266  22
                     value = defaultValue;
 267   
                 }
 268   
 
 269  32
                 if ( value != null )
 270   
                 {
 271  26
                     value = filter( value );
 272  26
                     System.setProperty( property, value );
 273   
                 }
 274   
             }
 275  114
             else if ( line.startsWith( "[" ) )
 276   
             {
 277  62
                 int rbrack = line.indexOf( "]" );
 278   
 
 279  62
                 if ( rbrack < 0 )
 280   
                 {
 281  2
                     throw new ConfigurationException( "Invalid realm specifier", lineNo, line );
 282   
                 }
 283   
 
 284  60
                 String realmName = line.substring( 1, rbrack );
 285   
 
 286  60
                 curRealm = world.newRealm( realmName );
 287   
 
 288   
                 // Stash the configured realm for subsequent association processing.
 289  58
                 configuredRealms.put( realmName, curRealm );
 290   
             }
 291  52
             else if ( line.startsWith( IMPORT_PREFIX ) )
 292   
             {
 293  6
                 if ( curRealm == null )
 294   
                 {
 295  2
                     throw new ConfigurationException( "Unhandled import", lineNo, line );
 296   
                 }
 297   
 
 298  4
                 String conf = line.substring( IMPORT_PREFIX.length() ).trim();
 299   
 
 300  4
                 int fromLoc = conf.indexOf( "from" );
 301   
 
 302  4
                 if ( fromLoc < 0 )
 303   
                 {
 304  0
                     throw new ConfigurationException( "Missing from clause", lineNo, line );
 305   
                 }
 306   
 
 307  4
                 String importSpec = conf.substring( 0, fromLoc ).trim();
 308   
 
 309  4
                 String relamName = conf.substring( fromLoc + 4 ).trim();
 310   
 
 311  4
                 curRealm.importFrom( relamName, importSpec );
 312   
 
 313   
             }
 314  46
             else if ( line.startsWith( LOAD_PREFIX ) )
 315   
             {
 316  40
                 String constituent = line.substring( LOAD_PREFIX.length() ).trim();
 317   
 
 318  40
                 constituent = filter( constituent );
 319   
 
 320  40
                 if ( constituent.indexOf( "*" ) >= 0 )
 321   
                 {
 322  2
                     loadGlob( constituent, curRealm );
 323   
                 }
 324   
                 else
 325   
                 {
 326  38
                     File file = new File( constituent );
 327   
 
 328  38
                     if ( file.exists() )
 329   
                     {
 330  38
                         curRealm.addConstituent( file.toURL() );
 331   
                     }
 332   
                     else
 333   
                     {
 334  0
                         try
 335   
                         {
 336  0
                             curRealm.addConstituent( new URL( constituent ) );
 337   
                         }
 338   
                         catch ( MalformedURLException e )
 339   
                         {
 340  0
                             throw new FileNotFoundException( constituent );
 341   
                         }
 342   
                     }
 343   
                 }
 344   
             }
 345  6
             else if ( line.startsWith( OPTIONALLY_PREFIX ) )
 346   
             {
 347  4
                 String constituent = line.substring( OPTIONALLY_PREFIX.length() ).trim();
 348   
 
 349  4
                 constituent = filter( constituent );
 350   
 
 351  4
                 if ( constituent.indexOf( "*" ) >= 0 )
 352   
                 {
 353  2
                     loadGlob( constituent, curRealm, true );
 354   
                 }
 355   
                 else
 356   
                 {
 357  2
                     File file = new File( constituent );
 358   
 
 359  2
                     if ( file.exists() )
 360   
                     {
 361  2
                         curRealm.addConstituent( file.toURL() );
 362   
                     }
 363   
                     else
 364   
                     {
 365  0
                         try
 366   
                         {
 367  0
                             curRealm.addConstituent( new URL( constituent ) );
 368   
                         }
 369   
                         catch (MalformedURLException e)
 370   
                         {
 371   
                             // swallow
 372   
                         }
 373   
                     }
 374   
                 }
 375   
             }
 376   
             else
 377   
             {
 378  2
                 throw new ConfigurationException( "Unhandled configuration", lineNo, line );
 379   
             }
 380   
         }
 381   
 
 382   
         // Associate child realms to their parents.
 383  42
         associateRealms();
 384   
 
 385  42
         if ( this.launcher != null ) this.launcher.setWorld( world );
 386   
 
 387  42
         reader.close();
 388   
     }
 389   
 
 390   
     /**
 391   
      * Associate parent realms with their children.
 392   
      */
 393  42
     protected void associateRealms()
 394   
     {
 395  42
         List sortRealmNames = new ArrayList( configuredRealms.keySet() );
 396   
 
 397   
         // sort by name
 398  42
         Comparator comparator = new Comparator()
 399   
         {
 400  14
             public int compare( Object o1, Object o2 )
 401   
             {
 402  14
                 String g1 = (String) o1;
 403  14
                 String g2 = (String) o2;
 404  14
                 return g1.compareTo( g2 );
 405   
             }
 406   
         };
 407   
 
 408  42
         Collections.sort( sortRealmNames, comparator );
 409   
 
 410   
         // So now we have something like the following for defined
 411   
         // realms:
 412   
         //
 413   
         // root
 414   
         // root.maven
 415   
         // root.maven.plugin
 416   
         //
 417   
         // Now if the name of a realm is a superset of an existing realm
 418   
         // the we want to make child/parent associations.
 419   
 
 420  42
         for ( Iterator i = sortRealmNames.iterator(); i.hasNext(); )
 421   
         {
 422  52
             String realmName = (String) i.next();
 423   
 
 424  52
             int j = realmName.lastIndexOf( '.' );
 425   
 
 426  52
             if ( j > 0 )
 427   
             {
 428  4
                 String parentRealmName = realmName.substring( 0, j );
 429   
 
 430  4
                 ClassRealm parentRealm = (ClassRealm) configuredRealms.get( parentRealmName );
 431   
 
 432  4
                 if ( parentRealm != null )
 433   
                 {
 434  4
                     ClassRealm realm = (ClassRealm) configuredRealms.get( realmName );
 435   
 
 436  4
                     realm.setParent( parentRealm );
 437   
                 }
 438   
             }
 439   
         }
 440   
     }
 441   
 
 442   
     /**
 443   
      * Load a glob into the specified classloader.
 444   
      *
 445   
      * @param line  The path configuration line.
 446   
      * @param realm The realm to populate
 447   
      * @throws MalformedURLException If the line does not represent
 448   
      *                               a valid path element.
 449   
      * @throws FileNotFoundException If the line does not represent
 450   
      *                               a valid path element in the filesystem.
 451   
      */
 452  2
     protected void loadGlob( String line, ClassRealm realm )
 453   
         throws MalformedURLException, FileNotFoundException
 454   
     {
 455  2
         loadGlob( line, realm, false );
 456   
     }
 457   
 
 458   
     /**
 459   
      * Load a glob into the specified classloader.
 460   
      *
 461   
      * @param line  The path configuration line.
 462   
      * @param realm The realm to populate
 463   
      * @param optionally Whether the path is optional or required
 464   
      * @throws MalformedURLException If the line does not represent
 465   
      *                               a valid path element.
 466   
      * @throws FileNotFoundException If the line does not represent
 467   
      *                               a valid path element in the filesystem.
 468   
      */
 469  4
     protected void loadGlob( String line, ClassRealm realm, boolean optionally )
 470   
         throws MalformedURLException, FileNotFoundException
 471   
     {
 472  4
         File globFile = new File( line );
 473   
 
 474  4
         File dir = globFile.getParentFile();
 475  4
         if ( ! dir.exists() )
 476   
         {
 477  2
             if ( optionally )
 478   
             {
 479  2
                 return;
 480   
             }
 481   
             else
 482   
             {
 483  0
                 throw new FileNotFoundException( dir.toString() );
 484   
             }
 485   
         }
 486   
 
 487  2
         String localName = globFile.getName();
 488   
 
 489  2
         int starLoc = localName.indexOf( "*" );
 490   
 
 491  2
         final String prefix = localName.substring( 0, starLoc );
 492   
 
 493  2
         final String suffix = localName.substring( starLoc + 1 );
 494   
 
 495  2
         File[] matches = dir.listFiles( new FilenameFilter()
 496   
         {
 497  56
             public boolean accept( File dir, String name )
 498   
             {
 499  56
                 if ( !name.startsWith( prefix ) )
 500   
                 {
 501  0
                     return false;
 502   
                 }
 503   
 
 504  56
                 if ( !name.endsWith( suffix ) )
 505   
                 {
 506  46
                     return false;
 507   
                 }
 508   
 
 509  10
                 return true;
 510   
             }
 511   
         } );
 512   
 
 513  2
         for ( int i = 0; i < matches.length; ++i )
 514   
         {
 515  10
             realm.addConstituent( matches[i].toURL() );
 516   
         }
 517   
     }
 518   
 
 519   
     /**
 520   
      * Filter a string for system properties.
 521   
      *
 522   
      * @param text The text to filter.
 523   
      * @return The filtered text.
 524   
      * @throws ConfigurationException If the property does not
 525   
      *                                exist or if there is a syntax error.
 526   
      */
 527  108
     protected String filter( String text )
 528   
         throws ConfigurationException
 529   
     {
 530  108
         String result = "";
 531   
 
 532  108
         int cur = 0;
 533  108
         int textLen = text.length();
 534   
 
 535  108
         int propStart = -1;
 536  108
         int propStop = -1;
 537   
 
 538  108
         String propName = null;
 539  108
         String propValue = null;
 540   
 
 541  108
         while ( cur < textLen )
 542   
         {
 543  188
             propStart = text.indexOf( "${", cur );
 544   
 
 545  188
             if ( propStart < 0 )
 546   
             {
 547  100
                 break;
 548   
             }
 549   
 
 550  88
             result += text.substring( cur, propStart );
 551   
 
 552  88
             propStop = text.indexOf( "}", propStart );
 553   
 
 554  88
             if ( propStop < 0 )
 555   
             {
 556  2
                 throw new ConfigurationException( "Unterminated property: " + text.substring( propStart ) );
 557   
             }
 558   
 
 559  86
             propName = text.substring( propStart + 2, propStop );
 560   
 
 561  86
             propValue = System.getProperty( propName );
 562   
 
 563  86
             if ( propValue == null )
 564   
             {
 565  2
                 throw new ConfigurationException( "No such property: " + propName );
 566   
             }
 567  84
             result += propValue;
 568   
 
 569  84
             cur = propStop + 1;
 570   
         }
 571   
 
 572  104
         result += text.substring( cur );
 573   
 
 574  104
         return result;
 575   
     }
 576   
 
 577   
     /**
 578   
      * Determine if a line can be ignored because it is
 579   
      * a comment or simply blank.
 580   
      *
 581   
      * @param line The line to test.
 582   
      * @return <code>true</code> if the line is ignorable,
 583   
      *         otherwise <code>false</code>.
 584   
      */
 585  618
     private boolean canIgnore( String line )
 586   
     {
 587  618
         return ( line.length() == 0
 588   
             ||
 589   
             line.startsWith( "#" ) );
 590   
     }
 591   
 }
 592   
 
 593