http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-interaction-activity/src/main/resources/pmrpc.js ---------------------------------------------------------------------- diff --git a/taverna-interaction-activity/src/main/resources/pmrpc.js b/taverna-interaction-activity/src/main/resources/pmrpc.js deleted file mode 100644 index 0edc8cf..0000000 --- a/taverna-interaction-activity/src/main/resources/pmrpc.js +++ /dev/null @@ -1,686 +0,0 @@ -/* - * pmrpc 0.6 - Inter-widget remote procedure call library based on HTML5 - * postMessage API and JSON-RPC. https://github.com/izuzak/pmrpc - * - * Copyright 2011 Ivan Zuzak, Marko Ivankovic - * - * 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. - */ - -pmrpc = self.pmrpc = function() { - // check if JSON library is available - if (typeof JSON === "undefined" || typeof JSON.stringify === "undefined" || - typeof JSON.parse === "undefined") { - throw "pmrpc requires the JSON library"; - } - - // TODO: make "contextType" private variable - // check if postMessage APIs are available - if (typeof this.postMessage === "undefined" && // window or worker - typeof this.onconnect === "undefined") { // shared worker - throw "pmrpc requires the HTML5 cross-document messaging and worker APIs"; - } - - // Generates a version 4 UUID - function generateUUID() { - var uuid = [], nineteen = "89AB", hex = "0123456789ABCDEF"; - for (var i=0; i<36; i++) { - uuid[i] = hex[Math.floor(Math.random() * 16)]; - } - uuid[14] = '4'; - uuid[19] = nineteen[Math.floor(Math.random() * 4)]; - uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; - return uuid.join(''); - } - - // TODO: remove this - make everything a regex? - // Converts a wildcard expression into a regular expression - function convertWildcardToRegex(wildcardExpression) { - var regex = wildcardExpression.replace( - /([\^\$\.\+\?\=\!\:\|\\\/\(\)\[\]\{\}])/g, "\\$1"); - regex = "^" + regex.replace(/\*/g, ".*") + "$"; - return regex; - } - - // Checks whether a domain satisfies the access control list. The access - // control list has a whitelist and a blacklist. In order to satisfy the acl, - // the domain must be on the whitelist, and must not be on the blacklist. - function checkACL(accessControlList, origin) { - var aclWhitelist = accessControlList.whitelist; - var aclBlacklist = accessControlList.blacklist; - - var isWhitelisted = false; - var isBlacklisted = false; - - for (var i=0; i<aclWhitelist.length; ++i) { - var aclRegex = convertWildcardToRegex(aclWhitelist[i]); - if(origin.match(aclRegex)) { - isWhitelisted = true; - break; - } - } - - for (var j=0; i<aclBlacklist.length; ++j) { - var aclRegex = convertWildcardToRegex(aclBlacklist[j]); - if(origin.match(aclRegex)) { - isBlacklisted = true; - break; - } - } - - return isWhitelisted && !isBlacklisted; - } - - // Calls a function with either positional or named parameters - // In either case, additionalParams will be appended to the end - function invokeProcedure(fn, self, params, additionalParams) { - if (!(params instanceof Array)) { - // get string representation of function - var fnDef = fn.toString(); - - // parse the string representation and retrieve order of parameters - var argNames = fnDef.substring(fnDef.indexOf("(")+1, fnDef.indexOf(")")); - argNames = (argNames === "") ? [] : argNames.split(", "); - - var argIndexes = {}; - for (var i=0; i<argNames.length; i++) { - argIndexes[argNames[i]] = i; - } - - // construct an array of arguments from a dictionary - var callParameters = []; - for (var paramName in params) { - if (typeof argIndexes[paramName] !== "undefined") { - callParameters[argIndexes[paramName]] = params[paramName]; - } else { - throw "No such param!"; - } - } - - params = callParameters; - } - - // append additional parameters - if (typeof additionalParams !== "undefined") { - params = params.concat(additionalParams); - } - - // invoke function with specified context and arguments array - return fn.apply(self, params); - } - - // JSON encode an object into pmrpc message - function encode(obj) { - return "pmrpc." + JSON.stringify(obj); - } - - // JSON decode a pmrpc message - function decode(str) { - return JSON.parse(str.substring("pmrpc.".length)); - } - - // Creates a base JSON-RPC object, usable for both request and response. - // As of JSON-RPC 2.0 it only contains one field "jsonrpc" with value "2.0" - function createJSONRpcBaseObject() { - var call = {}; - call.jsonrpc = "2.0"; - return call; - } - - // Creates a JSON-RPC request object for the given method and parameters - function createJSONRpcRequestObject(procedureName, parameters, id) { - var call = createJSONRpcBaseObject(); - call.method = procedureName; - call.params = parameters; - if (typeof id !== "undefined") { - call.id = id; - } - return call; - } - - // Creates a JSON-RPC error object complete with message and error code - function createJSONRpcErrorObject(errorcode, message, data) { - var error = {}; - error.code = errorcode; - error.message = message; - error.data = data; - return error; - } - - // Creates a JSON-RPC response object. - function createJSONRpcResponseObject(error, result, id) { - var response = createJSONRpcBaseObject(); - response.id = id; - - if (typeof error === "undefined" || error === null) { - response.result = (result === "undefined") ? null : result; - } else { - response.error = error; - } - - return response; - } - - // dictionary of services registered for remote calls - var registeredServices = {}; - // dictionary of requests being processed on the client side - var callQueue = {}; - - var reservedProcedureNames = {}; - // register a service available for remote calls - // if no acl is given, assume that it is available to everyone - function register(config) { - if (config.publicProcedureName in reservedProcedureNames) { - return false; - } else { - registeredServices[config.publicProcedureName] = { - "publicProcedureName" : config.publicProcedureName, - "procedure" : config.procedure, - "context" : config.procedure.context, - "isAsync" : typeof config.isAsynchronous !== "undefined" ? - config.isAsynchronous : false, - "acl" : typeof config.acl !== "undefined" ? - config.acl : {whitelist: ["*"], blacklist: []}}; - return true; - } - } - - // unregister a previously registered procedure - function unregister(publicProcedureName) { - if (publicProcedureName in reservedProcedureNames) { - return false; - } else { - delete registeredServices[publicProcedureName]; - return true; - } - } - - // retreive service for a specific procedure name - function fetchRegisteredService(publicProcedureName){ - return registeredServices[publicProcedureName]; - } - - // receive and execute a pmrpc call which may be a request or a response - function processPmrpcMessage(eventParams) { - var serviceCallEvent = eventParams.event; - var eventSource = eventParams.source; - var isWorkerComm = typeof eventSource !== "undefined" && eventSource !== null; - - // if the message is not for pmrpc, ignore it. - if (serviceCallEvent.data.indexOf("pmrpc.") !== 0) { - return; - } else { - var message = decode(serviceCallEvent.data); - //if (typeof console !== "undefined" && console.log !== "undefined" && (typeof this.frames !== "undefined")) { console.log("Received:" + encode(message)); } - if (typeof message.method !== "undefined") { - // this is a request - - // ako je - var newServiceCallEvent = { - data : serviceCallEvent.data, - source : isWorkerComm ? eventSource : serviceCallEvent.source, - origin : isWorkerComm ? "*" : serviceCallEvent.origin, - shouldCheckACL : !isWorkerComm - }; - - response = processJSONRpcRequest(message, newServiceCallEvent); - - // return the response - if (response !== null) { - sendPmrpcMessage( - newServiceCallEvent.source, response, newServiceCallEvent.origin); - } - } else { - // this is a response - processJSONRpcResponse(message); - } - } - } - - // Process a single JSON-RPC Request - function processJSONRpcRequest(request, serviceCallEvent, shouldCheckACL) { - if (request.jsonrpc !== "2.0") { - // Invalid JSON-RPC request - return createJSONRpcResponseObject( - createJSONRpcErrorObject(-32600, "Invalid request.", - "The recived JSON is not a valid JSON-RPC 2.0 request."), - null, - null); - } - - var id = request.id; - var service = fetchRegisteredService(request.method); - - if (typeof service !== "undefined") { - // check the acl rights - if (!serviceCallEvent.shouldCheckACL || - checkACL(service.acl, serviceCallEvent.origin)) { - try { - if (service.isAsync) { - // if the service is async, create a callback which the service - // must call in order to send a response back - var cb = function (returnValue) { - sendPmrpcMessage( - serviceCallEvent.source, - createJSONRpcResponseObject(null, returnValue, id), - serviceCallEvent.origin); - }; - invokeProcedure( - service.procedure, service.context, request.params, [cb, serviceCallEvent]); - return null; - } else { - // if the service is not async, just call it and return the value - var returnValue = invokeProcedure( - service.procedure, - service.context, - request.params, [serviceCallEvent]); - return (typeof id === "undefined") ? null : - createJSONRpcResponseObject(null, returnValue, id); - } - } catch (error) { - if (typeof id === "undefined") { - // it was a notification nobody cares if it fails - return null; - } - - if (error === "No such param!") { - return createJSONRpcResponseObject( - createJSONRpcErrorObject( - -32602, "Invalid params.", error.description), - null, - id); - } - - // the -1 value is "application defined" - return createJSONRpcResponseObject( - createJSONRpcErrorObject( - -1, "Application error.", error.description), - null, - id); - } - } else { - // access denied - return (typeof id === "undefined") ? null : createJSONRpcResponseObject( - createJSONRpcErrorObject( - -2, "Application error.", "Access denied on server."), - null, - id); - } - } else { - // No such method - return (typeof id === "undefined") ? null : createJSONRpcResponseObject( - createJSONRpcErrorObject( - -32601, - "Method not found.", - "The requestd remote procedure does not exist or is not available."), - null, - id); - } - } - - // internal rpc service that receives responses for rpc calls - function processJSONRpcResponse(response) { - var id = response.id; - var callObj = callQueue[id]; - if (typeof callObj === "undefined" || callObj === null) { - return; - } else { - delete callQueue[id]; - } - - // check if the call was sucessful or not - if (typeof response.error === "undefined") { - callObj.onSuccess( { - "destination" : callObj.destination, - "publicProcedureName" : callObj.publicProcedureName, - "params" : callObj.params, - "status" : "success", - "returnValue" : response.result} ); - } else { - callObj.onError( { - "destination" : callObj.destination, - "publicProcedureName" : callObj.publicProcedureName, - "params" : callObj.params, - "status" : "error", - "description" : response.error.message + " " + response.error.data} ); - } - } - - // call remote procedure - function call(config) { - // check that number of retries is not -1, that is a special internal value - if (config.retries && config.retries < 0) { - throw new Exception("number of retries must be 0 or higher"); - } - - var destContexts = []; - - if (typeof config.destination === "undefined" || config.destination === null || config.destination === "workerParent") { - destContexts = [{context : null, type : "workerParent"}]; - } else if (config.destination === "publish") { - destContexts = findAllReachableContexts(); - } else if (config.destination instanceof Array) { - for (var i=0; i<config.destination.length; i++) { - if (config.destination[i] === "workerParent") { - destContexts.push({context : null, type : "workerParent"}); - } else if (typeof config.destination[i].frames !== "undefined") { - destContexts.push({context : config.destination[i], type : "window"}); - } else { - destContexts.push({context : config.destination[i], type : "worker"}); - } - } - } else { - if (typeof config.destination.frames !== "undefined") { - destContexts.push({context : config.destination, type : "window"}); - } else { - destContexts.push({context : config.destination, type : "worker"}); - } - } - - for (var i=0; i<destContexts.length; i++) { - var callObj = { - destination : destContexts[i].context, - destinationDomain : typeof config.destinationDomain === "undefined" ? ["*"] : (typeof config.destinationDomain === "string" ? [config.destinationDomain] : config.destinationDomain), - publicProcedureName : config.publicProcedureName, - onSuccess : typeof config.onSuccess !== "undefined" ? - config.onSuccess : function (){}, - onError : typeof config.onError !== "undefined" ? - config.onError : function (){}, - retries : typeof config.retries !== "undefined" ? config.retries : 5, - timeout : typeof config.timeout !== "undefined" ? config.timeout : 500, - status : "requestNotSent" - }; - - isNotification = typeof config.onError === "undefined" && typeof config.onSuccess === "undefined"; - params = (typeof config.params !== "undefined") ? config.params : []; - callId = generateUUID(); - callQueue[callId] = callObj; - - if (isNotification) { - callObj.message = createJSONRpcRequestObject( - config.publicProcedureName, params); - } else { - callObj.message = createJSONRpcRequestObject( - config.publicProcedureName, params, callId); - } - - waitAndSendRequest(callId); - } - } - - // Use the postMessage API to send a pmrpc message to a destination - function sendPmrpcMessage(destination, message, acl) { - //if (typeof console !== "undefined" && console.log !== "undefined" && (typeof this.frames !== "undefined")) { console.log("Sending:" + encode(message)); } - if (typeof destination === "undefined" || destination === null) { - self.postMessage(encode(message)); - } else if (typeof destination.frames !== "undefined") { - return destination.postMessage(encode(message), acl); - } else { - destination.postMessage(encode(message)); - } - } - - // Execute a remote call by first pinging the destination and afterwards - // sending the request - function waitAndSendRequest(callId) { - var callObj = callQueue[callId]; - if (typeof callObj === "undefined") { - return; - } else if (callObj.retries <= -1) { - processJSONRpcResponse( - createJSONRpcResponseObject( - createJSONRpcErrorObject( - -4, "Application error.", "Destination unavailable."), - null, - callId)); - } else if (callObj.status === "requestSent") { - return; - } else if (callObj.retries === 0 || callObj.status === "available") { - callObj.status = "requestSent"; - callObj.retries = -1; - callQueue[callId] = callObj; - for (var i=0; i<callObj.destinationDomain.length; i++) { - sendPmrpcMessage( - callObj.destination, callObj.message, callObj.destinationDomain[i], callObj); - self.setTimeout(function() { waitAndSendRequest(callId); }, callObj.timeout); - } - } else { - // if we can ping some more - send a new ping request - callObj.status = "pinging"; - callObj.retries = callObj.retries - 1; - - call({ - "destination" : callObj.destination, - "publicProcedureName" : "receivePingRequest", - "onSuccess" : function (callResult) { - if (callResult.returnValue === true && - typeof callQueue[callId] !== 'undefined') { - callQueue[callId].status = "available"; - waitAndSendRequest(callId); - } - }, - "params" : [callObj.publicProcedureName], - "retries" : 0, - "destinationDomain" : callObj.destinationDomain}); - callQueue[callId] = callObj; - self.setTimeout(function() { waitAndSendRequest(callId); }, callObj.timeout / callObj.retries); - } - } - - // attach the pmrpc event listener - function addCrossBrowserEventListerner(obj, eventName, handler, bubble) { - if ("addEventListener" in obj) { - // FF - obj.addEventListener(eventName, handler, bubble); - } else { - // IE - obj.attachEvent("on" + eventName, handler); - } - } - - function createHandler(method, source, destinationType) { - return function(event) { - var params = {event : event, source : source, destinationType : destinationType}; - method(params); - }; - } - - if ('window' in this) { - // window object - window-to-window comm - var handler = createHandler(processPmrpcMessage, null, "window"); - addCrossBrowserEventListerner(this, "message", handler, false); - } else if ('onmessage' in this) { - // dedicated worker - parent X to worker comm - var handler = createHandler(processPmrpcMessage, this, "worker"); - addCrossBrowserEventListerner(this, "message", handler, false); - } else if ('onconnect' in this) { - // shared worker - parent X to shared-worker comm - var connectHandler = function(e) { - //this.sendPort = e.ports[0]; - var handler = createHandler(processPmrpcMessage, e.ports[0], "sharedWorker"); - addCrossBrowserEventListerner(e.ports[0], "message", handler, false); - e.ports[0].start(); - }; - addCrossBrowserEventListerner(this, "connect", connectHandler, false); - } else { - throw "Pmrpc must be loaded within a browser window or web worker."; - } - - // Override Worker and SharedWorker constructors so that pmrpc may relay - // messages. For each message received from the worker, call pmrpc processing - // method. This is child worker to parent communication. - - var createDedicatedWorker = this.Worker; - this.nonPmrpcWorker = createDedicatedWorker; - var createSharedWorker = this.SharedWorker; - this.nonPmrpcSharedWorker = createSharedWorker; - - var allWorkers = []; - - this.Worker = function(scriptUri) { - var newWorker = new createDedicatedWorker(scriptUri); - allWorkers.push({context : newWorker, type : 'worker'}); - var handler = createHandler(processPmrpcMessage, newWorker, "worker"); - addCrossBrowserEventListerner(newWorker, "message", handler, false); - return newWorker; - }; - - this.SharedWorker = function(scriptUri, workerName) { - var newWorker = new createSharedWorker(scriptUri, workerName); - allWorkers.push({context : newWorker, type : 'sharedWorker'}); - var handler = createHandler(processPmrpcMessage, newWorker.port, "sharedWorker"); - addCrossBrowserEventListerner(newWorker.port, "message", handler, false); - newWorker.postMessage = function (msg, portArray) { - return newWorker.port.postMessage(msg, portArray); - }; - newWorker.port.start(); - return newWorker; - }; - - // function that receives pings for methods and returns responses - function receivePingRequest(publicProcedureName) { - return typeof fetchRegisteredService(publicProcedureName) !== "undefined"; - } - - function subscribe(params) { - return register(params); - } - - function unsubscribe(params) { - return unregister(params); - } - - function findAllWindows() { - var allWindowContexts = []; - - if (typeof window !== 'undefined') { - allWindowContexts.push( { context : window.top, type : 'window' } ); - - // walk through all iframes, starting with window.top - for (var i=0; typeof allWindowContexts[i] !== 'undefined'; i++) { - var currentWindow = allWindowContexts[i]; - for (var j=0; j<currentWindow.context.frames.length; j++) { - allWindowContexts.push({ - context : currentWindow.context.frames[j], - type : 'window' - }); - } - } - } else { - allWindowContexts.push( {context : this, type : 'workerParent'} ); - } - - return allWindowContexts; - } - - function findAllWorkers() { - return allWorkers; - } - - function findAllReachableContexts() { - var allWindows = findAllWindows(); - var allWorkers = findAllWorkers(); - var allContexts = allWindows.concat(allWorkers); - - return allContexts; - } - - // register method for receiving and returning pings - register({ - "publicProcedureName" : "receivePingRequest", - "procedure" : receivePingRequest}); - - function getRegisteredProcedures() { - var regSvcs = []; - var origin = typeof this.frames !== "undefined" ? (window.location.protocol + "//" + window.location.host + (window.location.port !== "" ? ":" + window.location.port : "")) : ""; - for (publicProcedureName in registeredServices) { - if (publicProcedureName in reservedProcedureNames) { - continue; - } else { - regSvcs.push( { - "publicProcedureName" : registeredServices[publicProcedureName].publicProcedureName, - "acl" : registeredServices[publicProcedureName].acl, - "origin" : origin - } ); - } - } - return regSvcs; - } - - // register method for returning registered procedures - register({ - "publicProcedureName" : "getRegisteredProcedures", - "procedure" : getRegisteredProcedures}); - - function discover(params) { - var windowsForDiscovery = null; - - if (typeof params.destination === "undefined") { - windowsForDiscovery = findAllReachableContexts(); - for (var i=0; i<windowsForDiscovery.length; i++) { - windowsForDiscovery[i] = windowsForDiscovery[i].context; - } - } else { - windowsForDiscovery = params.destination; - } - var originRegex = typeof params.origin === "undefined" ? - ".*" : params.origin; - var nameRegex = typeof params.publicProcedureName === "undefined" ? - ".*" : params.publicProcedureName; - - var counter = windowsForDiscovery.length; - - var discoveredMethods = []; - function addToDiscoveredMethods(methods, destination) { - for (var i=0; i<methods.length; i++) { - if (methods[i].origin.match(originRegex) && methods[i].publicProcedureName.match(nameRegex)) { - discoveredMethods.push({ - publicProcedureName : methods[i].publicProcedureName, - destination : destination, - procedureACL : methods[i].acl, - destinationOrigin : methods[i].origin - }); - } - } - } - - pmrpc.call({ - destination : windowsForDiscovery, - destinationDomain : "*", - publicProcedureName : "getRegisteredProcedures", - onSuccess : function (callResult) { - counter--; - addToDiscoveredMethods(callResult.returnValue, callResult.destination); - if (counter === 0) { - params.callback(discoveredMethods); - } - }, - onError : function (callResult) { - counter--; - if (counter === 0) { - params.callback(discoveredMethods); - } - } - }); - } - - reservedProcedureNames = {"getRegisteredProcedures" : null, "receivePingRequest" : null}; - - // return public methods - return { - register : register, - unregister : unregister, - call : call, - discover : discover - }; -}();
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-interaction-activity/src/main/resources/schema.json ---------------------------------------------------------------------- diff --git a/taverna-interaction-activity/src/main/resources/schema.json b/taverna-interaction-activity/src/main/resources/schema.json deleted file mode 100644 index dcde96e..0000000 --- a/taverna-interaction-activity/src/main/resources/schema.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-03/schema#", - "id": "http://ns.taverna.org.uk/2010/activity/interaction.schema.json", - "title": Interaction activity configuration", - "type": "object", - "properties": { - "@context": { - "description": "JSON-LD context for interpreting the configuration as RDF", - "required": true, - "enum": ["http://ns.taverna.org.uk/2010/activity/interaction.context.json"] - }, - "presentationOrigin": { - "type": "string", - "required": true, - "minLength": 1, - "description": "The URL of the presentation page, or the identifier of the standard template" - }, - "interactionActivityType": { - "type": "string", - "required": true, - "minLength": 1, - "enum" : [ "VelocityTemplate", "LocallyPresentedHtml"], - "description": "Indication of the type of the definition for the interaction" - }, - "progressNotification": { - "type": "boolean", - "required": true, - "description": "True if the interaction should not block the workflow run" - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-interaction-activity/src/main/resources/select.vm ---------------------------------------------------------------------- diff --git a/taverna-interaction-activity/src/main/resources/select.vm b/taverna-interaction-activity/src/main/resources/select.vm deleted file mode 100644 index 6fe5764..0000000 --- a/taverna-interaction-activity/src/main/resources/select.vm +++ /dev/null @@ -1,61 +0,0 @@ -#require("valueList",1) -#require("message") -#require("title") -#produce("answer") -<!doctype html> -<html> - <head> - <meta charset="utf-8" /> - <title></title> - <style> - </style> - </head> - <body> - - <script type="text/javascript" src="$pmrpcUrl"></script> - - <script type="text/javascript"> - - function reply() { - pmrpc.call({ - destination : "publish", - publicProcedureName : "reply", - params : ["OK", {"answer" : document.myform.mySelect.options[document.myform.mySelect.selectedIndex].value}], - onSuccess : function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Data submitted</h1>';}, - onFailure: function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Data submission failed</h1>';} - }); - return true; - } - - function cancel() { - pmrpc.call({ - destination : "publish", - publicProcedureName : "reply", - params : ["Cancelled", {}], - onSuccess : function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Cancelled</h1>';}, - onFailure: function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Cancellation failed</h1>';} - }); - return true; - } - - pmrpc.call({ - destination : "publish", - publicProcedureName : "setTitle", - params : ["$!title"]}); - - </script> - - <h2>$!message</h2> - <form name="myform" onSubmit="reply(); return false;"> - <select name="mySelect"> -#foreach( $value in $valueList ) - <option value="$value">$value</option> -#end - </select> - <br/> - <input type="button" value="Cancel" onClick = "cancel()"/> - <input type="button" value="Submit" onClick = "reply()"/> - </form> - </body> -</html> - http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-interaction-activity/src/main/resources/tell.vm ---------------------------------------------------------------------- diff --git a/taverna-interaction-activity/src/main/resources/tell.vm b/taverna-interaction-activity/src/main/resources/tell.vm deleted file mode 100644 index 948c023..0000000 --- a/taverna-interaction-activity/src/main/resources/tell.vm +++ /dev/null @@ -1,54 +0,0 @@ -#require("message") -#require("title") -#produce("answer") -<!doctype html> -<html> - <head> - <meta charset="utf-8" /> - <title></title> - <style> - </style> - </head> - <body> - - <script type="text/javascript" src="$pmrpcUrl"></script> - - <script type="text/javascript"> - - function reply() { - pmrpc.call({ - destination : "publish", - publicProcedureName : "reply", - params : ["OK", {"answer" : "answer"}], - onSuccess : function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Data submitted</h1>';}, - onFailure: function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Data submission failed</h1>';} - }); - return true; - } - - function cancel() { - pmrpc.call({ - destination : "publish", - publicProcedureName : "reply", - params : ["Cancelled", {}], - onSuccess : function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Cancelled</h1>';}, - onFailure: function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Cancellation failed</h1>';} - }); - return true; - } - - pmrpc.call({ - destination : "publish", - publicProcedureName : "setTitle", - params : ["$!title"]}); - - </script> - - <h2>Message: $!message</h2> - <form name="myform" onSubmit="reply(); return false;"> - <input type="button" value="Cancel" onClick = "cancel()"/> - <input type="button" value="OK" onClick = "reply()"/> - </form> - </body> -</html> - http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-interaction-activity/src/main/resources/warn.vm ---------------------------------------------------------------------- diff --git a/taverna-interaction-activity/src/main/resources/warn.vm b/taverna-interaction-activity/src/main/resources/warn.vm deleted file mode 100644 index ae9f573..0000000 --- a/taverna-interaction-activity/src/main/resources/warn.vm +++ /dev/null @@ -1,54 +0,0 @@ -#require("message") -#require("title") -#produce("answer") -<!doctype html> -<html> - <head> - <meta charset="UTF-8" /> - <title></title> - <style> - </style> - </head> - <body> - - <script type="text/javascript" src="$pmrpcUrl"></script> - - <script type="text/javascript"> - - function reply() { - pmrpc.call({ - destination : "publish", - publicProcedureName : "reply", - params : ["OK", {"answer" : "answer"}], - onSuccess : function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Data submitted</h1>';}, - onFailure: function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Data submission failed</h1>';} - }); - return true; - } - - function cancel() { - pmrpc.call({ - destination : "publish", - publicProcedureName : "reply", - params : ["Cancelled", {}], - onSuccess : function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Cancelled</h1>';}, - onFailure: function() {document.getElementsByTagName('body')[0].innerHTML='<h1>Cancellation failed</h1>';} - }); - return true; - } - - pmrpc.call({ - destination : "publish", - publicProcedureName : "setTitle", - params : ["$!title"]}); - - </script> - - <h2>Warning: $!message</h2> - <form name="myform" onSubmit="reply(); return false;"> - <input type="button" value="Cancel" onClick = "cancel()"/> - <input type="button" value="OK" onClick = "reply()"/> - </form> - </body> -</html> - http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-rest-activity/pom.xml ---------------------------------------------------------------------- diff --git a/taverna-rest-activity/pom.xml b/taverna-rest-activity/pom.xml deleted file mode 100644 index aa0cba3..0000000 --- a/taverna-rest-activity/pom.xml +++ /dev/null @@ -1,96 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.apache.taverna.commonactivities</groupId> - <artifactId>taverna-common-activities</artifactId> - <version>2.1.0-incubating-SNAPSHOT</version> - </parent> - <artifactId>taverna-rest-activity</artifactId> - <name>Apache Taverna REST Activity</name> - <packaging>bundle</packaging> - - <dependencies> - <dependency> - <groupId>org.apache.taverna.engine</groupId> - <artifactId>taverna-reference-api</artifactId> - <version>${taverna.engine.version}</version> - </dependency> - <dependency> - <groupId>org.apache.taverna.engine</groupId> - <artifactId>taverna-workflowmodel-api</artifactId> - <version>${taverna.engine.version}</version> - </dependency> - <dependency> - <groupId>org.apache.taverna.engine</groupId> - <artifactId>taverna-credential-manager</artifactId> - <version>${taverna.engine.version}</version> - </dependency> - - <dependency> - <groupId>commons-codec</groupId> - <artifactId>commons-codec</artifactId> - <version>${commons.codec.version}</version> - </dependency> - - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient-osgi</artifactId> - <version>${apache.httpclient.version}</version> - <exclusions> - <!-- These are all embedded within httpclient-osgi --> - <exclusion> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient</artifactId> - </exclusion> - <exclusion> - <groupId>commons-codec</groupId> - <artifactId>commons-codec</artifactId> - </exclusion> - <exclusion> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpmime</artifactId> - </exclusion> - <exclusion> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient-cache</artifactId> - </exclusion> - <exclusion> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>fluent-hc</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpcore-osgi</artifactId> - <version>${apache.httpcore.version}</version> - <exclusions> - <exclusion> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpcore</artifactId> - </exclusion> - <exclusion> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpcore-nio</artifactId> - </exclusion> - </exclusions> - </dependency> - - - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>${junit.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.taverna.engine</groupId> - <artifactId>taverna-activity-test-utils</artifactId> - <version>${taverna.engine.version}</version> - <scope>test</scope> - </dependency> - - </dependencies> -</project> http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequest.java ---------------------------------------------------------------------- diff --git a/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequest.java b/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequest.java deleted file mode 100644 index 9ff240b..0000000 --- a/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequest.java +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2011 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program 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 program 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 program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - ******************************************************************************/ -package net.sf.taverna.t2.activities.rest; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import net.sf.taverna.t2.activities.rest.RESTActivity.HTTP_METHOD; -import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean; -import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty; - -/** - * HTTP Request configuration bean. - * - * @author David Withers - */ -@ConfigurationBean(uri = RESTActivity.URI + "#Request") -public class HTTPRequest { - - private HTTP_METHOD method; - - private String absoluteURITemplate; - - private List<HTTPRequestHeader> headers = new ArrayList<HTTPRequestHeader>(); - - public HTTP_METHOD getMethod() { - return method; - } - - @ConfigurationProperty(name = "mthd", label = "HTTP Method", uri="http://www.w3.org/2011/http#mthd") - public void setMethod(URI method) { - setMethod(HTTP_METHOD.valueOf(method.getFragment())); - } - - public void setMethod(HTTP_METHOD method) { - this.method = method; - } - - public String getAbsoluteURITemplate() { - return absoluteURITemplate; - } - - @ConfigurationProperty(name = "absoluteURITemplate", label = "URL Template") - public void setAbsoluteURITemplate(String absoluteURITemplate) { - this.absoluteURITemplate = absoluteURITemplate; - } - - public List<HTTPRequestHeader> getHeaders() { - return headers; - } - - @ConfigurationProperty(name = "headers", label = "HTTP Request Headers", uri="http://www.w3.org/2011/http#headers") - public void setHeaders(List<HTTPRequestHeader> headers) { - this.headers = headers; - } - - public HTTPRequestHeader getHeader(String name) { - for (HTTPRequestHeader httpRequestHeader : headers) { - if (httpRequestHeader.getFieldName().equals(name)) { - return httpRequestHeader; - } - } - return null; - } - - public void setHeader(String name, String value) { - HTTPRequestHeader httpRequestHeader = getHeader(name); - if (httpRequestHeader == null) { - httpRequestHeader = new HTTPRequestHeader(); - httpRequestHeader.setFieldName(name); - headers.add(httpRequestHeader); - } - httpRequestHeader.setFieldValue(value); - } - - public void setHeader(String name, boolean use100Continue) { - HTTPRequestHeader httpRequestHeader = getHeader(name); - if (httpRequestHeader == null) { - httpRequestHeader = new HTTPRequestHeader(); - httpRequestHeader.setFieldName(name); - headers.add(httpRequestHeader); - } - httpRequestHeader.setUse100Continue(use100Continue); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequestHandler.java ---------------------------------------------------------------------- diff --git a/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequestHandler.java b/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequestHandler.java deleted file mode 100644 index 6393550..0000000 --- a/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequestHandler.java +++ /dev/null @@ -1,586 +0,0 @@ -package net.sf.taverna.t2.activities.rest; - -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.ProxySelector; -import java.net.URL; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.net.ssl.SSLContext; - -import net.sf.taverna.t2.activities.rest.RESTActivity.DATA_FORMAT; - -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.scheme.SchemeRegistry; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.conn.ProxySelectorRoutePlanner; -import org.apache.http.impl.conn.SingleClientConnManager; -import org.apache.http.protocol.BasicHttpContext; -import org.apache.http.protocol.ExecutionContext; -import org.apache.http.protocol.HttpContext; -import org.apache.log4j.Logger; - -/** - * This class deals with the actual remote REST service invocation. The main - * four HTTP methods (GET | POST | PUT | DELETE) are supported. <br/> - * <br/> - * - * Configuration for request execution is obtained from the related REST - * activity - encapsulated in a configuration bean. - * - * @author Sergejs Aleksejevs - * @author Alex Nenadic - */ -public class HTTPRequestHandler { - private static final int HTTPS_DEFAULT_PORT = 443; - private static final String CONTENT_TYPE_HEADER_NAME = "Content-Type"; - private static final String ACCEPT_HEADER_NAME = "Accept"; - private static Logger logger = Logger.getLogger(HTTPRequestHandler.class); - - public static String PROXY_HOST = "http.proxyHost"; - public static String PROXY_PORT = "http.proxyPort"; - public static String PROXY_USERNAME = "http.proxyUser"; - public static String PROXY_PASSWORD = "http.proxyPassword"; - - /** - * This method is the entry point to the invocation of a remote REST - * service. It accepts a number of parameters from the related REST activity - * and uses those to assemble, execute and fetch results of a relevant HTTP - * request. - * - * @param requestURL - * The URL for the request to be made. This cannot be taken from - * the <code>configBean</code>, because this should be the - * complete URL which may be directly used to make the request ( - * <code>configBean</code> would only contain the URL signature - * associated with the REST activity). - * @param configBean - * Configuration of the associated REST activity is passed to - * this class as a configuration bean. Settings such as HTTP - * method, MIME types for "Content-Type" and "Accept" headers, - * etc are taken from the bean. - * @param inputMessageBody - * Body of the message to be sent to the server - only needed for - * POST and PUT requests; for GET and DELETE it will be - * discarded. - * @return - */ - @SuppressWarnings("deprecation") - public static HTTPRequestResponse initiateHTTPRequest(String requestURL, - RESTActivityConfigurationBean configBean, Object inputMessageBody, - Map<String, String> urlParameters, CredentialsProvider credentialsProvider) { - ClientConnectionManager connectionManager = null; - if (requestURL.toLowerCase().startsWith("https")) { - // Register a protocol scheme for https that uses Taverna's - // SSLSocketFactory - try { - URL url = new URL(requestURL); // the URL object which will - // parse the port out for us - int port = url.getPort(); - if (port == -1) // no port was defined in the URL - port = HTTPS_DEFAULT_PORT; // default HTTPS port - Scheme https = new Scheme("https", new org.apache.http.conn.ssl.SSLSocketFactory( - SSLContext.getDefault()), port); - SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(https); - connectionManager = new SingleClientConnManager(null, - schemeRegistry); - } catch (MalformedURLException ex) { - logger.error("Failed to extract port from the REST service URL: the URL " - + requestURL + " is malformed.", ex); - // This will cause the REST activity to fail but this method - // seems not to throw an exception so we'll just log the error - // and let it go through - } catch (NoSuchAlgorithmException ex2) { - // This will cause the REST activity to fail but this method - // seems not to throw an exception so we'll just log the error - // and let it go through - logger.error( - "Failed to create SSLContext for invoking the REST service over https.", - ex2); - } - } - - switch (configBean.getHttpMethod()) { - case GET: - return doGET(connectionManager, requestURL, configBean, urlParameters, credentialsProvider); - case POST: - return doPOST(connectionManager, requestURL, configBean, inputMessageBody, urlParameters, credentialsProvider); - case PUT: - return doPUT(connectionManager, requestURL, configBean, inputMessageBody, urlParameters, credentialsProvider); - case DELETE: - return doDELETE(connectionManager, requestURL, configBean, urlParameters, credentialsProvider); - default: - return new HTTPRequestResponse(new Exception("Error: something went wrong; " - + "no failure has occurred, but but unexpected HTTP method (\"" - + configBean.getHttpMethod() + "\") encountered.")); - } - } - - private static HTTPRequestResponse doGET(ClientConnectionManager connectionManager, - String requestURL, RESTActivityConfigurationBean configBean, - Map<String, String> urlParameters, CredentialsProvider credentialsProvider) { - HttpGet httpGet = new HttpGet(requestURL); - return performHTTPRequest(connectionManager, httpGet, configBean, urlParameters, credentialsProvider); - } - - private static HTTPRequestResponse doPOST(ClientConnectionManager connectionManager, - String requestURL, RESTActivityConfigurationBean configBean, Object inputMessageBody, - Map<String, String> urlParameters, CredentialsProvider credentialsProvider) { - HttpPost httpPost = new HttpPost(requestURL); - - // TODO - decide whether this is needed for PUT requests, too (or just - // here, for POST) - // check whether to send the HTTP Expect header or not - if (!configBean.getSendHTTPExpectRequestHeader()) - httpPost.getParams().setBooleanParameter("http.protocol.expect-continue", false); - - // If the user wants to set MIME type for the 'Content-Type' header - if (!configBean.getContentTypeForUpdates().isEmpty()) - httpPost.setHeader(CONTENT_TYPE_HEADER_NAME, configBean.getContentTypeForUpdates()); - try { - HttpEntity entity = null; - if (inputMessageBody == null) { - entity = new StringEntity(""); - } else if (configBean.getOutgoingDataFormat() == DATA_FORMAT.String) { - entity = new StringEntity((String) inputMessageBody); - } else { - entity = new ByteArrayEntity((byte[]) inputMessageBody); - } - httpPost.setEntity(entity); - } catch (UnsupportedEncodingException e) { - return (new HTTPRequestResponse(new Exception("Error occurred while trying to " - + "attach a message body to the POST request. See attached cause of this " - + "exception for details."))); - } - return performHTTPRequest(connectionManager, httpPost, configBean, urlParameters, credentialsProvider); - } - - private static HTTPRequestResponse doPUT(ClientConnectionManager connectionManager, - String requestURL, RESTActivityConfigurationBean configBean, Object inputMessageBody, - Map<String, String> urlParameters, CredentialsProvider credentialsProvider) { - HttpPut httpPut = new HttpPut(requestURL); - if (!configBean.getContentTypeForUpdates().isEmpty()) - httpPut.setHeader(CONTENT_TYPE_HEADER_NAME, configBean.getContentTypeForUpdates()); - try { - HttpEntity entity = null; - if (inputMessageBody == null) { - entity = new StringEntity(""); - } else if (configBean.getOutgoingDataFormat() == DATA_FORMAT.String) { - entity = new StringEntity((String) inputMessageBody); - } else { - entity = new ByteArrayEntity((byte[]) inputMessageBody); - } - httpPut.setEntity(entity); - } catch (UnsupportedEncodingException e) { - return new HTTPRequestResponse(new Exception("Error occurred while trying to " - + "attach a message body to the PUT request. See attached cause of this " - + "exception for details.")); - } - return performHTTPRequest(connectionManager, httpPut, configBean, urlParameters, credentialsProvider); - } - - private static HTTPRequestResponse doDELETE(ClientConnectionManager connectionManager, - String requestURL, RESTActivityConfigurationBean configBean, - Map<String, String> urlParameters, CredentialsProvider credentialsProvider) { - HttpDelete httpDelete = new HttpDelete(requestURL); - return performHTTPRequest(connectionManager, httpDelete, configBean, urlParameters, credentialsProvider); - } - - /** - * TODO - REDIRECTION output:: if there was no redirection, should just show - * the actual initial URL? - * - * @param httpRequest - * @param acceptHeaderValue - */ - private static HTTPRequestResponse performHTTPRequest( - ClientConnectionManager connectionManager, HttpRequestBase httpRequest, - RESTActivityConfigurationBean configBean, - Map<String, String> urlParameters, CredentialsProvider credentialsProvider) { - // headers are set identically for all HTTP methods, therefore can do - // centrally - here - - // If the user wants to set MIME type for the 'Accepts' header - String acceptsHeaderValue = configBean.getAcceptsHeaderValue(); - if ((acceptsHeaderValue != null) && !acceptsHeaderValue.isEmpty()) { - httpRequest.setHeader(ACCEPT_HEADER_NAME, - URISignatureHandler.generateCompleteURI(acceptsHeaderValue, urlParameters, configBean.getEscapeParameters())); - } - - // See if user wanted to set any other HTTP headers - ArrayList<ArrayList<String>> otherHTTPHeaders = configBean.getOtherHTTPHeaders(); - if (!otherHTTPHeaders.isEmpty()) - for (ArrayList<String> httpHeaderNameValuePair : otherHTTPHeaders) - if (httpHeaderNameValuePair.get(0) != null - && !httpHeaderNameValuePair.get(0).isEmpty()) { - String headerParameterizedValue = httpHeaderNameValuePair.get(1); - String headerValue = URISignatureHandler.generateCompleteURI(headerParameterizedValue, urlParameters, configBean.getEscapeParameters()); - httpRequest.setHeader(httpHeaderNameValuePair.get(0), headerValue); - } - - try { - HTTPRequestResponse requestResponse = new HTTPRequestResponse(); - DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager, null); - ((DefaultHttpClient) httpClient).setCredentialsProvider(credentialsProvider); - HttpContext localContext = new BasicHttpContext(); - - // Set the proxy settings, if any - if (System.getProperty(PROXY_HOST) != null - && !System.getProperty(PROXY_HOST).isEmpty()) { - // Instruct HttpClient to use the standard - // JRE proxy selector to obtain proxy information - ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(httpClient - .getConnectionManager().getSchemeRegistry(), ProxySelector.getDefault()); - httpClient.setRoutePlanner(routePlanner); - // Do we need to authenticate the user to the proxy? - if (System.getProperty(PROXY_USERNAME) != null - && !System.getProperty(PROXY_USERNAME).isEmpty()) - // Add the proxy username and password to the list of - // credentials - httpClient.getCredentialsProvider().setCredentials( - new AuthScope(System.getProperty(PROXY_HOST), Integer.parseInt(System - .getProperty(PROXY_PORT))), - new UsernamePasswordCredentials(System.getProperty(PROXY_USERNAME), - System.getProperty(PROXY_PASSWORD))); - } - - // execute the request - HttpResponse response = httpClient.execute(httpRequest, localContext); - - // record response code - requestResponse.setStatusCode(response.getStatusLine().getStatusCode()); - requestResponse.setReasonPhrase(response.getStatusLine().getReasonPhrase()); - - // record header values for Content-Type of the response - requestResponse.setResponseContentTypes(response.getHeaders(CONTENT_TYPE_HEADER_NAME)); - - // track where did the final redirect go to (if there was any) - HttpHost targetHost = (HttpHost) localContext - .getAttribute(ExecutionContext.HTTP_TARGET_HOST); - HttpUriRequest targetRequest = (HttpUriRequest) localContext - .getAttribute(ExecutionContext.HTTP_REQUEST); - requestResponse.setRedirectionURL("" + targetHost + targetRequest.getURI()); - requestResponse.setRedirectionHTTPMethod(targetRequest.getMethod()); - requestResponse.setHeaders(response.getAllHeaders()); - - /* read and store response body - (check there is some content - negative length of content means - unknown length; - zero definitely means no content...)*/ - // TODO - make sure that this test is sufficient to determine if - // there is no response entity - if (response.getEntity() != null && response.getEntity().getContentLength() != 0) - requestResponse.setResponseBody(readResponseBody(response.getEntity())); - - // release resources (e.g. connection pool, etc) - httpClient.getConnectionManager().shutdown(); - return requestResponse; - } catch (Exception ex) { - return new HTTPRequestResponse(ex); - } - } - - /** - * Dispatcher method that decides on the method of reading the server - * response data - either as a string or as binary data. - * - * @param entity - * @return - * @throws IOException - */ - private static Object readResponseBody(HttpEntity entity) throws IOException { - if (entity == null) - return null; - - /* - * test whether the data is binary or textual - for binary data will - * read just as it is, for textual data will attempt to perform charset - * conversion from the original one into UTF-8 - */ - - if (entity.getContentType() == null) - // HTTP message contains a body but content type is null??? - we - // have seen services like this - return readFromInputStreamAsBinary(entity.getContent()); - - String contentType = entity.getContentType().getValue().toLowerCase(); - if (contentType.startsWith("text") || contentType.contains("charset=")) - // read as text - return readResponseBodyAsString(entity); - // read as binary - enough to pass the input stream, not the - // whole entity - return readFromInputStreamAsBinary(entity.getContent()); - } - - /** - * Worker method that extracts the content of the received HTTP message as a - * string. It also makes use of the charset that is specified in the - * Content-Type header of the received data to read it appropriately. - * - * @param entity - * @return - * @throws IOException - */ - private static String readResponseBodyAsString(HttpEntity entity) throws IOException { - /* - * From RFC2616 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - * Content-Type = "Content-Type" ":" media-type, where media-type = type - * "/" subtype *( ";" parameter ) can have 0 or more parameters such as - * "charset", etc. Linear white space (LWS) MUST NOT be used between the - * type and subtype, nor between an attribute and its value. e.g. - * Content-Type: text/html; charset=ISO-8859-4 - */ - - // get charset name - String charset = null; - String contentType = entity.getContentType().getValue().toLowerCase(); - - String[] contentTypeParts = contentType.split(";"); - for (String contentTypePart : contentTypeParts) { - contentTypePart = contentTypePart.trim(); - if (contentTypePart.startsWith("charset=")) - charset = contentTypePart.substring("charset=".length()); - } - - // read the data line by line - StringBuilder responseBodyString = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader( - entity.getContent(), charset != null ? charset : "UTF-8"))) { - - String str; - while ((str = reader.readLine()) != null) - responseBodyString.append(str + "\n"); - - return responseBodyString.toString(); - } - } - - /** - * Worker method that extracts the content of the input stream as binary - * data. - * - * @param inputStream - * @return - * @throws IOException - */ - public static byte[] readFromInputStreamAsBinary(InputStream inputStream) throws IOException { - // use BufferedInputStream for better performance - try (BufferedInputStream in = new BufferedInputStream(inputStream)) { - // this list is to hold all fetched data - List<byte[]> data = new ArrayList<byte[]>(); - - // set up buffers for reading the data - int bufLength = 100 * 1024; // 100K - byte[] buf = new byte[bufLength]; - byte[] currentPortionOfData = null; - int currentlyReadByteCount = 0; - - // read the data portion by portion into a list - while ((currentlyReadByteCount = in.read(buf, 0, bufLength)) != -1) { - currentPortionOfData = new byte[currentlyReadByteCount]; - System.arraycopy(buf, 0, currentPortionOfData, 0, currentlyReadByteCount); - data.add(currentPortionOfData); - } - - // now check how much data was read and return that as a single byte - // array - if (data.size() == 1) - // just a single block of data - return it as it is - return data.get(0); - - // there is more than one block of data -- calculate total - // length of data - bufLength = 0; - for (byte[] portionOfData : data) - bufLength += portionOfData.length; - - // allocate a single large byte array that could contain all - // data - buf = new byte[bufLength]; - - // fill this byte array with data from all fragments - int lastFilledPositionInOutputArray = 0; - for (byte[] portionOfData : data) { - System.arraycopy(portionOfData, 0, buf, - lastFilledPositionInOutputArray, portionOfData.length); - lastFilledPositionInOutputArray += portionOfData.length; - } - - return buf; - } - } - - /** - * All fields have public accessor, but private mutators. This is because it - * should only be allowed to modify the HTTPRequestResponse partially inside - * the HTTPRequestHandler class only. For users of this class it will behave - * as immutable. - * - * @author Sergejs Aleksejevs - */ - public static class HTTPRequestResponse { - private int statusCode; - private String reasonPhrase; - private String redirectionURL; - private String redirectionHTTPMethod; - private Header[] responseContentTypes; - private Object responseBody; - - private Exception exception; - private Header[] allHeaders; - - /** - * Private default constructor - will only be accessible from - * HTTPRequestHandler. Values for the entity will then be set using the - * private mutator methods. - */ - private HTTPRequestResponse() { - /* - * do nothing here - values will need to be manually set later by - * using private mutator methods - */ - } - - public void setHeaders(Header[] allHeaders) { - this.allHeaders = allHeaders; - } - - public Header[] getHeaders() { - return allHeaders; - } - - public List<String> getHeadersAsStrings() { - List<String> headerStrings = new ArrayList<String>(); - for (Header h : getHeaders()) { - headerStrings.add(h.toString()); - } - return headerStrings; - } - - /** - * Standard public constructor for a regular case, where all values are - * known and the request has succeeded. - * - * @param statusCode - * @param reasonPhrase - * @param redirection - * @param responseContentTypes - * @param responseBody - */ - public HTTPRequestResponse(int statusCode, String reasonPhrase, String redirectionURL, - String redirectionHTTPMethod, Header[] responseContentTypes, String responseBody) { - this.statusCode = statusCode; - this.reasonPhrase = reasonPhrase; - this.redirectionURL = redirectionURL; - this.redirectionHTTPMethod = redirectionHTTPMethod; - this.responseContentTypes = responseContentTypes; - this.responseBody = responseBody; - } - - /** - * Standard public constructor for an error case, where an error has - * occurred and request couldn't be executed because of an internal - * exception (rather than an error received from the remote server). - * - * @param exception - */ - public HTTPRequestResponse(Exception exception) { - this.exception = exception; - } - - private void setStatusCode(int statusCode) { - this.statusCode = statusCode; - } - - public int getStatusCode() { - return statusCode; - } - - public String getReasonPhrase() { - return reasonPhrase; - } - - private void setReasonPhrase(String reasonPhrase) { - this.reasonPhrase = reasonPhrase; - } - - public String getRedirectionURL() { - return redirectionURL; - } - - private void setRedirectionURL(String redirectionURL) { - this.redirectionURL = redirectionURL; - } - - public String getRedirectionHTTPMethod() { - return redirectionHTTPMethod; - } - - private void setRedirectionHTTPMethod(String redirectionHTTPMethod) { - this.redirectionHTTPMethod = redirectionHTTPMethod; - } - - public Header[] getResponseContentTypes() { - return responseContentTypes; - } - - private void setResponseContentTypes(Header[] responseContentTypes) { - this.responseContentTypes = responseContentTypes; - } - - public Object getResponseBody() { - return responseBody; - } - - private void setResponseBody(Object outputBody) { - this.responseBody = outputBody; - } - - /** - * @return <code>true</code> if an exception has occurred while the HTTP - * request was executed. (E.g. this doesn't indicate a server - * error - just that the request couldn't be successfully - * executed. It could have been a network timeout, etc). - */ - public boolean hasException() { - return (this.exception != null); - } - - public Exception getException() { - return exception; - } - - /** - * @return <code>true</code> if HTTP code of server response is either - * 4xx or 5xx. - */ - public boolean hasServerError() { - return (statusCode >= 400 && statusCode < 600); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequestHeader.java ---------------------------------------------------------------------- diff --git a/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequestHeader.java b/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequestHeader.java deleted file mode 100644 index 5885870..0000000 --- a/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/HTTPRequestHeader.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2011 The University of Manchester - * - * Modifications to the initial code base are copyright of their - * respective authors, or their employers as appropriate. - * - * This program 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 program 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 program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - ******************************************************************************/ -package net.sf.taverna.t2.activities.rest; - -import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean; -import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty; - -/** - * HTTP Request Header configuration bean - * - * @author David Withers - */ -@ConfigurationBean(uri = "http://www.w3.org/2011/http#RequestHeader") -public class HTTPRequestHeader { - - private String fieldName, fieldValue; - - private boolean use100Continue; - - public String getFieldName() { - return fieldName; - } - - @ConfigurationProperty(name = "fieldName", label = "HTTP Header Name") - public void setFieldName(String fieldName) { - this.fieldName = fieldName; - } - - public String getFieldValue() { - return fieldValue; - } - - @ConfigurationProperty(name = "fieldValue", label = "HTTP Header Value") - public void setFieldValue(String fieldValue) { - this.fieldValue = fieldValue; - } - - public boolean isUse100Continue() { - return use100Continue; - } - - @ConfigurationProperty(name = "use100Continue", label = "Use 100 Continue", required = false, uri = RESTActivity.URI - + "#use100Continue") - public void setUse100Continue(boolean use100Continue) { - this.use100Continue = use100Continue; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/2e8f451e/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/RESTActivity.java ---------------------------------------------------------------------- diff --git a/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/RESTActivity.java b/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/RESTActivity.java deleted file mode 100644 index 76625f8..0000000 --- a/taverna-rest-activity/src/main/java/net/sf/taverna/t2/activities/rest/RESTActivity.java +++ /dev/null @@ -1,345 +0,0 @@ -package net.sf.taverna.t2.activities.rest; - -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import net.sf.taverna.t2.activities.rest.HTTPRequestHandler.HTTPRequestResponse; -import net.sf.taverna.t2.activities.rest.URISignatureHandler.URISignatureParsingException; -import net.sf.taverna.t2.invocation.InvocationContext; -import net.sf.taverna.t2.reference.ErrorDocument; -import net.sf.taverna.t2.reference.ReferenceService; -import net.sf.taverna.t2.reference.T2Reference; -import net.sf.taverna.t2.workflowmodel.processor.activity.AbstractAsynchronousActivity; -import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException; -import net.sf.taverna.t2.workflowmodel.processor.activity.AsynchronousActivityCallback; - -import org.apache.http.client.CredentialsProvider; -import org.apache.log4j.Logger; - -import com.fasterxml.jackson.databind.JsonNode; - -/** - * Generic REST activity that is capable to perform all four HTTP methods. - * - * @author Sergejs Aleksejevs - */ -public class RESTActivity extends AbstractAsynchronousActivity<JsonNode> { - - public static final String URI = "http://ns.taverna.org.uk/2010/activity/rest"; - - private static Logger logger = Logger.getLogger(RESTActivity.class); - - // This generic activity can deal with any of the four HTTP methods - public static enum HTTP_METHOD { - GET, POST, PUT, DELETE - }; - - // Default choice of data format (especially, for outgoing data) - public static enum DATA_FORMAT { - String(String.class), Binary(byte[].class); - - private final Class<?> dataFormat; - - DATA_FORMAT(Class<?> dataFormat) { - this.dataFormat = dataFormat; - } - - public Class<?> getDataFormat() { - return this.dataFormat; - } - }; - - // These ports are default ones; additional ports will be dynamically - // generated from the - // URI signature used to configure the activity - public static final String IN_BODY = "inputBody"; - public static final String OUT_RESPONSE_BODY = "responseBody"; - public static final String OUT_RESPONSE_HEADERS = "responseHeaders"; - public static final String OUT_STATUS = "status"; - public static final String OUT_REDIRECTION = "redirection"; - public static final String OUT_COMPLETE_URL = "actualURL"; - - // Configuration bean for this activity - essentially defines a particular - // instance - // of the activity through the values of its parameters - private RESTActivityConfigurationBean configBean; - private JsonNode json; - - private CredentialsProvider credentialsProvider; - - public RESTActivity(CredentialsProvider credentialsProvider) { - this.credentialsProvider = credentialsProvider; - } - - @Override - public JsonNode getConfiguration() { - return json; - } - - public RESTActivityConfigurationBean getConfigurationBean() { - return configBean; - } - - @Override - public void configure(JsonNode json) throws ActivityConfigurationException { - this.json = json; - configBean = new RESTActivityConfigurationBean(json); - // Check configBean is valid - mainly check the URI signature for being - // well-formed and - // other details being present and valid; - // - // NB! The URI signature will still be valid if there are no - // placeholders at all - in this - // case for GET and DELETE methods no input ports will be generated and - // a single input - // port for input message body will be created for POST / PUT methods. - if (!configBean.isValid()) { - throw new ActivityConfigurationException( - "Bad data in the REST activity configuration bean - " - + "possible causes are: missing or ill-formed URI signature, missing or invalid MIME types for the " - + "specified HTTP headers ('Accept' | 'Content-Type'). This should not have happened, as validation " - + "on the UI had to be performed prior to accepting this configuration."); - } - - // (Re)create input/output ports depending on configuration - configurePorts(); - } - - protected void configurePorts() { - // all input ports are dynamic and depend on the configuration - // of the particular instance of the REST activity - - // now process the URL signature - extract all placeholders and create - // an input data type for each - Map<String, Class<?>> activityInputs = new HashMap<>(); - List<String> placeholders = URISignatureHandler.extractPlaceholders(configBean - .getUrlSignature()); - String acceptsHeaderValue = configBean.getAcceptsHeaderValue(); - if (acceptsHeaderValue != null && !acceptsHeaderValue.isEmpty()) - try { - List<String> acceptsPlaceHolders = URISignatureHandler - .extractPlaceholders(acceptsHeaderValue); - acceptsPlaceHolders.removeAll(placeholders); - placeholders.addAll(acceptsPlaceHolders); - } catch (URISignatureParsingException e) { - logger.error(e); - } - for (ArrayList<String> httpHeaderNameValuePair : configBean.getOtherHTTPHeaders()) - try { - List<String> headerPlaceHolders = URISignatureHandler - .extractPlaceholders(httpHeaderNameValuePair.get(1)); - headerPlaceHolders.removeAll(placeholders); - placeholders.addAll(headerPlaceHolders); - } catch (URISignatureParsingException e) { - logger.error(e); - } - for (String placeholder : placeholders) - // these inputs will have a dynamic name each; - // the data type is string as they are the values to be - // substituted into the URL signature at the execution time - activityInputs.put(placeholder, String.class); - - // all inputs have now been configured - store the resulting set-up in - // the config bean; - // this configuration will be reused during the execution of activity, - // so that existing - // set-up could simply be referred to, rather than "re-calculated" - configBean.setActivityInputs(activityInputs); - - // ---- CREATE OUTPUTS ---- - // all outputs are of depth 0 - i.e. just a single value on each; - - // output ports for Response Body and Status are static - they don't - // depend on the configuration of the activity; - addOutput(OUT_RESPONSE_BODY, 0); - addOutput(OUT_STATUS, 0); - if (configBean.getShowActualUrlPort()) - addOutput(OUT_COMPLETE_URL, 0); - if (configBean.getShowResponseHeadersPort()) - addOutput(OUT_RESPONSE_HEADERS, 1); - - // Redirection port may be hidden/shown - if (configBean.getShowRedirectionOutputPort()) - addOutput(OUT_REDIRECTION, 0); - } - - /** - * Uses HTTP method value of the config bean of the current instance of - * RESTActivity. - * - * @see RESTActivity#hasMessageBodyInputPort(HTTP_METHOD) - */ - public boolean hasMessageBodyInputPort() { - return hasMessageBodyInputPort(configBean.getHttpMethod()); - } - - /** - * Return value of this method has a number of implications - various input - * ports and configuration options for this activity are applied based on - * the selected HTTP method. - * - * @param httpMethod - * HTTP method to make the decision for. - * @return True if this instance of the REST activity uses HTTP POST / PUT - * methods; false otherwise. - */ - public static boolean hasMessageBodyInputPort(HTTP_METHOD httpMethod) { - return httpMethod == HTTP_METHOD.POST || httpMethod == HTTP_METHOD.PUT; - } - - /** - * This method executes pre-configured instance of REST activity. It - * resolves inputs of the activity and registers its outputs; the real - * invocation of the HTTP request is performed by - * {@link HTTPRequestHandler#initiateHTTPRequest(String, RESTActivityConfigurationBean, String)} - * . - */ - @Override - public void executeAsynch(final Map<String, T2Reference> inputs, - final AsynchronousActivityCallback callback) { - // Don't execute service directly now, request to be run asynchronously - callback.requestRun(new Runnable() { - private Logger logger = Logger.getLogger(RESTActivity.class); - - @Override - public void run() { - - InvocationContext context = callback.getContext(); - ReferenceService referenceService = context.getReferenceService(); - - // ---- RESOLVE INPUTS ---- - - // RE-ASSEMBLE REQUEST URL FROM SIGNATURE AND PARAMETERS - // (just use the configuration that was determined in - // configurePorts() - all ports in this set are required) - Map<String, String> urlParameters = new HashMap<>(); - try { - for (String inputName : configBean.getActivityInputs().keySet()) - urlParameters.put(inputName, (String) referenceService.renderIdentifier( - inputs.get(inputName), configBean.getActivityInputs() - .get(inputName), context)); - } catch (Exception e) { - // problem occurred while resolving the inputs - callback.fail("REST activity was unable to resolve all necessary inputs" - + "that contain values for populating the URI signature placeholders " - + "with values.", e); - - // make sure we don't call callback.receiveResult later - return; - } - String completeURL = URISignatureHandler.generateCompleteURI( - configBean.getUrlSignature(), urlParameters, - configBean.getEscapeParameters()); - - // OBTAIN THE INPUT BODY IF NECESSARY - // ("IN_BODY" is treated as *optional* for now) - Object inputMessageBody = null; - if (hasMessageBodyInputPort() && inputs.containsKey(IN_BODY)) { - inputMessageBody = referenceService.renderIdentifier(inputs.get(IN_BODY), - configBean.getOutgoingDataFormat().getDataFormat(), context); - } - - // ---- DO THE ACTUAL SERVICE INVOCATION ---- - HTTPRequestResponse requestResponse = HTTPRequestHandler.initiateHTTPRequest( - completeURL, configBean, inputMessageBody, urlParameters, - credentialsProvider); - - // test if an internal failure has occurred - if (requestResponse.hasException()) { - callback.fail( - "Internal error has occurred while trying to execute the REST activity", - requestResponse.getException()); - - // make sure we don't call callback.receiveResult later - return; - } - - // ---- REGISTER OUTPUTS ---- - Map<String, T2Reference> outputs = new HashMap<String, T2Reference>(); - - T2Reference responseBodyRef = null; - if (requestResponse.hasServerError()) { - // test if a server error has occurred -- if so, return - // output as an error document - - // Check if error returned is a string - sometimes services return byte[] - ErrorDocument errorDocument = null; - if (requestResponse.getResponseBody() == null) { - // No response body - register empty string - errorDocument = referenceService.getErrorDocumentService().registerError( - "", 0, context); - } else { - if (requestResponse.getResponseBody() instanceof String) { - errorDocument = referenceService.getErrorDocumentService() - .registerError((String) requestResponse.getResponseBody(), 0, - context); - } else if (requestResponse.getResponseBody() instanceof byte[]) { - // Do the only thing we can - try to convert to - // UTF-8 encoded string - // and hope we'll get back something intelligible - String str = null; - try { - str = new String((byte[]) requestResponse.getResponseBody(), - "UTF-8"); - } catch (UnsupportedEncodingException e) { - logger.error( - "Failed to reconstruct the response body byte[]" - + " into string using UTF-8 encoding", - e); - // try with no encoding, probably will get garbage - str = new String((byte[]) requestResponse.getResponseBody()); - } - errorDocument = referenceService.getErrorDocumentService() - .registerError(str, 0, context); - } else { - // Do what we can - call toString() method and hope - // for the best - errorDocument = referenceService.getErrorDocumentService() - .registerError(requestResponse.getResponseBody().toString(), 0, - context); - } - } - responseBodyRef = referenceService.register(errorDocument, 0, true, context); - } else if (requestResponse.getResponseBody() != null) { - // some response data is available - responseBodyRef = referenceService.register(requestResponse.getResponseBody(), - 0, true, context); - } else { - // no data was received in response to the request - must - // have been just a response header... - responseBodyRef = referenceService.register("", 0, true, context); - } - outputs.put(OUT_RESPONSE_BODY, responseBodyRef); - - T2Reference statusRef = referenceService.register(requestResponse.getStatusCode(), - 0, true, context); - outputs.put(OUT_STATUS, statusRef); - - if (configBean.getShowActualUrlPort()) { - T2Reference completeURLRef = referenceService.register(completeURL, 0, true, - context); - outputs.put(OUT_COMPLETE_URL, completeURLRef); - } - if (configBean.getShowResponseHeadersPort()) - outputs.put(OUT_RESPONSE_HEADERS, referenceService.register( - requestResponse.getHeadersAsStrings(), 1, true, context)); - - // only put an output to the Redirection port if the processor - // is configured to display that port - if (configBean.getShowRedirectionOutputPort()) { - T2Reference redirectionRef = referenceService.register( - requestResponse.getRedirectionURL(), 0, true, context); - outputs.put(OUT_REDIRECTION, redirectionRef); - } - - // return map of output data, with empty index array as this is - // the only and final result (this index parameter is used if - // pipelining output) - callback.receiveResult(outputs, new int[0]); - } - }); - } -}