/*
* Copyright (C) 2015 yvolk (Yuri Volkov), http://yurivolkov.com
*
* 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 org.andstatus.app.net.http;
import android.net.Uri;
import android.text.TextUtils;
import org.andstatus.app.account.AccountDataWriter;
import org.andstatus.app.net.http.ConnectionException.StatusCode;
import org.andstatus.app.util.MyLog;
import org.andstatus.app.util.TriState;
import org.andstatus.app.util.UrlUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
public abstract class HttpConnection {
public HttpConnectionData data;
public static final String USER_AGENT = "AndStatus";
public static final String KEY_MEDIA_PART_NAME = "media_part_name";
public static final String KEY_MEDIA_PART_URI = "media_part_uri";
/**
* The URI is consistent with "scheme" and "host" in AndroidManifest
* Pump.io doesn't work with this scheme: "andstatus-oauth://andstatus.org"
*/
public static final Uri CALLBACK_URI = Uri.parse("http://oauth-redirect.andstatus.org");
public void registerClient(String path) throws ConnectionException {
// Do nothing in default in the Base implementation
}
public void setConnectionData(HttpConnectionData data) {
this.data = data;
}
public String pathToUrlString(String path) throws ConnectionException {
return UrlUtils.pathToUrlString(data.originUrl, path, errorOnInvalidUrls());
}
public boolean errorOnInvalidUrls() {
return true;
}
public final JSONObject postRequest(String path) throws ConnectionException {
return postRequest(path, null);
}
public final JSONObject postRequest(String path, JSONObject formParams) throws ConnectionException {
/* See https://github.com/andstatus/andstatus/issues/249 */
if (data.getUseLegacyHttpProtocol() == TriState.UNKNOWN) {
try {
return postRequestOneHttpProtocol(path, formParams, false);
} catch (ConnectionException e) {
if (e.getStatusCode() != StatusCode.LENGTH_REQUIRED) {
throw e;
}
MyLog.v(this, "Automatic fallback to legacy HTTP", e);
}
}
return postRequestOneHttpProtocol(path, formParams, data.getUseLegacyHttpProtocol().toBoolean(true));
}
private JSONObject postRequestOneHttpProtocol(String path, JSONObject formParams,
boolean isLegacyHttpProtocol ) throws ConnectionException {
if (TextUtils.isEmpty(path)) {
throw new IllegalArgumentException("path is empty");
}
HttpReadResult result = new HttpReadResult(pathToUrlString(path)).setFormParams(formParams)
.setLegacyHttpProtocol(isLegacyHttpProtocol);
if( result.hasFormParams()) {
MyLog.logNetworkLevelMessage("post_form", data.getLogName(), result.getFormParams());
}
postRequest(result);
MyLog.logNetworkLevelMessage("post_response", data.getLogName(), result.strResponse);
result.parseAndThrow();
return result.getJsonObject();
}
protected abstract void postRequest(HttpReadResult result) throws ConnectionException;
public final JSONObject getRequest(String path) throws ConnectionException {
return getRequestCommon(path, true).getJsonObject();
}
public final JSONObject getUnauthenticatedRequest(String path) throws ConnectionException {
return getRequestCommon(path, false).getJsonObject();
}
private HttpReadResult getRequestCommon(String path, boolean authenticated) throws ConnectionException {
if (TextUtils.isEmpty(path)) {
throw new IllegalArgumentException("path is empty");
}
HttpReadResult result = new HttpReadResult(pathToUrlString(path));
result.authenticate = authenticated;
getRequest(result);
MyLog.logNetworkLevelMessage("get_response", data.getLogName(), result.strResponse);
result.parseAndThrow();
return result;
}
public final JSONArray getRequestAsArray(String path) throws ConnectionException {
return getRequestCommon(path, true).getJsonArray();
}
public final void downloadFile(String url, File file) throws ConnectionException {
HttpReadResult result = new HttpReadResult(url, file);
getRequest(result);
result.parseAndThrow();
}
protected abstract void getRequest(HttpReadResult result) throws ConnectionException;
public abstract void clearAuthInformation();
public void clearClientKeys() {
if (data.areOAuthClientKeysPresent()) {
data.oauthClientKeys.clear();
}
}
public boolean isPasswordNeeded() {
return false;
}
public void setPassword(String password) {
// Nothing to do
}
/** return not null **/
public String getPassword() {
return "";
}
/**
* Persist the connection data
* @return true if something changed (so it needs to be rewritten to persistence...)
*/
public boolean save(AccountDataWriter dw) {
return false;
}
/** @return true if changed */
public boolean save(JSONObject jso) throws JSONException {
return false;
}
/**
* Do we have enough credentials to verify them?
* @return true == yes
*/
public abstract boolean getCredentialsPresent();
public SslModeEnum getSslMode() {
return data.getSslMode();
}
public void setUserTokenWithSecret(String token, String secret) {
throw new IllegalArgumentException("setUserTokenWithSecret is for OAuth only!");
}
String getUserToken() {
return "";
}
String getUserSecret() {
return "";
}
public HttpConnection getNewInstance() {
try {
return getClass().newInstance();
} catch (InstantiationException e) {
MyLog.e(this, e);
} catch (IllegalAccessException e) {
MyLog.e(this, e);
}
return null;
}
}