X-Git-Url: https://git.ktnx.net/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fnet%2Fktnx%2Fmobileledger%2Fasync%2FSendTransactionTask.java;h=dc0c24875469a74b5d6404097a21034d1690672a;hb=bb789332571609eeb1bef6e39b7ad359227d1045;hp=fa69f86c593fbacaa65de813d457a2eaa5db056d;hpb=b18cd774a08afb15f9c3b953508b4823211c547b;p=mobile-ledger.git diff --git a/app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java b/app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java index fa69f86c..dc0c2487 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Damyan Ivanov. + * Copyright © 2020 Damyan Ivanov. * This file is part of MoLe. * MoLe is free software: you can distribute it and/or modify it * under the term of the GNU General Public License as published by @@ -23,12 +23,13 @@ import android.util.Log; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; -import net.ktnx.mobileledger.json.ParsedLedgerTransaction; -import net.ktnx.mobileledger.model.Data; import net.ktnx.mobileledger.model.LedgerTransaction; import net.ktnx.mobileledger.model.LedgerTransactionAccount; +import net.ktnx.mobileledger.model.MobileLedgerProfile; import net.ktnx.mobileledger.utils.Globals; +import net.ktnx.mobileledger.utils.Logger; import net.ktnx.mobileledger.utils.NetworkUtil; +import net.ktnx.mobileledger.utils.SimpleDate; import net.ktnx.mobileledger.utils.UrlEncodedFormData; import java.io.BufferedReader; @@ -45,43 +46,96 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import static android.os.SystemClock.sleep; +import static net.ktnx.mobileledger.utils.Logger.debug; + +/* TODO: get rid of the custom session/cookie and auth code? + * (the last problem with the POST was the missing content-length header) + * This will resolve itself when hledger-web 1.14+ is released with Debian/stable, + * at which point the HTML form emulation can be dropped entirely + */ public class SendTransactionTask extends AsyncTask { private final TaskCallback taskCallback; + private final MobileLedgerProfile mProfile; + private final boolean simulate; protected String error; private String token; private String session; - private LedgerTransaction ltr; + private LedgerTransaction transaction; - public SendTransactionTask(TaskCallback callback) { + public SendTransactionTask(TaskCallback callback, MobileLedgerProfile profile, + boolean simulate) { taskCallback = callback; + mProfile = profile; + this.simulate = simulate; + } + public SendTransactionTask(TaskCallback callback, MobileLedgerProfile profile) { + taskCallback = callback; + mProfile = profile; + simulate = false; + } + private boolean send_1_15_OK() throws IOException { + HttpURLConnection http = NetworkUtil.prepareConnection(mProfile, "add"); + http.setRequestMethod("PUT"); + http.setRequestProperty("Content-Type", "application/json"); + http.setRequestProperty("Accept", "*/*"); + + net.ktnx.mobileledger.json.v1_15.ParsedLedgerTransaction jsonTransaction = + net.ktnx.mobileledger.json.v1_15.ParsedLedgerTransaction.fromLedgerTransaction( + transaction); + ObjectMapper mapper = new ObjectMapper(); + ObjectWriter writer = + mapper.writerFor(net.ktnx.mobileledger.json.v1_15.ParsedLedgerTransaction.class); + String body = writer.writeValueAsString(jsonTransaction); + + return sendRequest(http, body); } - private boolean sendOK() throws IOException { - HttpURLConnection http = NetworkUtil.prepareConnection(Data.profile.get(), "add"); + private boolean send_1_14_OK() throws IOException { + HttpURLConnection http = NetworkUtil.prepareConnection(mProfile, "add"); http.setRequestMethod("PUT"); http.setRequestProperty("Content-Type", "application/json"); http.setRequestProperty("Accept", "*/*"); - ParsedLedgerTransaction jsonTransaction; - jsonTransaction = ltr.toParsedLedgerTransaction(); + net.ktnx.mobileledger.json.v1_14.ParsedLedgerTransaction jsonTransaction = + net.ktnx.mobileledger.json.v1_14.ParsedLedgerTransaction.fromLedgerTransaction( + transaction); ObjectMapper mapper = new ObjectMapper(); - ObjectWriter writer = mapper.writerFor(ParsedLedgerTransaction.class); + ObjectWriter writer = + mapper.writerFor(net.ktnx.mobileledger.json.v1_14.ParsedLedgerTransaction.class); String body = writer.writeValueAsString(jsonTransaction); + return sendRequest(http, body); + } + private boolean sendRequest(HttpURLConnection http, String body) throws IOException { + if (simulate) { + debug("network", "The request would be: " + body); + try { + Thread.sleep(1500); + if (Math.random() > 0.3) + throw new RuntimeException("Simulated test exception"); + } + catch (InterruptedException ex) { + Logger.debug("network", ex.toString()); + } + + return true; + } + byte[] bodyBytes = body.getBytes(StandardCharsets.UTF_8); http.setDoOutput(true); http.setDoInput(true); http.addRequestProperty("Content-Length", String.valueOf(bodyBytes.length)); - Log.d("network", "request header: " + http.getRequestProperties().toString()); + debug("network", "request header: " + http.getRequestProperties() + .toString()); try (OutputStream req = http.getOutputStream()) { - Log.d("network", "Request body: " + body); + debug("network", "Request body: " + body); req.write(bodyBytes); final int responseCode = http.getResponseCode(); - Log.d("network", - String.format("Response: %d %s", responseCode, http.getResponseMessage())); + debug("network", String.format(Locale.US, "Response: %d %s", responseCode, + http.getResponseMessage())); try (InputStream resp = http.getErrorStream()) { @@ -89,12 +143,24 @@ public class SendTransactionTask extends AsyncTask"); String line; while ((line = reader.readLine()) != null) { - //Log.d("dump", line); + //debug("dump", line); Matcher m = re.matcher(line); if (m.matches()) { token = m.group(1); - Log.d("save-transaction", line); - Log.d("save-transaction", "Token=" + token); + debug("save-transaction", line); + debug("save-transaction", "Token=" + token); return false; // retry } } @@ -189,21 +263,42 @@ public class SendTransactionTask extends AsyncTask= 2) - throw new IOException(String.format("aborting after %d tries", tried)); - sleep(100); - } + transaction = ledgerTransactions[0]; + + switch (mProfile.getApiVersion()) { + case auto: + Logger.debug("network", "Trying version 1.5."); + if (!send_1_15_OK()) { + Logger.debug("network", "Version 1.5 request failed. Trying with 1.14"); + if (!send_1_14_OK()) { + Logger.debug("network", + "Version 1.14 failed too. Trying HTML form emulation"); + legacySendOkWithRetry(); + } + else { + Logger.debug("network", "Version 1.14 request succeeded"); + } + } + else { + Logger.debug("network", "Version 1.15 request succeeded"); + } + break; + case html: + legacySendOkWithRetry(); + break; + case v1_14: + send_1_14_OK(); + break; + case v1_15: + send_1_15_OK(); + break; + default: + throw new IllegalStateException( + "Unexpected API version: " + mProfile.getApiVersion()); } } catch (Exception e) { @@ -213,10 +308,19 @@ public class SendTransactionTask extends AsyncTask= 2) + throw new IOException(String.format("aborting after %d tries", tried)); + sleep(100); + } + } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); taskCallback.done(error); } -} + +} \ No newline at end of file