001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.core.node;
028:
029: import java.io.FileNotFoundException;
030: import java.util.Collections;
031: import java.util.Enumeration;
032: import java.util.HashMap;
033: import java.util.Map;
034: import java.util.Properties;
035: import org.cougaar.bootstrap.SystemProperties;
036: import org.xml.sax.ContentHandler;
037:
038: /**
039: * Utility class used by the {@link
040: * XMLComponentInitializerServiceComponent} to parse the agent
041: * configurations.
042: * <p>
043: * <pre>
044: * @property org.cougaar.node.name
045: * The name for this Node.
046: *
047: * @property org.cougaar.society.xml.validate
048: * Indicates if the XML parser should be validating or not.
049: * Defaults to "false".
050: * @property org.cougaar.node.validate
051: * Same as "-Dorg.cougaar.society.xml.validate"
052: * @property org.cougaar.society.xsl.checkXML
053: * Check for an XSL stylesheet, e.g.:
054: * <?xml-stylesheet type="text/xml" href="society.xsl"?>
055: * Defaults to "true".
056: * @property org.cougaar.society.xsl.default.file
057: * Default XSL stylesheet if "-Dorg.cougaar.society.xsl.checkXML"
058: * is false or an xml-stylesheet is not found. Defaults to
059: * null.
060: * @property org.cougaar.society.xsl.dynamic.file
061: * Dynamic XSL stylesheet that generates the XSL stylesheet
062: * based upon the XML file contents, unless an XSL stylesheet
063: * is specified in the XML file
064: * (-Dorg.cougaar.society.xsl.checkXML) or specified
065: * (-Dorg.cougaar.society.xsl.default.file). Defaults to
066: * "make_society.xsl".
067: * @property org.cougaar.society.xsl.param.*
068: * XSL parameters passed to the xml-stylesheet or default XSL
069: * stylesheet, where the above system property prefix is
070: * removed. For example, if a system property is:
071: * -Dorg.cougaar.society.xsl.param.foo=bar
072: * then the parameter "foo=bar" will be passed to the XSL
073: * file's optional parameter:
074: * <xsl:param name="foo">my_default</xsl:param>
075: * </pre>
076: */
077: public final class XMLConfigParser {
078:
079: // xsl options:
080:
081: private static final boolean VALIDATE = SystemProperties
082: .getBoolean("org.cougaar.society.xml.validate")
083: || SystemProperties
084: .getBoolean("org.cougaar.core.node.validate");
085:
086: private static final boolean USE_XML_STYLESHEET = SystemProperties
087: .getBoolean("org.cougaar.society.xsl.checkXML", true);
088:
089: private static final String DEFAULT_XSL_FILE_NAME = SystemProperties
090: .getProperty("org.cougaar.society.xsl.default.file", null);
091:
092: private static final String DYNAMIC_XSL_FILE_NAME = SystemProperties
093: .getProperty("org.cougaar.society.xsl.dynamic.file",
094: "make_society.xsl");
095:
096: private static final String XSL_PARAM_PROP_PREFIX = "org.cougaar.society.xsl.param.";
097: private static final Map XSL_PARAMS = getSystemPropertiesAndTrim(XSL_PARAM_PROP_PREFIX);
098:
099: public static final Map parseAgents(String filename,
100: String nodename, String agentname, Map param_overrides) {
101:
102: XSLTransformer xslt = new XSLTransformer();
103:
104: // set xml filename
105: xslt.setXMLFileName(filename);
106:
107: // set defaults
108: xslt.setValidate(VALIDATE);
109: xslt.setUseXMLStylesheet(USE_XML_STYLESHEET);
110: xslt.setDefaultXSLFileName(DEFAULT_XSL_FILE_NAME);
111: xslt.setDynamicXSLFileName(DYNAMIC_XSL_FILE_NAME);
112:
113: // override some of the default XSL params:
114: xslt.setDefaultXSLParams(override_params(XSL_PARAMS,
115: param_overrides));
116: xslt.setDynamicXSLParams(override_params(XSL_PARAMS,
117: param_overrides));
118:
119: // set our sax handler
120: XMLConfigHandler handler = new XMLConfigHandler(nodename,
121: agentname);
122: xslt.setContentHandler(handler);
123:
124: try {
125: // parse, call our handler
126: xslt.parse();
127: } catch (Exception e) {
128: String msg = "Unable to parse XML file \"" + filename
129: + "\"";
130: // look for a simple file-not-found error
131: FileNotFoundException fnfe = null;
132: for (Throwable t = e; t != null; t = t.getCause()) {
133: if (t instanceof FileNotFoundException) {
134: fnfe = (FileNotFoundException) t;
135: break;
136: }
137: }
138: if (fnfe == null) {
139: // xslt error? append extra detail
140: msg += ", detail=" + xslt;
141: } else {
142: // simple file-not-found
143: if (fnfe.getMessage() != null) {
144: msg += ", file not found: " + fnfe.getMessage();
145: }
146: }
147: throw new RuntimeException(msg, e);
148: }
149:
150: // ask handler for agents
151: Map ret = handler.getAgents();
152:
153: return ret;
154: }
155:
156: /**
157: * Utility method to find all system properties with the specified
158: * prefix and create an unmodifiable map of the trailing
159: * "name=value" pairs.
160: * E.g. if prefix is "a.b.", and system properties are "-Da.b.x=y"
161: * and "-Da.b.p=q", then this method will return "{x=y, p=q}".
162: */
163: private static final Map getSystemPropertiesAndTrim(String prefix) {
164: Properties props = SystemProperties
165: .getSystemPropertiesWithPrefix(prefix);
166: Map ret;
167: if (props.isEmpty()) {
168: ret = Collections.EMPTY_MAP;
169: } else {
170: ret = new HashMap(props.size());
171: for (Enumeration en = props.propertyNames(); en
172: .hasMoreElements();) {
173: String name = (String) en.nextElement();
174: String key = name.substring(prefix.length());
175: String value = props.getProperty(name);
176: ret.put(key, value);
177: }
178: ret = Collections.unmodifiableMap(ret);
179: }
180: return ret;
181: }
182:
183: /** copy the "original" map and putAll the "overrides" */
184: private static Map override_params(Map original, Map overrides) {
185: if (overrides == null || overrides.isEmpty()) {
186: return original;
187: }
188: Map ret = new HashMap(original);
189: ret.putAll(overrides);
190: ret = Collections.unmodifiableMap(ret);
191: return ret;
192: }
193: }
|