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}