1920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson/*
2920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * Copyright (C) 2010 Google Inc.
3920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
4920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * Licensed under the Apache License, Version 2.0 (the "License");
5920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * you may not use this file except in compliance with the License.
6920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * You may obtain a copy of the License at
7920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
8920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * http://www.apache.org/licenses/LICENSE-2.0
9920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
10920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * Unless required by applicable law or agreed to in writing, software
11920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * distributed under the License is distributed on an "AS IS" BASIS,
12920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * See the License for the specific language governing permissions and
14920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * limitations under the License.
15920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson */
16920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
17920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonpackage com.google.doclava.apicheck;
18920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
19920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.FileInputStream;
20040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport java.io.FileNotFoundException;
21920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.IOException;
22920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.InputStream;
23040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport java.io.PrintStream;
24920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.net.URL;
25920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.ArrayList;
26920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.Set;
27920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.Stack;
28920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
290aff7e0b51a6ad0423bcba8101e17797872a492eJoe Onoratoimport com.google.doclava.Errors;
300aff7e0b51a6ad0423bcba8101e17797872a492eJoe Onoratoimport com.google.doclava.Errors.ErrorMessage;
31040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.Stubs;
320aff7e0b51a6ad0423bcba8101e17797872a492eJoe Onorato
33920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonpublic class ApiCheck {
34920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  // parse out and consume the -whatever command line flags
35920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private static ArrayList<String[]> parseFlags(ArrayList<String> allArgs) {
36920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ArrayList<String[]> ret = new ArrayList<String[]>();
37920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
38920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int i;
39920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (i = 0; i < allArgs.size(); i++) {
40920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // flags with one value attached
41920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String flag = allArgs.get(i);
42920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (flag.equals("-error") || flag.equals("-warning") || flag.equals("-hide")) {
43920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        String[] arg = new String[2];
44920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        arg[0] = flag;
45920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        arg[1] = allArgs.get(++i);
46920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        ret.add(arg);
47920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } else {
48920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // we've consumed all of the -whatever args, so we're done
49920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        break;
50920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
51920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
52920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
53920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // i now points to the first non-flag arg; strip what came before
54920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (; i > 0; i--) {
55920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      allArgs.remove(0);
56920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
57920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return ret;
58920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
59920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
60920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  public static void main(String[] originalArgs) {
61040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (originalArgs.length == 3 && "-convert".equals(originalArgs[0])) {
62040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      System.exit(convertToApi(originalArgs[1], originalArgs[2]));
63040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else if (originalArgs.length == 3 && "-convert2xml".equals(originalArgs[0])) {
64040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      System.exit(convertToXml(originalArgs[1], originalArgs[2]));
65040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else {
66040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      ApiCheck acheck = new ApiCheck();
67040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      Report report = acheck.checkApi(originalArgs);
68040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
69040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      Errors.printErrors(report.errors());
70040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      System.exit(report.code);
71040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
72920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
73920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
74920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
75920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Compares two api xml files for consistency.
76920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
77920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  public Report checkApi(String[] originalArgs) {
78920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // translate to an ArrayList<String> for munging
79920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ArrayList<String> args = new ArrayList<String>(originalArgs.length);
80920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (String a : originalArgs) {
81920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      args.add(a);
82920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
83920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
84920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ArrayList<String[]> flags = ApiCheck.parseFlags(args);
85920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (String[] a : flags) {
86920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (a[0].equals("-error") || a[0].equals("-warning") || a[0].equals("-hide")) {
87920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        try {
88920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          int level = -1;
89920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (a[0].equals("-error")) {
90920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            level = Errors.ERROR;
91920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else if (a[0].equals("-warning")) {
92920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            level = Errors.WARNING;
93920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else if (a[0].equals("-hide")) {
94920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            level = Errors.HIDDEN;
95920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
96920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          Errors.setErrorLevel(Integer.parseInt(a[1]), level);
97920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        } catch (NumberFormatException e) {
98920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          System.err.println("Bad argument: " + a[0] + " " + a[1]);
99920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          return new Report(2, Errors.getErrors());
100920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
101920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
102920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
103920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
104920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ApiInfo oldApi;
105920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ApiInfo newApi;
106920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
107920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    try {
108920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      oldApi = parseApi(args.get(0));
109920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      newApi = parseApi(args.get(1));
110920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } catch (ApiParseException e) {
111920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      e.printStackTrace();
112920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      System.err.println("Error parsing API");
113920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return new Report(1, Errors.getErrors());
114920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
115920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
116920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // only run the consistency check if we haven't had XML parse errors
117920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (!Errors.hadError) {
118920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      oldApi.isConsistent(newApi);
119920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
120920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
121920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return new Report(Errors.hadError ? 1 : 0, Errors.getErrors());
122920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
123920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
124040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public static ApiInfo parseApi(String filename) throws ApiParseException {
125040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    InputStream stream = null;
126de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler    Throwable textParsingError = null;
127040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // try it as our format
128920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    try {
129040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      stream = new FileInputStream(filename);
130920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } catch (IOException e) {
131040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("Could not open file for parsing: " + filename, e);
132040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
133040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
134040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return ApiFile.parseApi(filename, stream);
135040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (ApiParseException ignored) {
136de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler      textParsingError = ignored;
137040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (false) {
138040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return null;
139920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
140040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } finally {
141040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      try {
142040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        stream.close();
143040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } catch (IOException ignored) {}
144040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
145040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // try it as xml
146040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
147040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      stream = new FileInputStream(filename);
148040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (IOException e) {
149040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("Could not open file for parsing: " + filename, e);
150040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
151040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
152040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return XmlApiFile.parseApi(stream);
153de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler    } catch (ApiParseException ignored) {
154de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler        System.out.println("Couldn't parse API file \"" + filename + "\"");
155de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler        System.out.println("  ...as text: " + textParsingError.toString());
156de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler        System.out.println("  ...as XML:  " + ignored.toString());
157de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler        if (false) {
158de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler          if (textParsingError != null) textParsingError.printStackTrace();
159de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler          ignored.printStackTrace();
160de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler          return null;
161de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler        }
162040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } finally {
163040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      try {
164040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        stream.close();
165040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } catch (IOException ignored) {}
166920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
167de0f029b5e2b6c099504c9f89c294d2fea16944aDaniel Sandler    return null;
168920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
169040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
170040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public ApiInfo parseApi(URL url) throws ApiParseException {
171040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    InputStream stream = null;
172040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // try it as our format
173920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    try {
174040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      stream = url.openStream();
175920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } catch (IOException e) {
176040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("Could not open stream for parsing: " + url, e);
177040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
178040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
179040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return ApiFile.parseApi(url.toString(), stream);
180040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (ApiParseException ignored) {
181920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } finally {
182040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      try {
183040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        stream.close();
184040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } catch (IOException ignored) {}
185040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
186040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // try it as xml
187040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
188040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      stream = url.openStream();
189040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (IOException e) {
190040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("Could not open stream for parsing: " + url, e);
191040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
192040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
193040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return XmlApiFile.parseApi(stream);
194040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } finally {
195040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      try {
196040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        stream.close();
197040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } catch (IOException ignored) {}
198920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
199920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
200040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
201920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  public class Report {
202920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    private int code;
203920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    private Set<ErrorMessage> errors;
204920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
205920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    private Report(int code, Set<ErrorMessage> errors) {
206920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      this.code = code;
207920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      this.errors = errors;
208920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
209920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
210920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    public int code() {
211920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return code;
212920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
213920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
214920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    public Set<ErrorMessage> errors() {
215920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return errors;
216920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
217920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
218040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
219040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static int convertToApi(String src, String dst) {
220040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    ApiInfo api;
221040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
222040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      api = parseApi(src);
223040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (ApiParseException e) {
224040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      e.printStackTrace();
225040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      System.err.println("Error parsing API: " + src);
226040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return 1;
227040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
228040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
229040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    PrintStream apiWriter = null;
230040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
231040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter = new PrintStream(dst);
232040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (FileNotFoundException ex) {
233040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      System.err.println("can't open file: " + dst);
234040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
235040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
236040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Stubs.writeApi(apiWriter, api.getPackages().values());
237040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
238040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    return 0;
239040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
240040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
241040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static int convertToXml(String src, String dst) {
242040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    ApiInfo api;
243040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
244040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      api = parseApi(src);
245040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (ApiParseException e) {
246040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      e.printStackTrace();
247040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      System.err.println("Error parsing API: " + src);
248040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return 1;
249040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
250040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
251040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    PrintStream apiWriter = null;
252040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
253040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter = new PrintStream(dst);
254040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (FileNotFoundException ex) {
255040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      System.err.println("can't open file: " + dst);
256040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
257040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
258040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Stubs.writeXml(apiWriter, api.getPackages().values());
259040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
260040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    return 0;
261040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
262040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
263920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson}
264