1 package ro
.ieval
.fonbot
;
3 import static ro
.ieval
.fonbot
.R
.string
.*;
4 import static ro
.ieval
.fonbot
.Utils
.toNonNull
;
6 import java
.io
.InputStream
;
7 import java
.io
.OutputStream
;
9 import java
.util
.Collection
;
11 import java
.net
.HttpURLConnection
;
12 import org
.eclipse
.jdt
.annotation
.Nullable
;
14 import android
.content
.Context
;
15 import android
.preference
.PreferenceManager
;
16 import android
.util
.Base64
;
17 import android
.util
.Log
;
20 * Copyright © 2013 Marius Gavrilescu
22 * This file is part of FonBot.
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.
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.
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/>.
39 * ExecutableRunnable that makes a HTTP(S) call to the server and hands the response to a callback
41 * @author Marius Gavrilescu <marius@ieval.ro>
43 public final class HttpCallExecutableRunnable
extends ExecutableRunnable
{
46 * Callback which is run after a HTTP call.
48 * @author Marius Gavrilescu
50 public interface ResultCallback
{
52 * Callback invoked if the HTTP call is successful.
54 * @param responseCode HTTP response code
55 * @param responseMessage HTTP response message
56 * @param inputStream HTTP content InputStream
58 void onResult(final int responseCode
, final String responseMessage
, final InputStream inputStream
);
60 * Callback invoked if the HTTP call is unsuccessful.
62 * @param error localized error message
64 void onError(final String error
);
68 * List of extra request headers.
70 private final Collection
<Header
> headers
;
72 * Context instance used by this class
74 private final Context context
;
76 * Data to send to the server
78 private final byte[] data
;
82 private final String path
;
84 * Callback to run after the request returns
86 private final ResultCallback callback
;
87 /** If true, the task should be retried if it fails */
88 private final boolean mustRetryTask
;
91 * Constructs a SendHttpMessageAsyncTask which sends a binary message.
93 * @param path URL path
94 * @param headers the extra headers
95 * @param context the context instance
96 * @param resultCallback {@link ResultCallback} instance
97 * @param mustRetryTask true if this task should be retried if it fails
98 * @param data the message to send
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.
102 this.headers
=headers
;
103 this.context
=context
;
104 this.callback
=resultCallback
;
105 this.mustRetryTask
=mustRetryTask
;
110 * Constructs a SendHttpMessageAsyncTask which sends a text message.
112 * @param path URL path
113 * @param headers the extra headers
114 * @param context the context instance
115 * @param resultCallback {@link ResultCallback} instance
116 * @param mustRetryTask true if this task should be retried if it fails
117 * @param message message to send
119 public HttpCallExecutableRunnable(final String path
, final @Nullable Collection
<Header
> headers
, final Context context
, final @Nullable ResultCallback resultCallback
, final boolean mustRetryTask
, final String
... message
){
121 this.headers
=headers
;
122 this.context
=context
;
123 this.callback
=resultCallback
;
124 this.mustRetryTask
=mustRetryTask
;
125 if(message
.length
== 0)
126 this.data
=null;//NOPMD final field
128 this.data
=Utils
.join(" ", message
).getBytes();
135 } catch (Exception e
) {
138 callback
.onError(toNonNull(context
.getString(connection_error
)));
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
149 conn
.setDoOutput(true);
150 conn
.setFixedLengthStreamingMode(data
.length
);
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){
156 callback
.onError(toNonNull(context
.getString(user_or_password_not_set
)));
160 conn
.setRequestProperty("Authorization", "Basic "+Base64
.encodeToString((user
+':'+password
).getBytes(), Base64
.NO_WRAP
));
162 for (final Header header
: headers
)
163 conn
.setRequestProperty(header
.name
, header
.value
);
166 final OutputStream stream
=conn
.getOutputStream();
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);