/* Copyright (C) 2009 Mobile Sorcery AB
This program is free software; you can redistribute it and/or modify it
under the terms of the Eclipse Public License v1.0.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse Public License v1.0 for
more details.
You should have received a copy of the Eclipse Public License v1.0 along
with this program. It is also available at http://www.eclipse.org/legal/epl-v10.html
*/
package com.mobilesorcery.sdk.builder.linux;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
/**
* This is a simple class that was refactored out or PackageParser,
* it handles variables and resolving them in strings and files.
*
* @author Ali Mosavian
*/
public class VariableResolver
{
private Map<String, String> m_variableMap;
/**
* Constructor
*/
public VariableResolver ( )
{
m_variableMap = new HashMap<String, String>( );
}
/**
* Sets a variable value pair, this is used to resolve
* unknown variables during template package processing.
*
* @param s Variable name
* @param v Variable value
*/
public void addVariable ( String s,
String v )
{
m_variableMap.put( s.toLowerCase( ), v );
}
/**
* Parse an input stream and resolves variables. Result
* is parsed string.
*
* @param i Input stream to parse
*
* @throws Exception If recursion is too deep or a variable isn't defined
* @throws IOException Error while reading from stream
*/
public String doParseStream ( InputStream i )
throws Exception,
IOException
{
StringBuilder res = new StringBuilder( );
BufferedReader r = new BufferedReader( new InputStreamReader( i ) );
// Read and parse
while ( r.ready( ) == true )
res.append( doResolveString( r.readLine( ) )+"\n" );
return res.toString( );
}
/**
* Copies an inputstream to a file, recursivly resolving
* variables while copying.
* @param o Output file
* @param i Input stream to parse and copy
*
* @throws Exception If recursion is too deep or a variable isn't defined
* @throws IOException Error while reading from stream/writing to file
*/
public void doParseCopyStream ( File o,
InputStream i )
throws Exception,
IOException
{
BufferedReader r = new BufferedReader( new InputStreamReader( i ) );
BufferedWriter w = new BufferedWriter( new BufferedWriter( new FileWriter( o ) ));
// Copy and parse
while ( r.ready( ) == true )
w.write( doResolveString( r.readLine( ) )+"\n" );
// Close output
w.close( );
}
/**
* Processes a string recursivly replacing all variables with their
* values.
*
* @param s String to process
*
* @return Resolved string
* @throws Exception If recursion is too deep or a variable isn't defined
*/
public String doResolveString ( String s )
throws Exception
{
int state = 0;
StringBuilder str = new StringBuilder( );
StringBuilder var = new StringBuilder( );
// State machine for extracting variables
for ( char c : s.toCharArray( ) )
{
switch ( state )
{
case 0:
if ( c == '%' )
state = 1;
else
str.append( c );
break;
case 1:
if ( c == '%' )
{
str.append( doResolveVariable( var.toString( ) ) );
var = new StringBuilder( );
state = 0;
}
else
var.append( c );
break;
}
}
return str.toString( );
}
/**
* Recursivly resolves a variable to its value.
*
* @param s Variable name
*
* @return Variable value
* @throws Exception If recursion is too deep or a variable isn't defined
*/
private String doResolveVariable ( String s )
throws Exception
{
return doResolveVariable( s, 0 );
}
/**
* Recursivly resolves a variable to its value.
*
* @param s Variable name
* @param d Current recursion depth
*
* @return Variable value
* @throws Exception If recursion is too deep or a variable isn't defined
*/
private String doResolveVariable ( String s,
int d )
throws Exception
{
if ( d > 32 )
throw new Exception( "Variable resolve - recursion too deep" );
s = s.toLowerCase( );
if ( m_variableMap.containsKey( s ) == false )
throw new Exception( "Variable resolve - undefined variable" );
String val = m_variableMap.get( s );
if ( val.charAt( 0 ) == '%' )
return doResolveVariable( val.replaceAll( "%", "" ), d+1 );
return val;
}
}