1 /*
2    D-Bus Java Implementation
3    Copyright (c) 2005-2006 Matthew Johnson
4 
5    This program is free software; you can redistribute it and/or modify it
6    under the terms of either the GNU Lesser General Public License Version 2 or the
7    Academic Free Licence Version 2.1.
8 
9    Full licence texts are included in the COPYING file with this program.
10 */
11 package org.freedesktop.dbus.bin;
12 
13 import static org.freedesktop.dbus.Gettext._;
14 import static org.freedesktop.dbus.bin.IdentifierMangler.mangle;
15 
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.FileNotFoundException;
19 import java.io.FileOutputStream;
20 import java.io.IOException;
21 import java.io.InputStreamReader;
22 import java.io.PrintStream;
23 import java.io.Reader;
24 import java.io.StringReader;
25 import java.text.MessageFormat;
26 import java.util.HashMap;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.TreeSet;
30 import java.util.Vector;
31 
32 import java.lang.reflect.Field;
33 import java.lang.reflect.ParameterizedType;
34 import java.lang.reflect.Type;
35 
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 
40 import org.freedesktop.DBus.Introspectable;
41 import org.freedesktop.dbus.DBusConnection;
42 import org.freedesktop.dbus.Marshalling;
43 import org.freedesktop.dbus.exceptions.DBusException;
44 import org.freedesktop.dbus.exceptions.DBusExecutionException;
45 import org.freedesktop.dbus.types.DBusStructType;
46 
47 import org.w3c.dom.Document;
48 import org.w3c.dom.Element;
49 import org.w3c.dom.Node;
50 import org.xml.sax.InputSource;
51 import org.xml.sax.SAXException;
52 
53 /**
54  * Converts a DBus XML file into Java interface definitions.
55  */
56 public class CreateInterface
57 {
58    @SuppressWarnings("unchecked")
collapseType(Type t, Set<String> imports, Map<StructStruct, Type[]> structs, boolean container, boolean fullnames)59    private static String collapseType(Type t, Set<String> imports, Map<StructStruct, Type[]> structs, boolean container, boolean fullnames) throws DBusException
60    {
61       if (t instanceof ParameterizedType) {
62          String s;
63          Class<? extends Object> c = (Class<? extends Object>) ((ParameterizedType) t).getRawType();
64          if (null != structs && t instanceof DBusStructType) {
65             int num = 1;
66             String name = "Struct";
67             while (null != structs.get(new StructStruct(name+num))) num++;
68             name = name+num;
69             structs.put(new StructStruct(name), ((ParameterizedType) t).getActualTypeArguments());
70             return name;
71          }
72          if (null != imports) imports.add(c.getName());
73          if (fullnames) return c.getName();
74          else s = c.getSimpleName();
75          s += '<';
76          Type[] ts = ((ParameterizedType) t).getActualTypeArguments();
77          for (Type st: ts)
78             s += collapseType(st, imports, structs, true, fullnames)+',';
79          s = s.replaceAll(",$", ">");
80          return s;
81       } else if (t instanceof Class) {
82          Class<? extends Object> c = (Class<? extends Object>) t;
83          if (c.isArray()) {
84             return collapseType(c.getComponentType(), imports, structs, container, fullnames)+"[]";
85          } else {
86             Package p = c.getPackage();
87             if (null != imports &&
88                   !"java.lang".equals(p.getName())) imports.add(c.getName());
89             if (container) {
90                if (fullnames) return c.getName();
91                else return c.getSimpleName();
92             } else {
93                try {
94                   Field f = c.getField("TYPE");
95                   Class<? extends Object> d = (Class<? extends Object>) f.get(c);
96                   return d.getSimpleName();
97                } catch (Exception e) {
98                   return c.getSimpleName();
99                }
100             }
101          }
102       } else return "";
103    }
getJavaType(String dbus, Set<String> imports, Map<StructStruct,Type[]> structs, boolean container, boolean fullnames)104    private static String getJavaType(String dbus, Set<String> imports, Map<StructStruct,Type[]> structs, boolean container, boolean fullnames) throws DBusException
105    {
106       if (null == dbus || "".equals(dbus)) return "";
107       Vector<Type> v = new Vector<Type>();
108       int c = Marshalling.getJavaType(dbus, v, 1);
109       Type t = v.get(0);
110       return collapseType(t, imports, structs, container, fullnames);
111    }
112    public String comment = "";
113    boolean builtin;
114 
CreateInterface(PrintStreamFactory factory, boolean builtin)115    public CreateInterface(PrintStreamFactory factory, boolean builtin)
116    {
117       this.factory = factory;
118       this.builtin = builtin;
119    }
120    @SuppressWarnings("fallthrough")
parseReturns(Vector<Element> out, Set<String> imports, Map<String,Integer> tuples, Map<StructStruct, Type[]> structs)121    String parseReturns(Vector<Element> out, Set<String> imports, Map<String,Integer> tuples, Map<StructStruct, Type[]> structs) throws DBusException
122    {
123       String[] names = new String[] { "Pair", "Triplet", "Quad", "Quintuple", "Sextuple", "Septuple" };
124       String sig = "";
125       String name = null;
126       switch (out.size()) {
127          case 0:
128             sig += "void ";
129             break;
130          case 1:
131             sig += getJavaType(out.get(0).getAttribute("type"), imports, structs, false, false)+" ";
132             break;
133          case 2:
134          case 3:
135          case 4:
136          case 5:
137          case 6:
138          case 7:
139             name = names[out.size() - 2];
140          default:
141             if (null == name)
142                name = "NTuple"+out.size();
143 
144             tuples.put(name, out.size());
145             sig += name + "<";
146             for (Element arg: out)
147                sig += getJavaType(arg.getAttribute("type"), imports, structs, true, false)+", ";
148             sig = sig.replaceAll(", $","> ");
149             break;
150       }
151       return sig;
152    }
parseMethod(Element meth, Set<String> imports, Map<String,Integer> tuples, Map<StructStruct, Type[]> structs, Set<String> exceptions, Set<String> anns)153    String parseMethod(Element meth, Set<String> imports, Map<String,Integer> tuples, Map<StructStruct, Type[]> structs, Set<String> exceptions, Set<String> anns) throws DBusException
154    {
155       Vector<Element> in = new Vector<Element>();
156       Vector<Element> out = new Vector<Element>();
157       if (null == meth.getAttribute("name") ||
158             "".equals(meth.getAttribute("name"))) {
159          System.err.println(_("ERROR: Method name was blank, failed"));
160          System.exit(1);
161       }
162       String annotations = "";
163       String throwses = null;
164 
165       for (Node a: new IterableNodeList(meth.getChildNodes())) {
166 
167          if (Node.ELEMENT_NODE != a.getNodeType()) continue;
168 
169          checkNode(a, "arg", "annotation");
170 
171          if ("arg".equals(a.getNodeName())) {
172             Element arg = (Element) a;
173 
174             // methods default to in
175             if ("out".equals(arg.getAttribute("direction")))
176                out.add(arg);
177             else
178                in.add(arg);
179          }
180          else if ("annotation".equals(a.getNodeName())) {
181             Element e = (Element) a;
182             if (e.getAttribute("name").equals("org.freedesktop.DBus.Method.Error")) {
183                if (null == throwses)
184                   throwses = e.getAttribute("value");
185                else
186                   throwses += ", " + e.getAttribute("value");
187                exceptions.add(e.getAttribute("value"));
188             } else
189                annotations += parseAnnotation(e, imports, anns);
190          }
191       }
192 
193       String sig = "";
194       comment = "";
195       sig += parseReturns(out, imports, tuples, structs);
196 
197       sig += mangle(meth.getAttribute("name"))+"(";
198 
199       char defaultname = 'a';
200       String params = "";
201       for (Element arg: in) {
202          String type = getJavaType(arg.getAttribute("type"), imports, structs, false, false);
203          String name = arg.getAttribute("name");
204          if (null == name || "".equals(name)) name = ""+(defaultname++);
205          params += type+" "+mangle(name)+", ";
206       }
207       return ("".equals(comment) ? "" : "   /**\n" + comment + "   */\n")
208          + annotations + "  public " + sig +
209          params.replaceAll("..$", "")+")"+
210          (null == throwses? "": " throws "+throwses)+";";
211    }
parseSignal(Element signal, Set<String> imports, Map<StructStruct, Type[]> structs, Set<String> anns)212    String parseSignal(Element signal, Set<String> imports, Map<StructStruct, Type[]> structs, Set<String> anns) throws DBusException
213    {
214       Map<String, String> params = new HashMap<String, String>();
215       Vector<String> porder = new Vector<String>();
216       char defaultname = 'a';
217       imports.add("org.freedesktop.dbus.DBusSignal");
218       imports.add("org.freedesktop.dbus.exceptions.DBusException");
219       String annotations = "";
220       for (Node a: new IterableNodeList(signal.getChildNodes())) {
221 
222          if (Node.ELEMENT_NODE != a.getNodeType()) continue;
223 
224          checkNode(a, "arg", "annotation");
225 
226          if ("annotation".equals(a.getNodeName()))
227             annotations += parseAnnotation((Element) a, imports, anns);
228          else {
229             Element arg = (Element) a;
230             String type = getJavaType(arg.getAttribute("type"), imports, structs, false, false);
231             String name = arg.getAttribute("name");
232             if (null == name || "".equals(name)) name = ""+(defaultname++);
233             params.put(mangle(name), type);
234             porder.add(mangle(name));
235          }
236       }
237 
238       String out = "";
239       out += annotations;
240       out += "   public static class "+signal.getAttribute("name");
241       out += " extends DBusSignal\n   {\n";
242       for (String name: porder)
243          out += "      public final "+params.get(name)+" "+name+";\n";
244       out += "      public "+signal.getAttribute("name")+"(String path";
245       for (String name: porder)
246          out += ", "+params.get(name)+" "+name;
247       out += ") throws DBusException\n      {\n         super(path";
248       for (String name: porder)
249          out += ", "+name;
250       out += ");\n";
251       for (String name: porder)
252          out += "         this."+name+" = "+name+";\n";
253       out += "      }\n";
254 
255       out += "   }\n";
256       return out;
257    }
258 
parseAnnotation(Element ann, Set<String> imports, Set<String> annotations)259    String parseAnnotation(Element ann, Set<String> imports, Set<String> annotations)
260    {
261       String s = "  @"+ann.getAttribute("name").replaceAll(".*\\.([^.]*)$","$1")+"(";
262       if (null != ann.getAttribute("value")
263             && !"".equals(ann.getAttribute("value")))
264          s += '"'+ann.getAttribute("value")+'"';
265       imports.add(ann.getAttribute("name"));
266       annotations.add(ann.getAttribute("name"));
267       return s += ")\n";
268    }
269 
parseInterface(Element iface, PrintStream out, Map<String,Integer> tuples, Map<StructStruct, Type[]> structs, Set<String> exceptions, Set<String> anns)270    void parseInterface(Element iface, PrintStream out, Map<String,Integer> tuples, Map<StructStruct, Type[]> structs, Set<String> exceptions, Set<String> anns) throws DBusException
271    {
272       if (null == iface.getAttribute("name") ||
273             "".equals(iface.getAttribute("name"))) {
274          System.err.println(_("ERROR: Interface name was blank, failed"));
275          System.exit(1);
276       }
277 
278       out.println("package "+iface.getAttribute("name").replaceAll("\\.[^.]*$","")+";");
279 
280       String methods = "";
281       String signals = "";
282       String annotations = "";
283       Set<String> imports = new TreeSet<String>();
284       imports.add("org.freedesktop.dbus.DBusInterface");
285       for (Node meth: new IterableNodeList(iface.getChildNodes())) {
286 
287          if (Node.ELEMENT_NODE != meth.getNodeType()) continue;
288 
289          checkNode(meth, "method", "signal", "property", "annotation");
290 
291          if ("method".equals(meth.getNodeName()))
292             methods += parseMethod((Element) meth, imports, tuples, structs, exceptions, anns) + "\n";
293          else if ("signal".equals(meth.getNodeName()))
294             signals += parseSignal((Element) meth, imports, structs, anns);
295          else if ("property".equals(meth.getNodeName()))
296             System.err.println("WARNING: Ignoring property");
297          else if ("annotation".equals(meth.getNodeName()))
298             annotations += parseAnnotation((Element) meth, imports, anns);
299       }
300 
301       if (imports.size() > 0)
302          for (String i: imports)
303             out.println("import "+i+";");
304 
305       out.print(annotations);
306       out.print("public interface "+iface.getAttribute("name").replaceAll("^.*\\.([^.]*)$","$1"));
307       out.println(" extends DBusInterface");
308       out.println("{");
309       out.println(signals);
310       out.println(methods);
311       out.println("}");
312    }
createException(String name, String pack, PrintStream out)313    void createException(String name, String pack, PrintStream out) throws DBusException
314    {
315       out.println("package "+pack+";");
316       out.println("import org.freedesktop.dbus.DBusExecutionException;");
317       out.print("public class "+name);
318       out.println(" extends DBusExecutionException");
319       out.println("{");
320       out.println("   public "+name+"(String message)");
321       out.println("   {");
322       out.println("      super(message);");
323       out.println("   }");
324       out.println("}");
325    }
createAnnotation(String name, String pack, PrintStream out)326    void createAnnotation(String name, String pack, PrintStream out) throws DBusException
327    {
328       out.println("package "+pack+";");
329       out.println("import java.lang.annotation.Retention;");
330       out.println("import java.lang.annotation.RetentionPolicy;");
331       out.println("@Retention(RetentionPolicy.RUNTIME)");
332       out.println("public @interface "+name);
333       out.println("{");
334       out.println("   String value();");
335       out.println("}");
336    }
createStruct(String name, Type[] type, String pack, PrintStream out, Map<StructStruct, Type[]> existing)337    void createStruct(String name, Type[] type, String pack, PrintStream out, Map<StructStruct, Type[]> existing) throws DBusException, IOException
338    {
339       out.println("package "+pack+";");
340 
341       Set<String> imports = new TreeSet<String>();
342       imports.add("org.freedesktop.dbus.Position");
343       imports.add("org.freedesktop.dbus.Struct");
344       Map<StructStruct, Type[]> structs = new HashMap<StructStruct, Type[]>(existing);
345       String[] types = new String[type.length];
346       for (int i = 0; i < type.length; i++)
347          types[i] = collapseType(type[i], imports, structs, false, false);
348 
349       for (String im: imports) out.println("import "+im+";");
350 
351       out.println("public final class "+name+" extends Struct");
352       out.println("{");
353       int i = 0;
354       char c = 'a';
355       String params = "";
356       for (String t: types) {
357          out.println("   @Position("+i++ +")");
358          out.println("   public final "+t+" "+c+";");
359          params += t+" "+c+", ";
360          c++;
361       }
362       out.println("  public "+name+"("+params.replaceAll("..$", "")+")");
363       out.println("  {");
364       for (char d = 'a'; d < c; d++)
365          out.println("   this."+d+" = "+d+";");
366 
367       out.println("  }");
368       out.println("}");
369 
370       structs = StructStruct.fillPackages(structs, pack);
371       Map<StructStruct, Type[]> tocreate = new HashMap<StructStruct, Type[]>(structs);
372       for (StructStruct ss: existing.keySet()) tocreate.remove(ss);
373       createStructs(tocreate, structs);
374    }
createTuple(String name, int num, String pack, PrintStream out)375    void createTuple(String name, int num, String pack, PrintStream out) throws DBusException
376    {
377       out.println("package "+pack+";");
378       out.println("import org.freedesktop.dbus.Position;");
379       out.println("import org.freedesktop.dbus.Tuple;");
380       out.println("/** Just a typed container class */");
381       out.print("public final class "+name);
382       String types = " <";
383       for (char v = 'A'; v < 'A'+num; v++)
384          types += v + ",";
385       out.print(types.replaceAll(",$","> "));
386       out.println("extends Tuple");
387       out.println("{");
388 
389       char t = 'A';
390       char n = 'a';
391       for (int i = 0; i < num; i++,t++,n++) {
392          out.println("   @Position("+i+")");
393          out.println("   public final "+t+" "+n+";");
394       }
395 
396       out.print("   public "+name+"(");
397       String sig = "";
398       t = 'A';
399       n = 'a';
400       for (int i = 0; i < num; i++,t++,n++)
401          sig += t+" "+n+", ";
402       out.println(sig.replaceAll(", $", ")"));
403       out.println("   {");
404       for (char v = 'a'; v < 'a'+num; v++)
405          out.println("      this."+v+" = "+v+";");
406       out.println("   }");
407 
408       out.println("}");
409    }
parseRoot(Element root)410    void parseRoot(Element root) throws DBusException, IOException
411    {
412       Map<StructStruct, Type[]> structs = new HashMap<StructStruct, Type[]>();
413       Set<String> exceptions = new TreeSet<String>();
414       Set<String> annotations = new TreeSet<String>();
415 
416       for (Node iface: new IterableNodeList(root.getChildNodes())) {
417 
418          if (Node.ELEMENT_NODE != iface.getNodeType()) continue;
419 
420          checkNode(iface, "interface", "node");
421 
422          if ("interface".equals(iface.getNodeName())) {
423 
424             Map<String, Integer> tuples = new HashMap<String, Integer>();
425             String name = ((Element) iface).getAttribute("name");
426             String file = name.replaceAll("\\.","/")+".java";
427             String path = file.replaceAll("/[^/]*$", "");
428             String pack = name.replaceAll("\\.[^.]*$","");
429 
430             // don't create interfaces in org.freedesktop.DBus by default
431             if (pack.startsWith("org.freedesktop.DBus") && !builtin) continue;
432 
433             factory.init(file, path);
434             parseInterface((Element) iface,
435                   factory.createPrintStream(file), tuples, structs, exceptions, annotations);
436 
437             structs = StructStruct.fillPackages(structs, pack);
438             createTuples(tuples, pack);
439          }
440          else if ("node".equals(iface.getNodeName()))
441             parseRoot((Element) iface);
442          else {
443             System.err.println(_("ERROR: Unknown node: ")+iface.getNodeName());
444             System.exit(1);
445          }
446       }
447 
448       createStructs(structs, structs);
449       createExceptions(exceptions);
450       createAnnotations(annotations);
451    }
createAnnotations(Set<String> annotations)452    private void createAnnotations(Set<String> annotations) throws DBusException, IOException
453    {
454       for (String fqn: annotations) {
455          String name = fqn.replaceAll("^.*\\.([^.]*)$", "$1");
456          String pack = fqn.replaceAll("\\.[^.]*$","");
457          // don't create things in org.freedesktop.DBus by default
458          if (pack.startsWith("org.freedesktop.DBus") && !builtin)
459             continue;
460          String path = pack.replaceAll("\\.", "/");
461          String file = name.replaceAll("\\.","/")+".java";
462          factory.init(file, path);
463          createAnnotation(name, pack,
464                factory.createPrintStream(path, name));
465       }
466    }
createExceptions(Set<String> exceptions)467    private void createExceptions(Set<String> exceptions) throws DBusException, IOException
468    {
469       for (String fqn: exceptions) {
470          String name = fqn.replaceAll("^.*\\.([^.]*)$", "$1");
471          String pack = fqn.replaceAll("\\.[^.]*$","");
472          // don't create things in org.freedesktop.DBus by default
473          if (pack.startsWith("org.freedesktop.DBus") && !builtin)
474             continue;
475          String path = pack.replaceAll("\\.", "/");
476          String file = name.replaceAll("\\.","/")+".java";
477          factory.init(file, path);
478          createException(name, pack,
479                factory.createPrintStream(path, name));
480       }
481    }
createStructs(Map<StructStruct, Type[]> structs, Map<StructStruct, Type[]> existing)482    private void createStructs(Map<StructStruct, Type[]> structs, Map<StructStruct, Type[]> existing) throws DBusException, IOException
483    {
484       for (StructStruct ss: structs.keySet())  {
485          String file = ss.name.replaceAll("\\.","/")+".java";
486          String path = ss.pack.replaceAll("\\.", "/");
487          factory.init(file, path);
488          createStruct(ss.name, structs.get(ss), ss.pack,
489                factory.createPrintStream(path, ss.name), existing);
490       }
491    }
492 
createTuples(Map<String, Integer> typeMap, String pack)493    private void createTuples(Map<String, Integer> typeMap, String pack) throws DBusException, IOException
494    {
495       for (String tname: typeMap.keySet())
496          createTuple(tname, typeMap.get(tname), pack,
497                factory.createPrintStream(pack.replaceAll("\\.","/"), tname));
498    }
499 
500    public static abstract class PrintStreamFactory
501    {
502 
init(String file, String path)503       public abstract void init(String file, String path);
504 
505       /**
506        * @param path
507        * @param tname
508        * @return PrintStream
509        * @throws IOException
510        */
createPrintStream(String path, String tname)511       public PrintStream createPrintStream(String path, String tname) throws IOException
512       {
513          final String file = path+"/"+tname+".java";
514          return createPrintStream(file);
515       }
516 
517       /**
518        * @param file
519        * @return PrintStream
520        * @throws IOException
521        */
createPrintStream(final String file)522       public abstract PrintStream createPrintStream(final String file) throws IOException;
523 
524    }
525    static class ConsoleStreamFactory extends PrintStreamFactory
526    {
527 
528       @Override
529          public
init(String file, String path)530          void init(String file, String path)
531          {
532          }
533 
534       @Override
535          public
createPrintStream(String file)536          PrintStream createPrintStream(String file) throws IOException
537          {
538             System.out.println("/* File: "+file+" */");
539             return System.out;
540          }
541 
createPrintStream(String path, String tname)542       public PrintStream createPrintStream(String path, String tname) throws IOException
543       {
544          return super.createPrintStream(path, tname);
545       }
546 
547    }
548 
549    static class FileStreamFactory extends PrintStreamFactory
550    {
init(String file, String path)551       public void init(String file, String path)
552       {
553          new File(path).mkdirs();
554       }
555 
556 
557       /**
558        * @param file
559        * @return
560        * @throws IOException
561        */
createPrintStream(final String file)562       public PrintStream createPrintStream(final String file) throws IOException
563       {
564          return new PrintStream(new FileOutputStream(file));
565       }
566 
567    }
568 
checkNode(Node n, String... names)569    static void checkNode(Node n, String... names)
570    {
571       String expected = "";
572       for (String name: names) {
573          if (name.equals(n.getNodeName())) return;
574          expected += name + " or ";
575       }
576       System.err.println(MessageFormat.format(_("ERROR: Expected {0}, got {1}, failed."), new Object[] { expected.replaceAll("....$", ""), n.getNodeName() }));
577       System.exit(1);
578    }
579 
580    private final PrintStreamFactory factory;
581 
582    static class Config
583    {
584       int bus = DBusConnection.SESSION;
585       String busname = null;
586       String object = null;
587       File datafile = null;
588       boolean printtree = false;
589       boolean fileout = false;
590       boolean builtin = false;
591    }
592 
printSyntax()593    static void printSyntax()
594    {
595       printSyntax(System.err);
596    }
printSyntax(PrintStream o)597    static void printSyntax(PrintStream o)
598    {
599       o.println("Syntax: CreateInterface <options> [file | busname object]");
600       o.println("        Options: --no-ignore-builtin --system -y --session -s --create-files -f --help -h --version -v");
601    }
version()602    public static void version()
603    {
604       System.out.println("Java D-Bus Version "+System.getProperty("Version"));
605       System.exit(1);
606    }
607 
parseParams(String[] args)608    static Config parseParams(String[] args)
609    {
610       Config config = new Config();
611       for (String p: args) {
612          if ("--system".equals(p) || "-y".equals(p))
613             config.bus = DBusConnection.SYSTEM;
614          else if ("--session".equals(p) || "-s".equals(p))
615             config.bus = DBusConnection.SESSION;
616          else if ("--no-ignore-builtin".equals(p))
617             config.builtin = true;
618          else if ("--create-files".equals(p) || "-f".equals(p))
619             config.fileout = true;
620          else if ("--print-tree".equals(p) || "-p".equals(p))
621             config.printtree = true;
622          else if ("--help".equals(p) || "-h".equals(p)) {
623             printSyntax(System.out);
624             System.exit(0);
625          } else if ("--version".equals(p) || "-v".equals(p)) {
626             version();
627             System.exit(0);
628          } else if (p.startsWith("-")) {
629             System.err.println(_("ERROR: Unknown option: ")+p);
630             printSyntax();
631             System.exit(1);
632          }
633          else {
634             if (null == config.busname) config.busname = p;
635             else if (null == config.object) config.object = p;
636             else {
637                printSyntax();
638                System.exit(1);
639             }
640          }
641       }
642       if (null == config.busname) {
643          printSyntax();
644          System.exit(1);
645       }
646       else if (null == config.object) {
647          config.datafile = new File(config.busname);
648          config.busname = null;
649       }
650       return config;
651    }
652 
main(String[] args)653    public static void main(String[] args) throws Exception
654    {
655       Config config = parseParams(args);
656 
657       Reader introspectdata = null;
658 
659       if (null != config.busname) try {
660          DBusConnection conn = DBusConnection.getConnection(config.bus);
661          Introspectable in = conn.getRemoteObject(config.busname, config.object, Introspectable.class);
662          String id = in.Introspect();
663          if (null == id) {
664             System.err.println(_("ERROR: Failed to get introspection data"));
665             System.exit(1);
666          }
667          introspectdata = new StringReader(id);
668          conn.disconnect();
669       } catch (DBusException DBe) {
670          System.err.println(_("ERROR: Failure in DBus Communications: ")+DBe.getMessage());
671          System.exit(1);
672       } catch (DBusExecutionException DEe) {
673          System.err.println(_("ERROR: Failure in DBus Communications: ")+DEe.getMessage());
674          System.exit(1);
675 
676       } else if (null != config.datafile) try {
677          introspectdata = new InputStreamReader(new FileInputStream(config.datafile));
678       } catch (FileNotFoundException FNFe) {
679          System.err.println(_("ERROR: Could not find introspection file: ")+FNFe.getMessage());
680          System.exit(1);
681       }
682       try {
683          PrintStreamFactory factory = config.fileout  ? new FileStreamFactory() : new ConsoleStreamFactory();
684          CreateInterface createInterface = new CreateInterface(factory, config.builtin);
685          createInterface.createInterface(introspectdata);
686       } catch (DBusException DBe) {
687          System.err.println("ERROR: "+DBe.getMessage());
688          System.exit(1);
689       }
690    }
691    /** Output the interface for the supplied xml reader
692     * @param introspectdata The introspect data reader
693     * @throws ParserConfigurationException If the xml parser could not be configured
694     * @throws SAXException If a problem occurs reading the xml data
695     * @throws IOException If an IO error occurs
696     * @throws DBusException If the dbus related error occurs
697     */
createInterface(Reader introspectdata)698    public void createInterface(Reader introspectdata) throws ParserConfigurationException, SAXException, IOException, DBusException
699    {
700       DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
701       DocumentBuilder builder = factory.newDocumentBuilder();
702       Document document = builder.parse(new InputSource(introspectdata));
703 
704       Element root = document.getDocumentElement();
705       checkNode(root, "node");
706       parseRoot(root);
707 
708    }
709 }
710 
711 
712