Java tutorial
/* RESTfulDConnectTestCase.java Copyright (c) 2014 NTT DOCOMO,INC. Released under the MIT license http://opensource.org/licenses/mit-license.php */ package org.deviceconnect.android.profile.restful.test; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.util.ArrayList; import java.util.List; import junit.framework.Assert; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.entity.mime.content.AbstractContentBody; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.deviceconnect.android.test.DConnectTestCase; import org.deviceconnect.message.DConnectMessage; import org.deviceconnect.profile.AuthorizationProfileConstants; import org.deviceconnect.profile.NetworkServiceDiscoveryProfileConstants; import org.deviceconnect.profile.SystemProfileConstants; import org.deviceconnect.utils.URIBuilder; import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; /** * RESTful API. * @author NTT DOCOMO, INC. */ public class RESTfulDConnectTestCase extends DConnectTestCase { /** ??. */ private static final int WAIT_FOR_EVENT = 10000; /** ?. */ private static final int BUF_SIZE = 8192; /** . */ private static final int RETRY_COUNT = 3; /** . */ private final Object mLockObj = new Object(); /** * . * @param tag */ public RESTfulDConnectTestCase(final String tag) { super(tag); } /** * ?API????. * * @param scopes * @return ????? */ private static String createScopeParameter(final String[] scopes) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < scopes.length; i++) { if (i > 0) { sb.append(","); } sb.append(scopes[i]); } return sb.toString(); } @Override protected String[] createClient(final String packageName) { URIBuilder builder = TestURIBuilder.createURIBuilder(); builder.setProfile(AuthorizationProfileConstants.PROFILE_NAME); builder.setAttribute(AuthorizationProfileConstants.ATTRIBUTE_CREATE_CLIENT); builder.addParameter(AuthorizationProfileConstants.PARAM_PACKAGE, packageName); try { HttpGet request = new HttpGet(builder.toString()); JSONObject root = sendRequest(request, false); assertResultOK(root); String clientId = root.getString(AuthorizationProfileConstants.PARAM_CLIENT_ID); String clientSecret = root.getString(AuthorizationProfileConstants.PARAM_CLIENT_SECRET); if (clientId != null && clientSecret != null) { return new String[] { clientId, clientSecret }; } } catch (JSONException e) { fail(); } return null; } @Override protected String requestAccessToken(final String clientId, final String clientSecret, final String[] scopes) { URIBuilder builder = TestURIBuilder.createURIBuilder(); builder.setProfile(AuthorizationProfileConstants.PROFILE_NAME); builder.setAttribute(AuthorizationProfileConstants.ATTRIBUTE_REQUEST_ACCESS_TOKEN); builder.addParameter(AuthorizationProfileConstants.PARAM_CLIENT_ID, clientId); builder.addParameter(AuthorizationProfileConstants.PARAM_GRANT_TYPE, "authorization_code"); builder.addParameter(AuthorizationProfileConstants.PARAM_SCOPE, createScopeParameter(scopes)); builder.addParameter(AuthorizationProfileConstants.PARAM_APPLICATION_NAME, "dConnectManagerTest"); builder.addParameter(AuthorizationProfileConstants.PARAM_SIGNATURE, createSignature(clientId, scopes, clientSecret)); try { HttpGet request = new HttpGet(builder.toString()); JSONObject root = sendRequestInternal(request, false); assertResultOK(root); return root.getString(AuthorizationProfileConstants.PARAM_ACCESS_TOKEN); } catch (JSONException e) { fail("Exception in JSONObject." + e.getMessage()); } return null; } /** * ?RestfulAPI???. * @return ? */ @Override protected List<DeviceInfo> searchDevices() { List<DeviceInfo> services = new ArrayList<DeviceInfo>(); HttpGet request = new HttpGet(DCONNECT_MANAGER_URI + "/network_service_discovery/getnetworkservices"); try { JSONObject root = sendRequest(request); assertResultOK(root); JSONArray servicesJson = root.getJSONArray(NetworkServiceDiscoveryProfileConstants.PARAM_SERVICES); for (int i = 0; i < servicesJson.length(); i++) { JSONObject serviceJson = servicesJson.getJSONObject(i); String deviceId = serviceJson.getString(NetworkServiceDiscoveryProfileConstants.PARAM_ID); String deviceName = serviceJson.getString(NetworkServiceDiscoveryProfileConstants.PARAM_NAME); services.add(new DeviceInfo(deviceId, deviceName)); } } catch (JSONException e) { fail("Exception in JSONObject." + e.getMessage()); } return services; } @Override protected List<PluginInfo> searchPlugins() { List<PluginInfo> plugins = new ArrayList<PluginInfo>(); URIBuilder builder = TestURIBuilder.createURIBuilder(); builder.setProfile(SystemProfileConstants.PROFILE_NAME); try { HttpUriRequest request = new HttpGet(builder.toString()); JSONObject response = sendRequest(request); assertResultOK(response); JSONArray pluginsJson = response.getJSONArray(SystemProfileConstants.PARAM_PLUGINS); for (int i = 0; i < pluginsJson.length(); i++) { JSONObject pluginJson = pluginsJson.getJSONObject(i); String id = pluginJson.getString(SystemProfileConstants.PARAM_ID); String name = pluginJson.getString(SystemProfileConstants.PARAM_NAME); plugins.add(new PluginInfo(id, name)); } } catch (JSONException e) { fail("Exception in JSONObject." + e.getMessage()); } return plugins; } /** * HTTP???. * @param uri ??URI * @return */ protected final byte[] getBytesFromHttp(final String uri) { HttpUriRequest request = new HttpGet(uri); HttpClient client = new DefaultHttpClient(); try { HttpResponse response = client.execute(request); switch (response.getStatusLine().getStatusCode()) { case HttpStatus.SC_OK: InputStream in = response.getEntity().getContent(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[BUF_SIZE]; int len; while ((len = in.read(buf)) > 0) { baos.write(buf, 0, len); } return baos.toByteArray(); case HttpStatus.SC_NOT_FOUND: Assert.fail("Not found page. 404: " + uri); break; default: Assert.fail("Connection Error. " + response.getStatusLine().getStatusCode()); break; } } catch (ClientProtocolException e) { Assert.fail("ClientProtocolException: " + e.getMessage()); } catch (IOException e) { Assert.fail("IOException: " + e.getMessage()); } return null; } /** * RESTful?dConnectManager??. * @param request Http * @return HttpResponse */ protected final HttpResponse requestHttpResponse(final HttpUriRequest request) { HttpClient client = new DefaultHttpClient(); try { return client.execute(request); } catch (ClientProtocolException e) { Assert.fail("ClientProtocolException: " + e.getMessage()); } catch (IOException e) { Assert.fail("IOException: " + e.getMessage()); } return null; } /** * RESTful?dConnectManager??. * @param request Http * @return ??intent */ protected final JSONObject sendRequest(final HttpUriRequest request) { return sendRequest(request, true); } /** * HTTP??. * @param request HTTP * @param requiredAuth ???????????? * @return ? */ protected final JSONObject sendRequest(final HttpUriRequest request, final boolean requiredAuth) { return sendRequest(request, requiredAuth, 0); } /** * HTTP??. * @param request HTTP * @param requiredAuth ???????????? * @param count ? * @return ? */ protected final JSONObject sendRequest(final HttpUriRequest request, final boolean requiredAuth, final int count) { try { JSONObject response = sendRequestInternal(request, requiredAuth); int result = response.getInt(DConnectMessage.EXTRA_RESULT); if (result == DConnectMessage.RESULT_ERROR && count <= RETRY_COUNT) { if (!response.has(DConnectMessage.EXTRA_ERROR_CODE)) { return response; } int errorCode = response.getInt(DConnectMessage.EXTRA_ERROR_CODE); if (errorCode == DConnectMessage.ErrorCode.EXPIRED_ACCESS_TOKEN.getCode()) { mAccessToken = requestAccessToken(mClientId, mClientSecret, PROFILES); assertNotNull(mAccessToken); storeOAuthInfo(mClientId, mClientSecret, mAccessToken); URI uri = request.getURI(); URIBuilder builder = new URIBuilder(uri); builder.addParameter(AuthorizationProfileConstants.PARAM_ACCESS_TOKEN, getAccessToken()); final HttpUriRequest newRequest; if (request instanceof HttpGet) { newRequest = new HttpGet(builder.toString()); } else if (request instanceof HttpPost) { HttpPost newPostRequest = new HttpPost(builder.toString()); newPostRequest.setEntity(((HttpPost) request).getEntity()); newRequest = newPostRequest; } else if (request instanceof HttpPut) { HttpPut newPostRequest = new HttpPut(builder.toString()); newPostRequest.setEntity(((HttpPost) request).getEntity()); newRequest = newPostRequest; } else if (request instanceof HttpDelete) { newRequest = new HttpDelete(builder.toString()); } else { fail("Invalid method is specified: " + request.getMethod()); return null; } return sendRequest(newRequest, requiredAuth, count + 1); } } return response; } catch (JSONException e) { Assert.fail("IOException: " + e.getMessage()); } return null; } /** * RESTful?dConnectManager??. * @param request Http * @param requiredAuth OAuth???????????????.true????? * @return ??intent */ protected final JSONObject sendRequestInternal(final HttpUriRequest request, final boolean requiredAuth) { try { HttpResponse response = requestHttpResponse(request); if (response == null) { return null; } switch (response.getStatusLine().getStatusCode()) { case HttpStatus.SC_OK: String msg = EntityUtils.toString(response.getEntity(), "UTF-8"); try { return new JSONObject(msg); } catch (JSONException e) { Assert.fail("JSON Format error: " + msg); } break; case HttpStatus.SC_NOT_FOUND: Assert.fail("Not found page. 404 "); break; default: Assert.fail("Connection Error. " + response.getStatusLine().getStatusCode() + " : " + response.getStatusLine().getReasonPhrase()); break; } } catch (IOException e) { Assert.fail("IOException: " + e.getMessage()); } return null; } /** * 1?. * ??????null?? * @return ??????? */ protected final JSONObject waitForEvent() { return waitForEvent(WAIT_FOR_EVENT); } /** * ?????. * ??????null?? * @param time ? * @return ??????? */ protected final JSONObject waitForEvent(long time) { StringBuilder sb = new StringBuilder(); sb.append("ws://localhost:4035/websocket"); final JSONObject[] response = new JSONObject[1]; URI uri = URI.create(sb.toString()); WebSocketClient client = new WebSocketClient(uri) { @Override public void onOpen(final ServerHandshake handshake) { try { JSONObject root = new JSONObject(); root.put(DConnectMessage.EXTRA_SESSION_KEY, getClientId()); send(root.toString()); } catch (JSONException e) { return; // do nothing. } } @Override public void onMessage(final String message) { try { response[0] = new JSONObject(message); } catch (JSONException e) { response[0] = null; } synchronized (mLockObj) { mLockObj.notify(); } } @Override public void onError(final Exception ex) { synchronized (mLockObj) { mLockObj.notify(); } } @Override public void onClose(final int code, final String reason, final boolean remote) { synchronized (mLockObj) { mLockObj.notify(); } } }; client.connect(); // ??? try { synchronized (mLockObj) { mLockObj.wait(time); } } catch (InterruptedException e) { return response[0]; } finally { // websocket????? if (client != null) { client.close(); } } return response[0]; } /** * result??{@link DConnectMessage#RESULT_OK}??????. * * @param response ? * @throws JSONException JSON?????? */ protected static void assertResultOK(final JSONObject response) throws JSONException { assertResult(DConnectMessage.RESULT_OK, response); } /** * result??{@link DConnectMessage#RESULT_ERROR}??????. * * @param response ? * @throws JSONException JSON?????? */ protected static void assertResultError(final JSONObject response) throws JSONException { assertResult(DConnectMessage.RESULT_ERROR, response); } /** * result??{@link DConnectMessage#RESULT_ERROR}??????. * * @param errorCode ? * @param response ? * @throws JSONException JSON?????? */ protected static void assertResultError(final int errorCode, final JSONObject response) throws JSONException { assertResult(DConnectMessage.RESULT_ERROR, response); assertErrorCode(errorCode, response); } /** * result??????????. * * @param expected ?result? * @param response ? * @throws JSONException JSON?????? */ protected static void assertResult(final int expected, final JSONObject response) throws JSONException { Assert.assertTrue(response.has(DConnectMessage.EXTRA_RESULT)); int actual = response.getInt(DConnectMessage.EXTRA_RESULT); if (expected != actual) { String message = "expected result=" + expected + " but actual result=" + actual + ". " + response.toString(); fail(message); } } /** * ??????????. * * @param expectedCode ? * @param actualResponse ?? * @throws JSONException JSON?????? */ private static void assertErrorCode(final int expectedCode, final JSONObject actualResponse) throws JSONException { if (!actualResponse.has(DConnectMessage.EXTRA_ERROR_CODE)) { fail("actualResponse is not a error response: " + actualResponse.toString()); } int actualCode = actualResponse.getInt(DConnectMessage.EXTRA_ERROR_CODE); if (expectedCode != actualCode) { String message = "expected=<" + expectedCode + "> but actual=<" + actualCode + ">: " + actualResponse.toString(); fail(message); } } /** * ??????. * @author NTT DOCOMO, INC. */ protected class BinaryBody extends AbstractContentBody { /** ??. */ private String mFileName; /** ???. */ private byte[] mBuffer; /** * . * @param buf ? * @param fileName ?? */ public BinaryBody(final byte[] buf, final String fileName) { super(fileName); mBuffer = buf; mFileName = fileName; } @Override public String getFilename() { return mFileName; } @Override public String getCharset() { return "UTF-8"; } @Override public long getContentLength() { return mBuffer.length; } @Override public String getTransferEncoding() { return "UTF-8"; } @Override public void writeTo(final OutputStream out) throws IOException { out.write(mBuffer); } } }