/// <summary> /// This is the entry point of the worker part of the process. It returns a first ExecuteResponse which /// will point to the stored Execute Response through it's statusLocation. /// </summary> /// <param name="args">Arguments</param> /// <param name="ret">Return value</param> /// <returns>The returnValue of the process.</returns> public override ProcessReturnValue Execute(ProcessInputParams args, ProcessReturnValue ret) { ///A simple check to make sure ret isn't null if (ret == null) ret = new ProcessReturnValue(); ///At this time, the process is accepted and will be executed. ret.status = ProcessState.Accepted; ///Provide advancement, obviously nothing has happened yet so it's 0% ret.percentageCompleted = 0; ///Make sure ret will be available to the async method, the easiest way is to copy it into ///the dedicated property of the class. If the thread is not parameterized, a Args property is also ///available. this.ExecuteResponseValue = ret; ///This check is performed to make sure this process is called asynchronously. Async processes ///are not compatible with synchronous calls at this time if (!ret.responseForm.responseDocument.storeExecuteResponse || !ret.responseForm.responseDocument.storeExecuteResponse) throw new Exception("This process must be executed asynchronously, please make sure that 'status' and 'storeExecuteResponse' are set to 'true'"); ///Initiate and start the worker thread. Thread workerThread = new Thread(new ParameterizedThreadStart(this.Work)); workerThread.IsBackground = false; workerThread.Start(args); ///Specify an empty output. this.ExecuteResponseValue.returnValues.Clear(); this.ExecuteResponseValue.returnValues.Add(new LiteralOutput("AsyncClockResult", "Async Clock Result", "A string containing the start datetime and the end datetime", "string")); ///Return the first response which will contain the statusLocation to the stored response ///(XML file stored on the server which will be updated with new values each time ///the ProgressChanged event is raised by this process. return ExecuteResponseValue; }
public ProcessData(ProcessReturnValue executeResponseValue, ProcessDescription processDescription, AppDomain parentAppDomain, AppDomain processAppDompain, int processProgress, Exception processError = null) { this.ExecuteResponseValue = executeResponseValue; this.ParentApplicationDomain = parentAppDomain; this.ProcessDescription = processDescription; this.Error = processError; this.ProcessApplicationDomain = processAppDompain; this.Progress = processProgress; }
public ProcessReturnValue CallProcess(ProcessInputParams args, ResponseFormType responseForm, bool asynchronous) { // A secondary operation domain has to be used so that the assemblies can be loaded/unloaded, as the function Assembly AppDomain operationDomain = null; ProcessReturnValue result = null; try { ArrayList methodArgs = new ArrayList(); methodArgs.Add(args); ProcessReturnValue processReturnValue = new ProcessReturnValue(); processReturnValue.responseForm = responseForm; methodArgs.Add(processReturnValue); operationDomain = Utils.CreateDomain(); if (!asynchronous) { // Load the assembly corresponding to the requested process Utils.AssemblyLoader assemblyLoader = Utils.AssemblyLoader.Create(operationDomain); assemblyLoader.Load(Utils.MapPath(Global.ProcessesBinPath + Identifier + ".dll")); result = (ProcessReturnValue)assemblyLoader.ExecuteMethod(processClass, processMethod, methodArgs.ToArray(), null); AppDomain.Unload(operationDomain); } else { asyncOperationDomain = operationDomain; asyncLoader = Utils.AssemblyLoader.Create(operationDomain); asyncLoader.Load(Utils.MapPath(Global.ProcessesBinPath + Identifier + ".dll")); result = (ProcessReturnValue)asyncLoader.ExecuteAsyncMethod(processClass, processMethod, methodArgs.ToArray(), new object[] { AppDomain.CurrentDomain, Global.StoredResultsPath, Utils.ResolveUrl(Global.StoredResultsPath) }); } } catch (ExceptionReport e) { if (operationDomain != null) { AppDomain.Unload(operationDomain); } throw new ExceptionReport(e, "An error occurred when invoking the process: " + Identifier + ". Check the process parameters. If necessary, contact the administrator."); } catch (Exception e) { if (operationDomain != null) { AppDomain.Unload(operationDomain); } throw new ExceptionReport("An error occurred when invoking the process: " + Identifier + ". Contact the administrator.\n" + e.ToString()); } return(result); }
private static XmlDocument FormatResponseMessage(ProcessDescription processDescription, ProcessInputParams args, ResponseFormType responseForm, ProcessReturnValue result, ExceptionReport exception, string xmlHeader = "") { // Format the response message StringBuilder retString = new StringBuilder(); retString.Append(xmlHeader); /* * if (responseForm.responseDocument.status) * {*/ retString.Append("<wps:Status creationTime=\"" + System.DateTime.Now.ToString("s") + "\">"); if (result.status == ProcessState.Succeeded) { retString.Append("<wps:ProcessSucceeded>" + (result.statusMessage != "" ? result.statusMessage : "Process completed successfully.") + "</wps:ProcessSucceeded>"); //TODO: retiré 'wps:' } else if (result.status == ProcessState.Accepted) { retString.Append("<wps:ProcessAccepted>" + (result.statusMessage != "" ? result.statusMessage : "Process has been accepted and is pending execution.") + "</wps:ProcessAccepted>"); //TODO: retiré 'wps:' } else if (result.status == ProcessState.Paused) { retString.Append("<wps:ProcessPaused percentCompleted=\"" + result.percentageCompleted + "\" >" + (result.statusMessage != "" ? result.statusMessage : "Process is paused.") + "</wps:ProcessPaused>"); } else if (result.status == ProcessState.Started) { retString.Append("<wps:ProcessStarted percentCompleted=\"" + result.percentageCompleted + "\" >" + (result.statusMessage != "" ? result.statusMessage : "Process is running.") + "</wps:ProcessStarted>"); } else if (result.status == ProcessState.Failed) { retString.Append("<wps:ProcessFailed>" + (exception != null ? exception.GetReport().InnerText + " - " + result.statusMessage : new ExceptionReport("Failed to execute WPS process : " + result.statusMessage, ExceptionCode.NoApplicableCode).GetReport().InnerText) + "</wps:ProcessFailed>"); } retString.Append("</wps:Status>"); // } if (responseForm.responseDocument.lineage) { retString.Append("<wps:DataInputs>"); foreach (KeyValuePair <string, InputData[]> ent in args.parameters) { foreach (InputData processInputParam in ent.Value) { retString.Append(processInputParam.GetXmlValue()); } } retString.Append("</wps:DataInputs>"); retString.Append("<wps:OutputDefinitions>"); // TODO do not retrieve output from return values (may not be the same as request) //foreach (OutputData processOutputParam in result.returnValues) foreach (OutputData processOutputParam in responseForm.responseDocument.Outputs) { retString.Append(processOutputParam.GetXmlDescription()); } retString.Append("</wps:OutputDefinitions>"); } if (result.returnValues.Count > 0) { retString.Append("<wps:ProcessOutputs>"); foreach (OutputData outputData in result.returnValues) { retString.Append(outputData.GetXmlValue()); } retString.Append("</wps:ProcessOutputs>"); } retString.Append("</wps:ExecuteResponse>"); try { XmlDocument doc = new XmlDocument(); doc.LoadXml(retString.ToString()); return(doc); } catch (Exception e) { throw new ExceptionReport("The service execution has encountered an error while formatting the result stream. Check the parameters values.\n" + e.ToString()); } }
public static XmlDocument Run(ProcessDescription processDescription, List <InputData> inputParams, ResponseFormType responseForm) { /* error is unreachable because check (via throwing an exception) is done before * if (processDescription == null) * throw new ExceptionReport("The ows:Identifier tag of the process can't be found in the xml file. It must be placed under the root 'Execute' node.", * ExceptionCode.MissingParameterValue);*/ string processId = processDescription.Identifier; List <InputData> processInputParams = processDescription.GetProcessInputParameters(); List <OutputData> processOutputParams = processDescription.GetProcessOutputParameters(); ExceptionReport exception = null; ProcessInputParams args = new ProcessInputParams(); // Get and check input parameters foreach (InputData processInputParam in processInputParams) { int occurs = 0; bool loop = processInputParam.MaxOccurs > 0 || processInputParam.MaxOccurs == -1; List <InputData> iargs = new List <InputData>(); while (loop) { loop = false; foreach (InputData input in inputParams) { if (input.Identifier != processInputParam.Identifier) { continue; } if (!input.IsValueAllowed()) { exception = new ExceptionReport(exception, "The parameter " + input.Identifier + " has not a valid value!", ExceptionCode.InvalidParameterValue, input.Identifier); } occurs++; iargs.Add(input.Clone()); inputParams.Remove(input); loop = true; break; } } if (occurs < processInputParam.MinOccurs || (occurs > processInputParam.MaxOccurs && processInputParam.MaxOccurs != -1)) { exception = new ExceptionReport(exception, "The parameter " + processInputParam.Identifier + " has " + occurs + " occurrences but it should have at least " + processInputParam.MinOccurs + " and at most " + processInputParam.MaxOccurs + " occurrences.", ExceptionCode.InvalidParameterValue, processInputParam.Identifier); } // default value for LiteralData if (occurs == 0 && processInputParam.asLiteralInput() != null && !String.IsNullOrEmpty(processInputParam.asLiteralInput().Default)) { iargs.Add(processInputParam); } args.parameters[processInputParam.Identifier] = iargs.ToArray(); } if (exception != null) { throw exception; } ProcessReturnValue result = null; try { processDescription = ProcessDescription.GetProcessDescription(processId); if (responseForm.responseDocument != null && responseForm.responseDocument.status && responseForm.responseDocument.storeExecuteResponse) { result = processDescription.CallProcess(args, responseForm, true); } else { result = processDescription.CallProcess(args, responseForm, false); } } catch (ExceptionReport e) { if (responseForm.responseDocument != null && responseForm.responseDocument.status) { exception = e; } else { throw;// new ExceptionReport(e, "Error during process...", ExceptionCode.NoApplicableCode); } } int requestedOutputCount = result.GetOutputIdentifiers().Count; int returnedOutputCount = result.returnValues.Count; // Problem during the process (validity check is done before launching the process)! if (requestedOutputCount != returnedOutputCount) { throw new ExceptionReport(String.Format("The process has generated {0} output{1} but {2} {3} requested. Contact the administrator to fix the process issue.", returnedOutputCount, returnedOutputCount > 1 ? "s" : "", requestedOutputCount, requestedOutputCount > 1 ? "were" : "was"), ExceptionCode.NoApplicableCode); } if (responseForm.outputDefinition != null) { OutputData data = result.returnValues[0]; if (result.fileName == "") { result.fileName = processId + "RawDataOuput"; } HttpContext.Current.Response.Clear(); HttpContext.Current.Response.ClearHeaders(); HttpContext.Current.Response.StatusCode = 200; HttpContext.Current.Response.Buffer = true; // not needed because rawdataoutput can only concern a ComplexOutput //string mimeType = (data is ComplexOutput) ? ((ComplexOutput)data).format.mimeType : "text/plain"; string mimeType = data.asComplexOutput().Format.mimeType; HttpContext.Current.Response.ContentType = mimeType; string dispo = true ? "inline" : "attachment"; HttpContext.Current.Response.AddHeader("Content-Disposition", dispo + "; filename=" + System.Uri.EscapeDataString(result.fileName)); HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); byte[] content = data.ToByteArray(); HttpContext.Current.Response.AddHeader("Content-Length", "" + content.Length); HttpContext.Current.Response.AddHeader("cache-control", "must-revalidate"); HttpContext.Current.Response.OutputStream.Write(content, 0, content.Length); HttpContext.Current.Response.Flush(); HttpContext.Current.ApplicationInstance.CompleteRequest(); return(new XmlDocument()); } else { s_processStartDate = DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss_ffff"); s_processArgs = args; s_responseHeader = Global.XmlHeader + "<wps:ExecuteResponse " + Global.WPSServiceVersion + " xml:lang='" + processDescription.Language + "' serviceInstance='" + HttpContext.Current.Request.Url.AbsoluteUri.Split('?')[0] + "?service=WPS&Request=GetCapabilities' " + Global.WPSXmlSchemas + " " + Global.WPSExecuteSchema /** In case of storeExecuteResponse==true : append the absolute url to the stored response file */ /**/ + (responseForm.responseDocument.storeExecuteResponse ? " statusLocation='" /**/ + Utils.ResolveUrl(Global.StoredResponsesPath /**/ + processDescription.processClass + "/response_" /**/ + s_processStartDate + ".xml' ") : " ") /************************************************************************************************/ + ">" + Environment.NewLine + "<wps:Process wps:processVersion=\"" + processDescription.Version + "\"><ows:Identifier>" + processDescription.Identifier + "</ows:Identifier><ows:Title>" + processDescription.Title + "</ows:Title></wps:Process>"; //TODO: retiré 'wps:' XmlDocument xmlResponse = FormatResponseMessage(processDescription, s_processArgs, responseForm, result, exception, s_responseHeader); if (responseForm.responseDocument.storeExecuteResponse) { if (!Directory.Exists(Global.StoredResponsesPath + "/" + processDescription.processClass)) { Directory.CreateDirectory(Global.StoredResponsesPath + "/" + processDescription.processClass); } xmlResponse.Save(Global.StoredResponsesPath + processDescription.processClass + "/response_" + s_processStartDate + ".xml"); } HttpContext.Current.Response.StatusCode = 200; return(xmlResponse); } }
public ProcessReturnValue Execute(ProcessInputParams args, ProcessReturnValue ret) { float fresult = 0; float fa = 0, fb = 0; ComplexInput a = args.GetData("a", 0).asComplexInput(); ComplexInput b = args.GetData("b", 0).asComplexInput(); XmlDocument doc = new XmlDocument(); try { doc.LoadXml(a.ToString()); fa = float.Parse(doc.InnerText); } catch { } try { doc.LoadXml(b.ToString()); fb = float.Parse(doc.InnerText); } catch { } LiteralInput oper = args.GetData("operator", 0).asLiteralInput(); string myOperator = oper.ToString(); if (ret.IsOutputIdentifierRequested("result")) { switch (myOperator) { case "sub": fresult = fa - fb; break; case "mult": fresult = fa * fb; break; case "div": if (fb != 0) fresult = fa / fb; else fresult = fa; break; case "add": default: fresult = fa + fb; break; } ComplexOutput result = null; List<OutputData> outputs = ret.GetOutputsForIdentifier("result"); if (ret.IsRawDataOutput()) { ret.fileName = "result.xml"; result = outputs[0].asComplexOutput(); result.SetValue(String.Format("<?xml version='1.0' encoding='{0}'?>\n<number>{1}</number>", result.Format.encoding, fresult)); ret.AddData(result); } else { foreach (OutputData output in outputs) { result = output.asComplexOutput(); result.SetValue("<number>" + fresult + "</number>"); ret.AddData(result); } } } ret.status = ProcessState.Succeeded; return ret; }
public ProcessReturnValue Execute(ProcessInputParams args, ProcessReturnValue ret) { int sum = 0; int i = 0; while (true) { LiteralInput a = args.GetData("a", i++).asLiteralInput(); if (a == null) break; sum += Int32.Parse(a.ToString()); } LiteralInput b = args.GetData("b", 0).asLiteralInput(); int ib = Int32.Parse(b.ToString()); sum += ib; if (ret.IsOutputIdentifierRequested("sum")) { List<OutputData> outputs = ret.GetOutputsForIdentifier("sum"); // Output 1: a literal containing the raw sum LiteralOutput sumOutput = null; foreach (OutputData output in outputs) { sumOutput = output.asLiteralOutput(); sumOutput.Value = sum.ToString(); ret.AddData(sumOutput); } } if (ret.IsOutputIdentifierRequested("sumFile")) { List<OutputData> outputs = ret.GetOutputsForIdentifier("sumFile"); // Output 2: a complex data type - plain text by default if (ret.IsRawDataOutput()) { ComplexOutput sumOutput = outputs[0].asComplexOutput(); if (Utils.StrICmp(sumOutput.Format.mimeType, "text/xml")) { sumOutput.SetValue("<number>" + sum + "</number>"); ret.fileName = "result.xml"; } else if (Utils.StrICmp(sumOutput.Format.mimeType, "plain/text")) { sumOutput.SetValue("sum is " + sum); ret.fileName = "result.txt"; } ret.AddData(sumOutput); } else { ComplexOutput sumOutput = null; foreach (OutputData output in outputs) { sumOutput = output.asComplexOutput(); if (Utils.StrICmp(sumOutput.Format.mimeType, "text/xml")) sumOutput.SetValue("<number>" + sum + "</number>"); else sumOutput.SetValue("sum is " + sum); ret.AddData(sumOutput); } } } ret.status = ProcessState.Succeeded; return ret; }
public ProcessReturnValue CallProcess(ProcessInputParams args, ResponseFormType responseForm, bool asynchronous) { // A secondary operation domain has to be used so that the assemblies can be loaded/unloaded, as the function Assembly AppDomain operationDomain = null; ProcessReturnValue result = null; try { ArrayList methodArgs = new ArrayList(); methodArgs.Add(args); ProcessReturnValue processReturnValue = new ProcessReturnValue(); processReturnValue.responseForm = responseForm; methodArgs.Add(processReturnValue); operationDomain = Utils.CreateDomain(); if (!asynchronous) { // Load the assembly corresponding to the requested process Utils.AssemblyLoader assemblyLoader = Utils.AssemblyLoader.Create(operationDomain); assemblyLoader.Load(Utils.MapPath(Global.ProcessesBinPath + Identifier + ".dll")); result = (ProcessReturnValue)assemblyLoader.ExecuteMethod(processClass, processMethod, methodArgs.ToArray(), null); AppDomain.Unload(operationDomain); } else { asyncOperationDomain = operationDomain; asyncLoader = Utils.AssemblyLoader.Create(operationDomain); asyncLoader.Load(Utils.MapPath(Global.ProcessesBinPath + Identifier + ".dll")); result = (ProcessReturnValue)asyncLoader.ExecuteAsyncMethod(processClass, processMethod, methodArgs.ToArray(), new object[] { AppDomain.CurrentDomain, Global.StoredResultsPath, Utils.ResolveUrl(Global.StoredResultsPath) }); } } catch (ExceptionReport e) { if (operationDomain != null) AppDomain.Unload(operationDomain); throw new ExceptionReport(e, "An error occurred when invoking the process: " + Identifier + ". Check the process parameters. If necessary, contact the administrator."); } catch (Exception e) { if (operationDomain != null) AppDomain.Unload(operationDomain); throw new ExceptionReport("An error occurred when invoking the process: " + Identifier + ". Contact the administrator.\n" + e.ToString()); } return result; }
public abstract ProcessReturnValue Execute(ProcessInputParams args, ProcessReturnValue ret);
private static XmlDocument FormatResponseMessage(ProcessDescription processDescription, ProcessInputParams args, ResponseFormType responseForm, ProcessReturnValue result, ExceptionReport exception, string xmlHeader = "") { // Format the response message StringBuilder retString = new StringBuilder(); retString.Append(xmlHeader); /* if (responseForm.responseDocument.status) {*/ retString.Append("<wps:Status creationTime=\"" + System.DateTime.Now.ToString("s") + "\">"); if (result.status == ProcessState.Succeeded) { retString.Append("<wps:ProcessSucceeded>" + (result.statusMessage != "" ? result.statusMessage : "Process completed successfully.") + "</wps:ProcessSucceeded>"); //TODO: retiré 'wps:' } else if (result.status == ProcessState.Accepted) { retString.Append("<wps:ProcessAccepted>" + (result.statusMessage != "" ? result.statusMessage : "Process has been accepted and is pending execution.") + "</wps:ProcessAccepted>"); //TODO: retiré 'wps:' } else if (result.status == ProcessState.Paused) { retString.Append("<wps:ProcessPaused percentCompleted=\""+result.percentageCompleted+"\" >" + (result.statusMessage != "" ? result.statusMessage : "Process is paused.") + "</wps:ProcessPaused>"); } else if (result.status == ProcessState.Started) { retString.Append("<wps:ProcessStarted percentCompleted=\""+result.percentageCompleted+"\" >" + (result.statusMessage != "" ? result.statusMessage : "Process is running.") + "</wps:ProcessStarted>"); } else if (result.status == ProcessState.Failed) { retString.Append("<wps:ProcessFailed>" + (exception != null ? exception.GetReport().InnerText + " - " + result.statusMessage : new ExceptionReport("Failed to execute WPS process : "+result.statusMessage, ExceptionCode.NoApplicableCode).GetReport().InnerText) + "</wps:ProcessFailed>"); } retString.Append("</wps:Status>"); // } if (responseForm.responseDocument.lineage) { retString.Append("<wps:DataInputs>"); foreach (KeyValuePair<string, InputData[]> ent in args.parameters) foreach (InputData processInputParam in ent.Value) retString.Append(processInputParam.GetXmlValue()); retString.Append("</wps:DataInputs>"); retString.Append("<wps:OutputDefinitions>"); // TODO do not retrieve output from return values (may not be the same as request) //foreach (OutputData processOutputParam in result.returnValues) foreach (OutputData processOutputParam in responseForm.responseDocument.Outputs) retString.Append(processOutputParam.GetXmlDescription()); retString.Append("</wps:OutputDefinitions>"); } if (result.returnValues.Count > 0) { retString.Append("<wps:ProcessOutputs>"); foreach (OutputData outputData in result.returnValues) retString.Append(outputData.GetXmlValue()); retString.Append("</wps:ProcessOutputs>"); } retString.Append("</wps:ExecuteResponse>"); try { XmlDocument doc = new XmlDocument(); doc.LoadXml(retString.ToString()); return doc; } catch (Exception e) { throw new ExceptionReport("The service execution has encountered an error while formatting the result stream. Check the parameters values.\n" + e.ToString()); } }