/*
* 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;
}
}