package com.mediafire.sdk.config;
import com.mediafire.sdk.MFApiException;
import com.mediafire.sdk.MFException;
import com.mediafire.sdk.api.responses.ApiResponse;
import com.mediafire.sdk.api.responses.UserGetSessionTokenResponse;
import com.mediafire.sdk.requests.ApiPostRequest;
import com.mediafire.sdk.requests.HttpApiResponse;
import com.mediafire.sdk.requests.PostRequest;
import com.mediafire.sdk.token.SessionToken;
import com.mediafire.sdk.util.RequestUtil;
import com.mediafire.sdk.util.ResponseUtil;
import java.util.List;
import java.util.Map;
public class DefaultSessionRequester implements MFSessionRequester {
private static final int MIN_TOKENS = 2;
private static final int MAX_TOKENS = 6;
private MFCredentials credentials;
private final MFHttpRequester http;
private final MFStore<SessionToken> sessionStore;
private boolean sessionStarted;
private final Object sessionLock = new Object();
private final String apiKey;
private final String appId;
public DefaultSessionRequester(MFCredentials credentials, String appId, String apiKey, MFHttpRequester http, MFStore<SessionToken> sessionStore) {
this.credentials = credentials;
this.apiKey = apiKey;
this.appId = appId;
this.http = http;
this.sessionStore = sessionStore;
}
public DefaultSessionRequester(MFCredentials credentials, String appId, MFHttpRequester http, MFStore<SessionToken> sessionStore) {
this(credentials, appId, null, http, sessionStore);
}
@Override
public void startSessionWithEmail(String email, String password, List<OnStartSessionCallback> sessionCallbacks) throws MFApiException, MFException {
if (sessionStarted) {
if (sessionCallbacks != null) {
for (OnStartSessionCallback callback : sessionCallbacks) {
callback.onSessionStarted();
}
}
return;
}
synchronized (sessionLock) {
// create api request
ApiPostRequest apiPostRequest = ApiPostRequest.newSessionRequestWithEmail(apiKey, appId, email, password);
// make request using http to get a response
makeNewSessionRequest(apiPostRequest, sessionCallbacks);
}
}
@Override
public void startSessionWithEkey(String ekey, String password, List<OnStartSessionCallback> sessionCallbacks) throws MFApiException, MFException {
if (sessionStarted) {
if (sessionCallbacks != null) {
for (OnStartSessionCallback callback : sessionCallbacks) {
callback.onSessionStarted();
}
}
return;
}
synchronized (sessionLock) {
// create api request
ApiPostRequest apiPostRequest = ApiPostRequest.newSessionRequestWithEkey(apiKey, appId, ekey, password);
// make request using http to get a response
makeNewSessionRequest(apiPostRequest, sessionCallbacks);
}
}
@Override
public void startSessionWithFacebook(String facebookAccessToken, List<OnStartSessionCallback> sessionCallbacks) throws MFApiException, MFException {
if (sessionStarted) {
if (sessionCallbacks != null) {
for (OnStartSessionCallback callback : sessionCallbacks) {
callback.onSessionStarted();
}
}
return;
}
synchronized (sessionLock) {
// create api request
ApiPostRequest apiPostRequest = ApiPostRequest.newSessionRequestWithFacebook(apiKey, appId, facebookAccessToken);
// make request using http to get a response
makeNewSessionRequest(apiPostRequest, sessionCallbacks);
}
}
@Override
public void endSession() {
sessionStarted = false;
sessionStore.clear();
}
@Override
public void sessionStarted() {
sessionStarted = true;
credentials.setValid();
getNewTokens(MIN_TOKENS);
}
@Override
public <T extends ApiResponse> T doApiRequest(ApiPostRequest apiPostRequest, Class<T> classOfT) throws MFException, MFApiException {
if (!sessionStarted) {
throw new MFException("cannot call doApiRequest() if session has not been started");
}
SessionToken sessionToken = null;
if (apiPostRequest.requiresToken()) {
//borrow token if available
synchronized (sessionStore) {
if (!sessionStore.available()) {
if (sessionStore.getAvailableCount() < MIN_TOKENS) {
getNewTokens(MIN_TOKENS);
}
doNewSessionRequestWithCredentials();
}
sessionToken = sessionStore.get();
if (sessionToken == null) {
throw new MFException("could not get session token from store");
}
}
apiPostRequest.addSessionToken(sessionToken.getToken());
apiPostRequest.addSignature(RequestUtil.makeSignatureForApiRequest(sessionToken.getSecretKey(), sessionToken.getTime(), apiPostRequest));
}
PostRequest postRequest = new PostRequest(apiPostRequest);
HttpApiResponse httpResponse = http.doApiRequest(postRequest);
ResponseUtil.validateHttpResponse(httpResponse);
// return token
synchronized (sessionStore) {
if (sessionStore.getAvailableCount() < MAX_TOKENS) {
ApiResponse apiResponse = ResponseUtil.makeApiResponseFromHttpResponse(httpResponse, classOfT);
if (!apiResponse.hasError() && apiResponse.needNewKey() && sessionToken != null) {
SessionToken updatedSessionToken = SessionToken.updateSessionToken(sessionToken);
sessionStore.put(updatedSessionToken);
} else if (!apiResponse.hasError() && sessionToken != null) {
sessionStore.put(sessionToken);
}
}
}
return ResponseUtil.makeApiResponseFromHttpResponse(httpResponse, classOfT);
}
@Override
public boolean hasSession() {
return sessionStore.available();
}
@Override
public <T extends ApiResponse> T doApiRequestWithoutSession(ApiPostRequest apiPostRequest, Class<T> classOfT) throws MFException, MFApiException {
PostRequest postRequest = new PostRequest(apiPostRequest);
HttpApiResponse httpResponse = http.doApiRequest(postRequest);
ResponseUtil.validateHttpResponse(httpResponse);
return ResponseUtil.makeApiResponseFromHttpResponse(httpResponse, classOfT);
}
@Override
public void setCredentials(MFCredentials credentials) {
this.credentials = credentials;
}
private void doNewSessionRequestWithCredentials() throws MFException, MFApiException {
if (!credentials.isValid()) {
throw new MFException("cannot make requests if credentials are not valid");
}
Map<String, String> credentials = this.credentials.getCredentials();
if (credentials.containsKey("email")) {
String email = credentials.get("email");
String password = credentials.get("password");
ApiPostRequest apiPostRequest = ApiPostRequest.newSessionRequestWithEmail(apiKey, appId, email, password);
makeNewSessionRequest(apiPostRequest, null);
} else if (credentials.containsKey("ekey")) {
String ekey = credentials.get("ekey");
String password = credentials.get("password");
ApiPostRequest apiPostRequest = ApiPostRequest.newSessionRequestWithEkey(apiKey, appId, ekey, password);
makeNewSessionRequest(apiPostRequest, null);
} else if (credentials.containsKey("fb_access_token")) {
String facebook = credentials.get("fb_access_token");
ApiPostRequest apiPostRequest = ApiPostRequest.newSessionRequestWithFacebook(apiKey, appId, facebook);
makeNewSessionRequest(apiPostRequest, null);
} else {
this.credentials.invalidate();
throw new MFException("invalid credentials stored");
}
}
private <T extends ApiResponse> T doNewSessionRequest(ApiPostRequest apiPostRequest, Class<T> classOfT) throws MFException, MFApiException {
PostRequest postRequest = new PostRequest(apiPostRequest);
HttpApiResponse httpResponse = http.doApiRequest(postRequest);
ResponseUtil.validateHttpResponse(httpResponse);
return ResponseUtil.makeApiResponseFromHttpResponse(httpResponse, classOfT);
}
private void makeNewSessionRequest(ApiPostRequest apiPostRequest, List<OnStartSessionCallback> sessionCallbacks) throws MFApiException {
try {
UserGetSessionTokenResponse apiResponse = doNewSessionRequest(apiPostRequest, UserGetSessionTokenResponse.class);
// handle the api response by notifying callback and (if successful) set session to started
handleApiResponse(apiResponse, sessionCallbacks);
} catch (MFException e) {
if (sessionCallbacks == null) {
return;
}
for (OnStartSessionCallback sessionCallback : sessionCallbacks) {
sessionCallback.onSessionFailed(-1, e.getMessage());
}
}
}
private void handleApiResponse(UserGetSessionTokenResponse apiResponse, List<OnStartSessionCallback> sessionCallbacks) throws MFApiException {
// throw ApiException if request has api error
if (apiResponse.hasError()) {
if (sessionCallbacks == null) {
throw new MFApiException(apiResponse.getError(), apiResponse.getMessage());
}
for (OnStartSessionCallback sessionCallback : sessionCallbacks) {
sessionCallback.onSessionFailed(apiResponse.getError(), apiResponse.getMessage());
}
throw new MFApiException(apiResponse.getError(), apiResponse.getMessage());
}
// set session to started state
sessionStarted = true;
// store token
SessionToken sessionToken = SessionToken.makeSessionTokenFromApiResponse(apiResponse);
sessionStore.put(sessionToken);
// notify callback session started successfully
if (sessionCallbacks == null) {
return;
}
for (OnStartSessionCallback sessionCallback : sessionCallbacks) {
sessionCallback.onSessionStarted();
}
}
private void getNewTokens(int numberOfNewTokensToGet) {
for (int i = 0; i < numberOfNewTokensToGet; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
doNewSessionRequestWithCredentials();
} catch (MFException e) {
e.printStackTrace();
} catch (MFApiException e) {
e.printStackTrace();
}
}
});
thread.start();
}
}
}