com.etalio.android.EtalioExtendedAPI.java Source code

Java tutorial

Introduction

Here is the source code for com.etalio.android.EtalioExtendedAPI.java

Source

/*
 * Copyright 2014 Ericsson AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.etalio.android;

import android.content.Context;
import android.util.Base64;

import com.etalio.android.client.exception.EtalioHttpError;
import com.etalio.android.client.exception.EtalioProfileExpiredException;
import com.etalio.android.client.models.PromotedApplications;
import com.etalio.android.client.models.Status;
import com.etalio.android.client.models.requests.MsisdnRequestClaim;
import com.etalio.android.client.models.requests.MsisdnVerifyToken;
import com.etalio.android.util.Log;

import com.etalio.android.client.GsonHttpBodyConverter;
import com.etalio.android.client.HttpRequest;
import com.etalio.android.client.HttpResponse;
import com.etalio.android.client.exception.EtalioHttpException;
import com.etalio.android.client.exception.EtalioTokenException;
import com.etalio.android.client.models.Action;
import com.etalio.android.client.models.Application;
import com.etalio.android.client.models.Country;
import com.etalio.android.client.models.NewUser;
import com.etalio.android.client.models.Operator;
import com.etalio.android.client.models.TokenResponse;
import com.etalio.android.client.models.User;
import com.etalio.android.client.models.Version;
import com.etalio.android.client.models.requests.CreateApplication;
import com.etalio.android.client.models.requests.Msisdn;
import com.etalio.android.client.models.requests.MsisdnRequestCodeResponse;
import com.etalio.android.client.models.requests.MsisdnResponseCode;
import com.etalio.android.client.models.requests.MsisdnResponseCodeResponse;
import com.etalio.android.client.models.requests.PasswordReset;
import com.etalio.android.client.models.requests.ProfileApplicationAdd;

import org.apache.http.client.HttpClient;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

public class EtalioExtendedAPI extends EtalioAPI {
    private static final String TAG = EtalioExtendedAPI.class.getCanonicalName();
    private static final String PARAM_USERNAME = "username";
    private static final String PARAM_PASSWORD = "password";

    protected static final String PROFILE_APP = "profileApp";
    protected static final String PROFILE_REMOVE_APP = "profileRemoveApp";
    protected static final String PASSWORD_RESET = "passwordReset";
    protected static final String PROFILE_SMS = "profileSms";
    protected static final String FEATURED_APPLICATIONS = "featured-applications";
    protected static final String COUNTRIES = "countries";
    protected static final String OPERATORS = "operators";
    protected static final String VERSION = "version";
    protected static final String MSISDN = "msisdn";
    protected static final String MYAPPS = "myapps";
    protected static final String ACTIONS = "actions";
    protected static final String APPLICATIONS = "applications";
    protected static final String PROFILES = "profiles";
    protected static final String CLAIM_MSISDN = "claim-msisdn";
    protected static final String PROMOTED_APPS = "promoted-apps";

    private final String baseUrl;

    public EtalioExtendedAPI(Context context, String clientID, String clientSecret) {
        this(context, clientID, clientSecret, API_URL, API_VERSION);
    }

    public EtalioExtendedAPI(Context context, String clientID, String clientSecret, String apiUrl,
            String apiVersion) {
        super(context, clientID, clientSecret, apiUrl, apiVersion);

        Log.e(TAG, "Creating extended API");

        baseUrl = apiUrl + apiVersion;
        domainMap.put(PROFILE_APP, baseUrl + "/profile/me/applications");
        domainMap.put(PROFILE_REMOVE_APP, baseUrl + "/profile/me/application");
        domainMap.put(PASSWORD_RESET, baseUrl + "/profile/password-reset");
        domainMap.put(PROFILE_SMS, baseUrl + "/profile/me/sms");
        domainMap.put(FEATURED_APPLICATIONS, baseUrl + "/applications?featured=true");
        domainMap.put(COUNTRIES, baseUrl + "/countries");
        domainMap.put(OPERATORS, baseUrl + "/netops");
        domainMap.put(VERSION, baseUrl + "/version");
        domainMap.put(MSISDN, baseUrl + "/msisdn");
        domainMap.put(MYAPPS, baseUrl + "/profile/me/applications");
        domainMap.put(ACTIONS, baseUrl + "/profile/me/notifications");
        domainMap.put(APPLICATIONS, baseUrl + "/applications");
        domainMap.put(PROFILES, baseUrl + "/profiles");
        domainMap.put(CLAIM_MSISDN, baseUrl + "/msisdn/claim");
        domainMap.put(PROMOTED_APPS, baseUrl + "/applications/promoted");
    }

    /**
     * Send a MT SMS to the device from the server with a request code.
     * @param phoneNumber
     * @return
     * @throws EtalioTokenException
     * @throws IOException
     * @throws EtalioHttpException
     */
    public Status sendRequestCode(String phoneNumber)
            throws EtalioTokenException, IOException, EtalioHttpException {
        Msisdn msisdn = new Msisdn(phoneNumber, true, null);
        return apiCall(MSISDN, HttpRequest.HttpMethod.POST, msisdn, Status.class);
    }

    /**
     * Verify if request code is correct.
     * @param phoneNumber
     * @param requestCode
     * @throws EtalioTokenException
     * @throws IOException
     * @throws EtalioHttpException
     */
    public void verifyRequestCode(String phoneNumber, String requestCode)
            throws EtalioTokenException, IOException, EtalioHttpException {
        MsisdnVerifyToken msisdn = new MsisdnVerifyToken(phoneNumber, requestCode);
        MsisdnRequestCodeResponse response = apiCall(MSISDN, HttpRequest.HttpMethod.POST, msisdn,
                MsisdnRequestCodeResponse.class);
    }

    /**
     * Get a MO SMS response code to be sent from device to server.
     * @param phoneNumber
     * @return
     * @throws EtalioTokenException
     * @throws IOException
     * @throws EtalioHttpException
     */
    public String getResponseCode(String phoneNumber)
            throws EtalioTokenException, IOException, EtalioHttpException {
        MsisdnResponseCode msisdn = new MsisdnResponseCode(phoneNumber, true);
        return apiCall(MSISDN, HttpRequest.HttpMethod.POST, msisdn, MsisdnResponseCodeResponse.class)
                .getResponseCode();
    }

    public User createProfile(final String name, final String msisdn, final String requestCode,
            final String responseCode, final String password, String email, Boolean acceptsEula)
            throws IOException, EtalioTokenException, EtalioHttpException {
        NewUser newUser = new NewUser(name, msisdn, requestCode, responseCode, password, email, acceptsEula);
        return apiCall(PROFILES, HttpRequest.HttpMethod.POST, newUser, User.class);
    }

    /**
     * Sign in as application and not as a user. Only available for trusted apps.
     * @return
     * @throws EtalioTokenException
     * @throws IOException
     * @throws EtalioHttpException
     */
    public boolean requestApplicationSignIn() throws EtalioTokenException, IOException, EtalioHttpException {
        byte[] body = buildApplicationAuthenticationRequestBody();
        boolean result;
        try {
            result = privateSignIn(body);
        } catch (EtalioHttpException e) {
            if (e.getResponseCode() == 401)
                return false;
            throw e;
        }
        return result;
    }

    /**
     * Sign in a user with grant-type password.
     * @param msisdn
     * @param password
     * @return
     * @throws IOException
     * @throws EtalioTokenException
     * @throws EtalioHttpException
     */
    public boolean requestPrivateSignIn(String msisdn, String password)
            throws IOException, EtalioTokenException, EtalioHttpException, EtalioProfileExpiredException {
        byte[] body = buildAuthenticationRequestBody(msisdn, password);
        boolean result;
        try {
            result = privateSignIn(body);
        } catch (EtalioHttpException e) {
            if (e.getErrorType() == EtalioHttpError.PROFILE_EXPIRED) {
                throw new EtalioProfileExpiredException();
            }
            if (e.getResponseCode() == 401)
                return false;
            throw e;
        }
        return result;
    }

    private boolean privateSignIn(byte[] body) throws IOException, EtalioHttpException, EtalioTokenException {
        Log.v(SDK_TAG, "privateSignIn");
        Map<String, String> headers = new HashMap<String, String>();
        addEtalioUserAgent(headers);
        String authenticationString = mClientId + ":" + mClientSecret;
        String authenticationString64 = Base64.encodeToString(authenticationString.getBytes(), Base64.NO_WRAP);
        headers.put("Authorization", "Basic " + authenticationString64);
        Log.v(TAG, "privateSignIn:: POST " + authenticationString + " " + getUrl("token", null) + " "
                + new String(body, "UTF-8"));
        HttpRequest request = new HttpRequest(HttpRequest.HttpMethod.POST, getUrl("token", null), headers, body,
                CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED, body.length);
        HttpResponse<TokenResponse> response = null;
        response = getHttpClient().executeRequest(request, new GsonHttpBodyConverter<TokenResponse>(),
                TokenResponse.class);
        Log.v(TAG, "privateSignIn::" + response.getStatus() + " : "
                + new String(getHttpBodyConverter().toBody(response.getBody(), "UTF-8"), "UTF-8"));
        updateEtalioToken(response);
        return true;
    }

    public boolean removeAccount() throws EtalioTokenException, IOException, EtalioHttpException {
        apiCall("myprofile", HttpRequest.HttpMethod.DELETE, null, Object.class);
        return true;
    }

    private byte[] buildApplicationAuthenticationRequestBody() {
        Map<String, String> params = new HashMap<String, String>();
        params.put(PARAM_GRANT_TYPE, "client_credentials");
        params.put(PARAM_USERNAME, mClientId);
        params.put(PARAM_PASSWORD, mClientSecret);
        return generateFormEncodedRequestBody(params);
    }

    private byte[] buildAuthenticationRequestBody(String username, String password) {
        Map<String, String> params = new HashMap<String, String>();
        params.put(PARAM_GRANT_TYPE, "password");
        try {
            params.put(PARAM_USERNAME, URLEncoder.encode(username, "UTF-8"));
            params.put(PARAM_PASSWORD, URLEncoder.encode(password, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            return null;
        }

        return generateFormEncodedRequestBody(params);
    }

    public Application createApplication(CreateApplication createApplication)
            throws EtalioTokenException, IOException, EtalioHttpException {
        return apiCall("applications", HttpRequest.HttpMethod.POST, createApplication, Application.class);
    }

    public TokenResponse addApplication(String clientId, String packageName)
            throws EtalioTokenException, IOException, EtalioHttpException {
        ProfileApplicationAdd profileApplicationAdd = new ProfileApplicationAdd(clientId, "profile.r", packageName);
        return apiCall(PROFILE_APP, HttpRequest.HttpMethod.POST, profileApplicationAdd, TokenResponse.class);
    }

    public boolean revokeAccess(String applicationId)
            throws EtalioTokenException, IOException, EtalioHttpException {
        String encodedId = URLEncoder.encode(applicationId, "UTF-8");
        String domain = addToDomainMap("profileRemoveApp-" + encodedId,
                domainMap.get(PROFILE_REMOVE_APP) + "/" + encodedId);
        try {
            apiCall(domain, HttpRequest.HttpMethod.DELETE, null, Object.class);
        } catch (EtalioHttpException e) {
            if (e.getResponseCode() == 404)
                return false;
            throw e;
        }
        return true;
    }

    public boolean resetPassword(String msisdn) throws EtalioTokenException, IOException, EtalioHttpException {
        PasswordReset passwordReset = new PasswordReset(msisdn);
        apiCall(PASSWORD_RESET, HttpRequest.HttpMethod.POST, passwordReset, Object.class);
        return true;
    }

    public boolean checkPhoneNumberExists(Msisdn msisdn)
            throws EtalioTokenException, IOException, EtalioHttpException {
        try {
            apiCall(MSISDN, HttpRequest.HttpMethod.POST, msisdn, Object.class);
        } catch (EtalioHttpException e) {
            if (e.getResponseCode() == 404)
                return false;
            throw e;
        }
        return true;
    }

    public Application[] getFeaturedApplications() throws EtalioTokenException, IOException, EtalioHttpException {
        return apiCall(FEATURED_APPLICATIONS, HttpRequest.HttpMethod.GET, null, Application[].class);
    }

    /**
     * Gets the operators in Etalio
     *
     * Use get @link{#getOperators(String) getOperators} instead.
     * @return all the operators in etalio
     *
     * @throws EtalioTokenException
     * @throws IOException
     * @throws EtalioHttpException
     */
    @Deprecated
    public Operator[] getOperators() throws EtalioTokenException, IOException, EtalioHttpException {
        return apiCall(OPERATORS, HttpRequest.HttpMethod.GET, null, Operator[].class);
    }

    /**
     * Get the operators for a given msisdn
     *
     * @param msisdn the phone number
     * @return the operators in the country for the MSISDN
     * @throws EtalioTokenException
     * @throws IOException
     * @throws EtalioHttpException
     */
    public Operator[] getOperators(String msisdn) throws EtalioTokenException, IOException, EtalioHttpException {
        String requestIdentifier = String.format("netops-%s", msisdn);
        String requestUrl = String.format("%s/netops?msisdn=%s", baseUrl, URLEncoder.encode(msisdn, "UTF-8"));
        domainMap.put(requestIdentifier, requestUrl);
        return apiCall(requestIdentifier, HttpRequest.HttpMethod.GET, null, Operator[].class);
    }

    public Country[] getCountries() throws EtalioTokenException, IOException, EtalioHttpException {
        return apiCall(COUNTRIES, HttpRequest.HttpMethod.GET, null, Country[].class, false);
    }

    public Version[] getVersions() throws EtalioTokenException, IOException, EtalioHttpException {
        return apiCall(VERSION, HttpRequest.HttpMethod.GET, null, Version[].class);
    }

    public Version getAndroidVersion() throws EtalioTokenException, IOException, EtalioHttpException {
        Version[] versions = getVersions();
        for (int i = 0; i < versions.length; i++) {
            if ("android".equals(versions[i].getPlatform())) {
                return versions[i];
            }
        }
        return null;
    }

    /**
     * Get list of granted of applications for the currently logged in User.
     * @return List of applications that the user granted access.
     * @throws IOException
     * @throws EtalioTokenException
     * @throws EtalioHttpException
     */
    public Application[] getMyGrantedApplications() throws IOException, EtalioTokenException, EtalioHttpException {
        return apiCall(MYAPPS, HttpRequest.HttpMethod.GET, null, Application[].class);
    }

    /**
     * Gets the list of operator promoted applications
     * @param operatorId the operator id
     * @return Array of operator promoted applications
     * @throws EtalioTokenException
     * @throws IOException
     * @throws EtalioHttpException
     */
    public Application[] getOperatorPromotedApplications(String operatorId)
            throws EtalioTokenException, IOException, EtalioHttpException {
        String requestIdentifier = String.format("operator-apps-%s", operatorId);
        String requestUrl = String.format("%s/applications?operator=%s",
                new Object[] { baseUrl, URLEncoder.encode(operatorId, "UTF8") });
        domainMap.put(requestIdentifier, requestUrl);
        return apiCall(requestIdentifier, HttpRequest.HttpMethod.GET, null, Application[].class);
    }

    /**
     * Gets the list of promoted applications
     * @return the applications
     * @throws EtalioTokenException
     * @throws IOException
     * @throws EtalioHttpException
     */
    public PromotedApplications getPromotedApplications()
            throws EtalioTokenException, IOException, EtalioHttpException {
        return apiCall(PROMOTED_APPS, HttpRequest.HttpMethod.GET, null, PromotedApplications.class);
    }

    /**
     * Get list of actions for the currently logged in User.
     * @return List of actions.
     * @throws IOException
     * @throws EtalioTokenException
     * @throws EtalioHttpException
     */
    public Action[] getMyActions() throws EtalioTokenException, IOException, EtalioHttpException {
        return apiCall(ACTIONS, HttpRequest.HttpMethod.GET, null, com.etalio.android.client.models.Action[].class);
    }

    /**
     * Claims a msisdn
     * @param msisdn the msisdn to claim
     * @param requestCode the request code to verify the number with. The request code is probably sent over SMS
     * @return
     * @throws EtalioTokenException
     * @throws IOException
     * @throws EtalioHttpException
     */
    public boolean requestClaimMsisdn(String msisdn, String requestCode)
            throws EtalioTokenException, IOException, EtalioHttpException {
        final String OK = "OK";
        MsisdnRequestClaim request = new MsisdnRequestClaim(msisdn, requestCode);
        Status s = apiCall(CLAIM_MSISDN, HttpRequest.HttpMethod.POST, request, Status.class);
        if (s != null) {
            return OK.equals(s.getStatus());
        }
        return false;
    }
}