Make FonBot usable
[fonbot.git] / src / ro / ieval / fonbot / HttpCallExecutableRunnable.java
CommitLineData
8dfb76c9
MG
1package ro.ieval.fonbot;
2
3import static ro.ieval.fonbot.R.string.*;
8dfb76c9
MG
4import static ro.ieval.fonbot.Utils.toNonNull;
5
2e5049c9 6import java.io.InputStream;
8dfb76c9 7import java.io.OutputStream;
8dfb76c9
MG
8import java.net.URL;
9import java.util.Collection;
10
ca40a5cc 11import java.net.HttpURLConnection;
8dfb76c9
MG
12import org.eclipse.jdt.annotation.Nullable;
13
14import android.content.Context;
d13f1533
MG
15import android.preference.PreferenceManager;
16import android.util.Base64;
8dfb76c9
MG
17import android.util.Log;
18
19/*
20 * Copyright © 2013 Marius Gavrilescu
21 *
22 * This file is part of FonBot.
23 *
24 * FonBot is free software: you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation, either version 3 of the License, or
27 * (at your option) any later version.
28 *
29 * FonBot is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License
35 * along with FonBot. If not, see <http://www.gnu.org/licenses/>.
36 */
37
38/**
ca40a5cc 39 * ExecutableRunnable that makes a HTTP(S) call to the server and hands the response to a callback
8dfb76c9
MG
40 *
41 * @author Marius Gavrilescu <marius@ieval.ro>
42 */
2e5049c9 43public final class HttpCallExecutableRunnable extends ExecutableRunnable{
9717b83e 44
8dfb76c9 45 /**
2e5049c9
MG
46 * Callback which is run after a HTTP call.
47 *
48 * @author Marius Gavrilescu
8dfb76c9 49 */
561cd6dc 50 public interface ResultCallback{
2e5049c9
MG
51 /**
52 * Callback invoked if the HTTP call is successful.
53 *
54 * @param responseCode HTTP response code
55 * @param responseMessage HTTP response message
56 * @param inputStream HTTP content InputStream
57 */
561cd6dc 58 void onResult(final int responseCode, final String responseMessage, final InputStream inputStream);
2e5049c9
MG
59 /**
60 * Callback invoked if the HTTP call is unsuccessful.
61 *
62 * @param error localized error message
63 */
561cd6dc 64 void onError(final String error);
2e5049c9 65 }
8dfb76c9
MG
66
67 /**
68 * List of extra request headers.
69 */
70 private final Collection<Header> headers;
8dfb76c9
MG
71 /**
72 * Context instance used by this class
73 */
74 private final Context context;
75 /**
76 * Data to send to the server
77 */
78 private final byte[] data;
d13f1533
MG
79 /**
80 * Server URL path
81 */
82 private final String path;
8dfb76c9 83 /**
2e5049c9 84 * Callback to run after the request returns
8dfb76c9 85 */
2e5049c9 86 private final ResultCallback callback;
b26f32d6
MG
87 /** If true, the task should be retried if it fails */
88 private final boolean mustRetryTask;
8dfb76c9
MG
89
90 /**
2e5049c9 91 * Constructs a SendHttpMessageAsyncTask which sends a binary message.
8dfb76c9 92 *
d13f1533 93 * @param path URL path
8dfb76c9
MG
94 * @param headers the extra headers
95 * @param context the context instance
2e5049c9 96 * @param resultCallback {@link ResultCallback} instance
b26f32d6 97 * @param mustRetryTask true if this task should be retried if it fails
8dfb76c9
MG
98 * @param data the message to send
99 */
b26f32d6 100 public HttpCallExecutableRunnable(final String path, final @Nullable Collection<Header> headers, final Context context, final @Nullable ResultCallback resultCallback, final boolean mustRetryTask, final byte[] data){//NOPMD array is supposed to be immutable.
d13f1533 101 this.path=path;
8dfb76c9 102 this.headers=headers;
8dfb76c9 103 this.context=context;
2e5049c9 104 this.callback=resultCallback;
b26f32d6 105 this.mustRetryTask=mustRetryTask;
8dfb76c9
MG
106 this.data=data;
107 }
108
109 /**
2e5049c9 110 * Constructs a SendHttpMessageAsyncTask which sends a text message.
8dfb76c9 111 *
d13f1533 112 * @param path URL path
8dfb76c9 113 * @param headers the extra headers
8dfb76c9 114 * @param context the context instance
2e5049c9 115 * @param resultCallback {@link ResultCallback} instance
b26f32d6 116 * @param mustRetryTask true if this task should be retried if it fails
2e5049c9 117 * @param message message to send
8dfb76c9 118 */
b26f32d6 119 public HttpCallExecutableRunnable(final String path, final @Nullable Collection<Header> headers, final Context context, final @Nullable ResultCallback resultCallback, final boolean mustRetryTask, final String... message){
d13f1533 120 this.path=path;
8dfb76c9 121 this.headers=headers;
8dfb76c9 122 this.context=context;
2e5049c9 123 this.callback=resultCallback;
b26f32d6 124 this.mustRetryTask=mustRetryTask;
2e5049c9
MG
125 if(message.length == 0)
126 this.data=null;//NOPMD final field
127 else
128 this.data=Utils.join(" ", message).getBytes();
8dfb76c9
MG
129 }
130
131 @Override
82a2d0c2 132 public void run(){
8dfb76c9 133 try {
82a2d0c2 134 doRun();
8dfb76c9 135 } catch (Exception e) {
a97d31fb 136 e.printStackTrace();
c33b4990
MG
137 if(callback != null)
138 callback.onError(toNonNull(context.getString(connection_error)));
b26f32d6
MG
139 if(mustRetryTask)
140 retry();
8dfb76c9
MG
141 }
142 }
82a2d0c2
MG
143
144 public void doRun() throws Exception{
145 final URL url=Utils.getServerURL(toNonNull(context),toNonNull(path));
146 final HttpURLConnection conn=(HttpURLConnection) url.openConnection();
147 conn.setReadTimeout(24*60*1000);//24 minutes
148 if(data!=null){
149 conn.setDoOutput(true);
150 conn.setFixedLengthStreamingMode(data.length);
151 }
152 final String user=PreferenceManager.getDefaultSharedPreferences(context).getString("username", null);
153 final String password=PreferenceManager.getDefaultSharedPreferences(context).getString("password", null);
154 if(user == null || password == null || user.length() == 0 || password.length() == 0){
155 if(callback!=null)
156 callback.onError(toNonNull(context.getString(user_or_password_not_set)));
157 return;
158 }
159
160 conn.setRequestProperty("Authorization", "Basic "+Base64.encodeToString((user+':'+password).getBytes(), Base64.NO_WRAP));
161 if(headers != null)
162 for (final Header header : headers)
163 conn.setRequestProperty(header.name, header.value);
164 conn.connect();
165 if(data!=null){
166 final OutputStream stream=conn.getOutputStream();
167 stream.write(data);
168 stream.close();
169 }
170 Log.d(getClass().getName(),"HTTP Response: "+conn.getResponseCode()+" "+conn.getResponseMessage());
171 String message=conn.getResponseMessage();
172 if(message==null && callback != null)
173 callback.onError(toNonNull(context.getString(no_response_returned_from_server)));
174 else if(message != null && callback != null){
175 if(message.charAt(message.length()-1) == ')')//message is (something)
176 message=message.substring(1, message.length()-1);
177 else if(message.charAt(0) == '(')//message is (something) something else
178 message=message.substring(message.indexOf(')')+2);
179 callback.onResult(conn.getResponseCode(), message, conn.getResponseCode() == 200 ? conn.getInputStream() : null);
180 }
181 conn.disconnect();
182 }
8dfb76c9 183}
This page took 0.027451 seconds and 4 git commands to generate.