org.jboss.bpm.console.server.FormProcessingFacade.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.bpm.console.server.FormProcessingFacade.java

Source

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2006, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.bpm.console.server;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.bpm.console.client.model.ProcessInstanceRef;
import org.jboss.bpm.console.server.integration.ManagementFactory;
import org.jboss.bpm.console.server.integration.ProcessManagement;
import org.jboss.bpm.console.server.integration.TaskManagement;
import org.jboss.bpm.console.server.plugin.FormAuthorityRef;
import org.jboss.bpm.console.server.plugin.FormDispatcherPlugin;
import org.jboss.bpm.console.server.plugin.PluginMgr;
import org.jboss.bpm.console.server.util.ProjectName;
import org.jboss.bpm.console.server.util.RsComment;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author Heiko.Braun <heiko.braun@jboss.com>
 */
@Path("form")
@RsComment(title = "Form Processing", description = "Web based form processing", project = { ProjectName.JBPM })
public class FormProcessingFacade {
    private static final Log log = LogFactory.getLog(FormProcessingFacade.class);

    private FormDispatcherPlugin formPlugin;

    private ProcessManagement processManagement;

    private TaskManagement taskManagement;
    private static final String SUCCESSFULLY_PROCESSED_INPUT = "<div style='font-family:sans-serif; padding:10px;'>"
            + "<h3>Successfully processed input</h3><p/>" + "You can now close this window." + "</div>";

    /**
     * Lazy load the {@link org.jboss.bpm.console.server.integration.TaskManagement}
     */
    private TaskManagement getTaskManagement() {
        if (null == this.taskManagement) {
            ManagementFactory factory = ManagementFactory.newInstance();
            this.taskManagement = factory.createTaskManagement();
            log.debug("Using ManagementFactory impl:" + factory.getClass().getName());
        }

        return this.taskManagement;
    }

    private ProcessManagement getProcessManagement() {
        if (null == this.processManagement) {
            ManagementFactory factory = ManagementFactory.newInstance();
            this.processManagement = factory.createProcessManagement();
            log.debug("Using ManagementFactory impl:" + factory.getClass().getName());
        }

        return this.processManagement;
    }

    /**
     * Lazy load the {@link org.jboss.bpm.console.server.integration.TaskManagement}
     */
    private FormDispatcherPlugin getFormDispatcherPlugin() {
        if (null == this.formPlugin) {
            this.formPlugin = PluginMgr.load(FormDispatcherPlugin.class);
            log.debug("Using FormDispatcherPlugin impl:" + this.formPlugin);
        }

        return this.formPlugin;
    }

    @GET
    @Path("task/{id}/render")
    @Produces("text/html")
    public Response renderTaskUI(@PathParam("id") String taskId) {
        return provideForm(new FormAuthorityRef(taskId));
    }

    @GET
    @Path("process/{id}/render")
    @Produces("text/html")
    public Response renderProcessUI(@PathParam("id") String definitionId) {
        return provideForm(new FormAuthorityRef(definitionId, FormAuthorityRef.Type.PROCESS));
    }

    @POST
    @Path("task/{id}/complete")
    @Produces("text/html")
    @Consumes("multipart/form-data")
    public Response closeTaskWithUI(@Context HttpServletRequest request, @PathParam("id") String taskId,
            MultipartFormDataInput payload) {
        FieldMapping mapping = createFieldMapping(payload);

        // complete task
        String username = request.getUserPrincipal() != null ? request.getUserPrincipal().getName() : null;

        String outcomeDirective = mapping.directives.get("outcome");

        if (outcomeDirective != null) {
            getTaskManagement().completeTask(Long.valueOf(taskId), // TODO: change to string id's
                    outcomeDirective, // actually a plugin implementation detail
                    mapping.processVars, username);
        } else {
            getTaskManagement().completeTask(Long.valueOf(taskId), mapping.processVars, username);
        }

        return Response.ok(SUCCESSFULLY_PROCESSED_INPUT).build();
    }

    @POST
    @Path("process/{id}/complete")
    @Produces("text/html")
    @Consumes("multipart/form-data")
    public Response startProcessWithUI(@Context HttpServletRequest request, @PathParam("id") String definitionId,
            MultipartFormDataInput payload) {
        FieldMapping mapping = createFieldMapping(payload);

        // start process
        ProcessInstanceRef instance = getProcessManagement().newInstance(definitionId, mapping.processVars);

        return Response.ok(SUCCESSFULLY_PROCESSED_INPUT).build();
    }

    private Response provideForm(FormAuthorityRef authorityRef) {
        DataHandler dh = getFormDispatcherPlugin().provideForm(authorityRef);

        if (null == dh) {
            throw new RuntimeException(
                    "No UI associated with " + authorityRef.getType() + " " + authorityRef.getReferenceId());
        }

        return Response.ok(dh.getDataSource()).type("text/html").build();
    }

    private FieldMapping createFieldMapping(MultipartFormDataInput payload) {
        FieldMapping mapping = new FieldMapping();

        Map<String, InputPart> formData = payload.getFormData();
        Iterator<String> partNames = formData.keySet().iterator();

        while (partNames.hasNext()) {
            final String partName = partNames.next();
            final InputPart part = formData.get(partName);
            final MediaType mediaType = part.getMediaType();

            String mType = mediaType.getType();
            String mSubtype = mediaType.getSubtype();

            if ("text".equals(mType) && "plain".equals(mSubtype)) {
                // RFC2045: Each part has an optional "Content-Type" header
                // that defaults to "text/plain".
                // Can go into process without conversion
                if (mapping.isReserved(partName))
                    mapping.directives.put(partName, part.getBodyAsString());
                else
                    mapping.processVars.put(partName, part.getBodyAsString());
            } else {
                // anything else turns into a DataHandler
                final byte[] data = part.getBodyAsString().getBytes();
                DataHandler dh = new DataHandler(new DataSource() {
                    public InputStream getInputStream() throws IOException {
                        return new ByteArrayInputStream(data);
                    }

                    public OutputStream getOutputStream() throws IOException {
                        throw new RuntimeException("This is a readonly DataHandler");
                    }

                    public String getContentType() {
                        return mediaType.getType();
                    }

                    public String getName() {
                        return partName;
                    }
                });

                mapping.processVars.put(partName, dh);
            }
        }

        return mapping;
    }

    private class FieldMapping {
        final String[] reservedNames = { "outcome", "form" }; // TODO: implementation detail of the form plugin

        Map<String, Object> processVars = new HashMap<String, Object>();
        Map<String, String> directives = new HashMap<String, String>();

        public boolean isReserved(String name) {
            boolean result = false;
            for (String s : reservedNames) {
                if (s.equals(name)) {
                    result = true;
                    break;
                }
            }
            return result;
        }
    }
}