/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2013, MPL CodeInside http://codeinside.ru */ package eform; import com.sun.jersey.core.header.ContentDisposition; import com.sun.jersey.core.header.FormDataContentDisposition; import com.sun.jersey.multipart.FormDataBodyPart; import com.sun.jersey.multipart.FormDataMultiPart; import com.vaadin.Application; import com.vaadin.terminal.gwt.server.WebApplicationContext; import commons.Streams; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; @Path("/") final public class Api { final static MediaType JSON_UTF8; final Logger logger = Logger.getLogger(getClass().getName()); static { Map<String, String> map = new HashMap<String, String>(); map.put("charset", "UTF-8"); JSON_UTF8 = new MediaType("application", "json", map); } @GET @Produces(MediaType.APPLICATION_JSON) public Response getForm(@Context HttpServletRequest req, @Context HttpServletRequest response) throws UnsupportedEncodingException { response.setCharacterEncoding("UTF-8"); Form form = getForm(req); return Response.ok(form, JSON_UTF8).header("Cache-Control", "no-cache").build(); } @GET @Path("{id}{file:(/.*)?}") public Response getContent(@Context HttpServletRequest req, @PathParam("id") String id, @PathParam("file") String file) { Form form = getForm(req); Property source = form.getProperty(id); if (source == null || !source.attachment() || source.content == null) { logger.info("Not attachment " + source); throw new WebApplicationException(Response.Status.NOT_FOUND); } Response.ResponseBuilder builder = Response.ok(source.content, source.mime) .header("Content-Length", source.content.length()) .header("Cache-Control", "no-cache"); if (file == null || file.isEmpty()) { ContentDisposition contentDisposition = ContentDisposition.type("attachment") .fileName(source.value) .modificationDate(new Date(source.content.lastModified())) .build(); builder.header("Content-Disposition", contentDisposition); } return builder.build(); } @POST @Path("plus/{name}/{newVal:[0-9]*}") public Response plus(@Context HttpServletRequest req, @PathParam("name") String name, @QueryParam("suffix") String suffix, @PathParam("newVal") Integer newVal) { Form form = getForm(req); String login = req.getUserPrincipal().getName(); if (suffix == null) { suffix = ""; } Map<String, Property> map = form.plusBlock(login, name, suffix, newVal); return Response.ok(map, JSON_UTF8).build(); } @POST @Path("minus/{name}/{newVal:[0-9]*}") public Response minus(@Context HttpServletRequest req, @PathParam("name") String name, @QueryParam("suffix") String suffix, @PathParam("newVal") Integer newVal) { Form form = getForm(req); if (suffix == null) { suffix = ""; } form.minusBlock(name, suffix, newVal); return Response.ok().build(); } @POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) public Response post(@Context HttpServletRequest req, FormDataMultiPart parts) { Form form = getForm(req); Map<String, List<FormDataBodyPart>> fields = parts.getFields(); for (String field : fields.keySet()) { Property property = form.getProperty(field); if (property != null) { if (!property.writable) { continue; } List<FormDataBodyPart> formDataBodyParts = fields.get(field); for (FormDataBodyPart part : formDataBodyParts) { if (!property.attachment()) { property.updateValue(part.getValue()); } else { FormDataContentDisposition disposition = part.getFormDataContentDisposition(); String fileName = disposition.getFileName(); if (fileName != null && !fileName.isEmpty()) { File src = part.getValueAs(File.class); try { File dst = Streams.copyToTempFile(src, "form-", ".tmp"); property.updateContent(fileName, part.getMediaType().toString(), dst, true); } catch (IOException e) { e.printStackTrace(); } } } } } } List<String> messages = getForm(req).save(); return Response.ok(messages).build(); } private Form getForm(HttpServletRequest req) { FormsHolder holder = getHolder(req); if (holder != null) { String referer = req.getHeader("Referer"); if (referer != null) { String[] parts = referer.split("-", 10); if (parts.length >= 3) { Long id = Long.parseLong(parts[parts.length - 2]); Form form = holder.getForms().get(id); if (form != null) { return form; } else { logger.info("No form " + id); } } else { logger.info("Invalid referer " + referer); } } } throw new WebApplicationException(Response.Status.FORBIDDEN); } private FormsHolder getHolder(HttpServletRequest req) { HttpSession session = req.getSession(false); if (session == null) { logger.info("No session"); return null; } WebApplicationContext ctx = (WebApplicationContext) session.getAttribute(WebApplicationContext.class.getName()); if (ctx == null) { logger.info("No app context"); return null; } for (Application app : ctx.getApplications()) { if (app instanceof FormsHolder) { return (FormsHolder) app; } } logger.info("No form holder"); return null; } }