Android Open Source - matkakortti-widget Matkakortti Api






From Project

Back to project page matkakortti-widget.

License

The source code is released under:

GNU General Public License

If you think the Android project matkakortti-widget listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Matkakortti Widget is licensed under GPLv2.
 * See LICENSE.txt for more information.
 *///from w w w .ja v  a2  s.  c o m

package fi.iki.dezgeg.matkakorttiwidget.matkakortti;

import com.gistlabs.mechanize.MechanizeAgent;
import com.gistlabs.mechanize.document.Document;
import com.gistlabs.mechanize.document.html.HtmlDocument;
import com.gistlabs.mechanize.document.html.HtmlElement;
import com.gistlabs.mechanize.document.html.HtmlNode;
import com.gistlabs.mechanize.document.html.form.Form;
import com.gistlabs.mechanize.document.html.form.FormElement;
import com.gistlabs.mechanize.document.html.form.SubmitButton;

import org.apache.http.impl.client.AbstractHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.gistlabs.mechanize.document.html.query.HtmlQueryBuilder.byId;
import static com.gistlabs.mechanize.document.html.query.HtmlQueryBuilder.byTag;

public class MatkakorttiApi {
    private String username;
    private String password;

    public static final String OMAMATKAKORTTI_URL_BASE = "https://omamatkakortti.hsl.fi";

    public static final Pattern CARDS_JSON_PATTERN = Pattern.compile(".*?parseJSON\\('(.*)'\\).*", Pattern.DOTALL);
    public static final Pattern DATE_PATTERN = Pattern.compile("^/Date\\(([0-9]+)\\)/$");
    public static final Pattern SESSION_EXISTS_PATTERN = Pattern.compile(".*on toinen avoin istunto.*"); // TODO english

    public MatkakorttiApi(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public List<Card> getCards() throws Exception {
        MechanizeAgent agent;
        try {
            agent = login();
        } catch (MatkakorttiException me) {
            if (!me.isInternalError() &&
                    SESSION_EXISTS_PATTERN.matcher(me.getMessage()).matches()) // Try again once
                agent = login();
            else
                throw me;
        }

        // TODO: Follow redirects
        HtmlDocument response = safeGet(agent, "/Basic/Cards.aspx");
        List<HtmlElement> scripts = response.htmlElements().getAll(byTag("script"));

        List<Card> cards = new ArrayList<Card>();
        for (HtmlElement script : scripts) {
            Matcher matcher = CARDS_JSON_PATTERN.matcher(script.getInnerHtml());
            if (matcher.matches()) {
                JSONArray cardsJson;
                try {
                    cardsJson = new JSONArray(matcher.group(1));
                } catch (JSONException jsone) {
                    throw new MatkakorttiException("JSON in page is not valid", jsone, true);
                }

                for (int i = 0; i < cardsJson.length(); i++) {
                    try {
                        cards.add(createCardFromJSON(cardsJson.getJSONObject(i)));
                    } catch (JSONException jsone) {
                        throw new MatkakorttiException("Error when parsing card JSON", jsone, true);
                    }
                }
                return cards;
            }
        }
        throw new MatkakorttiException("Couldn't locate JSON data in OmaMatkakortti response.", true);
    }

    private HtmlDocument safeGet(MechanizeAgent agent, String url) {
        try {
            return agent.get(OMAMATKAKORTTI_URL_BASE + url);
        } catch (ClassCastException cce) {
            // MechanizeAgent throws this if not text/html
            throw new MatkakorttiException("Page " + url + " not HTML", cce, true);
        }
    }

    private MechanizeAgent login() throws Exception {
        AbstractHttpClient httpClient = NonverifyingSSLSocketFactory.createNonverifyingHttpClient();

        MechanizeAgent agent = new MechanizeAgent(httpClient);
        Document page = safeGet(agent, "/Login.aspx");

        Form loginForm = page.forms().get(byId("aspnetForm"));
        if (loginForm == null)
            throw new MatkakorttiException("Couldn't find aspnetForm", true);


        findField(loginForm, "UserName").set(username);
        findField(loginForm, "Password").set(password);
        FormElement loginButton = findField(loginForm, "LoginButton");
        if (!(loginButton instanceof SubmitButton))
            throw new MatkakorttiException("LoginButton is not a SubmitButton", true);

        HtmlDocument loginResponse = loginForm.submit((SubmitButton) loginButton);
        HtmlElement validationSummary = loginResponse.htmlElements().get(byId("Etuile_mainValidationSummary"));

        if (validationSummary != null) {
            HtmlElement errorList = validationSummary.get(byTag("ul"));
            if (errorList == null)
                throw new MatkakorttiException("Login response has validation summary but no error list", true);
            String errors = "";
            // - 1 since the service will always complain about our browser.
            for (int i = 0; i < errorList.getChildren().size() - 1; i++) {
                HtmlNode elem = errorList.getChildren().get(i);
                if (elem instanceof HtmlElement)
                    errors += ((HtmlElement) elem).getText() + "\n";
            }
            throw new MatkakorttiException(errors, false);
        }
        return agent;
    }

    private FormElement findField(Form loginForm, String name) {
        final String PREFIX = "Etuile$MainContent$LoginControl$LoginForm$";
        FormElement formElement = loginForm.get(PREFIX + name);

        if (formElement == null)
            throw new MatkakorttiException("Couldn't find field " + name + " in login form", true);
        return formElement;
    }

    private Card createCardFromJSON(JSONObject card) throws JSONException {
        double moneyAsDouble = card.getDouble("RemainingMoney");
        // Round to BigDecimal cents safely
        BigDecimal money = new BigDecimal((int) Math.round(100 * moneyAsDouble)).divide(new BigDecimal(100));

        String expiryDateStr = card.getJSONObject("PeriodProductState").getString("ExpiringDate");
        Date expiryDate = null;
        if (!expiryDateStr.equals("null")) {
            Matcher expiryDateMatch = DATE_PATTERN.matcher(expiryDateStr);
            if (!expiryDateMatch.matches()) {
                throw new MatkakorttiException("Date pattern did not match regex: " + expiryDateStr, true);
            }
            expiryDate = new Date(Long.parseLong(expiryDateMatch.group(1)));
        }

        return new Card(card.getString("name"), card.getString("id"), money, expiryDate);
    }
}




Java Source Code List

fi.iki.dezgeg.matkakorttiwidget.gui.AboutAppActivity.java
fi.iki.dezgeg.matkakorttiwidget.gui.HomescreenWidgetProvider.java
fi.iki.dezgeg.matkakorttiwidget.gui.MatkakorttiWidgetApp.java
fi.iki.dezgeg.matkakorttiwidget.gui.SettingsActivity.java
fi.iki.dezgeg.matkakorttiwidget.gui.Utils.java
fi.iki.dezgeg.matkakorttiwidget.gui.WidgetUpdaterService.java
fi.iki.dezgeg.matkakorttiwidget.matkakortti.Card.java
fi.iki.dezgeg.matkakorttiwidget.matkakortti.MatkakorttiApi.java
fi.iki.dezgeg.matkakorttiwidget.matkakortti.MatkakorttiException.java
fi.iki.dezgeg.matkakorttiwidget.matkakortti.NonverifyingSSLSocketFactory.java