001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 */ 012package org.nuxeo.ecm.restapi.server.jaxrs.routing.io; 013 014import java.io.IOException; 015import java.io.InputStream; 016import java.io.Serializable; 017import java.lang.annotation.Annotation; 018import java.lang.reflect.Type; 019import java.util.ArrayList; 020import java.util.List; 021import java.util.Map; 022 023import javax.servlet.http.HttpServletRequest; 024import javax.ws.rs.WebApplicationException; 025import javax.ws.rs.core.Context; 026import javax.ws.rs.core.MediaType; 027import javax.ws.rs.core.MultivaluedMap; 028import javax.ws.rs.core.Response; 029import javax.ws.rs.core.UriInfo; 030import javax.ws.rs.ext.MessageBodyReader; 031import javax.ws.rs.ext.Provider; 032 033import org.apache.commons.io.IOUtils; 034import org.apache.commons.logging.Log; 035import org.apache.commons.logging.LogFactory; 036import org.codehaus.jackson.JsonFactory; 037import org.codehaus.jackson.JsonNode; 038import org.codehaus.jackson.JsonParseException; 039import org.codehaus.jackson.JsonParser; 040import org.codehaus.jackson.JsonToken; 041import org.codehaus.jackson.node.ArrayNode; 042import org.nuxeo.ecm.core.api.CoreSession; 043import org.nuxeo.ecm.core.api.NuxeoException; 044import org.nuxeo.ecm.restapi.server.jaxrs.routing.io.util.JsonEncodeDecodeUtils; 045import org.nuxeo.ecm.restapi.server.jaxrs.routing.model.WorkflowRequest; 046import org.nuxeo.ecm.webengine.WebException; 047import org.nuxeo.ecm.webengine.jaxrs.session.SessionFactory; 048 049/** 050 * @author <a href="mailto:grenard@nuxeo.com">Guillaume Renard</a> 051 */ 052@Provider 053public class WorkflowRequestReader implements MessageBodyReader<WorkflowRequest> { 054 055 protected static final Log log = LogFactory.getLog(WorkflowRequestReader.class); 056 057 public static final String ENTITY_TYPE = "workflow"; 058 059 @Context 060 private JsonFactory factory; 061 062 @Context 063 HttpServletRequest request; 064 065 @Context 066 UriInfo uriInfo; 067 068 @Override 069 public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 070 return WorkflowRequest.class.isAssignableFrom(type); 071 } 072 073 @Override 074 public WorkflowRequest readFrom(Class<WorkflowRequest> type, Type genericType, Annotation[] annotations, 075 MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 076 throws IOException, WebApplicationException { 077 String content = IOUtils.toString(entityStream); 078 if (content.isEmpty()) { 079 if (content.isEmpty()) { 080 throw new WebException("No content in request body", Response.Status.BAD_REQUEST.getStatusCode()); 081 } 082 083 } 084 085 try { 086 return readRequest(content, httpHeaders); 087 } catch (IOException | NuxeoException | ClassNotFoundException e) { 088 throw WebException.wrap(e); 089 } 090 } 091 092 protected WorkflowRequest readRequest(String content, MultivaluedMap<String, String> httpHeaders) 093 throws JsonParseException, IOException, ClassNotFoundException { 094 CoreSession session = SessionFactory.getSession(request); 095 JsonParser jp = factory.createJsonParser(content); 096 WorkflowRequest workflowRequest = new WorkflowRequest(); 097 098 JsonToken tok = jp.nextToken(); 099 100 // skip { 101 if (jp.getCurrentToken() == JsonToken.START_OBJECT) { 102 tok = jp.nextToken(); 103 } 104 String workflowModelName = null; 105 List<String> attachedDocumentIds = null; 106 JsonNode variableNode = null; 107 Map<String, Serializable> variables = null; 108 while (tok != JsonToken.END_OBJECT) { 109 String key = jp.getCurrentName(); 110 jp.nextToken(); 111 if ("workflowModelName".equals(key)) { 112 workflowModelName = jp.readValueAs(String.class); 113 } else if ("attachedDocumentIds".equals(key)) { 114 ArrayNode docNodes = (ArrayNode) jp.readValueAsTree(); 115 attachedDocumentIds = new ArrayList<String>(); 116 for (int i = 0; i < docNodes.size(); i++) { 117 JsonNode node = docNodes.get(i); 118 attachedDocumentIds.add(node.getTextValue()); 119 } 120 } else if ("variables".equals(key)) { 121 variableNode = jp.readValueAsTree(); 122 } else if ("entity-type".equals(key)) { 123 String entityType = jp.readValueAs(String.class); 124 if (!WorkflowRequestReader.ENTITY_TYPE.equals(entityType)) { 125 throw new WebApplicationException(Response.Status.BAD_REQUEST); 126 } 127 } else { 128 log.debug("Unknown key: " + key); 129 jp.skipChildren(); 130 } 131 tok = jp.nextToken(); 132 133 } 134 135 if (workflowModelName == null) { 136 throw new WebException("No workflowModelName found in request body", 137 Response.Status.BAD_REQUEST.getStatusCode()); 138 } 139 140 if (variableNode != null) { 141 variables = JsonEncodeDecodeUtils.decodeVariables(variableNode, null, session); 142 } 143 workflowRequest.setWorkflowModelName(workflowModelName); 144 workflowRequest.setVariables(variables); 145 workflowRequest.setAttachedDocumentIds(attachedDocumentIds); 146 147 return workflowRequest; 148 } 149 150}