diff --git a/src/main/java/com/nutomic/syncthingandroid/http/GetTask.java b/src/main/java/com/nutomic/syncthingandroid/http/GetTask.java index 32ceda1b..380e15ad 100644 --- a/src/main/java/com/nutomic/syncthingandroid/http/GetTask.java +++ b/src/main/java/com/nutomic/syncthingandroid/http/GetTask.java @@ -1,10 +1,15 @@ package com.nutomic.syncthingandroid.http; +import android.support.annotation.Nullable; import android.util.Log; import android.util.Pair; +import com.google.common.base.Optional; + import java.io.IOException; import java.net.URL; +import java.util.Collections; +import java.util.Map; import javax.net.ssl.HttpsURLConnection; @@ -13,7 +18,7 @@ import javax.net.ssl.HttpsURLConnection; * Performs a GET request with no parameters to the URL in uri[0] with the path in uri[1] and * returns the result as a String. */ -public class GetTask extends RestTask { +public class GetTask extends RestTask { private static final String TAG = "GetTask"; @@ -26,18 +31,18 @@ public class GetTask extends RestTask { public static final String URI_REPORT = "/rest/svc/report"; public static final String URI_EVENTS = "/rest/events"; + private final Map mParams; + public GetTask(URL url, String path, String httpsCertPath, String apiKey, - OnSuccessListener listener) { + @Nullable Map params, OnSuccessListener listener) { super(url, path, httpsCertPath, apiKey, listener); + mParams = Optional.fromNullable(params).or(Collections.emptyMap()); } - /** - * @param params Keys and values for the query string. - */ @Override - protected Pair doInBackground(String... params) { + protected Pair doInBackground(Void... aVoid) { try { - HttpsURLConnection connection = openConnection(params); + HttpsURLConnection connection = openConnection(mParams); Log.v(TAG, "Calling Rest API at " + connection.getURL()); return connect(connection); } catch (IOException e) { diff --git a/src/main/java/com/nutomic/syncthingandroid/http/PollWebGuiAvailableTask.java b/src/main/java/com/nutomic/syncthingandroid/http/PollWebGuiAvailableTask.java index 9f95ce97..aebd6849 100644 --- a/src/main/java/com/nutomic/syncthingandroid/http/PollWebGuiAvailableTask.java +++ b/src/main/java/com/nutomic/syncthingandroid/http/PollWebGuiAvailableTask.java @@ -4,8 +4,11 @@ package com.nutomic.syncthingandroid.http; import android.util.Log; import android.util.Pair; +import com.google.common.collect.Maps; + import java.io.IOException; import java.net.URL; +import java.util.Collections; import javax.net.ssl.HttpsURLConnection; @@ -32,7 +35,7 @@ public class PollWebGuiAvailableTask extends RestTask { int status = 0; do { try { - HttpsURLConnection connection = openConnection(); + HttpsURLConnection connection = openConnection(Collections.emptyMap()); connection.connect(); status = connection.getResponseCode(); } catch (IOException e) { diff --git a/src/main/java/com/nutomic/syncthingandroid/http/PostConfigTask.java b/src/main/java/com/nutomic/syncthingandroid/http/PostConfigTask.java new file mode 100644 index 00000000..1091dd7b --- /dev/null +++ b/src/main/java/com/nutomic/syncthingandroid/http/PostConfigTask.java @@ -0,0 +1,43 @@ +package com.nutomic.syncthingandroid.http; + +import android.util.Log; +import android.util.Pair; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; +import java.util.Collections; + +import javax.net.ssl.HttpsURLConnection; + +public class PostConfigTask extends RestTask { + + private static final String TAG = "PostConfigTask"; + + private static final String URI_CONFIG = "/rest/system/config"; + + private final String mConfig; + + public PostConfigTask(URL url, String httpsCertPath, String apiKey, String config, + OnSuccessListener listener) { + super(url, URI_CONFIG, httpsCertPath, apiKey, listener); + mConfig = config; + } + + @Override + protected Pair doInBackground(Void... params) { + try { + HttpsURLConnection connection = openConnection(Collections.emptyMap()); + connection.setRequestMethod("POST"); + Log.v(TAG, "Calling Rest API at " + connection.getURL()); + + OutputStream os = connection.getOutputStream(); + os.write(mConfig.getBytes("UTF-8")); + return connect(connection); + } catch (IOException e) { + Log.w(TAG, "Failed to call rest api", e); + return new Pair<>(false, null); + } + } + +} diff --git a/src/main/java/com/nutomic/syncthingandroid/http/PostScanTask.java b/src/main/java/com/nutomic/syncthingandroid/http/PostScanTask.java new file mode 100644 index 00000000..d87391c8 --- /dev/null +++ b/src/main/java/com/nutomic/syncthingandroid/http/PostScanTask.java @@ -0,0 +1,40 @@ +package com.nutomic.syncthingandroid.http; + +import android.util.Log; +import android.util.Pair; + +import com.google.common.collect.ImmutableMap; + +import java.io.IOException; +import java.net.URL; + +import javax.net.ssl.HttpsURLConnection; + +public class PostScanTask extends RestTask { + + private static final String TAG = "PostScanTask"; + + private static final String URI_SCAN = "/rest/db/scan"; + + private final String mFolder; + private final String mSub; + + public PostScanTask(URL url, String httpsCertPath, String apiKey, String folder, String sub) { + super(url, URI_SCAN, httpsCertPath, apiKey, null); + mFolder = folder; + mSub = sub; + } + + @Override + protected Pair doInBackground(Void... params) { + try { + HttpsURLConnection connection = openConnection(ImmutableMap.of("folder", mFolder, "sub", mSub)); + connection.setRequestMethod("POST"); + return connect(connection); + } catch (IOException e) { + Log.w(TAG, "Failed to call rest api", e); + return new Pair<>(false, null); + } + } + +} diff --git a/src/main/java/com/nutomic/syncthingandroid/http/PostTask.java b/src/main/java/com/nutomic/syncthingandroid/http/PostTask.java deleted file mode 100644 index ba338de5..00000000 --- a/src/main/java/com/nutomic/syncthingandroid/http/PostTask.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.nutomic.syncthingandroid.http; - -import android.util.Log; -import android.util.Pair; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.URL; - -import javax.net.ssl.HttpsURLConnection; - -/** - * Sends a POST request to the Syncthing API. - */ -public class PostTask extends RestTask { - - private static final String TAG = "PostTask"; - - public static final String URI_CONFIG = "/rest/system/config"; - public static final String URI_SCAN = "/rest/db/scan"; - - public PostTask(URL url, String path, String httpsCertPath, String apiKey, - OnSuccessListener listener) { - super(url, path, httpsCertPath, apiKey, listener); - } - - /** - * For {@link #URI_CONFIG}, params[0] must contain the config. - * - * For {@link #URI_SCAN}, params[0] must contain the folder, and params[1] the subfolder. - */ - @Override - protected Pair doInBackground(String... params) { - try { - HttpsURLConnection connection = (mPath.equals(URI_SCAN)) - ? openConnection("folder", params[0], "sub", params[1]) - : openConnection(); - connection.setRequestMethod("POST"); - Log.v(TAG, "Calling Rest API at " + connection.getURL()); - - if (mPath.equals(URI_CONFIG)) { - OutputStream os = connection.getOutputStream(); - os.write(params[0].getBytes("UTF-8")); - } - return connect(connection); - } catch (IOException e) { - Log.w(TAG, "Failed to call rest api", e); - return new Pair<>(false, null); - } - } - -} diff --git a/src/main/java/com/nutomic/syncthingandroid/http/RestTask.java b/src/main/java/com/nutomic/syncthingandroid/http/RestTask.java index d3e268f9..b6de5586 100644 --- a/src/main/java/com/nutomic/syncthingandroid/http/RestTask.java +++ b/src/main/java/com/nutomic/syncthingandroid/http/RestTask.java @@ -4,6 +4,7 @@ package com.nutomic.syncthingandroid.http; import android.annotation.SuppressLint; import android.net.Uri; import android.os.AsyncTask; +import android.support.annotation.Nullable; import android.util.Log; import android.util.Pair; @@ -26,6 +27,7 @@ import java.security.SignatureException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.Map; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; @@ -62,14 +64,15 @@ public abstract class RestTask extends mListener = listener; } - protected HttpsURLConnection openConnection(String... params) throws IOException { + protected HttpsURLConnection openConnection(Map params) throws IOException { Uri.Builder uriBuilder = Uri.parse(mUrl.toString()) .buildUpon() .path(mPath); - for (int paramCounter = 0; paramCounter + 1 < params.length; ) { - uriBuilder.appendQueryParameter(params[paramCounter++], params[paramCounter++]); + for (Map.Entry entry : params.entrySet()) { + uriBuilder.appendQueryParameter(entry.getKey(), entry.getValue()); } URL url = new URL(uriBuilder.build().toString()); + Log.v(TAG, "Calling Rest API at " + url); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setRequestProperty(HEADER_API_KEY, mApiKey); diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java index e3e73d98..f2ea662c 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java @@ -4,10 +4,10 @@ import android.app.Activity; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; -import android.os.AsyncTask; import android.util.Log; import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMap; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -18,7 +18,8 @@ import com.google.gson.JsonParser; import com.nutomic.syncthingandroid.BuildConfig; import com.nutomic.syncthingandroid.activities.RestartActivity; import com.nutomic.syncthingandroid.http.GetTask; -import com.nutomic.syncthingandroid.http.PostTask; +import com.nutomic.syncthingandroid.http.PostConfigTask; +import com.nutomic.syncthingandroid.http.PostScanTask; import com.nutomic.syncthingandroid.model.Config; import com.nutomic.syncthingandroid.model.Connection; import com.nutomic.syncthingandroid.model.Device; @@ -29,7 +30,6 @@ import com.nutomic.syncthingandroid.model.Options; import com.nutomic.syncthingandroid.model.SystemInfo; import com.nutomic.syncthingandroid.model.SystemVersion; import com.nutomic.syncthingandroid.util.FolderObserver; -import com.nutomic.syncthingandroid.util.Util; import org.json.JSONArray; import org.json.JSONException; @@ -130,13 +130,13 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, @Override public void onWebGuiAvailable() { mAvailableCount.set(0); - new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, result -> { + new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, null, result -> { JsonObject json = new JsonParser().parse(result).getAsJsonObject(); mVersion = json.get("version").getAsString(); Log.i(TAG, "Syncthing version is " + mVersion); tryIsAvailable(); }).execute(); - new GetTask(mUrl, GetTask.URI_CONFIG, mHttpsCertPath, mApiKey, result -> { + new GetTask(mUrl, GetTask.URI_CONFIG, mHttpsCertPath, mApiKey, null, result -> { mConfig = new Gson().fromJson(result, Config.class); tryIsAvailable(); }).execute(); @@ -194,19 +194,19 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * Sends current config to Syncthing. */ private void sendConfig() { - new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey, null) - .execute(new Gson().toJson(mConfig)); + new PostConfigTask(mUrl, mHttpsCertPath, mApiKey, new Gson().toJson(mConfig), null) + .execute(); } /** * Sends current config and restarts Syncthing. */ public void restart() { - new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey, result -> { + new PostConfigTask(mUrl, mHttpsCertPath, mApiKey, new Gson().toJson(mConfig), result -> { Intent intent = new Intent(mContext, SyncthingService.class) .setAction(SyncthingService.ACTION_RESTART); mContext.startService(intent); - }).execute(new Gson().toJson(mConfig)); + }).execute(); } /** @@ -310,7 +310,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * @param listener Callback invoked when the result is received. */ public void getSystemInfo(OnResultListener1 listener) { - new GetTask(mUrl, GetTask.URI_SYSTEM, mHttpsCertPath, mApiKey, result -> { + new GetTask(mUrl, GetTask.URI_SYSTEM, mHttpsCertPath, mApiKey, null, result -> { listener.onResult(new Gson().fromJson(result, SystemInfo.class)); }).execute(); } @@ -321,7 +321,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * @param listener Callback invoked when the result is received. */ public void getSystemVersion(OnResultListener1 listener) { - new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, result -> { + new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, null, result -> { SystemVersion systemVersion = new Gson().fromJson(result, SystemVersion.class); listener.onResult(systemVersion); }).execute(); @@ -342,7 +342,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * The result is cached internally. Do not modify it or any of its contents. */ public void getConnections(final OnResultListener1> listener) { - new GetTask(mUrl, GetTask.URI_CONNECTIONS, mHttpsCertPath, mApiKey, result -> { + new GetTask(mUrl, GetTask.URI_CONNECTIONS, mHttpsCertPath, mApiKey, null, result -> { Long now = System.currentTimeMillis(); Long timeElapsed = (now - mPreviousConnectionTime) / 1000; if (timeElapsed < 1) { @@ -451,11 +451,12 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * Returns status information about the folder with the given id. */ public void getModel(final String folderId, final OnResultListener2 listener) { - new GetTask(mUrl, GetTask.URI_MODEL, mHttpsCertPath, mApiKey, result -> { + new GetTask(mUrl, GetTask.URI_MODEL, mHttpsCertPath, mApiKey, + ImmutableMap.of("folder", folderId), result -> { Model m = new Gson().fromJson(result, Model.class); mCachedModelInfo.put(folderId, m); listener.onResult(folderId, m); - }).execute("folder", folderId); + }).execute(); } /** @@ -464,7 +465,9 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * The OnReceiveEventListeners onEvent method is called for each event. */ public final void getEvents(final long sinceId, final long limit, final OnReceiveEventListener listener) { - new GetTask(mUrl, GetTask.URI_EVENTS, mHttpsCertPath, mApiKey, result -> { + Map params = + ImmutableMap.of("since", String.valueOf(sinceId), "limit", String.valueOf(limit)); + new GetTask(mUrl, GetTask.URI_EVENTS, mHttpsCertPath, mApiKey, params, result -> { JsonArray jsonEvents = new JsonParser().parse(result).getAsJsonArray(); long lastId = 0; @@ -479,8 +482,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, } listener.onDone(lastId); - }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, - "since", String.valueOf(sinceId), "limit", String.valueOf(limit)); + }).execute(); } /** @@ -488,7 +490,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, */ public void normalizeDeviceId(String id, OnResultListener1 listener, OnResultListener1 errorListener) { - new GetTask(mUrl, GetTask.URI_DEVICEID, mHttpsCertPath, mApiKey, result -> { + new GetTask(mUrl, GetTask.URI_DEVICEID, mHttpsCertPath, mApiKey, ImmutableMap.of("id", id), + result -> { JsonObject json = new JsonParser().parse(result).getAsJsonObject(); JsonElement normalizedId = json.get("id"); JsonElement error = json.get("error"); @@ -496,7 +499,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, listener.onResult(normalizedId.getAsString()); if (error != null) errorListener.onResult(error.getAsString()); - }).execute("id", id); + }).execute(); } /** @@ -504,8 +507,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, */ @Override public void onFolderFileChange(String folderId, String relativePath) { - new PostTask(mUrl, PostTask.URI_SCAN, mHttpsCertPath, mApiKey, null) - .execute(folderId, relativePath); + new PostScanTask(mUrl, mHttpsCertPath, mApiKey, folderId, relativePath) + .execute(); } /** @@ -524,7 +527,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * Returns prettyfied usage report. */ public void getUsageReport(final OnResultListener1 listener) { - new GetTask(mUrl, GetTask.URI_REPORT, mHttpsCertPath, mApiKey, result -> { + new GetTask(mUrl, GetTask.URI_REPORT, mHttpsCertPath, mApiKey, null, result -> { JsonElement json = new JsonParser().parse(result); Gson gson = new GsonBuilder().setPrettyPrinting().create(); listener.onResult(gson.toJson(json));