org.deviceconnect.message.intent.util.IntentAuthProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.deviceconnect.message.intent.util.IntentAuthProcessor.java

Source

/*
 IntentAuthProcessor.java
 Copyright (c) 2014 NTT DOCOMO,INC.
 Released under the MIT license
 http://opensource.org/licenses/mit-license.php
 */
package org.deviceconnect.message.intent.util;

import java.io.IOException;
import java.net.URISyntaxException;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.deviceconnect.android.cipher.signature.AuthSignature;
import org.deviceconnect.message.DConnectMessage;
import org.deviceconnect.message.HttpHeaders;
import org.deviceconnect.message.DConnectMessage.ErrorCode;
import org.deviceconnect.message.intent.impl.client.DefaultIntentClient;
import org.deviceconnect.message.intent.params.IntentConnectionParams;
import org.deviceconnect.profile.AuthorizationProfileConstants;
import org.deviceconnect.utils.URIBuilder;
import org.deviceconnect.utils.AuthProcesser.AuthorizationHandler;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.ComponentName;
import android.content.Context;

/**
 * LocalOAuth???. Intent????
 * 
 * <h3></h3>
 * <h4>??????</h4>
 * <pre>
 * {@code
 * IntentAuthProcessor.asyncAuthorize(this, 
 *              ComponentName.unflattenFromString("org.deviceconnect.manager/.DConnectBroadcastReceiver"), 
 *              getPackageName(), 
 *              "Auth Example App", 
 *              new String[] {"battery", "system", "network_service_discovery"}, 
 *              new AuthorizationHandler() {
 *          
 *          public void onAuthorized(String clientId, String clientSecret, String accessToken) {
 *              // ???
 *          }
 *          
 *          public void onAuthFailed(ErrorCode error) {
 *              // ???
 *          }
 *      });
 * }
 * </pre>
 * 
 * @author NTT DOCOMO, INC.
 */
public final class IntentAuthProcessor {

    /**
     * ???private.
     */
    private IntentAuthProcessor() {
    }

