package com.openfarmanager.android.googledrive.api;
import com.openfarmanager.android.googledrive.model.About;
import com.openfarmanager.android.googledrive.model.File;
import com.openfarmanager.android.googledrive.model.Token;
import com.openfarmanager.android.googledrive.model.exceptions.CreateFolderException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import static com.openfarmanager.android.googledrive.GoogleDriveConstants.LIST_URL;
import static com.openfarmanager.android.googledrive.GoogleDriveConstants.UPLOAD_URL;
import static com.openfarmanager.android.googledrive.api.Fields.FOLDER_MIME_TYPE;
import static com.openfarmanager.android.googledrive.api.Fields.ID;
import static com.openfarmanager.android.googledrive.api.Fields.MIME_TYPE;
import static com.openfarmanager.android.googledrive.api.Fields.PARENTS;
import static com.openfarmanager.android.googledrive.api.Fields.TITLE;
/**
* author: Vlad Namashko
*/
public class GoogleDriveWebApi extends Api {
private String setupQuery(String path) {
switch (path) {
case File.SHARED_FOLDER_ID:
return "sharedWithMe";
case File.STARRED_FOLDER_ID:
return "starred=true";
default:
return String.format("'%s'+in+parents+and+trashed=false", path);
}
}
public List<File> listFiles(String path) throws Exception {
if (path == null || path.trim().equals("") || path.equals("/")) {
path = "root";
}
List<File> files = new ArrayList<File>();
list(files, null, setupQuery(path));
return files;
}
public List<File> search(String title) throws Exception {
List<File> files = new ArrayList<File>();
list(files, null, String.format("title+contains+'%s'+and+trashed=false", title));
return files;
}
public String getDownloadLink(String link) {
return link + '&' + getAuth();
}
public InputStream download(String downloadLink) throws IOException {
URL url = new URL(downloadLink + '&' + getAuth());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int statusCode = connection.getResponseCode();
if (isTokenExpired(statusCode, connection.getResponseMessage())) {
setupToken(refreshToken(mToken));
download(downloadLink);
}
if (statusCode > 200) throw new RuntimeException();
return connection.getInputStream();
}
public void upload(String parentId, String title, java.io.File file, UploadListener listener) {
try {
JSONObject postData = new JSONObject();
setupFileNameData(title, parentId, postData);
MultipartUtility multipartUtility = new MultipartUtility(new URL(UPLOAD_URL + '?' + getAuth() + "&uploadType=multipart"));
try {
multipartUtility.addFormField("meta", postData.toString(), "application/json");
multipartUtility.addFilePart("content", file, listener);
int statusCode = multipartUtility.doRequest();
String message = multipartUtility.getResponseMessage();
if (isTokenExpired(statusCode, message)) {
setupToken(refreshToken(mToken));
upload(parentId, title, file, listener);
}
} finally {
multipartUtility.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean delete(String fileId) {
try {
HttpURLConnection connection = createConnection(new URL(LIST_URL + "/" + fileId + '?' + getAuth()));
connection.setRequestMethod(METHOD_DELETE);
int responseCode = connection.getResponseCode();
if (responseCode == 403) {
return delete(fileId);
}
return responseCode >= 200 && responseCode <= 204;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public File createDirectory(String title, String parentId) {
try {
HttpURLConnection connection = createConnection(new URL(LIST_URL + '?' + getAuth()));
connection.setRequestMethod(METHOD_POST);
JSONObject postData = new JSONObject();
postData.put(MIME_TYPE, FOLDER_MIME_TYPE);
setupFileNameData(title, parentId, postData);
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(postData.toString());
out.close();
int statusCode = connection.getResponseCode();
if (isTokenExpired(statusCode, connection.getResponseMessage())) {
setupToken(refreshToken(mToken));
return createDirectory(title, parentId);
}
if (statusCode == 201 || statusCode == 200) {
return new File(streamToString(connection.getInputStream()));
}
throw new CreateFolderException();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public boolean rename(String fileId, String newTitle) {
try {
JSONObject obj = new JSONObject();
obj.put(TITLE, newTitle);
return updateData(fileId, obj.toString());
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean updateData(String fileId, String data) {
try {
HttpURLConnection connection = createConnection(new URL(LIST_URL + "/" + fileId + '?' + getAuth()));
connection.setRequestMethod(METHOD_PUT);
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(data);
out.close();
int statusCode = connection.getResponseCode();
if (isTokenExpired(statusCode, connection.getResponseMessage())) {
setupToken(refreshToken(mToken));
return updateData(fileId, data);
}
return statusCode == 200;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private void list(List<File> files, String nextPageToken, String query) throws Exception {
String url = LIST_URL + '?' + getAuth() + "&maxResults=1000&q=" + query;
if (nextPageToken != null) {
url += "&pageToken=" + URLEncoder.encode(nextPageToken, "UTF-8");
}
URL urlConnection = new URL(url);
HttpURLConnection connection = (HttpURLConnection) urlConnection.openConnection();
int statusCode = connection.getResponseCode();
if (isTokenExpired(statusCode, connection.getResponseMessage())) {
setupToken(refreshToken(mToken));
list(files, nextPageToken, query);
return;
}
if (statusCode == 201 || statusCode == 200) {
String json = streamToString(connection.getInputStream());
JSONObject responseObject = new JSONObject(json);
JSONArray items = responseObject.getJSONArray("items");
for (int i = 0; i < items.length(); i++) {
JSONObject object = (JSONObject) items.get(i);
try {
files.add(new File(object));
} catch (Exception e) {
e.printStackTrace();
}
}
String pageToken = null;
try {
pageToken = responseObject.getString("nextPageToken");
} catch (Exception ignore) {
}
if (pageToken != null) {
list(files, pageToken, query);
}
}
}
public File getFile(String fileId) throws Exception {
HttpURLConnection connection = (HttpURLConnection) new URL(LIST_URL + "/" + fileId + "?" + getAuth()).openConnection();
connection.setRequestProperty("Cache-Control", "no-cache");
int responseCode = connection.getResponseCode();
if (isTokenExpired(responseCode, connection.getResponseMessage())) {
setupToken(refreshToken(mToken));
return getFile(fileId);
}
if (responseCode == 201 || responseCode == 200) {
return new File(streamToString(connection.getInputStream()));
}
return null;
}
private HttpURLConnection createConnection(URL url) throws IOException {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
connection.setRequestProperty("Cache-Control", "no-cache");
return connection;
}
private void setupFileNameData(String title, String parentId, JSONObject postData) throws JSONException {
postData.put(TITLE, title);
JSONArray parents = new JSONArray();
JSONObject parent = new JSONObject();
parent.put(ID, parentId);
postData.put(PARENTS, parents.put(parent));
}
public static interface UploadListener {
void onProgress(int uploaded, int transferedPortion, int total);
}
}