package org.codehaus.plexus.classworlds.launcher;

/*
 * Copyright 2001-2006 Codehaus Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;

import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;

Event based launcher configuration parser, delegating effective configuration handling to ConfigurationHandler.
Author:bob mcwhirter, Jason van Zyl, Igor Fedorenko
See Also:
/** * Event based launcher configuration parser, delegating effective configuration handling to ConfigurationHandler. * * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a> * @author Jason van Zyl * @author Igor Fedorenko * @see ConfigurationHandler */
public class ConfigurationParser { public static final String MAIN_PREFIX = "main is"; public static final String SET_PREFIX = "set"; public static final String IMPORT_PREFIX = "import"; public static final String LOAD_PREFIX = "load";
Optionally spec prefix.
/** * Optionally spec prefix. */
public static final String OPTIONALLY_PREFIX = "optionally"; private ConfigurationHandler handler; private Properties systemProperties; public ConfigurationParser( ConfigurationHandler handler, Properties systemProperties ) { this.handler = handler; this.systemProperties = systemProperties; }
Parse launcher configuration file and send events to the handler.
Params:
  • is – the inputstream
Throws:
/** * Parse launcher configuration file and send events to the handler. * * @param is the inputstream * @throws IOException when IOException occurs * @throws ConfigurationException when ConfigurationException occurs * @throws DuplicateRealmException when realm already exists * @throws NoSuchRealmException when realm doesn't exist */
public void parse( InputStream is ) throws IOException, ConfigurationException, DuplicateRealmException, NoSuchRealmException { BufferedReader reader = new BufferedReader( new InputStreamReader( is, "UTF-8" ) ); String line = null; int lineNo = 0; boolean mainSet = false; String curRealm = null; while ( true ) { line = reader.readLine(); if ( line == null ) { break; } ++lineNo; line = line.trim(); if ( canIgnore( line ) ) { continue; } if ( line.startsWith( MAIN_PREFIX ) ) { if ( mainSet ) { throw new ConfigurationException( "Duplicate main configuration", lineNo, line ); } String conf = line.substring( MAIN_PREFIX.length() ).trim(); int fromLoc = conf.indexOf( "from" ); if ( fromLoc < 0 ) { throw new ConfigurationException( "Missing from clause", lineNo, line ); } String mainClassName = filter( conf.substring( 0, fromLoc ).trim() ); String mainRealmName = filter( conf.substring( fromLoc + 4 ).trim() ); this.handler.setAppMain( mainClassName, mainRealmName ); mainSet = true; } else if ( line.startsWith( SET_PREFIX ) ) { String conf = line.substring( SET_PREFIX.length() ).trim(); int usingLoc = conf.indexOf( " using" ) + 1; String property = null; String propertiesFileName = null; if ( usingLoc > 0 ) { property = conf.substring( 0, usingLoc ).trim(); propertiesFileName = filter( conf.substring( usingLoc + 5 ).trim() ); conf = propertiesFileName; } String defaultValue = null; int defaultLoc = conf.indexOf( " default" ) + 1; if ( defaultLoc > 0 ) { defaultValue = filter( conf.substring( defaultLoc + 7 ).trim() ); if ( property == null ) { property = conf.substring( 0, defaultLoc ).trim(); } else { propertiesFileName = conf.substring( 0, defaultLoc ).trim(); } } String value = systemProperties.getProperty( property ); if ( value != null ) { continue; } if ( propertiesFileName != null ) { File propertiesFile = new File( propertiesFileName ); if ( propertiesFile.exists() ) { Properties properties = new Properties(); try { properties.load( new FileInputStream( propertiesFileName ) ); value = properties.getProperty( property ); } catch ( Exception e ) { // do nothing } } } if ( value == null && defaultValue != null ) { value = defaultValue; } if ( value != null ) { value = filter( value ); systemProperties.setProperty( property, value ); } } else if ( line.startsWith( "[" ) ) { int rbrack = line.indexOf( "]" ); if ( rbrack < 0 ) { throw new ConfigurationException( "Invalid realm specifier", lineNo, line ); } String realmName = line.substring( 1, rbrack ); handler.addRealm( realmName ); curRealm = realmName; } else if ( line.startsWith( IMPORT_PREFIX ) ) { if ( curRealm == null ) { throw new ConfigurationException( "Unhandled import", lineNo, line ); } String conf = line.substring( IMPORT_PREFIX.length() ).trim(); int fromLoc = conf.indexOf( "from" ); if ( fromLoc < 0 ) { throw new ConfigurationException( "Missing from clause", lineNo, line ); } String importSpec = conf.substring( 0, fromLoc ).trim(); String relamName = conf.substring( fromLoc + 4 ).trim(); handler.addImportFrom( relamName, importSpec ); } else if ( line.startsWith( LOAD_PREFIX ) ) { String constituent = line.substring( LOAD_PREFIX.length() ).trim(); constituent = filter( constituent ); if ( constituent.indexOf( "*" ) >= 0 ) { loadGlob( constituent, false /*not optionally*/ ); } else { File file = new File( constituent ); if ( file.exists() ) { handler.addLoadFile( file ); } else { try { handler.addLoadURL( new URL( constituent ) ); } catch ( MalformedURLException e ) { throw new FileNotFoundException( constituent ); } } } } else if ( line.startsWith( OPTIONALLY_PREFIX ) ) { String constituent = line.substring( OPTIONALLY_PREFIX.length() ).trim(); constituent = filter( constituent ); if ( constituent.indexOf( "*" ) >= 0 ) { loadGlob( constituent, true /*optionally*/ ); } else { File file = new File( constituent ); if ( file.exists() ) { handler.addLoadFile( file ); } else { try { handler.addLoadURL( new URL( constituent ) ); } catch ( MalformedURLException e ) { // swallow } } } } else { throw new ConfigurationException( "Unhandled configuration", lineNo, line ); } } reader.close(); }
Load a glob into the specified classloader.
Params:
  • line – The path configuration line.
  • optionally – Whether the path is optional or required
Throws:
/** * Load a glob into the specified classloader. * * @param line The path configuration line. * @param optionally Whether the path is optional or required * @throws MalformedURLException If the line does not represent * a valid path element. * @throws FileNotFoundException If the line does not represent * a valid path element in the filesystem. * @throws ConfigurationException will never occur (thrown for backwards compatibility) */
protected void loadGlob( String line, boolean optionally ) throws MalformedURLException, FileNotFoundException, ConfigurationException { File globFile = new File( line ); File dir = globFile.getParentFile(); if ( !dir.exists() ) { if ( optionally ) { return; } else { throw new FileNotFoundException( dir.toString() ); } } String localName = globFile.getName(); int starLoc = localName.indexOf( "*" ); final String prefix = localName.substring( 0, starLoc ); final String suffix = localName.substring( starLoc + 1 ); File[] matches = dir.listFiles( new FilenameFilter() { public boolean accept( File dir, String name ) { if ( !name.startsWith( prefix ) ) { return false; } if ( !name.endsWith( suffix ) ) { return false; } return true; } } ); for ( File match : matches ) { handler.addLoadFile( match ); } }
Filter a string for system properties.
Params:
  • text – The text to filter.
Throws:
Returns:The filtered text.
/** * Filter a string for system properties. * * @param text The text to filter. * @return The filtered text. * @throws ConfigurationException If the property does not * exist or if there is a syntax error. */
protected String filter( String text ) throws ConfigurationException { String result = ""; int cur = 0; int textLen = text.length(); int propStart = -1; int propStop = -1; String propName = null; String propValue = null; while ( cur < textLen ) { propStart = text.indexOf( "${", cur ); if ( propStart < 0 ) { break; } result += text.substring( cur, propStart ); propStop = text.indexOf( "}", propStart ); if ( propStop < 0 ) { throw new ConfigurationException( "Unterminated property: " + text.substring( propStart ) ); } propName = text.substring( propStart + 2, propStop ); propValue = systemProperties.getProperty( propName ); /* do our best if we are not running from surefire */ if ( propName.equals( "basedir" ) && ( propValue == null || propValue.equals( "" ) ) ) { propValue = ( new File( "" ) ).getAbsolutePath(); } if ( propValue == null ) { throw new ConfigurationException( "No such property: " + propName ); } result += propValue; cur = propStop + 1; } result += text.substring( cur ); return result; }
Determine if a line can be ignored because it is a comment or simply blank.
Params:
  • line – The line to test.
Returns:true if the line is ignorable, otherwise false.
/** * Determine if a line can be ignored because it is * a comment or simply blank. * * @param line The line to test. * @return <code>true</code> if the line is ignorable, * otherwise <code>false</code>. */
private boolean canIgnore( String line ) { return ( line.length() == 0 || line.startsWith( "#" ) ); } }