/* * Copyright (c) 2006-2009 by Dirk Riehle, http://dirkriehle.com * * This file is part of the Wahlzeit photo rating application. * * 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 org.wahlzeit.model.persistence; import com.google.appengine.api.images.Image; import com.google.appengine.api.images.ImagesServiceFactory; import com.googlecode.objectify.ObjectifyService; import com.googlecode.objectify.Work; import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Id; import org.wahlzeit.services.LogBuilder; import org.wahlzeit.services.OfyService; import java.io.IOException; import java.io.Serializable; import java.security.InvalidParameterException; import java.util.logging.Logger; /** * Adapter for the Google Datastore. Use default constructor to create an instance. * * @review */ public class DatastoreAdapter extends ImageStorage { private static final Logger log = Logger.getLogger(DatastoreAdapter.class.getName()); @Override protected void doWriteImage(Serializable image, String photoIdAsString, int size) throws IOException, InvalidParameterException { if (image instanceof Image) { final ImageWrapper imageWrapper = new ImageWrapper(photoIdAsString + size); imageWrapper.setImage((Image) image); ObjectifyService.run(new Work<Boolean>() { @Override public Boolean run() { OfyService.ofy().save().entity(imageWrapper).now(); return null; } }); log.config(LogBuilder.createSystemMessage().addMessage("image successfully written").toString()); } else { log.warning(LogBuilder.createSystemMessage(). addMessage("did not get an Image type to store"). addParameter("image type", image.toString()).toString()); } } @Override protected Image doReadImage(final String photoIdAsString, final int size) throws IOException { Image result = null; ImageWrapper imageWrapper = ObjectifyService.run(new Work<ImageWrapper>() { @Override public ImageWrapper run() { return OfyService.ofy().load().type(ImageWrapper.class).id(photoIdAsString + size).now(); } }); if (imageWrapper == null) { log.info(LogBuilder.createSystemMessage().addMessage("does not exist!").toString()); } else { result = imageWrapper.getImage(); if (result != null) { log.config(LogBuilder.createSystemMessage().addMessage("image successfully read").toString()); } else { log.warning(LogBuilder.createSystemMessage().addMessage("ImageWrapper contains no Image").toString()); } } return result; } @Override protected boolean doDoesImageExist(String photoIdAsString, int size) { Image image = null; boolean result = false; try { image = doReadImage(photoIdAsString, size); } catch (IOException e) { log.warning( LogBuilder.createSystemMessage().addException("IOException when checking for Image existance", e) .toString()); } if (image != null) { result = true; } log.config(LogBuilder.createSystemMessage().addParameter("does image exist", result).toString()); return result; } /** * Wrapper class to store {@link Image}s in the Google Datastore with Objectify. * * @review */ @Entity public static class ImageWrapper { // see https://cloud.google.com/datastore/docs/tools/administration public final int maxEntitySize = 1024 * 1024; // = 1 MB @Id private String id; private byte[] imageData; public ImageWrapper() { // just for Objectify to load it from Datastore } public ImageWrapper(String id) { this.id = id; } /** * @methodtype get */ public Image getImage() { return ImagesServiceFactory.makeImage(imageData); } /** * @methodtype set * * Can not handle images >= 1 MB because this is the upper limit of entities in Google Datastore. */ public void setImage(Image image) throws ArrayIndexOutOfBoundsException { if(image.getImageData().length >= maxEntitySize) { throw new ArrayIndexOutOfBoundsException("Can not store images >= 1 MB in the Google Datastore."); } else { imageData = image.getImageData(); } } } }