001: // $Id: XmlConfigurator.java,v 1.17 2006/10/09 13:35:31 belaban Exp $
002:
003: package org.jgroups.conf;
004:
005: /**
006: * Uses XML to configure a protocol stack
007: * @author Filip Hanik (<a href="mailto:filip@filip.net">filip@filip.net)
008: * @version 1.0
009: */
010:
011: import org.apache.commons.logging.Log;
012: import org.apache.commons.logging.LogFactory;
013: import org.w3c.dom.*;
014: import org.jgroups.stack.Configurator;
015:
016: import javax.xml.parsers.DocumentBuilder;
017: import javax.xml.parsers.DocumentBuilderFactory;
018: import java.io.File;
019: import java.io.FileInputStream;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.net.URL;
023: import java.util.*;
024:
025: public class XmlConfigurator implements ProtocolStackConfigurator {
026: public static final String ATTR_NAME = "name";
027: public static final String ATTR_VALUE = "value";
028: public static final String ATTR_INHERIT = "inherit";
029: public static final String ELMT_PROT_OVERRIDE = "protocol-override";
030: public static final String ELMT_PROT = "protocol";
031: public static final String ELMT_PROT_NAME = "protocol-name";
032: public static final String ELMT_CLASS = "class-name";
033: public static final String ELMT_DESCRIPTION = "description";
034: public static final String ELMT_PROT_PARAMS = "protocol-params";
035:
036: private final ArrayList mProtocolStack = new ArrayList();
037: private final String mStackName;
038: protected static final Log log = LogFactory
039: .getLog(XmlConfigurator.class);
040:
041: protected XmlConfigurator(String stackName, ProtocolData[] protocols) {
042: mStackName = stackName;
043: for (int i = 0; i < protocols.length; i++)
044: mProtocolStack.add(protocols[i]);
045: }
046:
047: protected XmlConfigurator(String stackName) {
048: this (stackName, new ProtocolData[0]);
049: }
050:
051: public static XmlConfigurator getInstance(URL url)
052: throws java.io.IOException {
053: return getInstance(url.openStream());
054: }
055:
056: public static XmlConfigurator getInstanceOldFormat(URL url)
057: throws java.io.IOException {
058: return getInstanceOldFormat(url.openStream());
059: }
060:
061: public static XmlConfigurator getInstance(InputStream stream)
062: throws java.io.IOException {
063: return parse(stream);
064: }
065:
066: public static XmlConfigurator getInstanceOldFormat(
067: InputStream stream) throws java.io.IOException {
068: return parseOldFormat(stream);
069: }
070:
071: public static XmlConfigurator getInstance(Element el)
072: throws java.io.IOException {
073: return parse(el);
074: }
075:
076: /**
077: *
078: * @param convert If false: print old plain output, else print new XML format
079: * @return String with protocol stack in specified format
080: */
081: public String getProtocolStackString(boolean convert) {
082: StringBuffer buf = new StringBuffer();
083: Iterator it = mProtocolStack.iterator();
084: if (convert)
085: buf.append("<config>\n");
086: while (it.hasNext()) {
087: ProtocolData d = (ProtocolData) it.next();
088: if (convert)
089: buf.append(" <");
090: buf.append(d.getProtocolString(convert));
091: if (convert)
092: buf.append("/>");
093: if (it.hasNext()) {
094: if (convert)
095: buf.append('\n');
096: else
097: buf.append(':');
098: }
099: }
100: if (convert)
101: buf.append("\n</config>");
102: return buf.toString();
103: }
104:
105: public String getProtocolStackString() {
106: return getProtocolStackString(false);
107: }
108:
109: public ProtocolData[] getProtocolStack() {
110: return (ProtocolData[]) mProtocolStack
111: .toArray(new ProtocolData[mProtocolStack.size()]);
112: }
113:
114: public String getName() {
115: return mStackName;
116: }
117:
118: public void override(ProtocolData data) throws IOException {
119: int index = mProtocolStack.indexOf(data);
120: if (index < 0)
121: throw new IOException(
122: "You can not override a protocol that doesn't exist");
123: ProtocolData source = (ProtocolData) mProtocolStack.get(index);
124: source.override(data.getParametersAsArray());
125: }
126:
127: public void add(ProtocolData data) {
128: mProtocolStack.add(data);
129: }
130:
131: protected static XmlConfigurator parseOldFormat(InputStream stream)
132: throws java.io.IOException {
133: XmlConfigurator configurator = null;
134: try {
135: DocumentBuilderFactory factory = DocumentBuilderFactory
136: .newInstance();
137: factory.setValidating(false); //for now
138: DocumentBuilder builder = factory.newDocumentBuilder();
139: Document document = builder.parse(stream);
140: Element root = (Element) document.getElementsByTagName(
141: "protocol-stack").item(0);
142: root.normalize();
143: //print("",new PrintWriter(System.out),root);
144: String stackname = root.getAttribute(ATTR_NAME);
145: String inherit = root.getAttribute(ATTR_INHERIT);
146: boolean isinherited = (inherit != null && inherit.length() > 0);
147: NodeList protocol_list = document
148: .getElementsByTagName(isinherited ? ELMT_PROT_OVERRIDE
149: : ELMT_PROT);
150: Vector v = new Vector();
151: for (int i = 0; i < protocol_list.getLength(); i++) {
152: if (protocol_list.item(i).getNodeType() == Node.ELEMENT_NODE) {
153: v.addElement(parseProtocolData(protocol_list
154: .item(i)));
155: }
156: }
157: ProtocolData[] protocols = new ProtocolData[v.size()];
158: v.copyInto(protocols);
159:
160: if (isinherited) {
161: URL inheritURL = new URL(inherit);
162: configurator = XmlConfigurator.getInstance(inheritURL);
163: for (int i = 0; i < protocols.length; i++)
164: configurator.override(protocols[i]);
165: } else {
166: configurator = new XmlConfigurator(stackname, protocols);
167: }
168:
169: } catch (Exception x) {
170: if (x instanceof java.io.IOException)
171: throw (java.io.IOException) x;
172: else {
173: IOException tmp = new IOException();
174: tmp.initCause(x);
175: throw tmp;
176: }
177: }
178: return configurator;
179: }
180:
181: protected static XmlConfigurator parse(InputStream stream)
182: throws java.io.IOException {
183: /**
184: * CAUTION: crappy code ahead ! I (bela) am not an XML expert, so the code below is pretty amateurish...
185: * But it seems to work, and it is executed only on startup, so no perf loss on the critical path.
186: * If somebody wants to improve this, please be my guest.
187: */
188: try {
189: DocumentBuilderFactory factory = DocumentBuilderFactory
190: .newInstance();
191: factory.setValidating(false); //for now
192: DocumentBuilder builder = factory.newDocumentBuilder();
193: Document document = builder.parse(stream);
194:
195: // The root element of the document should be the "config" element,
196: // but the parser(Element) method checks this so a check is not
197: // needed here.
198: Element configElement = document.getDocumentElement();
199: return parse(configElement);
200: } catch (Exception x) {
201: if (x instanceof java.io.IOException)
202: throw (java.io.IOException) x;
203: else {
204: IOException tmp = new IOException();
205: tmp.initCause(x);
206: throw tmp;
207: }
208: }
209: }
210:
211: protected static XmlConfigurator parse(Element root_element)
212: throws java.io.IOException {
213: XmlConfigurator configurator = null;
214:
215: /** LinkedList<ProtocolData> */
216: LinkedList prot_data = new LinkedList();
217:
218: /**
219: * CAUTION: crappy code ahead ! I (bela) am not an XML expert, so the code below is pretty amateurish...
220: * But it seems to work, and it is executed only on startup, so no perf loss on the critical path.
221: * If somebody wants to improve this, please be my guest.
222: */
223: try {
224: Node root = root_element;
225: // NodeList roots=root_element.getChildNodes();
226: // for(int i =0; i < roots.getLength(); i++) {
227: // root=roots.item(i);
228: // if(root.getNodeType() != Node.ELEMENT_NODE)
229: // continue;
230: // }
231:
232: String root_name = root.getNodeName();
233: if (!"config".equals(root_name.trim().toLowerCase())) {
234: log
235: .fatal("XML protocol stack configuration does not start with a '<config>' element; "
236: + "maybe the XML configuration needs to be converted to the new format ?\n"
237: + "use 'java org.jgroups.conf.XmlConfigurator <old XML file> -new_format' to do so");
238: throw new IOException("invalid XML configuration");
239: }
240:
241: NodeList prots = root.getChildNodes();
242: for (int i = 0; i < prots.getLength(); i++) {
243: Node node = prots.item(i);
244: if (node.getNodeType() != Node.ELEMENT_NODE)
245: continue;
246:
247: Element tag = (Element) node;
248: String protocol = tag.getTagName();
249: // System.out.println("protocol: " + protocol);
250: LinkedList tmp = new LinkedList();
251:
252: NamedNodeMap attrs = tag.getAttributes();
253: int attrLength = attrs.getLength();
254: for (int a = 0; a < attrLength; a++) {
255: Attr attr = (Attr) attrs.item(a);
256: String name = attr.getName();
257: String value = attr.getValue();
258: // System.out.println(" name=" + name + ", value=" + value);
259: tmp.add(new ProtocolParameter(name, value));
260: }
261: ProtocolParameter[] params = new ProtocolParameter[tmp
262: .size()];
263: for (int j = 0; j < tmp.size(); j++)
264: params[j] = (ProtocolParameter) tmp.get(j);
265: ProtocolData data = new ProtocolData(protocol, "bla",
266: "" + protocol, params);
267: prot_data.add(data);
268: }
269:
270: ProtocolData[] data = new ProtocolData[(prot_data.size())];
271: for (int k = 0; k < prot_data.size(); k++)
272: data[k] = (ProtocolData) prot_data.get(k);
273: configurator = new XmlConfigurator("bla", data);
274: } catch (Exception x) {
275: if (x instanceof java.io.IOException)
276: throw (java.io.IOException) x;
277: else {
278: IOException tmp = new IOException();
279: tmp.initCause(x);
280: throw tmp;
281: }
282: }
283: return configurator;
284: }
285:
286: protected static ProtocolData parseProtocolData(Node protocol)
287: throws java.io.IOException {
288: try {
289: protocol.normalize();
290: boolean isOverride = ELMT_PROT_OVERRIDE.equals(protocol
291: .getNodeName());
292: int pos = 0;
293: NodeList children = protocol.getChildNodes();
294: /**
295: * there should be 4 Element Nodes if we are not overriding
296: * 1. protocol-name
297: * 2. description
298: * 3. class-name
299: * 4. protocol-params
300: *
301: * If we are overriding we should have
302: * 1. protocol-name
303: * 2. protocol-params
304: */
305:
306: //
307: String name = null;
308: String clazzname = null;
309: String desc = null;
310: ProtocolParameter[] plist = null;
311:
312: for (int i = 0; i < children.getLength(); i++) {
313: if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
314: pos++;
315: if (isOverride && (pos == 2))
316: pos = 4;
317: switch (pos) {
318: case 1:
319: name = children.item(i).getFirstChild()
320: .getNodeValue();
321: break;
322: case 2:
323: desc = children.item(i).getFirstChild()
324: .getNodeValue();
325: break;
326: case 3:
327: clazzname = children.item(i).getFirstChild()
328: .getNodeValue();
329: break;
330: case 4:
331: plist = parseProtocolParameters((Element) children
332: .item(i));
333: break;
334: }//switch
335: }//end if
336: }//for
337:
338: if (isOverride)
339: return new ProtocolData(name, plist);
340: else
341: return new ProtocolData(name, desc, clazzname, plist);
342: } catch (Exception x) {
343: if (x instanceof java.io.IOException)
344: throw (java.io.IOException) x;
345: else {
346: IOException tmp = new IOException();
347: tmp.initCause(x);
348: throw tmp;
349: }
350: }
351: }
352:
353: protected static ProtocolParameter[] parseProtocolParameters(
354: Element protparams) throws IOException {
355:
356: try {
357: Vector v = new Vector();
358: protparams.normalize();
359: NodeList parameters = protparams.getChildNodes();
360: for (int i = 0; i < parameters.getLength(); i++) {
361: if (parameters.item(i).getNodeType() == Node.ELEMENT_NODE) {
362: String pname = parameters.item(i).getAttributes()
363: .getNamedItem(ATTR_NAME).getNodeValue();
364: String pvalue = parameters.item(i).getAttributes()
365: .getNamedItem(ATTR_VALUE).getNodeValue();
366: ProtocolParameter p = new ProtocolParameter(pname,
367: pvalue);
368: v.addElement(p);
369: }//end if
370: }//for
371: ProtocolParameter[] result = new ProtocolParameter[v.size()];
372: v.copyInto(result);
373: return result;
374: } catch (Exception x) {
375: if (x instanceof java.io.IOException)
376: throw (java.io.IOException) x;
377: else {
378: IOException tmp = new IOException();
379: tmp.initCause(x);
380: throw tmp;
381: }
382: }
383: }
384:
385: public static void main(String[] args) throws Exception {
386: String input_file = null, output = null;
387: XmlConfigurator conf;
388: boolean old_format = false;
389:
390: for (int i = 0; i < args.length; i++) {
391: if (args[i].equals("-old")) {
392: old_format = true;
393: continue;
394: }
395: if (args[i].equals("-file")) {
396: input_file = args[++i];
397: continue;
398: }
399: help();
400: return;
401: }
402:
403: if (input_file != null) {
404: InputStream input = null;
405:
406: try {
407: input = new FileInputStream(new File(input_file));
408: } catch (Throwable t) {
409: }
410: if (input == null) {
411: try {
412: input = new URL(input_file).openStream();
413: } catch (Throwable t) {
414: }
415: }
416:
417: if (input == null)
418: input = Thread.currentThread().getContextClassLoader()
419: .getResourceAsStream(input_file);
420:
421: if (old_format) {
422: Configurator config = new Configurator();
423: String cfg = inputAsString(input);
424: Vector tmp = config.parseConfigurations(cfg);
425: System.out.println(dump(tmp));
426:
427: // conf=XmlConfigurator.getInstanceOldFormat(input);
428: // output=conf.getProtocolStackString(true);
429: // output=replace(output, "org.jgroups.protocols.", "");
430: // System.out.println(getTitle(input_file));
431: // System.out.println('\n' + output);
432: } else {
433: conf = XmlConfigurator.getInstance(input);
434: String tmp = conf.getProtocolStackString();
435: System.out.println("\n" + tmp);
436: }
437: } else {
438: log.error("no input file given");
439: }
440: }
441:
442: /**
443: *
444: * @param tmp Vector of Configurator.ProtocolConfiguration
445: * @return String (XML format)
446: */
447: private static String dump(Vector tmp) {
448: StringBuffer sb = new StringBuffer();
449: String indent = " ";
450: sb.append("<config>\n");
451:
452: for (Iterator it = tmp.iterator(); it.hasNext();) {
453: Configurator.ProtocolConfiguration cfg = (Configurator.ProtocolConfiguration) it
454: .next();
455: sb.append(indent).append("<").append(cfg.getProtocolName());
456: Properties props = cfg.getProperties();
457: if (props.size() == 0) {
458: sb.append(" />\n");
459: } else {
460: sb.append("\n").append(indent).append(indent);
461: for (Iterator it2 = props.entrySet().iterator(); it2
462: .hasNext();) {
463: Map.Entry entry = (Map.Entry) it2.next();
464: String key = (String) entry.getKey();
465: String val = (String) entry.getValue();
466: key = trim(key);
467: val = trim(val);
468: sb.append(key).append("=\"").append(val).append(
469: "\"");
470: if (it2.hasNext()) {
471: sb.append("\n").append(indent).append(indent);
472: }
473: }
474: sb.append(" />\n");
475: }
476: }
477:
478: sb.append("</config>\n");
479: return sb.toString();
480: }
481:
482: private static String trim(String val) {
483: String retval = "";
484: int index;
485:
486: val = val.trim();
487: while (true) {
488: index = val.indexOf('\n');
489: if (index == -1) {
490: retval += val;
491: break;
492: }
493: retval += val.substring(0, index);
494: val = val.substring(index + 1);
495: }
496:
497: return retval;
498: }
499:
500: private static String inputAsString(InputStream input)
501: throws IOException {
502: int len = input.available();
503: byte[] buf = new byte[len];
504: input.read(buf, 0, len);
505: return new String(buf);
506: }
507:
508: private static String getTitle(String input) {
509: StringBuffer sb = new StringBuffer();
510: sb
511: .append("\n\n<!-- ************ JGroups Protocol Stack Configuration ************** -->\n");
512: sb.append("<!-- generated by XmlConfigurator on " + new Date()
513: + " -->\n");
514: sb.append("<!-- input file: " + input + " -->");
515: return sb.toString();
516: }
517:
518: public static String replace(String input, final String expr,
519: String replacement) {
520: StringBuffer sb = new StringBuffer();
521: int new_index = 0, index = 0, len = expr.length(), input_len = input
522: .length();
523:
524: while (true) {
525: new_index = input.indexOf(expr, index);
526: if (new_index == -1) {
527: sb.append(input.substring(index, input_len));
528: break;
529: }
530: sb.append(input.substring(index, new_index));
531: sb.append(replacement);
532: index = new_index + len;
533: }
534:
535: return sb.toString();
536: }
537:
538: static void help() {
539: System.out
540: .println("XmlConfigurator -file <input XML file> [-old]");
541: System.out
542: .println("(-old: converts old (plain-text) input format into new XML format)");
543: }
544: }
|