/* * Copyright 2011 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jbpm.formbuilder.server; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FileUtils; import org.jboss.resteasy.annotations.providers.jaxb.DoNotUseJAXBProvider; import org.jbpm.formapi.server.form.FormEncodingServerFactory; import org.jbpm.formapi.server.render.Renderer; import org.jbpm.formapi.server.render.RendererException; import org.jbpm.formapi.server.render.RendererFactory; import org.jbpm.formapi.server.trans.Translator; import org.jbpm.formapi.server.trans.TranslatorException; import org.jbpm.formapi.server.trans.TranslatorFactory; import org.jbpm.formapi.shared.api.FormItemRepresentation; import org.jbpm.formapi.shared.api.FormRepresentation; import org.jbpm.formapi.shared.form.FormEncodingException; import org.jbpm.formapi.shared.form.FormEncodingFactory; import org.jbpm.formapi.shared.form.FormRepresentationDecoder; import org.jbpm.formbuilder.server.xml.FormPreviewDTO; import org.jbpm.formbuilder.server.xml.ListFormsDTO; import org.jbpm.formbuilder.server.xml.ListFormsItemsDTO; import org.jbpm.formbuilder.shared.form.FormDefinitionService; import org.jbpm.formbuilder.shared.form.FormServiceException; @Path("/form") public class RESTFormService extends RESTBaseService { private FormDefinitionService formService = null; public void setContext(@Context ServletContext context) { if (formService == null) { this.formService = ServiceFactory.getInstance().getFormDefinitionService(); } } public RESTFormService() { FormEncodingFactory.register(FormEncodingServerFactory.getEncoder(), FormEncodingServerFactory.getDecoder()); } @GET @Path("/definitions/package/{pkgName}") public Response getForms(@PathParam("pkgName") String pkgName, @Context ServletContext context) { setContext(context); try { List<FormRepresentation> forms = formService.getForms(pkgName); ListFormsDTO dto = new ListFormsDTO(forms); return Response.ok(dto, MediaType.APPLICATION_XML).build(); } catch (FormServiceException e) { return error("Problem reading forms of package " + pkgName, e); } catch (FormEncodingException e) { return error("Problem decoding forms of package " + pkgName, e); } } @GET @Path("/definitions/package/{pkgName}/id/{formId}") public Response getForm(@PathParam("pkgName") String pkgName, @PathParam("formId") String formId, @Context ServletContext context) { setContext(context); try { FormRepresentation form = formService.getForm(pkgName, formId); ListFormsDTO dto = new ListFormsDTO(form); return Response.ok(dto, MediaType.APPLICATION_XML).build(); } catch (FormServiceException e) { return error("Problem reading form " + formId, e); } catch (FormEncodingException e) { return error("Problem decoding form " + formId, e); } } @POST @Path("/definitions/package/{pkgName}") @Consumes("text/plain") @DoNotUseJAXBProvider public Response saveForm(String jsonBody, @PathParam("pkgName") String pkgName, @Context HttpServletRequest request) { setContext(request.getSession().getServletContext()); FormRepresentationDecoder decoder = FormEncodingFactory.getDecoder(); try { FormRepresentation form = decoder.decode(jsonBody); String formId = formService.saveForm(pkgName, form); return Response.ok("<formId>"+formId+"</formId>", MediaType.APPLICATION_XML). status(Status.CREATED).build(); } catch (FormEncodingException e) { return error("Problem decoding form", e); } catch (FormServiceException e) { return error("Problem saving form", e); } } @DELETE @Path("/definitions/package/{pkgName}/id/{formId}") public Response deleteForm(@PathParam("pkgName") String pkgName, @PathParam("formId") String formId, @Context HttpServletRequest request) { setContext(request.getSession().getServletContext()); try { formService.deleteForm(pkgName, formId); return Response.ok().build(); } catch (FormServiceException e) { return error("Problem deleting form " + formId, e); } } @GET @Path("/items/package/{pkgName}") public Response getFormItems(@PathParam("pkgName") String pkgName, @Context ServletContext context) { setContext(context); try { Map<String, FormItemRepresentation> formItems = formService.getFormItems(pkgName); ListFormsItemsDTO dto = new ListFormsItemsDTO(formItems); return Response.ok(dto, MediaType.APPLICATION_XML).build(); } catch (FormServiceException e) { return error("Problem getting form items of package " + pkgName, e); } catch (FormEncodingException e) { return error("Problem decoding form items of package " + pkgName, e); } } @GET @Path("/items/package/{pkgName}/id/{fItemId}") public Response getFormItem(@PathParam("pkgName") String pkgName, @PathParam("fItemId") String formItemId, @Context ServletContext context) { setContext(context); try { FormItemRepresentation formItem = formService.getFormItem(pkgName, formItemId); ListFormsItemsDTO dto = new ListFormsItemsDTO(formItemId, formItem); return Response.ok(dto, MediaType.APPLICATION_XML).build(); } catch (FormServiceException e) { return error("Problem reading form item " + formItemId, e); } catch (FormEncodingException e) { return error("Problem decoding form item " + formItemId, e); } } @POST @Path("/items/package/{pkgName}/name/{fItemName}") @Consumes("*/*") @DoNotUseJAXBProvider public Response saveFormItem(String jsonBody, @PathParam("pkgName") String pkgName, @PathParam("fItemName") String formItemName, @Context HttpServletRequest request) { setContext(request.getSession().getServletContext()); FormRepresentationDecoder decoder = FormEncodingFactory.getDecoder(); try { FormItemRepresentation item = decoder.decodeItem(jsonBody); String formItemId = formService.saveFormItem(pkgName, formItemName, item); return Response.ok("<formItemId>"+formItemId+"</formItemId>", MediaType.APPLICATION_XML).status(Status.CREATED).build(); } catch (FormEncodingException e) { return error("Problem encoding form item", e); } catch (FormServiceException e) { return error("Problem saving form item", e); } } @DELETE @Path("/items/package/{pkgName}/name/{fItemName}") public Response deleteFormItem(@PathParam("pkgName")String pkgName, @PathParam("fItemName") String formItemName, @Context HttpServletRequest request) { setContext(request.getSession().getServletContext()); try { formService.deleteFormItem(pkgName, formItemName); return Response.ok().build(); } catch (FormServiceException e) { return Response.noContent().build(); } } @POST @Path("/preview/lang/{language}") public Response getFormPreview(FormPreviewDTO dto, @PathParam("language") String language, @Context ServletContext context, @Context HttpServletRequest request) { setContext(context); try { URL url = createTemplate(language, dto); Map<String, Object> inputs = dto.getInputsAsMap(); Renderer renderer = getRenderer(language); inputs.put(Renderer.BASE_CONTEXT_PATH, context.getContextPath()); Locale locale = request.getLocale(); inputs.put(Renderer.BASE_LOCALE, locale == null ? "default" : locale.getDisplayName(locale)); Object html = renderer.render(url, inputs); String htmlUrl = createHtmlTemplate(html, language, context); return Response.ok(htmlUrl, MediaType.TEXT_PLAIN).build(); } catch (FormEncodingException e) { return error("Problem encoding form preview", e); } catch (TranslatorException e) { return error("Problem transforming form preview to " + language + " language", e); } catch (RendererException e) { return error("Problem rendering form preview in " + language + " language", e); } catch (IOException e) { return error("Problem writing form preview in " + language + " language", e); } } @POST @Path("/template/lang/{language}") public Response getFormTemplate(FormPreviewDTO dto, @PathParam("language") String language, @Context ServletContext context) { setContext(context); try { URL url = createTemplate(language, dto); String fileName = url.getFile(); return Response.ok("<fileName>"+fileName+"</fileName>", MediaType.APPLICATION_XML).build(); } catch (FormEncodingException e) { return error("Problem encoding form for templating", e); } catch (TranslatorException e) { return error("Problem transforming form to " + language + " language", e); } } @POST @Path("/template/file/{action}") public void processFormTemplate( @PathParam("action") String action, @Context ServletContext context, @Context HttpServletRequest request, @Context HttpServletResponse response) { try { request.setAttribute("org.jbpm.formbuilder.server.REST.processFormTemplate.action", action); if (ServletFileUpload.isMultipartContent(request)) { //read multipart request and populate request accordingly for display int maxMemorySize = 240000; File tmpDirectory = new File(System.getProperty("java.io.tmpdir")); DiskFileItemFactory factory = new DiskFileItemFactory(maxMemorySize, tmpDirectory); ServletFileUpload upload = new ServletFileUpload(factory); List<?> files = upload.parseRequest(request); for (Object obj : files) { FileItem item = (FileItem) obj; request.setAttribute(item.getFieldName(), item.getString()); } } String queryString = request.getQueryString(); if (queryString == null) { queryString = "?"; } if (!queryString.startsWith("?")) { queryString = "?" + queryString; } context.getRequestDispatcher("/fbapi/mockProcess.jsp" + queryString).forward(request, response); } catch (Exception e) { error("Couldn't process form template", e); } } @GET @Path("/template/file/{file}.temp") public Response getHtmlTemplate(@PathParam("file") String fileName) { try { File file = new File(System.getProperty("java.io.tmpdir") + File.separator + fileName + ".temp"); String content = FileUtils.readFileToString(file); return Response.ok(content, MediaType.TEXT_HTML).build(); } catch (IOException e) { return error("Problem reading html template for file " + fileName, e); } } private String createHtmlTemplate(Object html, String language, ServletContext context) throws IOException { String contextPath = context.getContextPath(); File file = File.createTempFile("createHtmlTemplate", ".temp"); FileUtils.writeStringToFile(file, html.toString()); String url = contextPath + "/rest/form/template/file/" + file.getName(); return url; } private URL createTemplate(String language, FormPreviewDTO dto) throws FormEncodingException, TranslatorException { FormRepresentationDecoder decoder = FormEncodingFactory.getDecoder(); String json = dto.getRepresentation(); FormRepresentation form = decoder.decode(json); dto.setForm(form); Translator translator = getTranslator(language); URL url = translator.translateForm(form); return url; } @GET @Path("/template/lang/{language}") public Response getExportTemplate(@QueryParam("fileName") String fileName, @QueryParam("formName") String formName, @PathParam("language") String language, @Context ServletContext context) { setContext(context); File file = new File(fileName); String headerValue = new StringBuilder("attachment; filename=\""). append(formName).append('.').append(language). append("\"").toString(); try { return Response.ok(FileUtils.readFileToByteArray(file), MediaType.APPLICATION_OCTET_STREAM). header("Content-Disposition", headerValue).build(); } catch (IOException e) { return Response.serverError().build(); } } protected Translator getTranslator(String language) throws TranslatorException { return TranslatorFactory.getInstance().getTranslator(language); } protected Renderer getRenderer(String language) throws RendererException { return RendererFactory.getInstance().getRenderer(language); } /** * @param formService the formService to set (for test cases purpose) */ public void setFormService(FormDefinitionService formService) { this.formService = formService; } public FormDefinitionService getFormService() { return this.formService; } }