• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.googlecode.android_scripting.jsonrpc;
18 
19 import java.io.BufferedReader;
20 import java.io.PrintWriter;
21 import java.net.Socket;
22 import java.util.Map;
23 
24 import org.json.JSONArray;
25 import org.json.JSONObject;
26 
27 import com.googlecode.android_scripting.Log;
28 import com.googlecode.android_scripting.SimpleServer;
29 import com.googlecode.android_scripting.rpc.MethodDescriptor;
30 import com.googlecode.android_scripting.rpc.RpcError;
31 
32 /**
33  * A JSON RPC server that forwards RPC calls to a specified receiver object.
34  *
35  */
36 public class JsonRpcServer extends SimpleServer {
37 
38     private static final String CMD_CLOSE_SESSION = "closeSl4aSession";
39 
40     private final RpcReceiverManagerFactory mRpcReceiverManagerFactory;
41 
42     // private final String mHandshake;
43 
44     /**
45      * Construct a {@link JsonRpcServer} connected to the provided {@link RpcReceiverManager}.
46      *
47      * @param managerFactory the {@link RpcReceiverManager} to register with the server
48      * @param handshake the secret handshake required for authorization to use this server
49      */
JsonRpcServer(RpcReceiverManagerFactory managerFactory, String handshake)50     public JsonRpcServer(RpcReceiverManagerFactory managerFactory, String handshake) {
51         // mHandshake = handshake;
52         mRpcReceiverManagerFactory = managerFactory;
53     }
54 
55     @Override
shutdown()56     public void shutdown() {
57         super.shutdown();
58         // Notify all RPC receiving objects. They may have to clean up some of their state.
59         for (RpcReceiverManager manager : mRpcReceiverManagerFactory.getRpcReceiverManagers()
60                 .values()) {
61             manager.shutdown();
62         }
63     }
64 
65     @Override
handleRPCConnection(Socket sock, Integer UID, BufferedReader reader, PrintWriter writer)66     protected void handleRPCConnection(Socket sock, Integer UID, BufferedReader reader,
67             PrintWriter writer) throws Exception {
68         RpcReceiverManager receiverManager = null;
69         Map<Integer, RpcReceiverManager> mgrs = mRpcReceiverManagerFactory.getRpcReceiverManagers();
70         synchronized (mgrs) {
71             Log.d("UID " + UID);
72             Log.d("manager map keys: "
73                     + mRpcReceiverManagerFactory.getRpcReceiverManagers().keySet());
74             if (mgrs.containsKey(UID)) {
75                 Log.d("Look up existing session");
76                 receiverManager = mgrs.get(UID);
77             } else {
78                 Log.d("Create a new session");
79                 receiverManager = mRpcReceiverManagerFactory.create(UID);
80             }
81         }
82         // boolean passedAuthentication = false;
83         String data;
84         while ((data = reader.readLine()) != null) {
85             Log.v("Session " + UID + " Received: " + data);
86             JSONObject request = new JSONObject(data);
87             int id = request.getInt("id");
88             String method = request.getString("method");
89             JSONArray params = request.getJSONArray("params");
90 
91             MethodDescriptor rpc = receiverManager.getMethodDescriptor(method);
92             if (rpc == null) {
93                 send(writer, JsonRpcResult.error(id, new RpcError("Unknown RPC: " + method)), UID);
94                 continue;
95             }
96             try {
97                 send(writer, JsonRpcResult.result(id, rpc.invoke(receiverManager, params)), UID);
98             } catch (Throwable t) {
99                 Log.e("Invocation error.", t);
100                 send(writer, JsonRpcResult.error(id, t), UID);
101             }
102             if (method.equals(CMD_CLOSE_SESSION)) {
103                 Log.d("Got shutdown signal");
104                 synchronized (writer) {
105                     receiverManager.shutdown();
106                     reader.close();
107                     writer.close();
108                     sock.close();
109                     shutdown();
110                     mgrs.remove(UID);
111                 }
112                 return;
113             }
114         }
115     }
116 
send(PrintWriter writer, JSONObject result, int UID)117     private void send(PrintWriter writer, JSONObject result, int UID) {
118         writer.write(result + "\n");
119         writer.flush();
120         Log.v("Session " + UID + " Sent: " + result);
121     }
122 
123     @Override
handleConnection(Socket socket)124     protected void handleConnection(Socket socket) throws Exception {
125     }
126 }
127