Java tutorial
// -*- mode: java; c-basic-offset: 2; -*- // Copyright 2009-2011 Google, All Rights reserved // Copyright 2011-2012 MIT, All rights reserved // Released under the Apache License, Version 2.0 // http://www.apache.org/licenses/LICENSE-2.0 package com.google.appinventor.server; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.nio.ByteBuffer; import java.util.logging.Logger; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItemIterator; import org.apache.commons.fileupload.FileItemStream; import org.apache.commons.fileupload.servlet.ServletFileUpload; import com.google.appengine.tools.cloudstorage.GcsFileOptions; import com.google.appengine.tools.cloudstorage.GcsFilename; import com.google.appengine.tools.cloudstorage.GcsOutputChannel; import com.google.appengine.tools.cloudstorage.GcsService; import com.google.appengine.tools.cloudstorage.GcsServiceFactory; import com.google.appinventor.server.util.CacheHeaders; import com.google.appinventor.server.util.CacheHeadersImpl; import com.google.appinventor.shared.rpc.ServerLayout; import com.google.appinventor.shared.rpc.UploadResponse; import com.google.appinventor.shared.rpc.project.GalleryService; import com.google.appinventor.shared.rpc.project.GallerySettings; /** * Servlet for handling gallery's app publishing. * */ public class GalleryServlet extends OdeServlet { private static int BUFFER_SIZE = 1024 * 1024 * 10; private static int MAX_IMAGE_FILE_SIZE = 1024 * 1024 * 5; /* * URIs for upload requests are structured as follows: * /<baseurl>/gallery_servlet/apps/galleryid/<filePath> * /<baseurl>/gallery_servlet/user/userid/<filePath> */ // Constants for accessing split URI /* * Upload kind can be: "project", "file", or "userfile". * Constants for these are defined in ServerLayout. */ // Constants used when upload kind is "file". // Since the file path may contain slashes, it must be the last component in the URI. private static final int REQUEST_TYPE_INDEX = 3; private static final int GALLERY_OR_USER_ID_INDEX = 4; private static final int FILE_PATH_INDEX = 5; // Logging support private static final Logger LOG = Logger.getLogger(UploadServlet.class.getName()); // Object used to safely set cache headers in responses private static final CacheHeaders CACHE_HEADERS = new CacheHeadersImpl(); // Content type for response header (to avoid security vulnerabilities) private static final String CONTENT_TYPE = "text/html; charset=utf-8"; private final GalleryService galleryService = new GalleryServiceImpl(); @Override public void doPost(HttpServletRequest req, HttpServletResponse resp) { setDefaultHeader(resp); UploadResponse uploadResponse; String uri = req.getRequestURI(); // First, call split with no limit parameter. String[] uriComponents = uri.split("/"); if (true) { String requestType = uriComponents[REQUEST_TYPE_INDEX]; LOG.info("######### GOT IN URI"); LOG.info(requestType); long project_Id = -1; String user_Id = "-1"; if (requestType.equalsIgnoreCase("apps")) { project_Id = Long.parseLong(uriComponents[GALLERY_OR_USER_ID_INDEX]); } else if (requestType.equalsIgnoreCase("user")) { //the code below doesn't check if user_Id is the id of current user //user_Id = uriComponents[GALLERY_OR_USER_ID_INDEX]; user_Id = userInfoProvider.getUserId(); } InputStream uploadedStream; try { if (req.getContentLength() < MAX_IMAGE_FILE_SIZE) { uploadedStream = getRequestStream(req, ServerLayout.UPLOAD_FILE_FORM_ELEMENT); // Converts the input stream to byte array byte[] buffer = new byte[8000]; int bytesRead = 0; ByteArrayOutputStream bao = new ByteArrayOutputStream(); while ((bytesRead = uploadedStream.read(buffer)) != -1) { bao.write(buffer, 0, bytesRead); } // Set up the cloud file (options) String key = ""; GallerySettings settings = galleryService.loadGallerySettings(); if (requestType.equalsIgnoreCase("apps")) { key = settings.getProjectImageKey(project_Id); } else if (requestType.equalsIgnoreCase("user")) { key = settings.getUserImageKey(user_Id); } // setup cloud GcsService gcsService = GcsServiceFactory.createGcsService(); GcsFilename filename = new GcsFilename(settings.getBucket(), key); GcsFileOptions options = new GcsFileOptions.Builder().mimeType("image/jpeg").acl("public-read") .cacheControl("no-cache").build(); GcsOutputChannel writeChannel = gcsService.createOrReplace(filename, options); writeChannel.write(ByteBuffer.wrap(bao.toByteArray())); // Now finalize writeChannel.close(); uploadResponse = new UploadResponse(UploadResponse.Status.SUCCESS); } else { /*file exceeds size of MAX_IMAGE_FILE_SIZE*/ uploadResponse = new UploadResponse(UploadResponse.Status.FILE_TOO_LARGE); } // Now, get the PrintWriter for the servlet response and print the UploadResponse. // On the client side, in the onSubmitComplete method in ode/client/utils/Uploader.java, the // UploadResponse value will be retrieved as a String via the // FormSubmitCompleteEvent.getResults() method. PrintWriter out = resp.getWriter(); out.print(uploadResponse.formatAsHtml()); } catch (Exception e) { throw CrashReport.createAndLogError(LOG, req, null, e); } // Set http response information resp.setStatus(HttpServletResponse.SC_OK); } // Now, get the PrintWriter for the servlet response and print the UploadResponse. // On the client side, in the onSubmitComplete method in ode/client/utils/Uploader.java, the // UploadResponse value will be retrieved as a String via the // FormSubmitCompleteEvent.getResults() method. // PrintWriter out = resp.getWriter(); // out.print(uploadResponse.formatAsHtml()); // Set http response information resp.setStatus(HttpServletResponse.SC_OK); } private InputStream getRequestStream(HttpServletRequest req, String expectedFieldName) throws Exception { ServletFileUpload upload = new ServletFileUpload(); FileItemIterator iterator = upload.getItemIterator(req); while (iterator.hasNext()) { FileItemStream item = iterator.next(); // LOG.info(item.getContentType()); if (item.getFieldName().equals(expectedFieldName)) { return item.openStream(); } } throw new IllegalArgumentException("Field " + expectedFieldName + " not found in upload"); } /** * Set a default http header to avoid security vulnerabilities. */ private static void setDefaultHeader(HttpServletResponse resp) { CACHE_HEADERS.setNotCacheable(resp); resp.setContentType(CONTENT_TYPE); } /** * Helper method for converting input stream * @param input * @param output * @throws IOException */ private void copy(InputStream input, OutputStream output) throws IOException { byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = input.read(buffer); while (bytesRead != -1) { output.write(buffer, 0, bytesRead); bytesRead = input.read(buffer); } } }