package org.activityinfo.server.util.blob; import com.google.appengine.api.blobstore.BlobKey; import com.google.appengine.api.blobstore.BlobstoreInputStream; import com.google.appengine.api.datastore.*; import com.google.appengine.api.files.AppEngineFile; import com.google.appengine.api.files.FileService; import com.google.appengine.api.files.FileServiceFactory; import com.google.appengine.api.files.FileWriteChannel; import com.google.common.io.ByteStreams; import com.google.common.io.InputSupplier; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.channels.Channels; public class BlobstoreBlobService implements BlobService { private FileService fileService = FileServiceFactory.getFileService(); private DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); @Override public void put(String key, InputSupplier<? extends InputStream> blob) throws IOException { OutputStream out = put(key); ByteStreams.copy(blob, out); out.close(); } @Override public OutputStream put(final String key) throws IOException { final AppEngineFile file = fileService.createNewBlobFile("application/octet-stream"); boolean lock = true; final FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock); final OutputStream os = Channels.newOutputStream(writeChannel); return new DelegatingOutputStream(os) { @Override protected void afterClosed() throws IOException { try { writeChannel.closeFinally(); } catch (IOException e) { throw e; } catch (Exception e) { throw new IOException(e); } Entity entity = new Entity("Blob", key); entity.setUnindexedProperty("blobKey", fileService.getBlobKey(file)); datastore.put(entity); } }; } @Override public InputSupplier<InputStream> get(String key) throws BlobNotFoundException { Entity entity; try { entity = datastore.get(KeyFactory.createKey("Blob", key)); } catch (EntityNotFoundException e) { throw new BlobNotFoundException(); } final BlobKey blobKey = (BlobKey) entity.getProperty("blobKey"); return new InputSupplier<InputStream>() { @Override public InputStream getInput() throws IOException { return new BlobstoreInputStream(blobKey); } }; } }