Java tutorial
/* * Copyright (c) 2016 Samsung Electronics America * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.samsung.msca.samsungvr.sdk; import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; import java.nio.charset.StandardCharsets; import java.util.List; class APIClientImpl extends Container.BaseImpl implements APIClient { private final Context mContext; private final String mEndPoint, mApiKey; private final Handler mMainHandler; private final HttpPlugin.RequestFactory mHttpRequestFactory; private final AsyncWorkQueue.AsyncWorkItemFactory mWorkItemFactory = new AsyncWorkQueue.AsyncWorkItemFactory<ClientWorkItemType, ClientWorkItem<?>>() { @Override public ClientWorkItem newWorkItem(ClientWorkItemType type) { return type.newInstance(APIClientImpl.this); } }; private static final int MUL = 1024; private final AsyncWorkQueue<ClientWorkItemType, ClientWorkItem<?>> mAsyncWorkQueue = new AsyncWorkQueue( mWorkItemFactory, 8 * MUL); private final AsyncWorkQueue<ClientWorkItemType, ClientWorkItem<?>> mAsyncUploadQueue = new AsyncWorkQueue( mWorkItemFactory, 1024 * MUL); static final String HEADER_API_KEY = "X-API-KEY"; APIClientImpl(Context context, String endPoint, String apiKey, HttpPlugin.RequestFactory httpRequestFactory) { super(true); mContext = context; mEndPoint = endPoint; mApiKey = apiKey; mHttpRequestFactory = httpRequestFactory; mMainHandler = new Handler(Looper.getMainLooper()); if (DEBUG) { Log.d(TAG, "Created api client endpoint: " + mEndPoint + " apiKey: " + mApiKey + " obj: " + Util.getHashCode(this)); } } HttpPlugin.RequestFactory getRequestFactory() { return mHttpRequestFactory; } @Override public void destroy() { mAsyncWorkQueue.quit(); mAsyncUploadQueue.quit(); if (DEBUG) { Log.d(TAG, "Destroyed api client endpoint: " + mEndPoint + " apiKey: " + mApiKey + " obj: " + Util.getHashCode(this)); } } @Override public String getEndPoint() { return mEndPoint; } @Override public String getApiKey() { return mApiKey; } @Override public Context getContext() { return mContext; } @Override public Handler getMainHandler() { return mMainHandler; } @Override public AsyncWorkQueue<ClientWorkItemType, ClientWorkItem<?>> getAsyncWorkQueue() { return mAsyncWorkQueue; } @Override public AsyncWorkQueue<ClientWorkItemType, ClientWorkItem<?>> getAsyncUploadQueue() { return mAsyncUploadQueue; } @Override public boolean login(String email, String password, VR.Result.Login callback, Handler handler, Object closure) { WorkItemPerformLogin workItem = mAsyncWorkQueue.obtainWorkItem(WorkItemPerformLogin.TYPE); workItem.set(email, password, callback, handler, closure); return mAsyncWorkQueue.enqueue(workItem); } private static final boolean DEBUG = Util.DEBUG; private static final String TAG = Util.getLogTag(APIClientImpl.class); @Override public User getUserById(String userId) { return getContainedByIdLocked(UserImpl.sType, userId); } @Override public boolean getUserBySessionId(String sessionId, VR.Result.GetUserBySessionId callback, Handler handler, Object closure) { WorkItemGetUserBySessionId workItem = mAsyncWorkQueue.obtainWorkItem(WorkItemGetUserBySessionId.TYPE); workItem.set(sessionId, callback, handler, closure); return mAsyncWorkQueue.enqueue(workItem); } @Override public boolean getUserBySessionToken(String sessionToken, VR.Result.GetUserBySessionToken callback, Handler handler, Object closure) { WorkItemGetUserBySessionToken workItem = mAsyncWorkQueue.obtainWorkItem(WorkItemGetUserBySessionToken.TYPE); workItem.set(sessionToken, callback, handler, closure); return mAsyncWorkQueue.enqueue(workItem); } @Override public <CONTAINED extends Contained.Spec> List<CONTAINED> containerOnQueryListOfContainedFromServiceLocked( Contained.Type type, JSONObject jsonObject) { return null; } @Override public <CONTAINED extends Contained.Spec> boolean containerOnQueryOfContainedFromServiceLocked( Contained.Type type, CONTAINED contained, JSONObject jsonObject) { return false; } @Override public <CONTAINED extends Contained.Spec> CONTAINED containerOnCreateOfContainedInServiceLocked( Contained.Type type, JSONObject jsonObject) { CONTAINED result = processCreateOfContainedInServiceLocked(UserImpl.sType, jsonObject, true); if (DEBUG) { Log.d(TAG, "Add contained: " + result); } return result; } @Override public <CONTAINED extends Contained.Spec> CONTAINED containerOnUpdateOfContainedToServiceLocked( Contained.Type type, CONTAINED contained) { return null; } @Override public <CONTAINED extends Contained.Spec> CONTAINED containerOnDeleteOfContainedFromServiceLocked( Contained.Type type, CONTAINED contained) { return null; } static class WorkItemGetUserBySessionId extends ClientWorkItem<VR.Result.GetUserBySessionId> { static final ClientWorkItemType TYPE = new ClientWorkItemType() { @Override public WorkItemGetUserBySessionId newInstance(APIClientImpl apiClient) { return new WorkItemGetUserBySessionId(apiClient); } }; WorkItemGetUserBySessionId(APIClientImpl apiClient) { super(apiClient, TYPE); } private String mSessionId; synchronized WorkItemGetUserBySessionId set(String sessionId, VR.Result.GetUserBySessionId callback, Handler handler, Object closure) { super.set(callback, handler, closure); mSessionId = sessionId; return this; } @Override protected synchronized void recycle() { super.recycle(); mSessionId = null; } private static final String TAG = Util.getLogTag(WorkItemGetUserBySessionId.class); @Override public void onRun() throws Exception { HttpPlugin.GetRequest request = null; String cookies[][] = { { "session_id", mSessionId } }; String headers[][] = { { HEADER_COOKIE, toCookieString(cookies) }, { HEADER_API_KEY, mAPIClient.getApiKey() } }; try { request = newGetRequest("user/authenticate", headers); if (null == request) { dispatchFailure(VR.Result.STATUS_HTTP_PLUGIN_NULL_CONNECTION); return; } if (isCancelled()) { dispatchCancelled(); return; } int rsp = getResponseCode(request); String data = readHttpStream(request, "code: " + rsp); if (null == data) { dispatchFailure(VR.Result.STATUS_HTTP_PLUGIN_STREAM_READ_FAILURE); return; } JSONObject jsonObject = new JSONObject(data); if (isHTTPSuccess(rsp)) { User user = mAPIClient.containerOnCreateOfContainedInServiceLocked(UserImpl.sType, jsonObject); if (null != user) { dispatchSuccessWithResult(user); } else { dispatchFailure(VR.Result.STATUS_SERVER_RESPONSE_INVALID); } return; } int status = jsonObject.optInt("status", VR.Result.STATUS_SERVER_RESPONSE_NO_STATUS_CODE); dispatchFailure(status); } finally { destroy(request); } } } static class WorkItemGetUserBySessionToken extends ClientWorkItem<VR.Result.GetUserBySessionToken> { static final ClientWorkItemType TYPE = new ClientWorkItemType() { @Override public WorkItemGetUserBySessionToken newInstance(APIClientImpl apiClient) { return new WorkItemGetUserBySessionToken(apiClient); } }; WorkItemGetUserBySessionToken(APIClientImpl apiClient) { super(apiClient, TYPE); } private String mSessionToken; synchronized WorkItemGetUserBySessionToken set(String sessionToken, VR.Result.GetUserBySessionToken callback, Handler handler, Object closure) { super.set(callback, handler, closure); mSessionToken = sessionToken; return this; } @Override protected synchronized void recycle() { super.recycle(); mSessionToken = null; } private static final String TAG = Util.getLogTag(WorkItemGetUserBySessionToken.class); @Override public void onRun() { HttpPlugin.BaseRequest request = null; try { if (isCancelled()) { dispatchCancelled(); return; } dispatchFailure(VR.Result.STATUS_FEATURE_NOT_SUPPORTED); } finally { destroy(request); } } } static class WorkItemPerformLogin extends ClientWorkItem<VR.Result.Login> { static final ClientWorkItemType TYPE = new ClientWorkItemType() { @Override public WorkItemPerformLogin newInstance(APIClientImpl apiClient) { return new WorkItemPerformLogin(apiClient); } }; WorkItemPerformLogin(APIClientImpl apiClient) { super(apiClient, TYPE); } private String mEmail, mPassword; synchronized WorkItemPerformLogin set(String email, String password, VR.Result.Login callback, Handler handler, Object closure) { super.set(callback, handler, closure); mEmail = email; mPassword = password; return this; } @Override protected synchronized void recycle() { super.recycle(); mEmail = null; mPassword = null; } private static final String TAG = Util.getLogTag(WorkItemPerformLogin.class); @Override public void onRun() throws Exception { HttpPlugin.PostRequest request = null; try { JSONObject jsonParam = new JSONObject(); jsonParam.put("email", mEmail); jsonParam.put("password", mPassword); String jsonStr = jsonParam.toString(); byte[] data = jsonStr.getBytes(StandardCharsets.UTF_8); String headers[][] = { { HEADER_CONTENT_LENGTH, String.valueOf(data.length) }, { HEADER_CONTENT_TYPE, "application/json" + ClientWorkItem.CONTENT_TYPE_CHARSET_SUFFIX_UTF8 }, { HEADER_API_KEY, mAPIClient.getApiKey() } }; request = newPostRequest("user/authenticate", headers); if (null == request) { dispatchFailure(VR.Result.STATUS_HTTP_PLUGIN_NULL_CONNECTION); return; } writeBytes(request, data, jsonStr); if (isCancelled()) { dispatchCancelled(); return; } int rsp = getResponseCode(request); String data2 = readHttpStream(request, "code: " + rsp); if (null == data2) { dispatchFailure(VR.Result.STATUS_HTTP_PLUGIN_STREAM_READ_FAILURE); return; } JSONObject jsonObject = new JSONObject(data2); if (isHTTPSuccess(rsp)) { User user = mAPIClient.containerOnCreateOfContainedInServiceLocked(UserImpl.sType, jsonObject); if (null != user) { dispatchSuccessWithResult(user); } else { dispatchFailure(VR.Result.STATUS_SERVER_RESPONSE_INVALID); } return; } int status = jsonObject.optInt("status", VR.Result.STATUS_SERVER_RESPONSE_NO_STATUS_CODE); dispatchFailure(status); } finally { destroy(request); } } } }