001/* 002 * Copyright (c) 2016 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2017-08-23 23:14:28 -0700 (Wed, 23 Aug 2017) $' 007 * '$Revision: 1383 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029package org.kepler.webview.server.handler; 030 031import java.net.HttpURLConnection; 032import java.util.Set; 033 034import org.kepler.webview.server.WebViewServer; 035 036import io.vertx.core.AsyncResult; 037import io.vertx.core.buffer.Buffer; 038import io.vertx.core.http.HttpServerRequest; 039import io.vertx.core.json.JsonObject; 040import io.vertx.ext.web.FileUpload; 041import io.vertx.ext.web.RoutingContext; 042 043/** Handler to execute workflows or apps. 044 * 045 * @author Daniel Crawl 046 * @version $Id: RunWorkflowHandler.java 1383 2017-08-24 06:14:28Z crawl $ 047 */ 048public class RunWorkflowHandler extends BaseHandler { 049 050 public RunWorkflowHandler(WebViewServer server) { 051 super(server); 052 } 053 054 public void handleRunApp(RoutingContext context) { 055 056 final long timestamp = System.currentTimeMillis(); 057 final JsonObject requestJson = new JsonObject(context.getBody().toString()); 058 059 _server.executeApp(requestJson, context.user(), res -> { 060 _handleResult(res, context, requestJson, timestamp); 061 }); 062 } 063 064 public void handleRunWorkflow(final RoutingContext context) { 065 066 final long timestamp = System.currentTimeMillis(); 067 068 final HttpServerRequest req = context.request(); 069 070 //System.out.println("headers: " + req.headers().names()); 071 //System.out.println("form attrs: " + req.formAttributes().names()); 072 //System.out.println(req.formAttributes().get("json")); 073 074 JsonObject reqJson = null; 075 076 String contentType = req.getHeader("Content-Type"); 077 078 //System.out.println(contentType); 079 080 if(contentType == null || contentType.startsWith("text/plain")) { 081 reqJson = new JsonObject(context.getBody().toString()); 082 } else { 083 String jsonString = req.formAttributes().get("json"); 084 if(jsonString != null) { 085 reqJson = new JsonObject(jsonString); 086 } 087 // TODO part name - should be workflow 088 Set<FileUpload> uploads = context.fileUploads(); 089 if(uploads.size() > 1) { 090 context.response() 091 .putHeader("Content-Type", "application/json") 092 .setStatusCode(HttpURLConnection.HTTP_BAD_REQUEST) 093 .setStatusMessage("Only expected single file upload.") 094 .end(Buffer.buffer(new JsonObject().put("error", "Only expected single file upload.").toString())); 095 _server.log(req, context.user(), HttpURLConnection.HTTP_BAD_REQUEST, timestamp); 096 return; 097 } 098 if(reqJson == null) { 099 reqJson = new JsonObject(); 100 } 101 String uploadName = uploads.iterator().next().uploadedFileName(); 102 reqJson.put("wf_name", uploadName.substring(uploadName.indexOf("file-uploads"))); 103 } 104 105 106 final JsonObject requestJson = reqJson; 107 108 //System.out.println(requestJson); 109 110 _server.executeWorkflow(requestJson, context.user(), res -> { 111 _handleResult(res, context, requestJson, timestamp); 112 }); 113 } 114 115 116 protected void _handleResult(AsyncResult<JsonObject> res, RoutingContext context, 117 JsonObject requestJson, long timestamp) { 118 119 int httpStatus; 120 String message; 121 JsonObject responseJson; 122 123 if(res.succeeded()) { 124 responseJson = res.result(); 125 httpStatus = HttpURLConnection.HTTP_OK; 126 message = "success."; 127 } else { 128 responseJson = new JsonObject().put("error", res.cause().getMessage()); 129 // TODO not all errors are HTTP_BAD_REQUEST. 130 httpStatus = HttpURLConnection.HTTP_BAD_REQUEST; 131 message = "Failed to execute."; 132 } 133 134 Object reqId = requestJson.getValue("reqid"); 135 if(reqId != null) { 136 responseJson.put("reqid", reqId); 137 } 138 139 StringBuilder responseStr; 140 Object callback = requestJson.getValue("callback"); 141 if(callback == null) { 142 responseStr = new StringBuilder(responseJson.encode()); 143 } else { 144 responseStr = new StringBuilder(callback.toString()) 145 .append("(") 146 .append(responseJson.encode()) 147 .append(");"); 148 } 149 150 //System.out.println(responseStr); 151 152 context.response() 153 .putHeader("Content-Type", "application/json") 154 .setStatusCode(httpStatus) 155 .setStatusMessage(message) 156 .end(Buffer.buffer(responseStr.toString())); 157 _server.log(context.request(), context.user(), httpStatus, timestamp); 158 } 159}