-/*
- * Copyright (C) 2001, 2002 The Mir-coders group
- *
- * This file is part of Mir.
- *
- * Mir is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Mir 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Mir; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with the com.oreilly.servlet library, any library
- * licensed under the Apache Software License, The Sun (tm) Java Advanced
- * Imaging library (JAI), The Sun JIMI library (or with modified versions of
- * the above that use the same license as the above), and distribute linked
- * combinations including the two. You must obey the GNU General Public
- * License in all respects for all of the code used other than the above
- * mentioned libraries. If you modify this file, you may extend this exception
- * to your version of the file, but you are not obligated to do so. If you do
- * not wish to do so, delete this exception statement from your version.
- */
-
-package mir.config;\r
-\r
-import java.io.*;\r
-import java.util.*;\r
-import java.lang.System;\r
-import org.xml.sax.helpers.DefaultHandler;\r
-import org.xml.sax.*;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-import javax.xml.parsers.SAXParser;\r
-import javax.xml.parsers.SAXParserFactory;\r
-\r
-import mir.config.exceptions.*;\r
-import mir.misc.Location;\r
-\r
-public class ConfigReader {\r
- final static String propertyTagName="property";\r
- final static String propertyNameAttribute="name";\r
- final static String propertyValueAttribute="value";\r
- final static String defineTagName="define";\r
- final static String defineNameAttribute="name";\r
- final static String defineValueAttribute="value";\r
- final static String includeTagName="include";\r
- final static String includeFileAttribute="file";\r
-\r
- public ConfigReader() {\r
- super();\r
- };\r
-\r
- public void parseFile(String aFileName, ConfigNodeBuilder aRootNode) throws ConfigException {\r
-\r
- try {\r
- SAXParserFactory parserFactory = SAXParserFactory.newInstance();\r
-\r
- parserFactory.setNamespaceAware(false);\r
- parserFactory.setValidating(true);\r
-\r
-\r
- ConfigReaderHandler handler = new ConfigReaderHandler(aRootNode, parserFactory);\r
-\r
- handler.includeFile(aFileName);\r
- }\r
- catch (Throwable e) {\r
- if (e instanceof SAXParseException && ((SAXParseException) e).getException() instanceof ConfigException) {\r
- throw (ConfigException) ((SAXParseException) e).getException();\r
- }\r
- else {\r
- e.printStackTrace();\r
- throw new ConfigException( e.getMessage() );\r
- }\r
- }\r
- }\r
-\r
- private class ConfigReaderHandler extends DefaultHandler {\r
- ConfigNodeBuilder builder;\r
- Stack nodeStack;\r
- Locator locator;\r
- DefinesManager definesManager;\r
- int level;\r
- Stack includeFileStack;\r
- SAXParserFactory parserFactory;\r
-\r
- public ConfigReaderHandler(ConfigNodeBuilder aBuilder, SAXParserFactory aParserFactory) {\r
- super();\r
-\r
- builder=aBuilder;\r
- nodeStack=new Stack();\r
- includeFileStack=new Stack();\r
- definesManager=new DefinesManager();\r
- parserFactory=aParserFactory;\r
- level=0;\r
- }\r
-\r
- public String getLocatorDescription(Locator aLocator) {\r
- return aLocator.getPublicId()+" ("+aLocator.getLineNumber()+")";\r
- }\r
-\r
- public void setDocumentLocator(Locator aLocator) {\r
- locator=aLocator;\r
- }\r
-\r
- private void includeFile(String aFileName) throws ConfigException, SAXParseException, SAXException {\r
- File file;\r
- SAXParser parser;\r
- InputSource inputSource;\r
- System.err.println("about to include "+aFileName);\r
-\r
- try {\r
- if (!includeFileStack.empty())\r
- file = new File(new File((String) includeFileStack.peek()).getParent(), aFileName);\r
- else\r
- file = new File(aFileName);\r
-\r
- System.err.println("about to include "+file.getCanonicalPath());\r
-\r
- if (includeFileStack.contains(file.getCanonicalPath())) {\r
- throw new ConfigException("recursive inclusion of file "+file.getCanonicalPath(), getLocatorDescription(locator));\r
- }\r
-\r
- parser=parserFactory.newSAXParser();\r
-\r
- inputSource = new InputSource(new FileInputStream(file));\r
- inputSource.setPublicId(file.getCanonicalPath());\r
-\r
- includeFileStack.push(file.getCanonicalPath());\r
- try {\r
- parser.parse(inputSource, this);\r
- }\r
- finally {\r
- includeFileStack.pop();\r
- }\r
- }\r
- catch (ParserConfigurationException e) {\r
- throw new ConfigException("Internal exception while including \""+aFileName+"\": "+e.getMessage(), e, getLocatorDescription(locator));\r
- }\r
- catch (SAXParseException e) {\r
- throw e;\r
- }\r
- catch (ConfigException e) {\r
- throw e;\r
- }\r
- catch (FileNotFoundException e) {\r
- throw new ConfigException("Include file \""+aFileName+"\" not found: "+e.getMessage(), e, getLocatorDescription(locator));\r
- }\r
- catch (IOException e) {\r
- throw new ConfigException("unable to open include file \""+aFileName+"\": "+e.getMessage(), e, getLocatorDescription(locator));\r
- }\r
-\r
- }\r
-\r
- public void startElement(String aUri, String aTag, String aQualifiedName, Attributes anAttributes) throws SAXException {\r
- nodeStack.push(builder);\r
- level++;\r
- try {\r
- if (builder==null) {\r
- throw new ConfigException("define, include and property tags cannot have content", getLocatorDescription(locator));\r
- }\r
- if (aQualifiedName.equals(propertyTagName)) {\r
- String name=anAttributes.getValue(propertyNameAttribute);\r
- String value=anAttributes.getValue(propertyValueAttribute);\r
-\r
- if (name==null) {\r
- throw new ConfigException("property has no name attribute", getLocatorDescription(locator));\r
- }\r
- else\r
- if (value==null) {\r
- throw new ConfigException("property \""+name+"\" has no value attribute", getLocatorDescription(locator));\r
- }\r
-\r
- builder.addProperty(name, definesManager.resolve(value, getLocatorDescription(locator)), value, getLocatorDescription(locator));\r
- builder=null;\r
-\r
- }\r
- else if (aQualifiedName.equals(defineTagName)) {\r
- String name=anAttributes.getValue(defineNameAttribute);\r
- String value=anAttributes.getValue(defineValueAttribute);\r
-\r
- if (name==null) {\r
- throw new ConfigException("define has no name attribute", getLocatorDescription(locator));\r
- }\r
- else\r
- if (value==null) {\r
- throw new ConfigException("define \""+name+"\" has no value attribute", getLocatorDescription(locator));\r
- }\r
-\r
- definesManager.addDefine(name, definesManager.resolve(value, getLocatorDescription(locator)));\r
- builder=null;\r
- }\r
- else if (aQualifiedName.equals(includeTagName)) {\r
- String fileName=anAttributes.getValue(includeFileAttribute);\r
-\r
- if (fileName==null) {\r
- throw new ConfigException("include has no file attribute", getLocatorDescription(locator));\r
- }\r
-\r
- includeFile(definesManager.resolve(fileName, getLocatorDescription(locator)));\r
- builder=null;\r
- }\r
- else\r
- {\r
- builder=builder.makeSubNode(aQualifiedName, getLocatorDescription(locator));\r
- }\r
- }\r
- catch (ConfigException e) {\r
- throw new SAXParseException(e.getMessage(), locator, e);\r
- }\r
- }\r
-\r
- public void endElement(String aUri, String aTag, String aQualifiedName) throws SAXParseException {\r
- builder=(ConfigNodeBuilder) nodeStack.pop();\r
- level--;\r
- }\r
-\r
- public void characters(char[] aBuffer, int aStart, int anEnd) throws SAXParseException {\r
- String text = new String(aBuffer, aStart, anEnd).trim();\r
- if ( text.length() > 0) {\r
- throw new SAXParseException("Text not allowed", locator, new ConfigException("text not allowed", getLocatorDescription(locator)));\r
- }\r
- }\r
- }\r
-\r
- private class DefinesManager {\r
- Map defines;\r
-\r
- public DefinesManager() {\r
- defines = new HashMap();\r
- }\r
-\r
- public void addDefine(String aName, String anExpression) {\r
- defines.put(aName, anExpression);\r
- }\r
-\r
- public String resolve(String anExpression, String aLocation) throws ConfigException {\r
- int previousPosition = 0;\r
- int position;\r
- int endOfNamePosition;\r
- String name;\r
-\r
- StringBuffer result = new StringBuffer();\r
-\r
- while ((position=anExpression.indexOf("$", previousPosition))>=0) {\r
- result.append(anExpression.substring(previousPosition, position));\r
-\r
- if (position>=anExpression.length()-1) {\r
- result.append(anExpression.substring(position, anExpression.length()));\r
- previousPosition=anExpression.length();\r
- }\r
- else\r
- {\r
- if (anExpression.charAt(position+1) == '{') {\r
- endOfNamePosition=anExpression.indexOf('}', position);\r
- if (endOfNamePosition>=0) {\r
- name=anExpression.substring(position+2, endOfNamePosition);\r
- if (defines.containsKey(name)) {\r
- result.append((String) defines.get(name));\r
- previousPosition=endOfNamePosition+1;\r
- }\r
- else {\r
- throw new ConfigDefineNotKnownException("Variable \""+name+"\" not defined", aLocation);\r
- }\r
- }\r
- else {\r
- throw new ConfigException("Missing }", aLocation);\r
- }\r
-\r
- }\r
- else\r
- {\r
- previousPosition=position+2;\r
- result.append(anExpression.charAt(position+1));\r
- }\r
- }\r
- }\r
- result.append(anExpression.substring(previousPosition, anExpression.length()));\r
-\r
- return result.toString();\r
- }\r
- }\r
-}\r
-\r
-\r