// WSDL generated classes import edu.isi.www.fedd_types.*; import edu.isi.www.topdl.*; import java.io.*; import java.util.*; import javax.xml.parsers.*; import org.xml.sax.*; import org.xml.sax.helpers.*; public class ParseTopdl { /** Parser instance */ protected XMLReader xr; /** Handler that parses topdl file */ protected TopdlHandler h; /** * This class encapsulates the state of an XML parse of a topdl file. It * contains abunch of parsing state and is called from the standard SAX * parser at 3 places: when an XML element starts (<element>) when * one ends (<element/>) and whenever characters inside an element * are encountered. It mostly initializes fields as elements are exited, * collecting other parsed fields into objects that are finally attached to * the topology itself. */ protected class TopdlHandler extends DefaultHandler { /** The name of the outermost element, "experiment" by default */ protected String topName; // Topology parameters /** The current topology being built */ protected TopologyType topo; /** The current element being built */ protected ElementType element; /** The current computer being built */ protected ComputerType comp; /** The current testbed being built */ protected TestbedType tb; /** The current segment being built */ protected SegmentType seg; /** The current other element being built */ protected OtherType other; // Many elements have a name /** the most recent name element parsed */ protected String name; // Many statuses as well protected StatusType status; // CPU parameters /** current cpu type */ protected String type; /** current number of cpus */ protected int ncpus; // Operatingsystem parameters /** Current OS version */ protected String version; /** Current OS distro */ protected String distribution; /** Current OS distro version */ protected String distributionversion; /** Local names of this node */ protected Vector localnames; /** True if in a Computer testbed or substrate that has local names */ protected boolean collectLocalnames; // Software parameters /** Current software installation point */ protected String install; /** Current software location */ protected String location; // Service Parameters protected Vector importers; protected Vector serviceParams; protected String description; //ServiceParam parameters protected String serviceParamName; protected ServiceParamTypeType serviceParamType; // Storage parameters /** Current storage amount */ protected double amount; /** Current storage persistence */ protected PersistenceType persistence; // Interface Parameters /** Vector of substrate names the current interface is attached to */ protected Vector ifsubs; /** Current interface capacity */ protected edu.isi.www.topdl.CapacityType cap; /** Current interface latency */ protected LatencyType lat; // Capacity parameters /** Current capacity rate (bandwidth) */ protected double rate; /** Current capacity kind (max, peak)*/ protected edu.isi.www.topdl.KindType kind; // Latency parameters (shares kind) /** Current latency time */ protected double time; // Testbed parameters (shares interfaces, type) /** Current URI */ protected String uri; // Segment parameters (shares interfaces, type, uri) /** Current segment ID */ protected IDType id; // IDType parameters /** Current ID uuid (if any) */ protected byte[] uuid; /** Current ID fedid (if any) */ protected byte[] fedid; /** Current ID uri (if any) */ protected String id_uri; /** Current ID localname (if any) */ protected String localname; /** Current ID kerberosUsername (if any) */ protected String kerberosUsername; /** True when we are parsing an ID (so URIs are stored in id_uri) */ protected boolean inID; // Attribute parameters /** Current attribute name */ protected String aname; /** Current attribute value */ protected String aval; /** Elements seen so far */ protected Vector elements; /** Substrates seen so far */ protected Vector subs; /** Attributes seen so far */ protected Vector attrs; /** CPUs seen so far */ protected Vector cpus; /** Operating Systems seen so far */ protected Vector oses; /** Software seen so far */ protected Vector software; /** Storage seen so far */ protected Vector storage; /** Interfaces seen so far */ protected Vector interfaces; /** Services seen so far */ protected Vector services; /** Operations seen so far */ protected Vector operations; /** * Attributes appear in many elements, some of which can appear inside * the definition of others. We keep a stack of live attributes so * that a sub-element does not overwrite a super-element's attributes. * attrElements is a set of element names that should start a new set * of recorded attributes, and attrStack keeps the contexts stacked. */ protected Set attrElements; /** * The stack of attribute contexts. */ protected Stack> attrStack; /** * Analogous to attrElements for names. */ protected Set nameElements; /** * Analogous to attrStack for names. */ protected Stack nameStack; /** * Analogous to attrStack for status */ protected Stack statusStack; /** * Analogous to attrElements for names. */ protected Set statusElements; /** * These elements collect localnames */ protected Set localnameElements; /** * The current buffer of characters collected. */ protected char[] c; /** * Print parsing info if true */ protected boolean debug; /** * Initialize the internal data structures. Top is the outer element * name. If d is true, debugging info is printed. * @param top a String containing the outer element name * @param d a boolean, if true pring debugging info */ TopdlHandler(String top, boolean d) { debug = d; topName = top; topo = null; element = null; comp = null; tb = null; seg = null; other = null; localnames = new Vector(); collectLocalnames = false; type = null; name = null; ncpus = 1; version = distribution = distributionversion = null; description = null; install = location = null; amount = 0.0; persistence = null; ifsubs = new Vector(); cap = null; lat = null; rate = 0.0; kind = null; time = 0.0; uri = null; id = null; uuid = fedid = null; id_uri = localname = kerberosUsername = null; inID = false; aname = aval = null; importers = new Vector();; serviceParams = new Vector(); elements = new Vector(); cpus = new Vector(); subs = new Vector(); oses = new Vector(); software = new Vector(); storage = new Vector(); interfaces = new Vector(); services = new Vector(); serviceParams = new Vector(); attrs = new Vector(); operations = new Vector(); attrElements = new TreeSet(); for (String e : new String[] { topName, "computer", "cpu", "os", "software", "storage", "interface", "segment", "testbed", "other", "substrates" }) attrElements.add(e); attrStack = new Stack>(); nameElements = new TreeSet(); for (String e : new String[] { "computer", "os", "interface", "substrates", "service", "param" }) nameElements.add(e); nameStack = new Stack(); statusElements = new TreeSet(); for (String e : new String[] { "computer", "testbed", "substrates", "service", }) statusElements.add(e); statusStack = new Stack(); localnameElements = new TreeSet(); for (String e : new String[] { "computer", "testbed", "substrates", }) localnameElements.add(e); c = new char[0]; } /** * Called when an element begins. qn is the element and a has * attributes assigned in the element. This starts new name or * attribute contexts, if necessary as well as noting the start of an * id (which is a lightweight uri context). The parameter definitions * below are from org.xml.sax.helpers.DefaultHandler * @param u - The Namespace URI, or the empty string if the element has * no Namespace URI or if Namespace processing is not being performed. * @param l - The local name (without prefix), or the empty string if * Namespace processing is not being performed. * @param qn - The qualified name (with prefix), or the empty string if * qualified names are not available. * @param a - The attributes attached to the element. If there are no * attributes, it shall be an empty Attributes object. */ public void startElement(String u, String l, String qn, Attributes a) throws SAXException { if (debug) System.err.println("<" + qn + ">"); c = new char[0]; if ( attrElements.contains(qn) ) { attrStack.push(attrs); attrs = new Vector(); } if ( nameElements.contains(qn) ) { nameStack.push(name); name = null; } if ( statusElements.contains(qn) ) { statusStack.push(status); status = null; } if ( localnameElements.contains(qn) ) { collectLocalnames = true; } if (qn.equals("id")) inID = true; if (qn.equals("cpu")) { String n = a.getValue("count"); if ( n != null) ncpus = Integer.valueOf(n); else ncpus = 1; } } /** * Collect the data from each element and stash it where any containing * elent can find it when it is time to construct that thing. Clear * any fields used. This is long but straightforward parsing. * @param u - The Namespace URI, or the empty string if the element has * no Namespace URI or if Namespace processing is not being performed. * @param l - The local name (without prefix), or the empty string if * Namespace processing is not being performed. * @param qn - The qualified name (with prefix), or the empty string if * qualified names are not available. */ public void endElement(String u, String l, String qn) throws SAXException { if (debug) System.err.println("<" + qn + "/>"); // Each branch parses the data from the given element, e.g, // "computer" parses the fields collected for . In that // case the data stashed by trips through here for // , , etc. // // The vector.toArray(new Type[vector.size()], idiom just returns // the contents of the vector as a java array of the vector's type. if (qn.equals(topName)) { topo = new TopologyType("1.0", subs.toArray(new SubstrateType[subs.size()]), elements.toArray(new ElementType[elements.size()]), attrs.toArray(new AttributeType[attrs.size()])); elements = new Vector(); subs = new Vector(); attrs = attrStack.pop(); } else if (qn.equals("elements")) { elements.add(new ElementType(comp, tb, seg, other)); comp = null; tb = null; seg = null; other = null; } else if (qn.equals("computer")) { comp = new ComputerType(name, cpus.toArray(new CpuType[cpus.size()]), oses.toArray(new OperatingsystemType[oses.size()]), software.toArray(new SoftwareType[software.size()]), storage.toArray(new StorageType[storage.size()]), interfaces.toArray( new InterfaceType[interfaces.size()]), attrs.toArray(new AttributeType[attrs.size()]), localnames.toArray(new String[localnames.size()]), status, services.toArray(new ServiceType[services.size()]), operations.toArray(new String[operations.size()]) ); name = nameStack.pop(); cpus = new Vector(); oses = new Vector(); software = new Vector(); storage = new Vector(); interfaces = new Vector(); attrs = attrStack.pop(); localnames = new Vector(); status = statusStack.pop(); services = new Vector(); operations = new Vector(); collectLocalnames = false; } else if (qn.equals("cpu")) { cpus.add(new CpuType(type, attrs.toArray(new AttributeType[attrs.size()]), ncpus)); type = null; attrs = attrStack.pop(); ncpus = 1; } else if (qn.equals("type")) { type = new String(c).trim(); } else if (qn.equals("os")) { oses.add(new OperatingsystemType(name, version, distribution, distributionversion, attrs.toArray(new AttributeType[attrs.size()]))); name = nameStack.pop(); version = distribution = distributionversion = null; attrs = attrStack.pop(); } else if ( qn.equals("version")) { version = new String(c).trim(); } else if ( qn.equals("distribution")) { distribution = new String(c).trim(); } else if ( qn.equals("distributionversion")) { distributionversion = new String(c).trim(); } else if (qn.equals("software")) { software.add(new SoftwareType(location, install, attrs.toArray(new AttributeType[attrs.size()]))); location = install = null; attrs = attrStack.pop(); } else if ( qn.equals("location")) { location = new String(c).trim(); } else if ( qn.equals("install")) { install = new String(c).trim(); } else if (qn.equals("storage")) { storage.add(new StorageType(amount, persistence, attrs.toArray(new AttributeType[attrs.size()]))); amount = 0.0; persistence = null; attrs = attrStack.pop(); } else if ( qn.equals("amount")) { amount = Double.valueOf(new String(c)); } else if ( qn.equals("persistence")) { persistence = PersistenceType.fromValue(new String(c)); } else if (qn.equals("interface")) { interfaces.add(new InterfaceType( ifsubs.toArray(new String[ifsubs.size()]), name, cap, lat, attrs.toArray(new AttributeType[attrs.size()]))); ifsubs = new Vector(); name = nameStack.pop(); cap = null; lat = null; attrs = attrStack.pop(); } else if (qn.equals("substrate")) { ifsubs.add(new String(c).trim()); } else if (qn.equals("capacity")) { cap = new edu.isi.www.topdl.CapacityType(rate, kind); rate = 0.0; kind = null; } else if ( qn.equals("rate")) { rate = Double.valueOf(new String(c)); } else if ( qn.equals("kind")) { kind = edu.isi.www.topdl.KindType.fromValue(new String(c)); } else if (qn.equals("latency")) { lat = new LatencyType(time, kind); time = 0.0; kind = null; } else if ( qn.equals("time")) { time = Double.valueOf(new String(c)); } else if (qn.equals("testbed")) { tb = new TestbedType(uri, type, interfaces.toArray( new InterfaceType[interfaces.size()]), attrs.toArray(new AttributeType[attrs.size()]), localnames.toArray(new String[localnames.size()]), status, services.toArray(new ServiceType[services.size()]), operations.toArray(new String[operations.size()])); uri = type = null; interfaces = new Vector(); attrs = attrStack.pop(); localnames = new Vector(); status = statusStack.pop(); services = new Vector(); operations = new Vector(); collectLocalnames = false; } else if (qn.equals("uri")) { if (inID) id_uri = new String(c).trim(); else uri = new String(c).trim(); } else if (qn.equals("segment")) { seg = new SegmentType(id, type, uri, interfaces.toArray( new InterfaceType[interfaces.size()]), attrs.toArray(new AttributeType[attrs.size()])); id = null; type = uri = null; interfaces = new Vector(); attrs = attrStack.pop(); } else if (qn.equals("id")) { id = new IDType(uuid, fedid, id_uri, localname, kerberosUsername); uuid = null; fedid = null; id_uri = null; localname = null; kerberosUsername = null; inID = false; } else if (qn.equals("uuid")) { uuid = new String(c).trim().getBytes(); } else if (qn.equals("fedid")) { fedid = new String(c).trim().getBytes(); } else if (qn.equals("localname")) { if (collectLocalnames) localnames.add(new String(c).trim()); else localname = new String(c).trim(); } else if (qn.equals("kerberosUsername")) { kerberosUsername = new String(c).trim(); } else if (qn.equals("description")) { description = new String(c).trim(); } else if (qn.equals("other")) { other = new OtherType( interfaces.toArray( new InterfaceType[interfaces.size()]), attrs.toArray(new AttributeType[attrs.size()])); interfaces = new Vector(); attrs = attrStack.pop(); } else if (qn.equals("substrates")) { subs.add(new SubstrateType(name, cap, lat, attrs.toArray(new AttributeType[attrs.size()]), localnames.toArray(new String[localnames.size()]), status, services.toArray(new ServiceType[services.size()]), operations.toArray(new String[operations.size()]) )); name = nameStack.pop(); cap = null; lat = null; attrs = attrStack.pop(); localnames = new Vector(); status = statusStack.pop(); services = new Vector(); operations = new Vector(); collectLocalnames = false; } else if (qn.equals("attribute")) { if ( aname != null && aval != null ) { attrs.add(new AttributeType(aname, aval)); aname = aval = null; } else { aname = new String(c).trim(); } } else if ( qn.equals("value")) { aval = new String(c).trim(); } else if ( qn.equals("name")) { name = new String(c).trim(); } else if ( qn.equals("param") ) { serviceParams.add(new ServiceParamType(name, ServiceParamTypeType.fromString(type))); name = nameStack.pop(); type = null; } else if (qn.equals("service")) { services.add(new ServiceType( name, importers.toArray(new String[importers.size()]), serviceParams.toArray( new ServiceParamType[serviceParams.size()]), description, status)); name = nameStack.pop(); importers = new Vector(); serviceParams = new Vector(); description = null; status = statusStack.pop(); } // Always clear any accumulated characters c = new char[0]; } /** * Collect text. */ public void characters(char[] ch, int s, int l) { char[] nc = new char[c.length + l]; System.arraycopy(c, 0, nc, 0, c.length); System.arraycopy(ch, s, nc, c.length, l); c = nc; } /** * Return the parsed topology * @return the parsed topology */ public TopologyType getTopology() { return topo; } } /** * Main constructor. Parse the given stream assuming that the outermost * element is in topName (defaults to "experiment" if topName is null). If * debug is true, print extra debugging information to the standard error * stream. * @param s the InputStream to parse * @param topName a String with the outer element name * @param debug a boolean, true for extra debugging output * @throws IOException if the stream cannot be read * @throws SAXException if the parsing fails * @throws ParserConfigurationException if the parser creation fails */ public ParseTopdl(InputStream s, String topName, boolean debug) throws IOException, SAXException, ParserConfigurationException { h = new TopdlHandler(topName != null ? topName: "experiment", debug); xr = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); xr.setContentHandler(h); xr.parse(new InputSource(s)); } /** * Equivalent to ParseTopdl(s, topName, false) * @param s the InputStream to parse * @param topName a String with the outer element name * @throws IOException if the stream cannot be read * @throws SAXException if the parsing fails * @throws ParserConfigurationException if the parser creation fails */ public ParseTopdl(InputStream s, String topName) throws IOException, SAXException, ParserConfigurationException { this(s, topName, false); } /** * Return the parsed topology * @return the parsed topology */ public TopologyType getTopology() { return h.getTopology(); } /** * Test code. Shouldn't really be called. */ static public void main(String args[]) { ParseTopdl p = null; System.out.println("Checking file: " + args[0]); try { p = new ParseTopdl(new FileInputStream(new File(args[0])), "experiment", false); System.out.println("Parse OK"); } catch (ParserConfigurationException e) { System.err.println("Parse failed: " + e); } catch (SAXException e) { System.err.println("Parse failed: " + e); } catch (IOException e) { System.err.println("Parse failed: " + e); } } }