137f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com/*
237f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com * Copyright (C) 2010 The Android Open Source Project
337f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com *
437f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com * Licensed under the Apache License, Version 2.0 (the "License");
537f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com * you may not use this file except in compliance with the License.
637f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com * You may obtain a copy of the License at
737f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com *
837f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com *      http://www.apache.org/licenses/LICENSE-2.0
937f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com *
1037f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com * Unless required by applicable law or agreed to in writing, software
1137f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com * distributed under the License is distributed on an "AS IS" BASIS,
1237f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1337f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com * See the License for the specific language governing permissions and
1437f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com * limitations under the License.
1537f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com */
1637f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com
1737f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.compackage vogar.monitor;
1837f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com
19b9e409160756d5f422da6a56cd2354d0afb27047Neil Fullerimport com.google.gson.Gson;
20b9e409160756d5f422da6a56cd2354d0afb27047Neil Fullerimport com.google.gson.JsonObject;
21693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.comimport java.io.IOException;
22693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.comimport java.io.PrintStream;
23693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.comimport java.net.ServerSocket;
24693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.comimport java.net.Socket;
2537f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.comimport vogar.Result;
2637f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.comimport vogar.target.Runner;
2737f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com
2837f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com/**
29693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com * Accepts a connection from the host process. Once connected, XML is sent over
30693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com * raw sockets.
3137f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com */
32693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.compublic class TargetMonitor {
3337f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com
34693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    private static final int ACCEPT_TIMEOUT_MILLIS = 10 * 1000;
3537f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com
36693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    private final Gson gson = new Gson();
37693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    private final String marker = "//00xx";
3837f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com
39693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    private final PrintStream writer;
403c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com
41693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    private TargetMonitor(PrintStream writer) {
42693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        this.writer = writer;
43693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    }
44693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com
45693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    public static TargetMonitor forPrintStream(PrintStream printStream) {
46693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        return new TargetMonitor(printStream);
47693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    }
48693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com
49693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    public static TargetMonitor await(int port) {
50693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        try {
51693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com            final ServerSocket serverSocket = new ServerSocket(port);
52693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com            serverSocket.setSoTimeout(ACCEPT_TIMEOUT_MILLIS);
53693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com            serverSocket.setReuseAddress(true);
54693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com            final Socket socket = serverSocket.accept();
55693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com            return new TargetMonitor(new PrintStream(socket.getOutputStream())) {
56693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com                @Override public void close() throws IOException {
57693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com                    socket.close();
58693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com                    serverSocket.close();
59693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com                }
60693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com            };
61693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com
62693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        } catch (IOException e) {
63693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com            throw new RuntimeException("Failed to accept a monitor on localhost:" + port, e);
64693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        }
65693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    }
66693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com
67693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    public void outcomeStarted(Runner runner, String outcomeName, String actionName) {
68693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        JsonObject jsonObject = new JsonObject();
69693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        jsonObject.addProperty("outcome", outcomeName);
70693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        if (runner != null) {
71693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com            jsonObject.addProperty("runner", runner.getClass().getName());
72693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        }
735b2080e28c579ae6e563143c6a1788846d8da2f1jessewilson@google.com        writer.print(marker + gson.toJson(jsonObject) + "\n");
74693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    }
75693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com
76693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    public void output(String text) {
77693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        writer.print(text);
78693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    }
79693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com
80693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    public void outcomeFinished(Result result) {
81693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        JsonObject jsonObject = new JsonObject();
82693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com        jsonObject.addProperty("result", result.name());
835b2080e28c579ae6e563143c6a1788846d8da2f1jessewilson@google.com        writer.print(marker + gson.toJson(jsonObject) + "\n");
84693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    }
85693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com
86023bda1190f439e7019404f461865963e892fc5bjessewilson@google.com    public synchronized void close() throws IOException {
87023bda1190f439e7019404f461865963e892fc5bjessewilson@google.com        writer.close();
88023bda1190f439e7019404f461865963e892fc5bjessewilson@google.com    }
893cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com
903cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com    public void completedNormally(boolean completedNormally) {
913cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com        JsonObject jsonObject = new JsonObject();
923cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com        jsonObject.addProperty("completedNormally", completedNormally);
933cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com        writer.print(marker + gson.toJson(jsonObject) + "\n");
943cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com    }
9537f7c3a73d290eed1bf4cdff80e029eaa7620801jessewilson@google.com}
96