Improve JSON parsing
[fonbot.git] / src / ro / ieval / fonbot / PollServerAsyncTask.java
1 package ro.ieval.fonbot;
2
3 import static ro.ieval.fonbot.Utils.toNonNull;
4
5 import java.io.IOException;
6 import java.net.HttpURLConnection;
7 import java.net.MalformedURLException;
8 import java.net.URL;
9 import java.util.ArrayList;
10 import java.util.List;
11
12 import org.eclipse.jdt.annotation.Nullable;
13 import org.json.JSONArray;
14 import org.json.JSONException;
15 import org.json.JSONObject;
16
17 import ro.ieval.fonbot.Address.Protocol;
18 import android.content.Context;
19 import android.os.AsyncTask;
20 import android.preference.PreferenceManager;
21 import android.util.Base64;
22 import android.util.Log;
23
24 import com.google.android.gcm.GCMRegistrar;
25
26 /*
27 * Copyright © 2013 Marius Gavrilescu
28 *
29 * This file is part of FonBot.
30 *
31 * FonBot is free software: you can redistribute it and/or modify
32 * it under the terms of the GNU General Public License as published by
33 * the Free Software Foundation, either version 3 of the License, or
34 * (at your option) any later version.
35 *
36 * FonBot is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
40 *
41 * You should have received a copy of the GNU General Public License
42 * along with FonBot. If not, see <http://www.gnu.org/licenses/>.
43 */
44
45 /**
46 * AsyncTask that polls the server for pending commands and executes any commands found.
47 *
48 * @author Marius Gavrilescu <marius@ieval.ro>
49 */
50 public final class PollServerAsyncTask extends AsyncTask<Void, Void, List<PollServerAsyncTask.Command>> {
51 /**
52 * POJO that represents a command in a basic form: a command name, a list of arguments and a reply address, all of them being strings
53 *
54 * @author Marius Gavrilescu <marius@ieval.ro>
55 */
56 final class Command{
57 /**
58 * The command name
59 */
60 final String command;//NOPMD no confusion here
61 /**
62 * The list of command arguments
63 */
64 final String[] args;
65 /**
66 * The reply address, excluding the protocol
67 */
68 final String replyto;
69
70 /**
71 * Construct a Command from its three parts
72 *
73 * @param command the command name
74 * @param args the command arguments
75 * @param replyto the reply address
76 */
77 Command(final String command, final String[] args, final String replyto) {//NOPMD array is immutable
78 this.command=command;
79 this.args=args;
80 this.replyto=replyto;
81 }
82 }
83
84 /** Context instance */
85 private final Context context;
86
87 /**
88 * Constructs a PollServerAsyncTask.
89 *
90 * @param context Context instance
91 */
92 public PollServerAsyncTask(final Context context) {
93 this.context=context;
94 }
95
96 @Override
97 protected List<Command> doInBackground(final @Nullable Void... params) {
98 Log.d(getClass().getName(), "Polling server");
99 final List<Command> commands=new ArrayList<Command>(10);
100 try {
101 final URL url=Utils.getServerURL(toNonNull(context),"/get");
102 final HttpURLConnection conn=(HttpURLConnection) url.openConnection();
103 conn.setRequestProperty("X-ID", GCMRegistrar.getRegistrationId(context));
104 final String user=PreferenceManager.getDefaultSharedPreferences(context).getString("username", null);
105 final String password=PreferenceManager.getDefaultSharedPreferences(context).getString("password", null);
106 if(user == null || password == null)
107 return commands;
108
109 conn.setRequestProperty("Authorization", "Basic "+Base64.encodeToString(
110 (user+':'+password).getBytes(), Base64.NO_WRAP));
111 conn.connect();
112 Log.d(getClass().getName(), "Server poll got response code "+conn.getResponseCode()+" and message "+conn.getResponseMessage());
113 if(conn.getResponseCode()!=200)
114 return commands;
115
116 final JSONArray array;
117 {
118 final byte[] buf=new byte[4096*1024];
119 conn.getInputStream().read(buf);
120 array=new JSONArray(new String(buf));
121 }
122
123 for(int i=0;i<array.length();i++){
124 final JSONObject object=array.getJSONObject(i);
125
126 final JSONArray jsonargs=object.getJSONArray("args");
127 final String[] args=new String[jsonargs.length()];
128 for(int j=0;j<args.length;j++)
129 args[j]=jsonargs.getString(j);
130
131 commands.add(new Command(//NOPMD command changes for each JSON object
132 toNonNull(object.getString("command")),
133 args,
134 toNonNull(object.getString("replyto"))));
135 }
136 } catch (MalformedURLException e) {
137 e.printStackTrace();
138 } catch (IOException e) {
139 e.printStackTrace();
140 } catch (JSONException e) {
141 e.printStackTrace();
142 }
143 if(commands==null)
144 throw new AssertionError("commands is null in PollServerAsyncTask#doInBackground");//silence Eclipse bug
145 return commands;
146 }
147
148 @Override
149 protected void onPostExecute(final @Nullable List<Command> commands) {
150 if(commands==null)
151 return;
152 for (Command command : commands) {
153 Log.d(getClass().getName(), "Poll got command "+command.command+" with "+((command.args.length==0)?"no args":"args "+Utils.join(
154 " ",toNonNull(command.args))));
155 Utils.processCommand(
156 toNonNull(context),
157 toNonNull(command.command),
158 toNonNull(command.args),
159 new Address(toNonNull(Protocol.HTTP), command.replyto));//NOPMD address depends on command
160 }
161 }
162 }
This page took 0.025255 seconds and 4 git commands to generate.