package org.kvj.lima1.gae.sync.data;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreInputStream;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Transaction;
public class FileStorage {
private static Logger log = LoggerFactory.getLogger(FileStorage.class);
public static String upload(String app, String user, BlobKey file,
String name) {
DatastoreService datastore = DatastoreServiceFactory
.getDatastoreService();
Transaction txn = datastore.beginTransaction();
try {
JSONObject schema = SchemaStorage.getInstance().getSchema(app);
if (null == schema) {
throw new Exception("Schema not found");
}
Query existing = new Query("User").addFilter("username",
FilterOperator.EQUAL, user);
Entity userEntity = datastore.prepare(existing).asSingleEntity();
if (null == userEntity) {
return "User not found";
}
Entity fileEntity = new Entity("File", userEntity.getKey());
fileEntity.setProperty("app", app);
fileEntity.setProperty("user", userEntity.getKey());
fileEntity.setProperty("file", file);
fileEntity.setProperty("created", new Date().getTime());
fileEntity.setProperty("name", name);
datastore.put(txn, fileEntity);
txn.commit();
return null;
} catch (Exception e) {
log.error("Save error", e);
return "Database error";
} finally {
if (txn.isActive()) {
txn.rollback();
}
}
}
public static BlobKey getFile(String app, String user, String name) {
DatastoreService datastore = DatastoreServiceFactory
.getDatastoreService();
try {
JSONObject schema = SchemaStorage.getInstance().getSchema(app);
if (null == schema) {
throw new Exception("Schema not found");
}
Query existing = new Query("User").addFilter("username",
FilterOperator.EQUAL, user);
Entity userEntity = datastore.prepare(existing).asSingleEntity();
if (null == userEntity) {
throw new Exception("User not found");
}
Query file = new Query("File")
.addFilter("user", FilterOperator.EQUAL,
userEntity.getKey())
.addFilter("app", FilterOperator.EQUAL, app)
.addFilter("name", FilterOperator.EQUAL, name);
Entity fileEntity = datastore.prepare(file).asSingleEntity();
if (null == fileEntity) {
throw new Exception("File not found");
}
return (BlobKey) fileEntity.getProperty("file");
} catch (Exception e) {
log.error("Download error", e);
return null;
}
}
public static String removeFile(String app, String user, String name) {
DatastoreService datastore = DatastoreServiceFactory
.getDatastoreService();
Transaction txn = datastore.beginTransaction();
try {
JSONObject schema = SchemaStorage.getInstance().getSchema(app);
if (null == schema) {
throw new Exception("Schema not found");
}
Query existing = new Query("User").addFilter("username",
FilterOperator.EQUAL, user);
Entity userEntity = datastore.prepare(existing).asSingleEntity();
if (null == userEntity) {
return "User not found";
}
Query file = new Query("File")
.addFilter("user", FilterOperator.EQUAL,
userEntity.getKey())
.addFilter("app", FilterOperator.EQUAL, app)
.addFilter("name", FilterOperator.EQUAL, name);
Entity fileEntity = datastore.prepare(file).asSingleEntity();
if (null == fileEntity) {
return null;
}
BlobstoreService blobstoreService = BlobstoreServiceFactory
.getBlobstoreService();
blobstoreService.delete((BlobKey) fileEntity.getProperty("file"));
datastore.delete(txn, fileEntity.getKey());
txn.commit();
return null;
} catch (Exception e) {
log.error("Save error", e);
return "Database error";
} finally {
if (txn.isActive()) {
txn.rollback();
}
}
}
public static int backupFiles(String app, String user, long from,
ZipOutputStream zip) {
DatastoreService datastore = DatastoreServiceFactory
.getDatastoreService();
try {
JSONObject schema = SchemaStorage.getInstance().getSchema(app);
if (null == schema) {
throw new Exception("Schema not found");
}
Query existing = new Query("User").addFilter("username",
FilterOperator.EQUAL, user);
Entity userEntity = datastore.prepare(existing).asSingleEntity();
if (null == userEntity) {
throw new Exception("User not found");
}
Query file = new Query("File").addFilter("user",
FilterOperator.EQUAL, userEntity.getKey()).addFilter("app",
FilterOperator.EQUAL, app);
if (from > 0) {
file.addFilter("created", FilterOperator.GREATER_THAN, from);
}
int filesAdded = 0;
StringBuilder meta = new StringBuilder();
for (Entity dataEntity : datastore.prepare(file).asIterable()) {
BlobKey blob = (BlobKey) dataEntity.getProperty("file");
String name = (String) dataEntity.getProperty("name");
try {
BlobstoreInputStream stream = new BlobstoreInputStream(blob);
ZipEntry entry = new ZipEntry(name);
zip.putNextEntry(entry);
byte[] buffer = new byte[BlobstoreService.MAX_BLOB_FETCH_SIZE];
int bytesRead = 0;
while ((bytesRead = stream.read(buffer)) > 0) {
zip.write(buffer, 0, bytesRead);
}
stream.close();
zip.closeEntry();
filesAdded++;
zip.flush();
try {
JSONObject metaObject = new JSONObject();
metaObject.put("name", name);
metaObject.put("created",
dataEntity.getProperty("created"));
meta.append(metaObject.toString());
meta.append("\n");
} catch (Exception e) {
}
} catch (Exception e) {
log.warn("Error writing blob", e);
continue;
}
}
if (filesAdded > 0) {
ZipEntry entry = new ZipEntry("meta.json");
zip.putNextEntry(entry);
zip.write(meta.toString().getBytes("utf-8"));
zip.closeEntry();
}
return filesAdded;
} catch (Exception e) {
log.error("Download error", e);
}
return 0;
}
}