flex2.compiler.config.FileConfigurator Maven / Gradle / Ivy
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*
*/
package flex2.compiler.config;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.SAXException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXParseException;
import org.xml.sax.Locator;
import org.xml.sax.InputSource;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.List;
import java.util.LinkedList;
import java.util.Stack;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.TreeMap;
import flex2.compiler.util.CompilerMessage;
import flex2.compiler.util.ThreadLocalToolkit;
//import flash.util.FileUtils;
//import flash.localization.LocalizationManager;
/**
* A utility class, which is used to parse an XML file of
* configuration options and populate a ConfigurationBuffer. A
* counterpart of CommandLineConfigurator and
* SystemPropertyConfigurator.
*
* @author Roger Gonzalez
*/
public class FileConfigurator
{
public static class SAXConfigurationException extends SAXParseException
{
private static final long serialVersionUID = -3388781933743434302L;
SAXConfigurationException( ConfigurationException e, Locator locator )
{
super( null, locator ); // ?
this.innerException = e;
}
public ConfigurationException innerException;
}
/**
* @deprecated
*/
public static void load( final ConfigurationBuffer buffer, final Reader r, final String path, String rootElement ) throws ConfigurationException
{
load( buffer, r, path, null, rootElement );
}
/**
* @deprecated
*/
public static void load( final ConfigurationBuffer buffer, final Reader r, final String path, final String context, String rootElement ) throws ConfigurationException
{
ThreadLocalToolkit.log( new LoadingConfiguration(path) );
Handler h = new Handler( buffer, path, context, rootElement, false );
SAXParserFactory factory = SAXParserFactory.newInstance();
try
{
SAXParser parser = factory.newSAXParser();
InputSource source = new InputSource( r );
parser.parse( source, h );
}
catch (SAXConfigurationException e)
{
throw e.innerException;
}
catch (SAXParseException e)
{
throw new ConfigurationException.OtherThrowable( e, null, path, e.getLineNumber() );
}
catch (Exception e)
{
throw new ConfigurationException.OtherThrowable( e, null, path, -1 );
}
}
public static void load( final ConfigurationBuffer buffer, final InputStream r, final String path, String rootElement ) throws ConfigurationException
{
load( buffer, r, path, null, rootElement, false );
}
public static void load( final ConfigurationBuffer buffer, final InputStream r, final String path,
final String context, String rootElement, boolean ignoreUnknownItems ) throws ConfigurationException
{
ThreadLocalToolkit.log( new LoadingConfiguration(path) );
Handler h = new Handler( buffer, path, context, rootElement, ignoreUnknownItems );
SAXParserFactory factory = SAXParserFactory.newInstance();
try
{
SAXParser parser = factory.newSAXParser();
InputSource source = new InputSource( r );
parser.parse( source, h );
}
catch (SAXConfigurationException e)
{
throw e.innerException;
}
catch (SAXParseException e)
{
throw new ConfigurationException.OtherThrowable( e, null, path, e.getLineNumber() );
}
catch (Exception e)
{
throw new ConfigurationException.OtherThrowable( e, null, path, -1 );
}
}
public static void load( ConfigurationBuffer buffer, String path, String rootElement ) throws ConfigurationException
{
load( buffer, path, null, -1, rootElement );
}
public static void load( ConfigurationBuffer buffer, String path, String contextPath, int line, String rootElement ) throws ConfigurationException
{
try
{
File f = new File( getFilePath( path, contextPath ) );
InputStream r = new BufferedInputStream( new FileInputStream( f ) );
load( buffer, r, f.getAbsolutePath(), f.getParent(), rootElement, false );
try
{
r.close();
}
catch(IOException e)
{
//
}
}
catch (FileNotFoundException e)
{
throw new ConfigurationException.ConfigurationIOError( path, null, contextPath, line );
}
}
// file to load should either be an absolute path or else relative to this config file
private static String getFilePath( String path, String contextPath )
{
File f = new File( path );
// file to load should either be an absolute path or else relative to this config file
if ( (contextPath != null) && ( !f.exists() || !f.isAbsolute() ) )
{
f = new File( contextPath + File.separator + path );
}
return f.getAbsolutePath();
}
private static class Handler extends DefaultHandler
{
public Handler( ConfigurationBuffer buffer, String source, String contextPath, String rootElement,
boolean ignoreUnknownItems )
{
this.cfgbuf = buffer;
this.source = source;
this.contextPath = contextPath;
this.rootElement = rootElement;
this.ignoreUnknownItems = ignoreUnknownItems;
}
public void startElement( String uri, String localName, String qName, Attributes attributes ) throws SAXException
{
String element = qName;
if (contextStack.size() == 0)
{
if (!element.equals( rootElement ))
{
throw new SAXConfigurationException(
new ConfigurationException.IncorrectElement( rootElement, qName, this.source, locator.getLineNumber() ),
locator );
}
ParseContext ctx = new ParseContext();
contextStack.push( ctx );
return;
}
ParseContext ctx = contextStack.peek();
if (ctx.ignore)
{
// ignore starting new elements
return;
}
if (text.length() > 0)
{
throw new SAXConfigurationException(
new ConfigurationException.UnexpectedCDATA( this.source, locator.getLineNumber() ),
locator );
}
String fullname = name( element, ctx.base );
if (ctx.item != null)
{
throw new SAXConfigurationException(
new ConfigurationException.UnexpectedElement( element, contextPath, locator.getLineNumber() ),
locator );
}
else if (ctx.var != null)
{
// we're setting values for a variable
if (ctx.varArgCount == 1)
{
// oops, we weren't expecting more than one value!
throw new SAXConfigurationException(
new ConfigurationException.UnexpectedElement( element, source, locator.getLineNumber() ),
locator );
}
ctx.item = element;
}
else if (cfgbuf.isValidVar( fullname ))
{
ctx.var = fullname;
ctx.varArgCount = cfgbuf.getVarArgCount( ctx.var );
ctx.append = false;
String a = attributes.getValue( "", "append" );
if (a != null)
{
try
{
if (a.equalsIgnoreCase( "true" ) || a.equalsIgnoreCase( "false" ))
ctx.append = Boolean.valueOf( a ).booleanValue();
else
throw new SAXConfigurationException( new ConfigurationException.BadAppendValue( ctx.var, source, locator.getLineNumber() ),
locator );
}
catch (Exception e)
{
throw new SAXConfigurationException( new ConfigurationException.BadAppendValue( ctx.var, source, locator.getLineNumber() ),
locator );
}
}
}
else if (cfgbuf.isChildConfig( fullname ))
{
String src = attributes.getValue( "", "file-path" );
if (src != null)
{
try
{
Class childClass = cfgbuf.getChildConfigClass( fullname );
ConfigurationBuffer childBuf = new ConfigurationBuffer( childClass );
// keep track of the file-path name
cfgbuf.setVar( element + "-file-path", getFilePath( src, contextPath ), contextPath, locator.getLineNumber() );
FileConfigurator.load( childBuf, src, contextPath, locator.getLineNumber(), element );
cfgbuf.mergeChild( element, childBuf );
}
catch (final ConfigurationException e)
{
throw new SAXConfigurationException( e, locator );
}
}
ParseContext newctx = new ParseContext();
newctx.base = fullname;
contextStack.push( newctx );
}
else
{
if (ignoreUnknownItems)
{
// push a new context and ignore everything until we get the end
// of this element.
ParseContext newctx = new ParseContext();
newctx.item = element;
newctx.ignore = true;
contextStack.push( newctx );
return;
}
throw new SAXConfigurationException(
new ConfigurationException.UnknownVariable(
fullname, source, locator.getLineNumber() ),
locator );
}
}
public void endElement( String uri, String localName, String qName ) throws SAXException
{
String element = qName;
ParseContext ctx = contextStack.peek();
if (ctx.ignore)
{
// if found the matching end element, then pop the context and stop ignoring input
if (ctx.item.equals(element))
{
contextStack.pop();
text = new StringBuilder(); // ignore any text read
}
return;
}
// There are four possible states here;
// 1. localname==rootElement -> end of file, pop, we're done
// 2. localname==itemElement -> finished gathering text, push onto arglist
// 2. var is set -> set the var to the argList, pop
// 3. var is null -> we're finishing a child config, pop
if (element.equals( rootElement ))
{
// Finished with the file!
}
else if (ctx.item != null)
{
// Finished with the current item.
ParseValue v = new ParseValue();
v.name = element;
v.value = text.toString();
v.line = locator.getLineNumber();
ctx.argList.add( v );
text = new StringBuilder();
ctx.item = null;
}
else if (ctx.var != null)
{
if ((ctx.varArgCount > 1) && (ctx.argList.size() == 0))
{
throw new SAXConfigurationException(
new ConfigurationException.IncorrectArgumentCount( ctx.varArgCount, 0,
ctx.var, source, locator.getLineNumber() ),
locator );
}
if (ctx.varArgCount == 1)
{
ParseValue v = new ParseValue();
v.name = null;
v.value = text.toString();
v.line = locator.getLineNumber();
ctx.argList.add( v );
text = new StringBuilder();
}
else
{
if (text.length() > 0)
{
// "unexpected CDATA encountered, " + ctx.var + " requires named arguments.", locator );
throw new SAXConfigurationException(
new ConfigurationException.UnexpectedCDATA( source, locator.getLineNumber() ),
locator );
}
}
// Finished with the current var, save the current list
try
{
setVar( ctx.var, ctx.argList, locator.getLineNumber(), ctx.append );
ctx.var = null;
ctx.argList.clear();
ctx.item = null;
ctx.append = false;
}
catch (ConfigurationException e)
{
throw new SAXConfigurationException( e, locator );
}
}
else
{
// done with a child config
contextStack.pop();
}
}
public void setVar( String var, List argList, int line, boolean append ) throws ConfigurationException
{
int varArgCount = cfgbuf.getVarArgCount( var );
Map items = new HashMap();
boolean byName = (varArgCount > 1);
if (byName)
{
for (Iterator it = argList.iterator(); it.hasNext();)
{
ParseValue v = it.next();
if (items.containsKey( v.name ))
{
byName = false; // can't support byName, duplicate item name!
break;
}
else
{
items.put( v.name, v.value );
}
}
}
List args = new LinkedList();
if (byName)
{
int argc = 0;
while (args.size() < items.size())
{
String name = cfgbuf.getVarArgName( var, argc++ );
String val = items.get( name );
if (val == null)
{
throw new ConfigurationException.MissingArgument( name, var, source, line );
}
args.add( val );
}
}
else
{
Iterator it = argList.iterator();
int argc = 0;
while (it.hasNext())
{
ParseValue v = it.next();
String name = cfgbuf.getVarArgName( var, argc++ );
if ((v.name != null) && !name.equals( v.name ))
{
throw new ConfigurationException.UnexpectedArgument( name, v.name, var, source, v.line );
}
args.add( v.value );
}
}
cfgbuf.setVar( var, args, source, line, contextPath, append );
}
public void characters( char ch[], int start, int length )
{
String chars = new String( ch, start, length ).trim();
text.append( chars );
}
public void setDocumentLocator( Locator locator )
{
this.locator = locator;
}
private Stack contextStack = new Stack();
private final ConfigurationBuffer cfgbuf;
private final String source;
private final String contextPath;
private final String rootElement;
/**
* if true, do not throw an error if a config var is found that is not defined in the config buffer.
*/
private final boolean ignoreUnknownItems;
private Locator locator;
StringBuilder text = new StringBuilder();
}
private static String name( String var, String base )
{
return (base == null)? var : (base + "." + var);
}
private static class ParseContext
{
ParseContext()
{
this.base = null;
this.var = null;
this.varArgCount = -2;
this.argList = new LinkedList();
this.append = false;
this.ignore = false;
}
//public String localVar;
public String var;
public String base;
public String item;
public int varArgCount;
public boolean append;
public List argList;
public boolean ignore; // ignore this variable, do not put in config buffer
}
private static class ParseValue
{
public String name;
public String value;
public int line;
}
private static class FormatNode
{
public String fullname;
public String shortname;
public ConfigurationInfo info;
public List values;
public TreeMap children; // only for configs
}
static final String pad = " ";
private static String classToArgName( Class c )
{
// we only support builtin classnames!
String className = c.getName();
if (className.startsWith( "java.lang." ))
className = className.substring( "java.lang.".length() );
return className.toLowerCase();
}
private static String formatBuffer1( ConfigurationBuffer cfgbuf,
FormatNode node,
String indent,
// LocalizationManager lmgr,
String prefix )
{
StringBuilder buf = new StringBuilder( 1024 );
buf.append( indent + "<" + node.shortname + ">\n" );
if (node.children != null) {
for (Iterator it = node.children.entrySet().iterator(); it.hasNext(); )
{
Map.Entry e = (Map.Entry) it.next();
FormatNode child = (FormatNode) e.getValue();
if (child.children != null) // its a config
{
buf.append( formatBuffer1( cfgbuf, child, indent + pad, /*lmgr, */ prefix ) );
}
else
{
String description = /*lmgr.getLocalizedTextString(*/ prefix + "." + child.fullname /*)*/;
if (description != null)
buf.append( indent + pad + "\n" );
if ((child.values == null) || !child.info.isDisplayed())
{
boolean newline = false;
buf.append( indent + pad + "\n" );
}
else
{
// var may be set multiple times...
boolean newline = false;
for (Iterator valit = child.values.iterator(); valit.hasNext();)
{
ConfigurationValue cv = (ConfigurationValue) valit.next();
buf.append( indent + pad + "<" + child.shortname + ">" );
int argCount = child.info.getArgCount();
// var may have multiple values...
int argc = 0;
for (Iterator argit = cv.getArgs().iterator(); argit.hasNext();)
{
String arg = (String) argit.next();
if (argCount == 1)
{
buf.append( arg );
break;
}
else
{
String argname = child.info.getArgName( argc++ );
newline = true;
buf.append( "\n" + indent + pad + pad + "<" + argname + ">" + arg + "" + argname + ">" );
}
}
if (newline)
buf.append( "\n" + indent + pad);
buf.append( "" + child.shortname + ">\n" );
}
}
}
}
}
buf.append( indent + "" + node.shortname + ">\n" );
return buf.toString();
}
private static void addNode( ConfigurationBuffer cfgbuf, String var, FormatNode root )
{
String name = null;
StringTokenizer t = new StringTokenizer( var, "." );
FormatNode current = root;
while (t.hasMoreTokens())
{
String token = t.nextToken();
if (name == null)
name = token;
else
name += "." + token;
if (current.children == null)
current.children = new TreeMap();
if (cfgbuf.isChildConfig( name ))
{
if (!current.children.containsKey( token ))
{
FormatNode node = new FormatNode();
node.fullname = name;
node.shortname = token;
node.children = new TreeMap();
current.children.put( token, node );
current = node;
}
else
{
current = current.children.get( token );
}
}
else if (cfgbuf.isValidVar( name ))
{
FormatNode node = new FormatNode();
node.fullname = name;
node.shortname = token;
node.info = cfgbuf.getInfo( name );
node.values = cfgbuf.getVar( name );
current.children.put( token, node );
}
}
}
public static String formatBuffer( ConfigurationBuffer cfgbuf,
String rootElement,
// LocalizationManager lmgr,
String prefix )
{
FormatNode root = new FormatNode();
root.shortname = rootElement;
for (Iterator it = cfgbuf.getVarIterator(); it.hasNext(); )
{
String var = (String) it.next();
// if var is a 'hidden' parameter, don't dump.
ConfigurationInfo info = cfgbuf.getInfo(var);
if (info != null && (info.isHidden() || !info.isDisplayed()))
{
continue;
}
addNode( cfgbuf, var, root );
}
return formatBuffer1( cfgbuf, root, "", /*lmgr, */ prefix );
}
public static String formatBuffer( ConfigurationBuffer cfgbuf, String rootElement)
{
return formatBuffer( cfgbuf, rootElement, /*null, */ null );
}
public static class LoadingConfiguration extends CompilerMessage.CompilerInfo
{
private static final long serialVersionUID = 7288323144791549482L;
public String file;
public LoadingConfiguration(String file)
{
this.file = file;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy