blob: 325c7407bede68fdef83f976276376d9375aa3c7 [file] [log] [blame]
/*
* Copyright (C) 2016 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.android_scripting.event;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.SimpleServer;
import com.googlecode.android_scripting.jsonrpc.JsonBuilder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import org.json.JSONException;
/**
* An Event Forwarding server that forwards events from the rpc queue in realtime to listener
* clients.
*
*/
public class EventServer extends SimpleServer implements EventObserver {
private static final Vector<Listener> mListeners = new Vector<Listener>();
private InetSocketAddress address = null;
public EventServer() {
this(0);
}
public EventServer(int port) {
address = startAllInterfaces(port);
}
public InetSocketAddress getAddress() {
return address;
}
@Override
public void shutdown() {
onEventReceived(new Event("sl4a", "{\"shutdown\": \"event-server\"}"));
for (Listener listener : mListeners) {
mListeners.remove(listener);
listener.lock.countDown();
}
super.shutdown();
}
@Override
protected void handleConnection(Socket socket) throws IOException {
Log.d("handle event connection.");
Listener l = new Listener(socket);
Log.v("Adding EventServer listener " + socket.getPort());
mListeners.add(l);
// we are running in the socket accept thread
// wait until the event dispatcher gets us the events
// or we die, what ever happens first
try {
l.lock.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
l.sock.close();
} catch (IOException e) {
e.printStackTrace();
}
Log.v("Ending EventServer listener " + socket.getPort());
}
@Override
public void onEventReceived(Event event) {
Object result = null;
try {
result = JsonBuilder.build(event);
} catch (JSONException e) {
return;
}
Log.v("EventServer dispatching " + result);
for (Listener listener : mListeners) {
if (!listener.out.checkError()) {
listener.out.write(result + "\n");
listener.out.flush();
} else {
// let the socket accept thread we're done
mListeners.remove(listener);
listener.lock.countDown();
}
}
}
private class Listener {
private Socket sock;
private PrintWriter out;
private CountDownLatch lock = new CountDownLatch(1);
public Listener(Socket l) throws IOException {
sock = l;
out = new PrintWriter(l.getOutputStream(), true);
}
}
@Override
protected void handleRPCConnection(Socket sock, Integer UID, BufferedReader reader, PrintWriter writer)
throws Exception {
}
}