    /**
     * ????. Device Connect Manager???????????
     * Device Connect Manager??Intent??<br/>
     * ??????<br/>
     * ??? AndroidManifest.xml??
     * {@link org.deviceconnect.message.intent.impl.io.IntentResponseReceiver}
     * ?????
     * 
     * @param context 
     * @param dConnectComponent Device Connect Manager????
     * @param packageName Authorization Create Client API?package?
     * @param appName Authorization Create Access Token
     *            API?applicationName?
     * @param scopes Authorization Create Access Token API?scope?
     * @param callback ??????
     */
    public static void asyncAuthorize(final Context context, final ComponentName dConnectComponent,
            final String packageName, final String appName, final String[] scopes,
            final AuthorizationHandler callback) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                authorize(context, dConnectComponent, packageName, appName, scopes, callback);
            }
        }).start();

    }

    /**
     * ????. Device Connect Manager???????????
     * Device Connect Manager??Intent??<br/>
     * ?????Intent????????UI?????<strong>????</strong><br/>
     * ??? AndroidManifest.xml??
     * {@link org.deviceconnect.message.intent.impl.io.IntentResponseReceiver}
     * ?????
     * 
     * @param context 
     * @param componentName Device Connect Manager????
     * @param packageName Authorization Create Client API?package?
     * @param appName Authorization Create Access Token
     *            API?applicationName?
     * @param scopes Authorization Create Access Token API?scope?
     * @param callback ??????
     */
    public static void authorize(final Context context, final ComponentName componentName, final String packageName,
            final String appName, final String[] scopes, final AuthorizationHandler callback) {

        if (callback == null) {
            throw new IllegalArgumentException("Callback is null.");
        } else if (scopes == null || scopes.length == 0) {
            throw new IllegalArgumentException("No scopes.");
        } else if (componentName == null) {
            throw new IllegalArgumentException("componentName is null.");
        } else if (packageName == null) {
            throw new IllegalArgumentException("Package name is null.");
        } else if (appName == null) {
            throw new IllegalArgumentException("App name is null.");
        }

        if (Thread.currentThread().equals(context.getMainLooper().getThread())) {
            throw new IllegalStateException("DON'T CALL this method in UI thread.");
        }

        URIBuilder builder = new URIBuilder();
        // ??ComponentName?????????????????????
        builder.setHost("localhost");
        builder.setPort(0);
        builder.setScheme("http");

        builder.setProfile(AuthorizationProfileConstants.PROFILE_NAME);
        builder.setAttribute(AuthorizationProfileConstants.ATTRIBUTE_CREATE_CLIENT);
        builder.addParameter(AuthorizationProfileConstants.PARAM_PACKAGE, packageName);

        HttpUriRequest request = null;
        try {
            request = new HttpGet(builder.build());
        } catch (URISyntaxException e1) {
            throw new IllegalArgumentException("Invalid Param. Check parameters.");
        }
        // DefaultIntentClient?????Host?????????????????
        request.setHeader(HttpHeaders.HOST, componentName.flattenToShortString());

        ErrorCode error = null;
        HttpParams params = new BasicHttpParams();
        IntentConnectionParams.setContext(params, context);
        IntentConnectionParams.setComponent(params, componentName);
        DefaultIntentClient client = new DefaultIntentClient(params);

        do {
            try {
                JSONObject json = execute(client, request);
                error = checkResponse(json);
                if (error != null) {
                    break;
                }

                String clientId = json.getString(AuthorizationProfileConstants.PARAM_CLIENT_ID);
                String clientSecret = json.getString(AuthorizationProfileConstants.PARAM_CLIENT_SECRET);
                String signature = AuthSignature.generateSignature(clientId,
                        AuthorizationProfileConstants.GrantType.AUTHORIZATION_CODE.getValue(), null, scopes,
                        clientSecret);
                // ???
                builder.setAttribute(AuthorizationProfileConstants.ATTRIBUTE_REQUEST_ACCESS_TOKEN);
                builder.addParameter(AuthorizationProfileConstants.PARAM_CLIENT_ID, clientId);
                builder.addParameter(AuthorizationProfileConstants.PARAM_SCOPE, combineStr(scopes));
                builder.addParameter(AuthorizationProfileConstants.PARAM_GRANT_TYPE,
                        AuthorizationProfileConstants.GrantType.AUTHORIZATION_CODE.getValue());
                builder.addParameter(AuthorizationProfileConstants.PARAM_SIGNATURE, signature);
                builder.addParameter(AuthorizationProfileConstants.PARAM_APPLICATION_NAME, appName);
                try {
                    request = new HttpGet(builder.build());
                } catch (URISyntaxException e1) {
                    error = ErrorCode.UNKNOWN;
                    break;
                }

                // client??????????
                client.getConnectionManager().shutdown();
                client = new DefaultIntentClient(params);
                json = execute(client, request);
                error = checkResponse(json);
                if (error != null) {
                    break;
                }
                String accessToken = json.getString(AuthorizationProfileConstants.PARAM_ACCESS_TOKEN);
                callback.onAuthorized(clientId, clientSecret, accessToken);
            } catch (Exception e) {
                error = ErrorCode.UNKNOWN;
                e.printStackTrace();
                break;
            }
        } while (false);

        client.getConnectionManager().shutdown();

        if (error != null) {
            callback.onAuthFailed(error);
        }

    }

    /**
     * ????JSON?.
     * 
     * @param client 
     * @param request 
     * @return ????null?
     * @throws IOException ???????
     */
    private static JSONObject execute(final HttpClient client, final HttpUriRequest request) throws IOException {

        HttpResponse response = client.execute(request);
        String entity = EntityUtils.toString(response.getEntity(), "UTF-8");
        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
            return null;
        }

        JSONObject json;
        try {
            json = new JSONObject(entity);
        } catch (JSONException e) {
            json = null;
        }
        return json;
    }

    /**
     * JSON???????.
     * 
     * @param json ??JSON
     * @return ???ErrorCode?????null?
     * @throws JSONException json????????
     */
    private static ErrorCode checkResponse(final JSONObject json) throws JSONException {

        if (json == null) {
            return ErrorCode.UNKNOWN;
        }

        int result = json.getInt(DConnectMessage.EXTRA_RESULT);
        if (result != DConnectMessage.RESULT_OK) {
            int errorCode = json.getInt(DConnectMessage.EXTRA_ERROR_CODE);
            return ErrorCode.getInstance(errorCode);
        }

        return null;

    }

    /**
     * ?????.
     * 
     * @param scopes 
     * @return ???
     */
    private static String combineStr(final String[] scopes) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < scopes.length; i++) {
            if (i > 0) {
                builder.append(",");
            }
            builder.append(scopes[i].trim());
        }
        return builder.toString();
    }

}