blob: 91f70f9d3bd436cc44a31dbd2c4387286bb5c180 [file] [log] [blame]
Brett Chabot9c27c902013-09-27 11:00:56 -07001/*
2 * Copyright (C) 2013 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 */
16package com.android.tradefed.command.remote;
17
18import com.android.tradefed.log.LogUtil.CLog;
19
20import org.json.JSONException;
21import org.json.JSONObject;
22
23/**
24 * Encapsulates data for a remote operation sent over the wire.
25 */
26abstract class RemoteOperation {
27 private static final String TYPE = "type";
28 private static final String VERSION = "version";
29 static final int CURRENT_PROTOCOL_VERSION = 1;
30
31 @SuppressWarnings("serial")
32 static class RemoteException extends Exception {
33 RemoteException(Throwable t) {
34 super(t);
35 }
36
37 RemoteException(String msg) {
38 super(msg);
39 }
40 }
41
42 /**
43 * Represents all types of remote operations that can be performed
44 */
45 enum OperationType {
46 ALLOCATE_DEVICE, FREE_DEVICE, CLOSE, ADD_COMMAND
47 }
48
49 /**
50 * Create and populate a {@link RemoteOperation} from given data.
51 *
52 * @param data the data to parse
53 * @throws RemoteException
54 */
55 final static RemoteOperation createRemoteOpFromString(String data) throws RemoteException {
56 try {
57 JSONObject jsonData = new JSONObject(data);
58 int protocolVersion = jsonData.getInt(VERSION);
59 // to keep things simple for now, just barf when protocol version is unknown
60 if (protocolVersion != CURRENT_PROTOCOL_VERSION) {
61 throw new RemoteException(String.format(
62 "Remote operation has unknown version '%d'. Expected '%d'",
63 protocolVersion, CURRENT_PROTOCOL_VERSION));
64 }
65 OperationType op = OperationType.valueOf(jsonData.getString(TYPE));
66 RemoteOperation rc = null;
67 switch (op) {
68 case ALLOCATE_DEVICE:
69 rc = new AllocateDeviceOp();
70 break;
71 case FREE_DEVICE:
72 rc = new FreeDeviceOp();
73 break;
74 case CLOSE:
75 rc = new CloseOp();
76 break;
77 case ADD_COMMAND:
78 rc = new AddCommandOp();
79 break;
80 default:
81 throw new RemoteException(String.format("unknown remote command '%s'", data));
82
83 }
84 rc.unpackFromJson(jsonData);
85 return rc;
86 } catch (JSONException e) {
87 throw new RemoteException(e);
88 }
89 }
90
91 protected abstract OperationType getType();
92
93 /**
94 * Abstract method to allow sub-classes to parse additional data from payload.
95 *
96 * @param json
97 * @throws RemoteException, JSONException
98 */
99 protected abstract void unpackFromJson(JSONObject json) throws RemoteException, JSONException;
100
101 /**
102 * Return the RemoteCommand data in its wire protocol format
103 * @return
104 */
105 String pack() throws RemoteException {
106 JSONObject j = new JSONObject();
107 try {
108 j.put(VERSION, CURRENT_PROTOCOL_VERSION);
109 j.put(TYPE, getType().toString());
110 packIntoJson(j);
111 } catch (JSONException e) {
112 CLog.e("Failed to serialize RemoteOperation", e);
113 }
114 return j.toString();
115 }
116
117 /**
118 * Callback to add subclass specific data to the JSON object
119 * @param j
120 * @throws JSONException
121 */
122 protected abstract void packIntoJson(JSONObject j) throws JSONException;
123
124}