/*
* Artcodes recognises a different marker scheme that allows the
* creation of aesthetically pleasing, even beautiful, codes.
* Copyright (C) 2013-2016 The University of Nottingham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package uk.ac.horizon.artcodes.account;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import java.io.File;
import java.io.FileWriter;
import java.util.UUID;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import uk.ac.horizon.artcodes.Artcodes;
import uk.ac.horizon.artcodes.GoogleAnalytics;
import uk.ac.horizon.artcodes.model.Experience;
class AppEngineUploadThread extends Thread
{
private static final String rootHTTP = "http://aestheticodes.appspot.com/experience";
private static final String rootHTTPS = "https://aestheticodes.appspot.com/experience";
private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
private final Experience experience;
private final Account.AccountProcessCallback saveCallback;
private final AppEngineAccount account;
private boolean finished = false;
AppEngineUploadThread(AppEngineAccount account, Experience experience, Account.AccountProcessCallback saveCallback)
{
this.account = account;
this.experience = experience;
this.saveCallback = saveCallback;
}
@Override
public void run()
{
boolean success = true;
Experience saved = null;
try
{
final File tempFile = createTempFile(experience.getId());
saveTempExperience(tempFile, experience);
uploadImage(experience.getImage());
uploadImage(experience.getIcon());
saveTempExperience(tempFile, experience);
final Request.Builder builder = new Request.Builder();
if (experience.getId() != null && experience.getId().startsWith(rootHTTP))
{
builder.url(experience.getId().replace("http://", "https://"));
builder.put(RequestBody.create(MEDIA_TYPE_JSON, account.getGson().toJson(experience)));
}
else if (experience.getId() != null && experience.getId().startsWith(rootHTTPS))
{
builder.url(experience.getId());
builder.put(RequestBody.create(MEDIA_TYPE_JSON, account.getGson().toJson(experience)));
}
else if (experience.getId() != null && experience.getId().startsWith(AppEngineAccount.appSavePrefix))
{
// Remove temp id for upload
final String id = experience.getId();
experience.setId(null);
builder.url(rootHTTPS);
builder.post(RequestBody.create(MEDIA_TYPE_JSON, account.getGson().toJson(experience)));
experience.setId(id);
}
else
{
builder.url(rootHTTPS);
builder.post(RequestBody.create(MEDIA_TYPE_JSON, account.getGson().toJson(experience)));
}
builder.headers(account.getHeaders());
final Request request = builder.build();
final Response response = Artcodes.httpClient.newCall(request).execute();
account.validateResponse(request, response);
saved = account.getGson().fromJson(response.body().charStream(), Experience.class);
response.body().close();
account.getContext()
.getSharedPreferences(Account.class.getName(), Context.MODE_PRIVATE)
.edit()
.putString(saved.getId(), account.getId())
.apply();
if (!tempFile.delete())
{
Log.w("upload", "Temp file not deleted");
}
Intent intent = new Intent(experience.getId());
intent.putExtra("experience", account.getGson().toJson(saved));
LocalBroadcastManager.getInstance(account.getContext()).sendBroadcast(intent);
}
catch (Exception e)
{
GoogleAnalytics.trackException(e);
success = false;
}
finished = true;
if (this.saveCallback != null)
{
this.saveCallback.accountProcessCallback(success, saved);
}
}
public boolean isFinished()
{
return finished;
}
Experience getExperience()
{
return experience;
}
private void saveTempExperience(final File file, final Experience experience)
{
try
{
if (file != null && file.canWrite())
{
FileWriter writer = new FileWriter(file);
account.getGson().toJson(experience, writer);
writer.flush();
writer.close();
}
}
catch (Exception e)
{
GoogleAnalytics.trackException(e);
}
}
private File getDirectory()
{
return account.getContext().getDir("experiences", Context.MODE_PRIVATE);
}
private File createTempFile(final String uri)
{
if (uri != null)
{
if (uri.startsWith(rootHTTP) || uri.startsWith(rootHTTPS))
{
String id = Uri.parse(uri).getLastPathSegment();
return new File(getDirectory(), id);
}
else if (uri.startsWith(AppEngineAccount.appSavePrefix))
{
String id = uri.substring(AppEngineAccount.appSavePrefix.length());
return new File(getDirectory(), id);
}
}
return new File(getDirectory(), UUID.randomUUID().toString());
}
private boolean exists(String url) throws Exception
{
final Request request = new Request.Builder()
.url(url)
.head()
.build();
final Response response = Artcodes.httpClient.newCall(request).execute();
return response.code() == 200;
}
private void uploadImage(String imageURI)
{
if (imageURI != null && (imageURI.startsWith("file:") || imageURI.startsWith("content:")))
{
try
{
final RequestBodyUtil.ImageRequestBody imageBody = RequestBodyUtil.createImageBody(account.getContext(), imageURI);
final String hash = imageBody.getHash();
final String url = "https://aestheticodes.appspot.com/image/" + hash;
if (!exists(url))
{
Request request = new Request.Builder()
.url(url)
.put(imageBody)
.headers(account.getHeaders())
.build();
Response response = Artcodes.httpClient.newCall(request).execute();
account.validateResponse(request, response);
}
if (imageURI.equals(experience.getImage()))
{
experience.setImage(url);
}
if (imageURI.equals(experience.getIcon()))
{
experience.setIcon(url);
}
Log.i("upload", imageURI + " is now " + url);
}
catch (Exception e)
{
Log.w("", e.getMessage(), e);
}
}
}
}