Index: trunk/docs/kernel/configuration.rst
===================================================================
--- trunk/docs/kernel/configuration.rst	(revision 961)
+++ trunk/docs/kernel/configuration.rst	(revision 962)
@@ -450,5 +450,16 @@
  * ``header_parameters``: the parameters list client applications can send as header
  * ``version``: the Open API Specification version
-   
+ * ``license_name``: the license name for the service
+ * ``license_url``: the license URL
+ * ``full_html_support``: set it to true to activate support of the
+   Accept header to choose between text/html or application/json
+   format  
+ * ``partial_html_support``: set it to true in case you have the
+   display service from the `open-api directory
+   <http://zoo-project.org/trac/browser/trunk/zoo-project/zoo-services/utils/open-api/cgi-env//cgi-env>`__
+   and you want to aknowledge the text/html format in links
+ * ``wsUrl``: the WebSocket URL to subscribe client to redis
+ * ``publisherUrl``: the URL used to publish status updates
+
 For any links and paths ``/A`` defined, you will have a corresponding
 ``[/A]`` and ``[A]`` sections. In the ``[/A]`` section you will define
@@ -494,4 +505,26 @@
  * ``[conformTo]``: referring to links list of the requirements classes the server implements and conforms to
 
+
+In case you have set ``partial_html_support`` or
+``partial_html_support`` set to true, then you can add a corresponding
+``[A.html]`` section providing the link informations. Also, it means
+that you are willing to let the client choose in between
+application/json and text/html format by providing the corresponding
+Accept header in its request, when ``full_html_support`` is set to
+true or by using the ``.html`` extension in the URL, in case
+``partial_html_support`` was set true. Also, the user interface
+provided in the `open-api directory
+<http://zoo-project.org/trac/browser/trunk/zoo-project/zoo-services/utils/open-api/cgi-env//cgi-env>`__ 
+will let the client goes untill the execution of a job. In case you
+want this functionality to be working correctly we invite you to use a
+``.htaccess`` equivalent to the one provided `here
+<http://zoo-project.org/trac/browser/trunk/zoo-project/zoo-services/utils/open-api/server/.htacess>`__. Also
+the WebSocket can be started using websocketd in combinaison with the
+`subscriber.py
+<http://zoo-project.org/trac/browser/trunk/zoo-project/zoo-services/utils/open-api/server/subscriber.py>`__
+script, finally you will need to add the `publish.py
+<http://zoo-project.org/trac/browser/trunk/zoo-project/zoo-services/utils/open-api/server/publish.py>`__
+script in the cgi-bin directory of your web server.
+
 For more information on how to interact with this WPS REST Binding, please refer
 to this `page
Index: trunk/zoo-project/HISTORY.txt
===================================================================
--- trunk/zoo-project/HISTORY.txt	(revision 961)
+++ trunk/zoo-project/HISTORY.txt	(revision 962)
@@ -1,6 +1,18 @@
 Version 1.8.0-dev
+  * Update OGC API - Processes documentation
+  * Add open-api directory in utils services containing a reddis
+  subscription example, the HTML UI and the display service using
+  Cheetah templating system
+  * Update the oas.cfg file to reflect new api definition
+  * Include basic microdata in the HTML home page 
+  * Add HTML support for basic interractions with OGC API - Processes
+  including execution of service from the service-desc link
+  * OGC API - Processes added support for syncrhonous Execute requests
+  * Reuse service_callback in OGC API - Processes when subscriber
+  object is provided in the JSON request
+  * OGC API - Processes implementation as available on 2020-10-19
   * Produce value string only when memory=load for Python support.
   * Make local files uris usable when cache is used
-  * Make GDAL/prilfe service usable in case memory=protect 
+  * Make GDAL/profile service usable in case memory=protect 
   * Add Dockerfile and docker-compose environment with pgbouncer, see #177
   * Add documentation on how to use asyncrhonous execution using the Javascript
Index: trunk/zoo-project/zoo-kernel/Makefile.in
===================================================================
--- trunk/zoo-project/zoo-kernel/Makefile.in	(revision 961)
+++ trunk/zoo-project/zoo-kernel/Makefile.in	(revision 962)
@@ -45,5 +45,5 @@
 
 service_callback.o: service_callback.c
-	g++ -fPIC ${XML2CFLAGS} ${GDAL_CFLAGS} ${JSON_CFLAGS} ${CFLAGS} -c service_callback.c
+	gcc -fPIC ${XML2CFLAGS} ${GDAL_CFLAGS} ${JSON_CFLAGS} ${CFLAGS} -c service_callback.c
 
 request_parser.o: request_parser.c request_parser.h
Index: trunk/zoo-project/zoo-kernel/configure.ac
===================================================================
--- trunk/zoo-project/zoo-kernel/configure.ac	(revision 961)
+++ trunk/zoo-project/zoo-kernel/configure.ac	(revision 962)
@@ -85,9 +85,9 @@
 		[], [AC_MSG_ERROR([could not find function in json-c library])])
 	CPPFLAGS="$CPPFLAGS_SAVE"
-	JSON_FILE="service_json.o"
+	JSON_FILE="service_json.o service_callback.o"
 	JSON_ENABLED="-DJSON"
 	if test "x$CALLBACK_ACTIVATED" == "xyes"
 	then
-		CALLBACK_FILE="service_callback.o"
+		CALLBACK_FILE=""
 		CALLBACK_USE="-DUSE_CALLBACK"
 	fi
Index: trunk/zoo-project/zoo-kernel/oas.cfg
===================================================================
--- trunk/zoo-project/zoo-kernel/oas.cfg	(revision 961)
+++ trunk/zoo-project/zoo-kernel/oas.cfg	(revision 962)
@@ -1,23 +1,15 @@
 [openapi]
-rootUrl=https://demo.mapmint.com/wps3/
+use_content=false
+rootUrl=https://myserver/ogc-api
 links=/,/api,/conformance,/processes
-paths=/root,/api,/conformance,/processes,/processes/{id},/processes/{id}/jobs,/processes/{id}/jobs/{jobID},/processes/{id}/jobs/{jobID}/result
+paths=/root,/api,/conformance,/processes,/processes/{id},/processes/{id}/jobs,/processes/{id}/jobs/{jobID},/processes/{id}/jobs/{jobID}/results
 parameters=id,jobID,resultID
-header_parameters=oas-header1,oas-header2
-version=3.0.1
-
-[oas-header1]
-in=header
-name=Prefer
-type=string
-required=false
-enum=respond-async
-
-[oas-header2]
-in=header
-name=Prefer
-type=string
-required=false
-enum=return=representation,return=minimal
+version=3.0.2
+license_name=OGC license
+license_url=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/LICENSE
+full_html_support=false
+partial_html_support=true
+wsUrl=wss://demo.mapmint.com:4430/
+publisherUrl=http://127.0.0.1/cgi-bin3/publish.py?jobid=
 
 [/]
@@ -32,10 +24,21 @@
 tags=Home
 tags_description=
-schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/root.yaml
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/LandingPage.yaml
+
+[/index.html]
+rel=alternate
+type=text/html
 
 [/api]
-rel=service
+rel=service-desc
 type=application/openapi+json;version=3.0
 title=the API definition
+
+[/api.html]
+rel=service-doc
+type=text/hml
+
+[api.html]
+href=https://demo.mapmint.com/swagger-ui/ogc-api-processes/
 
 [api]
@@ -55,8 +58,12 @@
 method=get
 title=information about standards that this API conforms to
-abstract==list all requirements classes specified in a standard (e.g., WPS REST/JSON Binding Core) that the server conforms to
+abstract=list all requirements classes specified in a standard (e.g., WPS REST/JSON Binding Core) that the server conforms to
 tags=Conformance
 tags_description=
-schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/req-classes.yaml
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/ConformanceDeclaration.yaml
+
+[/conformance.html]
+rel=alternate
+type=text/hml
 
 [/processes]
@@ -71,5 +78,9 @@
 tags=GetCapabilities
 tags_description=
-schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/processCollection.yaml
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/ProcessList.yaml
+
+[/processes.html]
+rel=alternate
+type=text/hml
 
 [processes/{id}]
@@ -79,5 +90,6 @@
 tags=ProcessDescription
 tags_description=
-schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/process.yaml
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/ProcessDescription.yaml
+ecode=404
 parameters=/components/parameters/id
 
@@ -95,6 +107,7 @@
 tags=JobList
 tags_description=
-schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/jobCollection.yaml
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/JobList.yaml
 parameters=/components/parameters/id
+ecode=404,500
 method_1=post
 title_1=execute a job
@@ -102,6 +115,9 @@
 tags_1=Execute Endpoint
 tags_description_1=
-schema_1=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/result.yaml
-parameters_1=/components/parameters/id,/components/parameters/oas-header1
+schema_1=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/ExecuteSync.yaml
+parameters_1=/components/parameters/id
+ecode_1=400,404,500
+eschema_1=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/ExecuteAsync.yaml
+ep=,/components/parameters/oas-header1
 
 [requestBody]
@@ -116,4 +132,5 @@
 
 [processes/{id}/jobs/{jobID}]
+length=2
 method=get
 title=The status of a job.
@@ -121,13 +138,22 @@
 tags=GetStatus
 tags_description=
-schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/statusInfo.yaml
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/Status.yaml
 parameters=/components/parameters/id,/components/parameters/jobID
-
-[/processes/{id}/jobs/{jobID}/result]
+method_1=delete
+title_1=Cancel a job
+abstract_1=Cancel the job execution.
+tags_1=Dismiss
+tags_description_1=Cencel a job execution
+schema_1=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/Status.yaml
+parameters_1=/components/parameters/id,/components/parameters/jobID
+ecode_1=404,500
+
+
+[/processes/{id}/jobs/{jobID}/results]
 rel=canonical
 type=application/json
 title=Get Result
 
-[processes/{id}/jobs/{jobID}/result]
+[processes/{id}/jobs/{jobID}/results]
 method=get
 title=The result of a job execution.
@@ -135,6 +161,7 @@
 tags=GetResult
 tags_description=
-schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/result.yaml
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/Results.yaml
 parameters=/components/parameters/id,/components/parameters/jobID
+ecode=404,500
 ep=,/components/parameters/oas-header2
 
@@ -151,5 +178,6 @@
 tags_description=
 schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/valueType.yaml
-parameters=/components/parameters/id,/components/parameters/jobID,/components/parameters/resultID,/components/parameters/oas-header2
+parameters=/components/parameters/id,/components/parameters/jobID,/components/parameters/resultID
+ep=,/components/parameters/oas-header2
 
 
@@ -184,13 +212,83 @@
 required=false
 
-[conformTo]
-rootUrl=http://www.opengis.net/spec/WPS/2.0/req/service/binding/rest-json/
+[conformsTo]
+rootUrl=http://www.opengis.net/spec/ogcapi-processes/1.0/conf/
+rootUrl0=http://www.opengis.net/spec/WPS/2.0/req/service/binding/rest-json/
 link=core
 link_1=oas30
 link_2=json
-length=3
+link_3=job-list
+link_4=dismiss
+link_5=callback
+length=6
 
 [exception]
 abstract=Exception
 type=application/json
-schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/exception.yaml
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/NotFound.yaml
+default_schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/ServerError.yaml
+
+[responses]
+length=5
+code=404
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/NotFound.yaml
+type=application/json
+title=NotFound
+code_1=500
+schema_1=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/ServerError.yaml
+type_1=application/json
+title_1=ServerError
+code_2=400
+schema_2=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/InvalidParameter.yaml
+type_2=appliction/json
+title_2=InvalidParameter
+code_3=405
+schema_3=https://github.com/opengeospatial/wps-rest-binding/blob/master/core/openapi/responses/NotAllowed.yaml
+type_3=appliction/json
+title_3=NotAllowed
+code_4=406
+schema_4=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/responses/NotSupported.yaml
+type_4=appliction/json
+title_4=NotSupported
+
+[callbacks]
+length=3
+state=jobSuccess
+uri=successUri
+schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/result.yaml
+type=application/json
+title=Results received successfully
+state_1=jobInProgress
+uri_1=inProgressUri
+schema_1=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/statusInfo.yaml
+type_1=application/json
+title_1=Results received successfully
+state_2=jobFailed
+uri_2=failedUrii
+schema_2=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/exception.yaml
+type_2=application/json
+title_2=Exception received successfully
+
+[links_title]
+self=View this document in JSON.
+alternate=View the alternative version in HTML.
+conformance=View the specifications that the link’s context conforms to.
+service-desc=View the service description.
+service-doc=View service documentation.
+processes=View the list of processes the API offers.
+results=View the results of a process.
+status=View the current status of a job execution.
+execute=View the execution endpoint of a process.
+
+[provider_alt]
+addressDeliveryPoint=streetAddress
+addressCity=addressLocality
+addressAdministrativeArea=addressRegion
+addressPostalCode=postalCode
+addressCountry=addressCountry
+addressElectronicMailAddress=email
+phoneVoice=telephone
+phoneFacsimile=faxNumber
+hoursOfService=hoursAvailable
+contactInstructions=contactOption
+
Index: trunk/zoo-project/zoo-kernel/otbZooWatcher.cxx
===================================================================
--- trunk/zoo-project/zoo-kernel/otbZooWatcher.cxx	(revision 961)
+++ trunk/zoo-project/zoo-kernel/otbZooWatcher.cxx	(revision 962)
@@ -45,5 +45,8 @@
     {
       int progressPercent = static_cast<int>(m_Process->GetProgress() * 100);
-      updateStatus(m_Conf,progressPercent,m_Comment.c_str());
+      if(progressPercent>iCounter){
+	updateStatus(m_Conf,progressPercent,m_Comment.c_str());
+	iCounter=progressPercent;
+      }
     }
 }
@@ -56,4 +59,5 @@
   m_TimeProbe.Start();
 #endif
+  iCounter=-1;
 }
 
Index: trunk/zoo-project/zoo-kernel/otbZooWatcher.h
===================================================================
--- trunk/zoo-project/zoo-kernel/otbZooWatcher.h	(revision 961)
+++ trunk/zoo-project/zoo-kernel/otbZooWatcher.h	(revision 962)
@@ -87,4 +87,7 @@
   maps* m_Conf;
 
+  /** Counter */
+  int iCounter;
+
 };
 
Index: trunk/zoo-project/zoo-kernel/request_parser.c
===================================================================
--- trunk/zoo-project/zoo-kernel/request_parser.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/request_parser.c	(revision 962)
@@ -317,5 +317,6 @@
 		    if (strncasecmp (tmpx2, "http://", 7) != 0 &&
 			strncasecmp (tmpx2, "ftp://", 6) != 0 &&
-			strncasecmp (tmpx2, "https://", 8) != 0)
+			strncasecmp (tmpx2, "https://", 8) != 0 &&
+			strncasecmp (tmpx2, "file://", 7) != 0)
 		      {
 			char emsg[1024];
Index: trunk/zoo-project/zoo-kernel/response_print.c
===================================================================
--- trunk/zoo-project/zoo-kernel/response_print.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/response_print.c	(revision 962)
@@ -2719,15 +2719,5 @@
   }
   if(res==SERVICE_FAILED){
-    map *lenv;
-    lenv=getMapFromMaps(m,"lenv","message");
-    char *tmp0;
-    if(lenv!=NULL){
-      tmp0=(char*)malloc((strlen(lenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char));
-      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
-    }
-    else{
-      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
-      sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
-    }
+    char* tmp0=produceErrorMessage(m);
     errorException(m,tmp0,"InternalError",NULL);
     free(tmp0);
Index: trunk/zoo-project/zoo-kernel/server_internal.c
===================================================================
--- trunk/zoo-project/zoo-kernel/server_internal.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/server_internal.c	(revision 962)
@@ -952,6 +952,8 @@
       free(res);
     }
-  else
-    addToMap(statusInfo,"Status","Failed");  
+  else{
+    addToMap(statusInfo,"Status","Failed");
+    addToMap(statusInfo,"NotFound",pid);
+  }
   free(fbkpid);
 }
@@ -992,19 +994,33 @@
 void runGetStatus(maps* conf,char* pid,char* req){
   map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  map* e_type = getMapFromMaps (conf, "lenv", "executionType");
   char *sid=getStatusId(conf,pid);
   if(sid==NULL){
-    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
-		    "NoSuchJob", pid);
+    if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0)
+      errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
+		      "NoSuchJob", pid);
+    else{
+      setMapInMaps(conf,"lenv","error","true");
+      setMapInMaps(conf,"lenv","code","NoSuchJob");
+      setMapInMaps(conf,"lenv","message",_("The JobID from the request does not match any of the Jobs running on this server"));
+    }
   }else{
     map* statusInfo=createMap("JobID",pid);
-    if(isRunning(conf,pid)>0){		
+    if(isRunning(conf,pid)>0){
       if(strncasecmp(req,"GetResult",strlen(req))==0){
-	errorException (conf, _("The result for the requested JobID has not yet been generated. The service is currently running."),
-			"ResultNotReady", pid);
+	if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0)
+	  errorException (conf, _("The result for the requested JobID has not yet been generated. The service is currently running."),
+			  "ResultNotReady", pid);
+	else{
+	  setMapInMaps(conf,"lenv","error","true");
+	  setMapInMaps(conf,"lenv","code","ResultNotReady");
+	  setMapInMaps(conf,"lenv","message",_("The result for the requested JobID has not yet been generated. The service is currently running."));
+	}
 	return;
       }
-      else
+      else{
 	if(strncasecmp(req,"GetStatus",strlen(req))==0){
 	  addToMap(statusInfo,"Status","Running");
+	  setMapInMaps(conf,"lenv","status","Running");
 	  char* tmpStr=_getStatus(conf,pid);
 	  if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
@@ -1015,8 +1031,11 @@
 	    addToMap(statusInfo,"PercentCompleted",tmpStr1);
 	    addToMap(statusInfo,"Message",tmpStr0);
+	    setMapInMaps(conf,"lenv","PercentCompleted",tmpStr1);
+	    setMapInMaps(conf,"lenv","Message",tmpStr0);
 	    free(tmpStr0);
 	    free(tmpStr1);
 	  }
 	}
+      }
     }
     else{
@@ -1043,4 +1062,9 @@
 	if(strncasecmp(req,"GetStatus",strlen(req))==0){
 	  readFinalRes(conf,pid,statusInfo);
+	  if(e_type==NULL || strncasecmp(e_type->value,"json",4)==0){
+	    map* pmStatus=getMap(statusInfo,"status");	    
+	    if(pmStatus!=NULL)
+	      setMapInMaps(conf,"lenv","status",pmStatus->value);    
+	  }
 	  char* tmpStr=_getStatus(conf,pid);
 	  if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
@@ -1051,4 +1075,6 @@
 	    addToMap(statusInfo,"PercentCompleted",tmpStr1);
 	    addToMap(statusInfo,"Message",tmpStr0);
+	    setMapInMaps(conf,"lenv","PercentCompleted",tmpStr1);
+	    setMapInMaps(conf,"lenv","Message",tmpStr0);
 	    free(tmpStr0);
 	    free(tmpStr1);
@@ -1057,5 +1083,8 @@
     }
     free(sid);
-    printStatusInfo(conf,statusInfo,req);
+    if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0)
+      printStatusInfo(conf,statusInfo,req);
+    else
+      setMapInMaps(conf,"lenv","error","false");
     freeMap(&statusInfo);
     free(statusInfo);
@@ -1072,8 +1101,16 @@
 void runDismiss(maps* conf,char* pid){
   map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  map* e_type = getMapFromMaps (conf, "lenv", "executionType");
   char *sid=getStatusId(conf,pid);
   if(sid==NULL){
-    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
-		    "NoSuchJob", pid);
+    if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0)
+      errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
+		      "NoSuchJob", pid);
+    else{
+      setMapInMaps(conf,"lenv","error","true");
+      setMapInMaps(conf,"lenv","code","NoSuchJob");
+      setMapInMaps(conf,"lenv","message",_("The JobID from the request does not match any of the Jobs running on this server"));
+    }
+    return;
   }else{
     // We should send the Dismiss request to the target host if it differs
@@ -1115,24 +1152,48 @@
 	  sprintf(fileName,"%s/%s",r_inputs->value,dp->d_name);
 	  if(zUnlink(fileName)!=0){
-	    errorException (conf, 
-			    _("The job cannot be removed, a file cannot be removed"),
-			    "NoApplicableCode", NULL);
+	    if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0)
+	      errorException (conf, 
+			      _("The job cannot be removed, a file cannot be removed"),
+			      "NoApplicableCode", NULL);
+	    else{
+	            setMapInMaps(conf,"lenv","error","true");
+		    setMapInMaps(conf,"lenv","code","NoApplicableCode");
+		    setMapInMaps(conf,"lenv","message",_("The job cannot be removed, a file cannot be removed"));
+	    }
 	    return;
 	  }
-	}
-      }
-    }
+	  
+	}
+      }
+    }
+    map* pmStatusFile=getMapFromMaps(conf,"lenv","file.statusFile");
+    if(pmStatusFile!=NULL && zUnlink(pmStatusFile->value)!=0){
+	if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0)
+	  errorException (conf, 
+			  _("The job cannot be removed, a file cannot be removed"),
+			  "NoApplicableCode", NULL);
+	else{
+	  setMapInMaps(conf,"lenv","error","true");
+		    setMapInMaps(conf,"lenv","code","NoApplicableCode");
+		    setMapInMaps(conf,"lenv","message",_("The job cannot be removed, a file cannot be removed"));
+	}
+	return;
+      }
 #ifdef RELY_ON_DB
     removeService(conf,pid);
 #endif
-    /* No need to call 7_1 when an execution is dismissed.
-      fprintf(stderr,"************************* %s %d \n\n",__FILE__,__LINE__);
-      invokeCallback(conf,NULL,NULL,7,1);
-      fprintf(stderr,"************************* %s %d \n\n",__FILE__,__LINE__);
-    */
-    map* statusInfo=createMap("JobID",pid);
-    addToMap(statusInfo,"Status","Dismissed");
-    printStatusInfo(conf,statusInfo,"Dismiss");
-    free(statusInfo);
+    if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0){
+      /* No need to call 7_1 when an execution is dismissed.
+	 fprintf(stderr,"************************* %s %d \n\n",__FILE__,__LINE__);
+	 invokeCallback(conf,NULL,NULL,7,1);
+	 fprintf(stderr,"************************* %s %d \n\n",__FILE__,__LINE__);
+      */
+      map* statusInfo=createMap("JobID",pid);
+      addToMap(statusInfo,"Status","Dismissed");
+      printStatusInfo(conf,statusInfo,"Dismiss");
+      free(statusInfo);
+    }else{
+      setMapInMaps(conf,"lenv","error","false");
+    }
   }
   return;
@@ -1249,4 +1310,24 @@
 }
 
+/**
+ * Create a string containing the basic error message.
+ *
+ * @param pmConf the main configuration maps pointer
+ * @return a new char* containing the error message (ressource should be freed)
+ */
+char* produceErrorMessage(maps* pmConf){
+  char *pacTmp;
+  map *pmLenv=getMapFromMaps(pmConf,"lenv","message");
+  if(pmLenv!=NULL){
+    pacTmp=(char*)malloc((strlen(pmLenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char));
+    sprintf(pacTmp,_("Unable to run the Service. The message returned back by the Service was the following: %s"),pmLenv->value);
+  }
+  else{
+    pacTmp=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
+    sprintf(pacTmp,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
+  }
+  return pacTmp;
+}
+
 #ifdef WIN32
 /**
Index: trunk/zoo-project/zoo-kernel/server_internal.h
===================================================================
--- trunk/zoo-project/zoo-kernel/server_internal.h	(revision 961)
+++ trunk/zoo-project/zoo-kernel/server_internal.h	(revision 962)
@@ -60,5 +60,7 @@
   void dumpMapsValuesToFiles(maps**,maps**);
   void runDismiss(maps*,char*);
+  int isRunning(maps*,char*);
   void runGetStatus(maps*,char*,char*);
+  void readFinalRes(maps*,char*,map*);
 
   int isValidLang(maps*,const char*);
@@ -67,4 +69,5 @@
   int readServiceFile (maps *, char *, service **, char *);
   int createRegistry (maps*,registry **,char *);
+  char* produceErrorMessage(maps*);
 
   int zoo_path_compare(char* path1, char* path2);
Index: trunk/zoo-project/zoo-kernel/service.h
===================================================================
--- trunk/zoo-project/zoo-kernel/service.h	(revision 961)
+++ trunk/zoo-project/zoo-kernel/service.h	(revision 962)
@@ -185,4 +185,8 @@
  */
 #define SERVICE_FAILED 4
+/**
+ * The global dismissed status for a service
+ */
+#define SERVICE_DISMISSED 5
 
 /**
Index: trunk/zoo-project/zoo-kernel/service_callback.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service_callback.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/service_callback.c	(revision 962)
@@ -27,7 +27,5 @@
  */
 
-#include "service_json.h"
 #include "service_internal_ms.h"
-#include "sqlapi.h"
 #include <pthread.h>
 #include <libxml/tree.h>
@@ -42,4 +40,8 @@
 
 #include "service_callback.h"
+#include "service_json.h"
+#include "sqlapi.h"
+#include <ulinet.h>
+
 
 #ifdef __cplusplus
@@ -66,4 +68,8 @@
    */
   int cStep=0;
+  /**
+   * Maximum value of PercentCompleted
+   */
+  int maxProgress=0;
   /**
    * Is there any ongoing HTTP request
@@ -112,5 +118,171 @@
     return false;
   }
-
+  /**
+   * Practically invoke the callback, meaning sending the HTTP POST request.
+   * 
+   * @param args local_params containing all the variables required
+   */
+  void* _invokeBasicCallback(void* args){
+#ifdef CALLBACK_DEBUG
+    fprintf(stderr,"************************* From thread %d %s %d: REQUEST CONFIGURE (%s)\n",pthread_self(),__FILE__,__LINE__,arg->url->value);
+    fflush(stderr);
+#endif
+    local_params* arg=(local_params*)args;
+    if(arg->state<cStep){
+#ifdef CALLBACK_DEBUG
+      fprintf(stderr,"************************* From thread %d %s %d: REQUEST CANCELLED (%s) EXIT!\n",pthread_self(),__FILE__,__LINE__,arg->url->value);
+      fflush(stderr);
+#endif
+      freeMaps(&arg->conf);
+      free(arg->conf);
+      freeMap(&arg->url);
+      free(arg->url);
+      pthread_exit(NULL);
+      return NULL;
+    }
+    HINTERNET hInternet,res1;
+    const struct tm *tm;
+    size_t len;
+    char *tmp1;
+    map *tmpStatus;
+    map* pmTmp=getMapFromMaps(arg->conf,"lenv","status");
+    hInternet=InternetOpen("ZooWPSClient\0",
+			   INTERNET_OPEN_TYPE_PRECONFIG,
+			   NULL,NULL, 0);
+    if(!CHECK_INET_HANDLE(hInternet)){
+      InternetCloseHandle (&hInternet);
+      return NULL;
+    }
+    const char* jsonStr=json_object_to_json_string_ext(arg->res,JSON_C_TO_STRING_PLAIN);
+    while( arg->state != SERVICE_SUCCEEDED && arg->state != SERVICE_FAILED && isOngoing>0 ){
+      zSleep(100);
+    }
+    if(arg->state==SERVICE_STARTED && pmTmp!=NULL){
+      if(maxProgress<=atoi(pmTmp->value)){
+	maxProgress=atoi(pmTmp->value);
+      }else{
+#ifdef CALLBACK_DEBUG
+	fprintf(stderr,"************************* From thread %d %s %d: REQUEST CANCELLED (%s) EXIT!\n",pthread_self(),__FILE__,__LINE__,arg->url->value);
+	fflush(stderr);
+#endif
+	freeMaps(&arg->conf);
+	free(arg->conf);
+	freeMap(&arg->url);
+	free(arg->url);
+	pthread_exit(NULL);
+	return NULL;
+      }
+    }else
+      maxProgress=101;
+    isOngoing=1;
+    maps* tmpConf=createMaps("main");
+    tmpConf->content=createMap("memory","load");
+
+    hInternet.waitingRequests[0] = zStrdup(arg->url->value);
+    res1 = InternetOpenUrl (&hInternet,
+			    hInternet.waitingRequests[0], 
+			    (char*)jsonStr, strlen(jsonStr),
+			    INTERNET_FLAG_NO_CACHE_WRITE,
+			    0,tmpConf);
+    AddHeaderEntries(&hInternet,arg->conf);
+    AddMissingHeaderEntry(&hInternet.ihandle[hInternet.nb-1],"Content-Type","application/json");
+#ifdef CALLBACK_DEBUG
+    curl_easy_setopt(hInternet.ihandle[hInternet.nb-1].handle, CURLOPT_VERBOSE, 1);
+#endif
+    if(hInternet.ihandle[hInternet.nb-1].header!=NULL)
+      curl_easy_setopt(hInternet.ihandle[hInternet.nb-1].handle,CURLOPT_HTTPHEADER,hInternet.ihandle[hInternet.nb-1].header);
+    processDownloads(&hInternet);
+    freeMaps(&tmpConf);
+    free(tmpConf);
+#ifdef CALLBACK_DEBUG
+    char *tmp = (char *) malloc ((hInternet.ihandle[0].nDataLen + 1)
+				 * sizeof (char));
+    if (tmp == NULL)
+      {
+	setMapInMaps(arg->conf,"lenv","message",_("Unable to allocate memory"));
+	setMapInMaps(arg->conf,"lenv","code","InternalError");
+	return NULL;
+      }
+    size_t bRead;
+    InternetReadFile (hInternet.ihandle[0],
+		      (LPVOID) tmp,
+		      hInternet.
+		      ihandle[0].nDataLen,
+		      &bRead);
+    tmp[hInternet.ihandle[0].nDataLen] = 0;
+    fprintf(stderr,"************************* From thread %d %s %d: REQUEST END \n%s",pthread_self(),__FILE__,__LINE__,tmp);
+    fflush(stderr);
+    free(tmp);
+#endif
+    json_object_put(arg->res);
+    InternetCloseHandle(&hInternet);
+    isOngoing=0;
+    freeMaps(&arg->conf);
+    free(arg->conf);
+    freeMap(&arg->url);
+    if(arg->url!=NULL)
+      free(arg->url);
+    pthread_exit(NULL);
+  }
+
+  /**
+   * Invoke the callback in case there is a [subscriber] section containing one
+   * or more url parameter.
+   * 
+   * @param conf the maps containing the main configuration file definitions
+   * @param state the service state SERVICE_SUCCEEDED / STARTED / FAILED
+   * @return bool true in case of success, false in other cases
+   */
+  bool invokeBasicCallback(maps* conf,int state){
+    map* url=getMapFromMaps(conf,"subscriber","inProgressUri");
+    if(state==SERVICE_SUCCEEDED)
+      url=getMapFromMaps(conf,"subscriber","successUri");
+    else
+      if(state==SERVICE_FAILED)
+	url=getMapFromMaps(conf,"subscriber","failedUri");
+    if(url==NULL)
+      return false;
+    map* url0=createMap("url",url->value);
+    map* sname=getMapFromMaps(conf,"lenv","identifier");
+    if(sname!=NULL && isProhibited(conf,sname->value))
+      return false;
+    if(state<cStep)
+      return true;
+    if(cStep!=state || isOngoing==0){
+      json_object *res=NULL;
+      if(state==SERVICE_SUCCEEDED || state==SERVICE_FAILED){
+	maps* pmsTmp=getMaps(conf,"lenv");
+	setMapInMaps(conf,"lenv","no-write","true");
+	map* pmTmp=getMapFromMaps(conf,"lenv","usid");
+	if(pmTmp!=NULL){
+	  map* pmResponse=getMapFromMaps(conf,"lenv","jsonStr");
+	  res=parseJson(conf,pmResponse->value);
+	}
+      }else
+	res=createStatus(conf,state);
+      if(local_arguments==NULL)
+	local_arguments=(local_params**)malloc(sizeof(local_params*));
+      else
+	local_arguments=(local_params**)realloc(local_arguments,(nbThreads+1)*sizeof(local_params*));
+      local_arguments[nbThreads]=(local_params*)malloc(MAPS_SIZE+MAP_SIZE+sizeof(json_object*)+(2*sizeof(int)));	
+      local_arguments[nbThreads]->conf=dupMaps(&conf);
+      local_arguments[nbThreads]->url=url0;
+      local_arguments[nbThreads]->res=res;
+      local_arguments[nbThreads]->step=0;
+      local_arguments[nbThreads]->state=state;
+      cStep=state;
+      if(myThreads==NULL)
+	myThreads=(pthread_t*)malloc((nbThreads+1)*sizeof(pthread_t));
+      else
+	myThreads=(pthread_t*)realloc(myThreads,(nbThreads+1)*sizeof(pthread_t));
+      if(pthread_create(&myThreads[nbThreads], NULL, _invokeBasicCallback, (void*)local_arguments[nbThreads])==-1){
+	setMapInMaps(conf,"lenv","message",_("Unable to create a new thread"));
+	return false;
+      }
+      nbThreads++;
+    }
+    return true;
+  }
+  
   /**
    * Practically invoke the callback, meaning sending the HTTP POST request.
@@ -336,5 +508,5 @@
 	      map* tmpMap=getMapArray(curs->content,"value",ii);
 	      char tmpStr[100];
-	      sprintf(tmpStr,"%d",strlen(tmpMap->value));
+	      sprintf(tmpStr,"%ld",strlen(tmpMap->value));
 	      setMapArray(curs->content,"size",ii,tmpStr);
 	      tmpMap=getMapArray(curs->content,"mimeType",ii);
@@ -570,16 +742,18 @@
 	      jsStr=json_object_new_string(tmp2->value);
 	      json_object_object_add(res2,"target_path",jsStr);
-	      json_object *res4=json_object_object_get(res1,tmp0->value);
-	      if(json_object_is_type(res4,json_type_null)){
-		json_object_object_add(res1,tmp0->value,res2);
-	      }else{
-		if(json_object_is_type(res4,json_type_object) && !json_object_is_type(res4, json_type_array)){
-		  json_object *res3=json_object_new_array();
-		  json_object_array_add(res3,json_object_get(res4));
-		  json_object_array_add(res3,res2);
-		  json_object_object_del(res1,tmp0->value);
-		  json_object_object_add(res1,tmp0->value,res3);
-		}else
-		  json_object_array_add(res4,res2);
+	      json_object *res4=NULL;
+	      if(json_object_object_get_ex(res1,tmp0->value,&res4)!=FALSE){
+		if(json_object_is_type(res4,json_type_null)){
+		  json_object_object_add(res1,tmp0->value,res2);
+		}else{
+		  if(json_object_is_type(res4,json_type_object) && !json_object_is_type(res4, json_type_array)){
+		    json_object *res3=json_object_new_array();
+		    json_object_array_add(res3,json_object_get(res4));
+		    json_object_array_add(res3,res2);
+		    json_object_object_del(res1,tmp0->value);
+		    json_object_object_add(res1,tmp0->value,res3);
+		  }else
+		    json_object_array_add(res4,res2);
+		}
 	      }
 	    }
@@ -866,4 +1040,7 @@
    */
   void cleanupCallbackThreads(){
+    while( isOngoing>0 ){
+      zSleep(100);
+    }
     int i=0;
     for(i=0;i<nbThreads;i++){
Index: trunk/zoo-project/zoo-kernel/service_callback.h
===================================================================
--- trunk/zoo-project/zoo-kernel/service_callback.h	(revision 961)
+++ trunk/zoo-project/zoo-kernel/service_callback.h	(revision 962)
@@ -32,7 +32,4 @@
 #pragma once
 
-#include <ulinet.h>
-#include <stdio.h>
-#include <ctype.h>
 #include <service.h>
 
@@ -41,4 +38,5 @@
 #endif
 
+  bool invokeBasicCallback(maps*,int);
   bool invokeCallback(maps*,maps*,maps*,int,int);
   void cleanupCallbackThreads();
Index: trunk/zoo-project/zoo-kernel/service_internal.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service_internal.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/service_internal.c	(revision 962)
@@ -412,5 +412,6 @@
     free(fbkpid);
     char* stat=getStatusId(conf,lid);
-    setMapInMaps(conf,"lenv","lid",stat);
+    if(stat!=NULL)
+      setMapInMaps(conf,"lenv","lid",stat);
     removeShmLock(conf,1);
     return NULL;
@@ -470,4 +471,5 @@
       fflush(fstatus);
       fclose(fstatus);
+      invokeBasicCallback(conf,SERVICE_STARTED);
     }
     if(stat!=NULL){
Index: trunk/zoo-project/zoo-kernel/service_internal_otb.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service_internal_otb.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/service_internal_otb.c	(revision 962)
@@ -122,8 +122,12 @@
   map* tmp=NULL;
   int res=-1;
+  int saved_stdout = zDup (fileno (stdout));
+  zDup2 (fileno (stderr), fileno (stdout));
   std::vector<std::string> list = ApplicationRegistry::GetAvailableApplications();
   if (list.size() == 0){
     map* tmps=createMap("text","No OTB Application found.");
     addToMap(tmps,"code","InternalError");
+    zDup2 (saved_stdout, fileno (stdout));
+    zClose(saved_stdout);
     printExceptionReportResponse(m,tmps);
     freeMap(&tmps);
@@ -142,4 +146,6 @@
 	  map* tmps=createMap("text",tmpS);
 	  addToMap(tmps,"code","InternalError");
+	  zDup2 (saved_stdout, fileno (stdout));
+	  zClose(saved_stdout);
 	  printExceptionReportResponse(m,tmps);
 	  freeMap(&tmps);
@@ -460,4 +466,6 @@
 	  catch(std::exception& err){
 	    setMapInMaps(m,"lenv","message",err.what());
+	    zDup2 (saved_stdout, fileno (stdout));
+	    zClose(saved_stdout);
 	    return SERVICE_FAILED;
 	    
@@ -479,5 +487,7 @@
   }
   m_WatcherList.clear();
-
+  fflush(stdout);
+  zDup2 (saved_stdout, fileno (stdout));
+  zClose(saved_stdout);
   return res;
 }
Index: trunk/zoo-project/zoo-kernel/service_internal_python.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service_internal_python.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/service_internal_python.c	(revision 962)
@@ -446,5 +446,5 @@
     Py_DECREF(name);
     tmp=tmp->next;
-  }  
+  }
   return (PyDictObject*) res;
 }
@@ -572,5 +572,5 @@
     }
     else{
-      if(PyDict_GetItem(res,name)==NULL){
+      if(PyDict_GetItem(res,name)==NULL && strlen(tmp->value)>0){
 	PyObject* value=PyString_FromString(tmp->value);
 	if(PyDict_SetItem(res,name,value)<0){
Index: trunk/zoo-project/zoo-kernel/service_json.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service_json.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/service_json.c	(revision 962)
@@ -2,5 +2,5 @@
  * Author : Gérald FENOY
  *
- *  Copyright 2017-2019 GeoLabs SARL. All rights reserved.
+ *  Copyright 2017-2020 GeoLabs SARL. All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -223,4 +223,8 @@
       if(tmpMap1!=NULL){
 	json_object_object_add(prop2,"name",json_object_new_string(tmpMap1->value));
+	char *tmp=(char*)malloc((strlen(tmpMap1->value)+35)*sizeof(char));
+	sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmpMap1->value);
+	json_object_object_add(prop2,"reference",json_object_new_string(tmp));
+	free(tmp);
 	json_object_object_add(prop1,"dataType",prop2);
       }
@@ -371,12 +375,16 @@
       tmpMap=getMap(in->content,"abstract");
       if(tmpMap!=NULL)
-	json_object_object_add(input,"abstract",json_object_new_string(tmpMap->value));
+	json_object_object_add(input,"description",json_object_new_string(tmpMap->value));
       if(strcmp(io,"input")==0){
 	tmpMap=getMap(in->content,"minOccurs");
 	if(tmpMap!=NULL)
-	  json_object_object_add(input,"minOccurs",json_object_new_string(tmpMap->value));
+	  json_object_object_add(input,"minOccurs",json_object_new_int(atoi(tmpMap->value)));
 	tmpMap=getMap(in->content,"maxOccurs");
-	if(tmpMap!=NULL)
-	  json_object_object_add(input,"maxOccurs",json_object_new_string(tmpMap->value));
+	if(tmpMap!=NULL){
+	  if(strncasecmp(tmpMap->value,"unbounded",9)==0)
+	    json_object_object_add(input,"maxOccurs",json_object_new_string(tmpMap->value));
+	  else
+	    json_object_object_add(input,"maxOccurs",json_object_new_int(atoi(tmpMap->value)));
+	}
       }
       if(in->format!=NULL){
@@ -439,5 +447,10 @@
     json_object* doc=(json_object*) doc0;
     json_object* nc=(json_object*) nc0;
-    json_object *res=json_object_new_object();
+    json_object *res;
+    if(doc!=NULL)
+      res=json_object_new_object();
+    else
+      res=(json_object*) nc0;
+      
     map* tmpMap0=getMapFromMaps(m,"lenv","level");
     char* rUrl=serv->name;
@@ -486,5 +499,5 @@
       tmpMap=getMap(serv->content,"abstract");
       if(tmpMap!=NULL){
-	json_object_object_add(res,"abstract",json_object_new_string(tmpMap->value));
+	json_object_object_add(res,"description",json_object_new_string(tmpMap->value));
       }
       tmpMap=getMap(serv->content,"processVersion");
@@ -498,5 +511,6 @@
 	else
 	  json_object_object_add(res,"version",json_object_new_string(tmpMap->value));
-      }
+      }else
+	json_object_object_add(res,"version",json_object_new_string("1.0.0"));
       int limit=4;
       int i=0;
@@ -517,5 +531,13 @@
       json_object *res1=json_object_new_array();
       json_object *res2=json_object_new_object();
-      json_object_object_add(res2,"rel",json_object_new_string("canonical"));
+      json_object *res3=json_object_new_object();
+      map* pmTmp=getMapFromMaps(m,"lenv","requestType");
+      if(pmTmp!=NULL && strncasecmp(pmTmp->value,"desc",4)==0)
+	json_object_object_add(res2,"rel",json_object_new_string("process-desc"));
+      else{
+	json_object_object_add(res2,"rel",json_object_new_string("execute"));
+	json_object_object_add(res3,"rel",json_object_new_string("alternate"));
+	json_object_object_add(res3,"type",json_object_new_string("text/html"));
+      }
       json_object_object_add(res2,"type",json_object_new_string("application/json"));
       json_object_object_add(res2,"title",json_object_new_string("Process Description"));
@@ -525,12 +547,22 @@
       if(doc==NULL){
 	json_object_object_add(res2,"title",json_object_new_string("Execute End Point"));
+	json_object_object_add(res3,"title",json_object_new_string("Execute End Point"));
 	char* tmpStr1=zStrdup(tmpStr);
 	tmpStr=(char*) realloc(tmpStr,(strlen(tmpStr)+6)*sizeof(char));
-	sprintf(tmpStr,"%sjobs/",tmpStr1);
+	sprintf(tmpStr,"%sjobs",tmpStr1);
 	free(tmpStr1);
+	char* tmpStr3=(char*) malloc((strlen(tmpStr)+6)*sizeof(char));
+	sprintf(tmpStr3,"%s.html",tmpStr);
+	json_object_object_add(res3,"href",json_object_new_string(tmpStr3));
+	free(tmpStr3);
       }
       json_object_object_add(res2,"href",json_object_new_string(tmpStr));
       free(tmpStr);
       json_object_array_add(res1,res2);
+      tmpUrl=getMapFromMaps(m,"openapi","partial_html_support");
+      if(tmpUrl!=NULL && strncasecmp(tmpUrl->value,"true",4)==0)
+	json_object_array_add(res1,res3);
+      else
+	json_object_put(res3);
       json_object_object_add(res,"links",res1);
     }
@@ -551,7 +583,4 @@
     if(doc!=NULL)
       json_object_array_add(doc,res);
-    else
-      json_object_object_add(nc,"process",json_object_get(res));
-
   }
 
@@ -577,5 +606,5 @@
       if(strcmp(tmp->value,"OperationNotSupported")==0 ||
 	 strcmp(tmp->value,"NoApplicableCode")==0)
-	exceptionCode="501 Not Implemented";
+	exceptionCode="500 Not Implemented";
       else
 	if(strcmp(tmp->value,"MissingParameterValue")==0 ||
@@ -586,29 +615,37 @@
 	  exceptionCode="400 Bad request";
 	else
-	  if(strcmp(tmp->value,"NotFound")==0)
+	  if(strcmp(tmp->value,"NotFound")==0 ||
+	     strcmp(tmp->value,"NoSuchProcess")==0 ||
+	     strcmp(tmp->value,"NoSuchJob")==0 ||
+	     strcmp(tmp->value,"ResultNotReady")==0)
 	    exceptionCode="404 Not Found";
 	  else
-	    exceptionCode="501 Internal Server Error";
+	    exceptionCode="500 Internal Server Error";
       json_object_object_add(res,"code",json_object_new_string(tmp->value));
     }
-    else
-      exceptionCode="501 Internal Server Error";
-    printHeaders(m);
+    else{
+      exceptionCode="500 Internal Server Error";
+      json_object_object_add(res,"code",json_object_new_string("NoApplicableCode"));
+    }
+    if(getMapFromMaps(m,"lenv","no-headers")==NULL)
+      printHeaders(m);
 
     tmp=getMapFromMaps(m,"lenv","status_code");
     if(tmp!=NULL)
       exceptionCode=tmp->value;
-    if(m!=NULL){
-      map *tmpSid=getMapFromMaps(m,"lenv","sid");
-      if(tmpSid!=NULL){
-	if( getpid()==atoi(tmpSid->value) ){
+    if(getMapFromMaps(m,"lenv","no-headers")==NULL){
+      if(m!=NULL){
+	map *tmpSid=getMapFromMaps(m,"lenv","sid");
+	if(tmpSid!=NULL){
+	  if( getpid()==atoi(tmpSid->value) ){
+	    printf("Status: %s\r\n\r\n",exceptionCode);
+	  }
+	}
+	else{
 	  printf("Status: %s\r\n\r\n",exceptionCode);
 	}
-      }
-      else{
+      }else{
 	printf("Status: %s\r\n\r\n",exceptionCode);
       }
-    }else{
-      printf("Status: %s\r\n\r\n",exceptionCode);
     }
     tmp=getMap(s,"text");
@@ -620,4 +657,7 @@
       json_object_object_add(res,"description",json_object_new_string(tmp->value));
     const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN);
+    if(getMapFromMaps(m,"lenv","jsonStr")==NULL)
+      setMapInMaps(m,"lenv","jsonStr",jsonStr);
+    maps* pmsTmp=getMaps(m,"lenv");
     printf(jsonStr);
     if(m!=NULL)
@@ -876,5 +916,5 @@
    * @param outputs the produced maps
    */
-  void parseJRequest(maps* conf, service* s,json_object* req,maps** inputs,maps** outputs){
+  void parseJRequest(maps* conf, service* s,json_object* req, map* request_inputs, maps** inputs,maps** outputs){
     elements* io=s->inputs;
 
@@ -890,5 +930,39 @@
 	parseJIO(conf,req,s->outputs,outputs,"outputs");
       }
-    }      
+      json_io=NULL;
+      if(json_object_object_get_ex(req,"mode",&json_io)!=FALSE){
+	addToMap(request_inputs,"mode",json_object_get_string(json_io));
+	setMapInMaps(conf,"request","mode",json_object_get_string(json_io));
+      }
+      json_io=NULL;
+      if(json_object_object_get_ex(req,"response",&json_io)!=FALSE){
+	addToMap(request_inputs,"response",json_object_get_string(json_io));
+	setMapInMaps(conf,"request","response",json_object_get_string(json_io));
+      }
+      json_io=NULL;
+      if(json_object_object_get_ex(req,"subscriber",&json_io)!=FALSE){
+	maps* subscribers=createMaps("subscriber");
+	json_object* json_subscriber=NULL;
+	if(json_object_object_get_ex(json_io,"successUri",&json_subscriber)!=FALSE){
+	  subscribers->content=createMap("successUri",json_object_get_string(json_subscriber));
+	}
+	if(json_object_object_get_ex(json_io,"inProgressUri",&json_subscriber)!=FALSE){
+	  if(subscribers->content==NULL)
+	    subscribers->content=createMap("inProgressUri",json_object_get_string(json_subscriber));
+	  else
+	    addToMap(subscribers->content,"inProgressUri",json_object_get_string(json_subscriber));
+	}
+	if(json_object_object_get_ex(json_io,"failedUri",&json_subscriber)!=FALSE){
+	  if(subscribers->content==NULL)
+	    subscribers->content=createMap("failedUri",json_object_get_string(json_subscriber));
+	  else
+	    addToMap(subscribers->content,"failedUri",json_object_get_string(json_subscriber));
+	}
+	addMapsToMaps(&conf,subscribers);
+	freeMaps(&subscribers);
+	free(subscribers);
+      }
+    }
+    
   }
 
@@ -934,8 +1008,8 @@
 	    if (jerr != json_tokener_success) {
 	      fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
-	      return res;
+	      return NULL;
 	    }
 	    if (tok->char_offset < slen){
-	      return res;
+	      return NULL;
 	    }
 	    json_object_object_add(cjob,"infos",jobj);
@@ -951,5 +1025,5 @@
     return res;
   }
-
+  
   /**
    * Print the result of an execution
@@ -958,10 +1032,23 @@
    * @param s service pointer to metadata
    * @param result outputs of the service
-   * @param res the status of executino SERVICE_FAILED/SERVICE_SUCCEEDED
+   * @param res the status of execution SERVICE_FAILED/SERVICE_SUCCEEDED
    * @return the JSON object pointer to the result
    */
   json_object* printJResult(maps* conf,service* s,maps* result,int res){
-    printHeaders(conf);
     json_object* eres1=json_object_new_object();
+    if(res==SERVICE_FAILED){
+      char* pacTmp=produceErrorMessage(conf);
+      map* pamTmp=createMap("message",pacTmp);
+      free(pacTmp);
+      map* pmTmp=getMapFromMaps(conf,"lenv","code");
+      if(pmTmp!=NULL)
+	addToMap(pamTmp,"code",pmTmp->value);
+      printExceptionReportResponseJ(conf,pamTmp);
+      freeMap(&pamTmp);
+      free(pamTmp);
+      return NULL;
+    }
+    if(getMapFromMaps(conf,"lenv","no-headers")==NULL)
+      printHeaders(conf);
     json_object* eres=json_object_new_array();
     maps* resu=result;
@@ -970,5 +1057,8 @@
       json_object* res1=json_object_new_object();
       json_object_object_add(res1,"id",json_object_new_string(resu->name));
-      map* tmpMap=NULL;
+      map* tmpMap=getMap(resu->content,"mimeType");
+      json_object* res3=json_object_new_object();
+      if(tmpMap!=NULL)
+	json_object_object_add(res3,"mimeType",json_object_new_string(tmpMap->value));
       if((tmpMap=getMap(resu->content,"value"))!=NULL ||
 	 (getMap(resu->content,"generated_file"))!=NULL){
@@ -994,7 +1084,31 @@
 		return eres1;		
 	      }
+	      json_object_object_add(res3,"encoding",json_object_new_string("utf-8"));
 	      json_object_object_add(res2,"inlineValue",jobj);
-	    }else
-	      json_object_object_add(res2,"inlineValue",json_object_new_string(tmpMap->value));
+	    }else{
+	      map* tmp1=getMapFromMaps(conf,"main","tmpPath");
+	      map *gfile=getMap(resu->content,"generated_file");
+	      if(gfile!=NULL){
+		gfile=getMap(resu->content,"expected_generated_file");
+		if(gfile==NULL){
+		  gfile=getMap(resu->content,"generated_file");
+		}
+		FILE* pfData=fopen(gfile->value,"rb");
+		if(pfData!=NULL){
+		  zStatStruct f_status;
+		  int s=zStat(gfile->value, &f_status);
+		  char* pcaTmp=(char*)malloc((f_status.st_size+1)*sizeof(char));
+		  fread(pcaTmp,1,f_status.st_size,pfData);
+		  pcaTmp[f_status.st_size]=0;	    
+		  fclose(pfData);
+		  json_object_object_add(res2,"inlineValue",json_object_new_string(base64(pcaTmp,f_status.st_size)));
+		  json_object_object_add(res3,"encoding",json_object_new_string("base64"));
+		  free(pacTmp);
+		}
+	      }else{
+		json_object_object_add(res3,"encoding",json_object_new_string("utf-8"));
+		json_object_object_add(res2,"inlineValue",json_object_new_string(tmpMap->value));
+	      }
+	    }
 	  }
 	  else{
@@ -1098,4 +1212,5 @@
 	}
 	json_object_object_add(res1,"value",res2);	
+	json_object_object_add(res1,"format",res3);	
 	json_object_array_add(eres,res1);
       }
@@ -1108,23 +1223,29 @@
     map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier");
     map *sessId = getMapFromMaps (conf, "lenv", "usid");
-    char tmp[1024];
-    sprintf(tmp,"%s/%s_%s.json",
+    char *pacTmp=(char*)malloc((strlen(tmpPath->value)+strlen(cIdentifier->value)+strlen(sessId->value)+8)*sizeof(char));
+    sprintf(pacTmp,"%s/%s_%s.json",
 	    tmpPath->value,cIdentifier->value,sessId->value);
-    FILE* foutput=fopen(tmp,"w+");
-    if(foutput!=NULL){
-      fclose(foutput);
-      char tmpUrl[1024];
+    zStatStruct zsFStatus;
+    int iS=zStat(pacTmp, &zsFStatus);
+    if(iS==0 && zsFStatus.st_size>0){
       map* tmpPath1 = getMapFromMaps (conf, "main", "tmpUrl");
-      sprintf(tmpUrl,"%s/%s_%s.json",tmpPath1->value,
+      char* pacTmpUrl=(char*)malloc((strlen(tmpPath1->value)+strlen(cIdentifier->value)+strlen(sessId->value)+8)*sizeof(char));;
+      sprintf(pacTmpUrl,"%s/%s_%s.json",tmpPath1->value,
 	      cIdentifier->value,sessId->value);
-      setMapInMaps(conf,"headers","Location",tmpUrl);
-    }
+      if(getMapFromMaps(conf,"lenv","gs_location")==NULL)
+	setMapInMaps(conf,"headers","Location",pacTmpUrl);
+      free(pacTmpUrl);
+    }
+    free(pacTmp);
     if(res==3){
-      setMapInMaps(conf,"headers","Status","201 Created");
+      map* mode=getMapFromMaps(conf,"request","mode");
+      if(mode!=NULL && strncasecmp(mode->value,"async",5)==0)
+	setMapInMaps(conf,"headers","Status","201 Created");
+      else
+	setMapInMaps(conf,"headers","Status","200 Ok");
     }
     else{
       setMapInMaps(conf,"headers","Status","500 Issue running your service");
     }
-
     return eres1;
   }
@@ -1144,4 +1265,7 @@
     map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier");
     map *sessId = getMapFromMaps (conf, "lenv", "usid");
+    if(sessId==NULL){
+      sessId = getMapFromMaps (conf, "lenv", "gs_usid");
+    }
     char *Url0=(char*) malloc((strlen(tmpPath->value)+
 			       strlen(cIdentifier->value)+
@@ -1153,8 +1277,13 @@
 	    cIdentifier->value,
 	    sessId->value);
-    setMapInMaps(conf,"headers","Location",Url0);
+    if(getMapFromMaps(conf,"lenv","gs_location")==NULL)
+      setMapInMaps(conf,"headers","Location",Url0);
     json_object* val=json_object_new_object();
-    json_object_object_add(val,"Title",
+    json_object_object_add(val,"title",
 			   json_object_new_string(_("Status location")));
+    json_object_object_add(val,"rel",
+			   json_object_new_string(_("status")));
+    json_object_object_add(val,"type",
+			   json_object_new_string(_("application/json")));
     json_object_object_add(val,"href",json_object_new_string(Url0));
     json_object_array_add(res,val);
@@ -1164,11 +1293,15 @@
 			   strlen(cIdentifier->value)+strlen(sessId->value)+
 			   25)*sizeof(char));
-      sprintf(Url0,"%s/processes/%s/jobs/%s/result",
+      sprintf(Url0,"%s/processes/%s/jobs/%s/results",
 	      tmpPath->value,
 	      cIdentifier->value,
 	      sessId->value);
       json_object* val1=json_object_new_object();
-      json_object_object_add(val1,"Title",
+      json_object_object_add(val1,"title",
 			     json_object_new_string(_("Result location")));
+      json_object_object_add(val1,"rel",
+			     json_object_new_string(_("results")));
+      json_object_object_add(val1,"type",
+			     json_object_new_string(_("application/json")));
       json_object_object_add(val1,"href",json_object_new_string(Url0));
       json_object_array_add(res,val1);
@@ -1204,8 +1337,7 @@
       return NULL;
     }
-    free(tmp1);
-    tmp1=(char*) malloc((strlen(tmpPath->value)+
+    tmp1=(char*) realloc(tmp1,(strlen(tmpPath->value)+
 			 strlen(cIdentifier->value)+
-			 strlen(sessId->value)+20)*sizeof(char));
+			 strlen(sessId->value)+21)*sizeof(char));
     int needResult=0;
     char *message, *rstatus;
@@ -1214,24 +1346,67 @@
 	    cIdentifier->value,
 	    sessId->value);
-    
     return tmp1;
   }
+
+  char* getResultPath(maps* conf,char* jobId){
+    map *tmpPath = getMapFromMaps (conf, "main", "tmpPath");
+    map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier");
+    char *pacUrl=(char*) malloc((strlen(tmpPath->value)+
+				 strlen(cIdentifier->value)+
+				 strlen(jobId)+8)*sizeof(char));
+    sprintf(pacUrl,"%s/%s_%s.json",tmpPath->value,
+	    cIdentifier->value,jobId);
+    return pacUrl;
+  }
+
+  json_object* parseJson(maps* conf,char* myString){
+    json_object *pajObj = NULL;
+    enum json_tokener_error jerr;
+    struct json_tokener* tok=json_tokener_new();
+    int slen = 0;
+    do {
+      slen = strlen(myString);
+      pajObj = json_tokener_parse_ex(tok, myString, slen);
+    } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
+    if (jerr != json_tokener_success) {
+      setMapInMaps(conf,"lenv","message",json_tokener_error_desc(jerr));
+      fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
+      return NULL;
+    }
+    if (tok->char_offset < slen){
+      return NULL;
+    }
+    return pajObj;
+  }
   
-  /**
-   * Create the status file 
-   *
-   * @param conf the maps containing the settings of the main.cfg file
-   * @param status an integer (SERVICE_ACCEPTED,SERVICE_STARTED...)
-   * @return an integer (0 in case of success, 1 in case of failure)
-   */
-  int createStatusFile(maps* conf,int status){
+  json_object* json_readFile(maps* conf,char* filePath){
+    json_object *pajObj = NULL;
+    zStatStruct zsFStatus;
+    int iS=zStat(filePath, &zsFStatus);
+    if(iS==0 && zsFStatus.st_size>0){
+      FILE* cdat=fopen(filePath,"rb");
+      if(cdat!=NULL){
+	char* pacMyString=(char*)malloc((zsFStatus.st_size+1)*sizeof(char));
+	fread(pacMyString,1,zsFStatus.st_size,cdat);
+	pacMyString[zsFStatus.st_size]=0;
+	fclose(cdat);
+	pajObj=parseJson(conf,pacMyString);
+	free(pacMyString);
+      }
+      else
+	return NULL;
+    }else
+      return NULL;
+    return pajObj;
+  }
+  
+  json_object* createStatus(maps* conf,int status){
     int needResult=0;
-    const char *message, *rstatus;
-    char* tmp1=json_getStatusFilePath(conf);
+    const char *rstatus;
+    char *message;
     // Create statusInfo JSON object
     // cf. https://github.com/opengeospatial/wps-rest-binding/blob/master/core/
     //     openapi/schemas/statusInfo.yaml
     json_object* res=json_object_new_object();
-    json_object_object_add(res,"status",json_object_new_string("successful"));
     switch(status){
     case SERVICE_ACCEPTED:
@@ -1244,4 +1419,10 @@
       {
 	message=_("ZOO-Kernel is currently running your service!");
+	map* pmStatus=getMapFromMaps(conf,"lenv","status");
+	if(pmStatus!=NULL)
+	  setMapInMaps(conf,"lenv","PercentCompleted",pmStatus->value);
+	pmStatus=getMapFromMaps(conf,"lenv","message");
+	if(pmStatus!=NULL)
+	  setMapInMaps(conf,"lenv","gs_message",pmStatus->value);
 	rstatus="running";
 	break;
@@ -1257,10 +1438,36 @@
 	message=_("ZOO-Kernel successfully run your service!");
 	rstatus="successful";
+	setMapInMaps(conf,"lenv","PercentCompleted","100");
 	needResult=1;
 	break;
       }
+    case SERVICE_DISMISSED:
+      {
+	message=_("ZOO-Kernel successfully dismissed your service!");
+	rstatus="dismissed";
+	needResult=1;
+	break;
+      }
     default:
       {
-	message=_("ZOO-Kernel failed to run your service!");
+	map* pmTmp=getMapFromMaps(conf,"lenv","force");
+	if(pmTmp==NULL || strncasecmp(pmTmp->value,"false",5)==0){
+	  char* pacTmp=json_getStatusFilePath(conf);
+	  json_object* pjoStatus=json_readFile(conf,pacTmp);
+	  free(pacTmp);
+	  if(pjoStatus!=NULL){
+	    json_object* pjoMessage=NULL;
+	    if(json_object_object_get_ex(pjoStatus,"message",&pjoMessage)!=FALSE){
+	      message=(char*)json_object_get_string(pjoMessage);
+	    }
+	  }
+	  // TODO: Error
+	}else{
+	  map* mMap=getMapFromMaps(conf,"lenv","gs_message");
+	  if(mMap!=NULL)
+	    setMapInMaps(conf,"lenv","message",mMap->value);
+	  message=produceErrorMessage(conf);
+	  needResult=-1;
+	}
 	rstatus="failed";
 	break;
@@ -1269,11 +1476,62 @@
     setMapInMaps(conf,"lenv","message",message);
     setMapInMaps(conf,"lenv","status",rstatus);
-	
-    map* mess=getMapFromMaps(conf,"lenv","message");
-    if(mess!=NULL)
-      json_object_object_add(res,"message",json_object_new_string(mess->value));
-
-    createStatusLinks(conf,needResult,res);
-    
+
+    map *sessId = getMapFromMaps (conf, "lenv", "usid");
+    if(sessId!=NULL){
+      sessId = getMapFromMaps (conf, "lenv", "gs_usid");
+      if(sessId==NULL)
+	sessId = getMapFromMaps (conf, "lenv", "usid");
+    }else
+      sessId = getMapFromMaps (conf, "lenv", "gs_usid");
+    if(sessId!=NULL)
+      json_object_object_add(res,"jobID",json_object_new_string(sessId->value));
+    json_object_object_add(res,"status",json_object_new_string(rstatus));
+    map* mMap=getMapFromMaps(conf,"lenv","gs_message");
+    if(mMap==NULL)
+      json_object_object_add(res,"message",json_object_new_string(message));
+    else{
+      json_object_object_add(res,"message",json_object_new_string(mMap->value));
+      if((mMap=getMapFromMaps(conf,"lenv","PercentCompleted"))!=NULL)
+	json_object_object_add(res,"progress",json_object_new_int(atoi(mMap->value)));
+    }
+    if(status!=SERVICE_DISMISSED)
+      createStatusLinks(conf,needResult,res);
+    else{
+      json_object* res1=json_object_new_array();
+      map *tmpPath = getMapFromMaps (conf, "openapi", "rootUrl");
+      map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier");
+      char *Url0=(char*) malloc((strlen(tmpPath->value)+
+				 strlen(cIdentifier->value)+
+				 17)*sizeof(char));
+      sprintf(Url0,"%s/processes/%s/jobs",	      
+	      tmpPath->value,
+	      cIdentifier->value);
+      json_object* val=json_object_new_object();
+      json_object_object_add(val,"title",
+			     json_object_new_string(_("The job list for the current process")));
+      json_object_object_add(val,"rel",
+			     json_object_new_string(_("parent")));
+      json_object_object_add(val,"type",
+			     json_object_new_string(_("application/json")));
+      json_object_object_add(val,"href",json_object_new_string(Url0));
+      json_object_array_add(res1,val);
+      free(Url0);
+      json_object_object_add(res,"links",res1);
+    }
+    if(needResult<0)
+      free(message);
+    return res;
+  }
+  
+  /**
+   * Create the status file 
+   *
+   * @param conf the maps containing the settings of the main.cfg file
+   * @param status an integer (SERVICE_ACCEPTED,SERVICE_STARTED...)
+   * @return an integer (0 in case of success, 1 in case of failure)
+   */
+  int createStatusFile(maps* conf,int status){
+    json_object* res=createStatus(conf,status);
+    char* tmp1=json_getStatusFilePath(conf);
     FILE* foutput1=fopen(tmp1,"w+");
     if(foutput1!=NULL){
@@ -1303,16 +1561,19 @@
     map* tmpMap=getMapFromMaps(conf,"lenv","gs_usid");
     if(tmpMap!=NULL){
-	char* tmpStr=_getStatus(conf,tmpMap->value);
-	if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
-	  char *tmpStr1=zStrdup(tmpStr);
-	  char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1);
-	  free(tmpStr);
-	  tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
-	  setMapInMaps(conf,"lenv","PercentCompleted",tmpStr1);
-	  setMapInMaps(conf,"lenv","gs_message",tmpStr0);
-	  free(tmpStr0);
-	  free(tmpStr1);
-	}
-      }
+      char* tmpStr=_getStatus(conf,tmpMap->value);
+      if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
+	char *tmpStr1=zStrdup(tmpStr);
+	char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1);
+	free(tmpStr);
+	tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
+	setMapInMaps(conf,"lenv","PercentCompleted",tmpStr1);
+	setMapInMaps(conf,"lenv","gs_message",tmpStr0);
+	free(tmpStr0);
+	free(tmpStr1);
+	return 0;
+      }else{
+	  
+      }
+    }
   }
 
@@ -1371,8 +1632,8 @@
 
     json_object *res4=json_object_new_object();
-    tmpMap=getMapFromMaps(conf,"main","license_name");
+    tmpMap=getMapFromMaps(conf,"openapi","license_name");
     if(tmpMap!=NULL){
       json_object_object_add(res4,"name",json_object_new_string(tmpMap->value));
-      tmpMap=getMapFromMaps(conf,"main","license_url");
+      tmpMap=getMapFromMaps(conf,"openapi","license_url");
       if(tmpMap!=NULL){
 	json_object_object_add(res4,"url",json_object_new_string(tmpMap->value));      
@@ -1384,4 +1645,64 @@
   }
 
+  // addResponse(pmUseContent,cc3,vMap,tMap,"200","successful operation");
+  void addResponse(const map* useContent,json_object* res,const map* pmSchema,const map* pmType,const char* code,const char* msg){
+    json_object *cc=json_object_new_object();
+    if(pmSchema!=NULL)
+      json_object_object_add(cc,"$ref",json_object_new_string(pmSchema->value));
+    if(useContent!=NULL && strncasecmp(useContent->value,"true",4)!=0){
+	json_object_object_add(res,code,cc);
+    }else{
+	json_object *cc0=json_object_new_object();
+	if(pmSchema!=NULL)
+	  json_object_object_add(cc0,"schema",cc);
+	json_object *cc1=json_object_new_object();
+	if(pmType!=NULL)
+	  json_object_object_add(cc1,pmType->value,cc0);
+	else
+	  json_object_object_add(cc1,"application/json",cc0);
+	json_object *cc2=json_object_new_object();
+	json_object_object_add(cc2,"content",cc1);
+	json_object_object_add(cc2,"description",json_object_new_string(msg));
+	json_object_object_add(res,code,cc2);
+    }
+  }
+
+  void addParameter(maps* conf,const char* oName,const char* fName,const char* in,json_object* res){
+    maps* tmpMaps1=getMaps(conf,oName);
+    json_object *res8=json_object_new_object();
+    if(tmpMaps1!=NULL){
+      map* tmpMap=getMap(tmpMaps1->content,"title");
+      if(tmpMap!=NULL)
+	json_object_object_add(res8,"x-internal-summary",json_object_new_string(tmpMap->value));
+      tmpMap=getMap(tmpMaps1->content,"abstract");
+      if(tmpMap!=NULL)
+	json_object_object_add(res8,"description",json_object_new_string(tmpMap->value));
+      tmpMap=getMap(tmpMaps1->content,"example");
+      if(tmpMap!=NULL)
+	json_object_object_add(res8,"example",json_object_new_string(tmpMap->value));
+      tmpMap=getMap(tmpMaps1->content,"required");
+      if(tmpMap!=NULL){
+	if(strcmp(tmpMap->value,"true")==0)
+	  json_object_object_add(res8,"required",json_object_new_boolean(TRUE));
+	else
+	  json_object_object_add(res8,"required",json_object_new_boolean(FALSE));
+      }
+      else
+	json_object_object_add(res8,"required",json_object_new_boolean(FALSE));
+      json_object_object_add(res8,"in",json_object_new_string(in));
+      json_object_object_add(res8,"name",json_object_new_string(fName));
+      json_object *res6=json_object_new_object();
+      tmpMap=getMap(tmpMaps1->content,"type");
+      if(tmpMap!=NULL)
+	json_object_object_add(res6,"type",json_object_new_string(tmpMap->value));
+      else
+	json_object_object_add(res6,"type",json_object_new_string("string"));
+	
+      json_object_object_add(res8,"schema",res6);
+	
+    }	
+    json_object_object_add(res,fName,res8);    
+  }
+  
   /**
    * Produce the JSON object for api parameter
@@ -1397,104 +1718,38 @@
     char *tmps12 = strtok_r (tmpMap2->value, ",", &saveptr12);
     while(tmps12!=NULL){
-      char* tmpId=(char*) malloc((strlen(tmps12)+3)*sizeof(char));
-      sprintf(tmpId,"{%s}",tmps12);
-      tmpMaps1=getMaps(conf,tmpId);
-      json_object *res8=json_object_new_object();
-      if(tmpMaps1!=NULL){
-	map* tmpMap=getMap(tmpMaps1->content,"title");
-	if(tmpMap!=NULL)
-	  json_object_object_add(res8,"x-internal-summary",json_object_new_string(tmpMap->value));
-	tmpMap=getMap(tmpMaps1->content,"abstract");
-	if(tmpMap!=NULL)
-	  json_object_object_add(res8,"description",json_object_new_string(tmpMap->value));
-	tmpMap=getMap(tmpMaps1->content,"example");
-	if(tmpMap!=NULL)
-	  json_object_object_add(res8,"example",json_object_new_string(tmpMap->value));
-	tmpMap=getMap(tmpMaps1->content,"required");
-	if(tmpMap!=NULL){
-	  if(strcmp(tmpMap->value,"true")==0)
-	    json_object_object_add(res8,"required",json_object_new_boolean(TRUE));
-	  else
-	    json_object_object_add(res8,"required",json_object_new_boolean(FALSE));
-	}
-	else
-	  json_object_object_add(res8,"required",json_object_new_boolean(FALSE));
-	json_object_object_add(res8,"in",json_object_new_string("path"));
-	json_object_object_add(res8,"name",json_object_new_string(tmps12));
-	json_object *res6=json_object_new_object();
-	json_object *res7=json_object_new_object();
-	tmpMap=getMap(tmpMaps1->content,"type");
-	if(tmpMap!=NULL)
-	  json_object_object_add(res6,"type",json_object_new_string(tmpMap->value));
-	else
-	  json_object_object_add(res6,"type",json_object_new_string("string"));
-	
-	json_object_object_add(res8,"schema",res6);
-	
-      }
-	
-      json_object_object_add(res9,tmps12,res8);
+      char* pacId=(char*) malloc((strlen(tmps12)+3)*sizeof(char));
+      sprintf(pacId,"{%s}",tmps12);
+      addParameter(conf,pacId,tmps12,"path",res9);
+      free(pacId);
       tmps12 = strtok_r (NULL, ",", &saveptr12);
     }    
     tmpMap2=getMapFromMaps(conf,"openapi","header_parameters");
-    char *saveptr13;
-    char *tmps13 = strtok_r (tmpMap2->value, ",", &saveptr13);
-    while(tmps13!=NULL){
-      char* tmpId=zStrdup(tmps13);
-      maps *tmpMaps2=getMaps(conf,tmpId);
-      json_object *res8=json_object_new_object();
-      if(tmpMaps2!=NULL){
-	map* tmpMap=getMap(tmpMaps2->content,"title");
-	if(tmpMap!=NULL)
-	  json_object_object_add(res8,"x-internal-summary",json_object_new_string(tmpMap->value));
-	tmpMap=getMap(tmpMaps2->content,"abstract");
-	if(tmpMap!=NULL)
-	  json_object_object_add(res8,"description",json_object_new_string(tmpMap->value));
-	tmpMap=getMap(tmpMaps2->content,"example");
-	if(tmpMap!=NULL)
-	  json_object_object_add(res8,"example",json_object_new_string(tmpMap->value));
-	tmpMap=getMap(tmpMaps2->content,"required");
-	if(tmpMap!=NULL){
-	  if(strcmp(tmpMap->value,"true")==0)
-	    json_object_object_add(res8,"required",json_object_new_boolean(TRUE));
-	  else
-	    json_object_object_add(res8,"required",json_object_new_boolean(FALSE));
-	}
-	else
-	  json_object_object_add(res8,"required",json_object_new_boolean(FALSE));
-	json_object_object_add(res8,"in",json_object_new_string("header"));
-	tmpMap=getMap(tmpMaps2->content,"name");
-	if(tmpMap!=NULL)
-	  json_object_object_add(res8,"name",json_object_new_string(tmpMap->value));
-	json_object *res6=json_object_new_object();
-	json_object *res7=json_object_new_object();
-	tmpMap=getMap(tmpMaps2->content,"type");
-	if(tmpMap!=NULL)
-	  json_object_object_add(res6,"type",json_object_new_string(tmpMap->value));
-	else
-	  json_object_object_add(res6,"type",json_object_new_string("string"));
-
-	{
-	  tmpMap=getMap(tmpMaps2->content,"enum");
-	  if(tmpMap!=NULL){
-	    char *saveptr11;
-	    char *tmps11 = strtok_r (tmpMap->value, ",", &saveptr11);
-	    json_object *res71=json_object_new_array();
-	    while(tmps11!=NULL){		
-	      json_object_array_add(res71,json_object_new_string(tmps11));
-	      tmps11 = strtok_r (NULL, ",", &saveptr11);
-	    }
-	    json_object_object_add(res6,"enum",res71);				  
-	  }
-	}
-	
-	json_object_object_add(res8,"schema",res6);
-	
-      }
-	
-      json_object_object_add(res9,tmpId,res8);
-      tmps13 = strtok_r (NULL, ",", &saveptr13);
-    } 
-    json_object_object_add(res,"parameters",res9);    
+    if(tmpMap2!=NULL){
+      char *saveptr13;
+      char *tmps13 = strtok_r (tmpMap2->value, ",", &saveptr13);
+      while(tmps13!=NULL){
+	char* pacId=zStrdup(tmps13);
+	addParameter(conf,pacId,pacId,"header",res9);
+	free(pacId);
+	tmps13 = strtok_r (NULL, ",", &saveptr13);
+      }
+    }
+    json_object_object_add(res,"parameters",res9);
+    maps* pmResponses=getMaps(conf,"responses");
+    if(pmResponses!=NULL){
+      json_object *cc=json_object_new_object();
+      map* pmLen=getMap(pmResponses->content,"length");
+      int iLen=atoi(pmLen->value);
+      map* pmUseContent=getMapFromMaps(conf,"openapi","use_content");
+      for(int i=0;i<iLen;i++){
+	map* cMap=getMapArray(pmResponses->content,"code",i);
+	map* vMap=getMapArray(pmResponses->content,"schema",i);
+	map* tMap=getMapArray(pmResponses->content,"type",i);
+	map* tMap0=getMapArray(pmResponses->content,"title",i);
+	if(vMap!=NULL)
+	  addResponse(pmUseContent,cc,vMap,tMap,cMap->value,(tMap0==NULL)?"successful operation":tMap0->value);
+      }
+      json_object_object_add(res,"responses",cc);
+    }
   }
 
@@ -1504,5 +1759,5 @@
     json_object_object_add(res,"components",res1);
   }
-
+  
   /**
    * Produce the JSON object for /api
@@ -1512,8 +1767,8 @@
    */
   void produceApi(maps* conf,json_object* res){
+    // TODO: add 401 Gone for dismiss request
     json_object *res9=json_object_new_object();
     json_object *res10=json_object_new_object();
     maps* tmpMaps1=getMaps(conf,"{id}");
-
     produceApiComponents(conf,res);
     json_object *res4=json_object_new_object();
@@ -1562,62 +1817,40 @@
 	    json_object *responses=json_object_new_object();
 	    json_object *cc3=json_object_new_object();
+	    map* pmUseContent=getMapFromMaps(conf,"openapi","use_content");
 	    vMap=getMapArray(tmpMaps->content,"schema",i);
 	    if(vMap!=NULL){
-	      json_object *cc=json_object_new_object();
-	      json_object_object_add(cc,"$ref",json_object_new_string(vMap->value));
-	      json_object *cc0=json_object_new_object();
-	      json_object_object_add(cc0,"schema",cc);
-	      json_object *cc1=json_object_new_object();
-	      map* tmpMap3=getMapFromMaps(conf,tmps,"type");
-	      if(tmpMap3!=NULL)
-		json_object_object_add(cc1,tmpMap3->value,cc0);
-	      else
-		json_object_object_add(cc1,"application/json",cc0);
-	      json_object *cc2=json_object_new_object();
-	      json_object_object_add(cc2,"content",cc1);
-	      json_object_object_add(cc2,"description",json_object_new_string("successful operation"));
-	      if(i==1)
-		json_object_object_add(cc3,"201",cc2);
-	      else
-		json_object_object_add(cc3,"200",cc2);
+	      map* tMap=getMapArray(tmpMaps->content,"type",i);
+	      addResponse(pmUseContent,cc3,vMap,tMap,"200","successful operation");
+	      vMap=getMapArray(tmpMaps->content,"eschema",i);
+	      if(vMap!=NULL && cMap!=NULL && strncasecmp(cMap->value,"post",4)==0)
+		addResponse(pmUseContent,cc3,vMap,tMap,"201","successful operation");
 	    }else{
-	      json_object *cc1=json_object_new_object();
-	      map* tmpMap3=getMapFromMaps(conf,tmps,"type");
-	      if(tmpMap3!=NULL)
-		json_object_object_add(cc1,tmpMap3->value,json_object_new_object());
-	      else
-		json_object_object_add(cc1,"application/json",json_object_new_object());
-	      json_object *cc2=json_object_new_object();
-	      json_object_object_add(cc2,"content",cc1);
-	      json_object_object_add(cc2,"description",json_object_new_string("successful operation"));
-	      if(i==1)
-		json_object_object_add(cc3,"201",cc2);
-	      else
-		json_object_object_add(cc3,"200",cc2);
+	      map* tMap=getMapFromMaps(conf,tmps,"type");
+	      map* pMap=createMap("ok","true");
+	      addResponse(pMap,cc3,vMap,tMap,"200","successful operation");
+	      if(cMap!=NULL && strncasecmp(cMap->value,"post",4)==0)
+		addResponse(pmUseContent,cc3,vMap,tMap,"201","successful operation");
 	    }
-	    if(strstr(tmps,"{id}")!=NULL){
-	      vMap=getMapFromMaps(conf,"exception","schema");
-	      json_object *cc=json_object_new_object();
-	      json_object_object_add(cc,"$ref",json_object_new_string(vMap->value));
-	      json_object *cc01=json_object_new_array();
-	      json_object_array_add(cc01,cc);
-
-	      json_object *cc0=json_object_new_object();
-	      json_object_object_add(cc0,"schema",cc);
-	      json_object *cc1=json_object_new_object();
-	      map* tmpMap3=getMapFromMaps(conf,"exception","type");
-	      if(tmpMap3!=NULL)
-		json_object_object_add(cc1,tmpMap3->value,cc0);
-	      else
-		json_object_object_add(cc1,"application/json",cc0);
-
-	      json_object *cc2=json_object_new_object();
-	      json_object_object_add(cc2,"content",cc1);
-	      if(strstr(tmps,"{jobID}")==NULL)
-		json_object_object_add(cc2,"description",json_object_new_string("The process with id {id} does not exist."));
-	      else
-		json_object_object_add(cc2,"description",json_object_new_string("The process with id {id} or job with id {jobID} does not exist."));
-	      json_object_object_add(cc3,"404",cc2);
-	      json_object_object_add(cc3,"default",cc2);
+	    vMap=getMapArray(tmpMaps->content,"ecode",i);
+	    if(vMap!=NULL){
+	      char *saveptr0;
+	      char *tmps1 = strtok_r (vMap->value, ",", &saveptr0);
+	      while(tmps1!=NULL){
+		char* tmpStr=(char*)malloc((strlen(tmps1)+24)*sizeof(char));
+		sprintf(tmpStr,"#/components/responses/%s",tmps1);
+		vMap=createMap("ok",tmpStr);
+		map* pMap=createMap("ok","false");
+		//TODO: fix successful operation with correct value
+		addResponse(pMap,cc3,vMap,NULL,tmps1,"successful operation");
+		tmps1 = strtok_r (NULL, ",", &saveptr0);
+	      }
+	    }else{
+	      if(strstr(tmps,"{id}")!=NULL){
+		vMap=getMapFromMaps(conf,"exception","schema");
+		map* tMap=getMapFromMaps(conf,"exception","type");
+		if(vMap!=NULL)
+		  addResponse(pmUseContent,cc3,vMap,tMap,"404",
+			      (strstr(tmps,"{jobID}")==NULL)?"The process with id {id} does not exist.":"The process with id {id} or job with id {jobID} does not exist.");
+	      }
 	    }
 	    json_object_object_add(methodc,"responses",cc3);
@@ -1640,5 +1873,5 @@
 	      json_object_object_add(methodc,"parameters",cc2);
 	    }
-	    if(i==1){
+	    if(i==1 && cMap!=NULL && strncasecmp(cMap->value,"post",4)==0){
 	      maps* tmpMaps1=getMaps(conf,"requestBody");
 	      if(tmpMaps1!=NULL){
@@ -1663,5 +1896,55 @@
 		  json_object_object_add(methodc,"requestBody",cc2);
 
+		}		
+	      }
+	      // TODO: callbacks
+	      tmpMaps1=getMaps(conf,"callbacks");
+	      if(tmpMaps1!=NULL){
+		map* pmTmp2=getMap(tmpMaps1->content,"length");
+		int iLen=atoi(pmTmp2->value);
+		json_object *pajRes=json_object_new_object();
+		for(int i=0;i<iLen;i++){
+		  map* pmState=getMapArray(tmpMaps1->content,"state",i);
+		  map* pmUri=getMapArray(tmpMaps1->content,"uri",i);
+		  map* pmSchema=getMapArray(tmpMaps1->content,"schema",i);
+		  map* pmType=getMapArray(tmpMaps1->content,"type",i);
+		  map* pmTitle=getMapArray(tmpMaps1->content,"title",i);
+		  json_object *pajSchema=json_object_new_object();
+		  if(pmSchema!=NULL)
+		    json_object_object_add(pajSchema,"$ref",json_object_new_string(pmSchema->value));
+		  json_object *pajType=json_object_new_object();
+		  json_object_object_add(pajType,"schema",pajSchema);
+		  json_object *pajContent=json_object_new_object();
+		  if(pmType!=NULL)
+		    json_object_object_add(pajContent,pmType->value,pajType);
+		  else		  
+		    json_object_object_add(pajContent,"application/json",pajType);
+		  json_object *pajRBody=json_object_new_object();
+		  json_object_object_add(pajRBody,"content",pajContent);
+		  
+		  json_object *pajDescription=json_object_new_object();
+		  if(pmTitle!=NULL)
+		    json_object_object_add(pajDescription,"description",json_object_new_string(pmTitle->value));
+		  json_object *pajResponse=json_object_new_object();
+		  json_object_object_add(pajResponse,"200",pajDescription);
+
+		  json_object *pajPost=json_object_new_object();
+		  json_object_object_add(pajPost,"requestBody",pajRBody);
+		  json_object_object_add(pajPost,"responses",pajResponse);
+
+		  json_object *pajMethod=json_object_new_object();
+		  json_object_object_add(pajMethod,"post",pajPost);
+
+		  
+		  char* pacUri=(char*) malloc((strlen(pmUri->value)+29)*sizeof(char));
+		  sprintf(pacUri,"{$request.body#/subscriber/%s}",pmUri->value);
+
+		  json_object *pajFinal=json_object_new_object();
+		  json_object_object_add(pajFinal,pacUri,pajMethod);
+
+		  json_object_object_add(pajRes,pmState->value,pajFinal);
+
 		}
+		json_object_object_add(methodc,"callbacks",pajRes);
 	      }
 	    }
Index: trunk/zoo-project/zoo-kernel/service_json.h
===================================================================
--- trunk/zoo-project/zoo-kernel/service_json.h	(revision 961)
+++ trunk/zoo-project/zoo-kernel/service_json.h	(revision 962)
@@ -2,5 +2,5 @@
  * Author : Gérald FENOY
  *
- *  Copyright 2014 GeoLabs SARL. All rights reserved.
+ *  Copyright 2014-2020 GeoLabs SARL. All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -50,8 +50,13 @@
   void printGetCapabilitiesForProcessJ(registry*, maps*,void*,void*,service*);
   void printExceptionReportResponseJ(maps*,map*);
-  void parseJRequest(maps*,service* s,json_object*,maps**,maps**);
+  void parseJRequest(maps*,service* s,json_object*,map*,maps**,maps**);
   json_object*  printJResult(maps*,service*,maps*,int);
   json_object* printJobList(maps*);
   int createStatusFile(maps*,int);
+  json_object* createStatus(maps*,int);
+  char* json_getStatusFilePath(maps*);
+  json_object* parseJson(maps*,char*);
+  json_object* json_readFile(maps*,char*);
+  char* getResultPath(maps*,char*);
   int json_getStatusFile(maps*);
   void produceApi(maps*,json_object*);
Index: trunk/zoo-project/zoo-kernel/sqlapi.c
===================================================================
--- trunk/zoo-project/zoo-kernel/sqlapi.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/sqlapi.c	(revision 962)
@@ -33,4 +33,5 @@
 #include <fcgi_stdio.h>
 #include "sqlapi.h"
+#include "service_callback.h"
 
 /**
@@ -375,7 +376,11 @@
   map *msg=getMapFromMaps(conf,"lenv","message");
   map *schema=getMapFromMaps(conf,"database","schema");
-  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(msg->value)+strlen(p->value)+strlen(sid->value)+64+1)*sizeof(char));
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(msg->value)+strlen(p->value)+strlen(sid->value)+62+1)*sizeof(char));
   sprintf(sqlQuery,"UPDATE %s.services set status=$$%s$$,message=$$%s$$ where uuid=$$%s$$;",schema->value,p->value,msg->value,sid->value);
   if( zoo_DS == NULL || zoo_DS[zoo_ds_nb-1]==NULL ){
+    if(getMapFromMaps(conf,"lenv","file.log")==NULL){
+      free(sqlQuery);
+      return 1;
+    }
     init_sql(conf);
     zoo_ds_nb++;
@@ -384,4 +389,5 @@
   cleanUpResultSet(conf,zoo_ds_nb-1);
   free(sqlQuery);
+  invokeBasicCallback(conf,SERVICE_STARTED);
   return 0;
 }
@@ -398,6 +404,6 @@
   int created=-1;
   map *schema=getMapFromMaps(conf,"database","schema");
-  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(pid)+58+1)*sizeof(char));
-  sprintf(sqlQuery,"select status||'|'||message from %s.services where uuid=$$%s$$;",schema->value,pid);
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(pid)+104+1)*sizeof(char));  
+  sprintf(sqlQuery,"select CASE WHEN message is null THEN '-1' ELSE status||'|'||message END from %s.services where uuid=$$%s$$;",schema->value,pid);
   if( zoo_ds_nb==
 #ifdef META_DB
Index: trunk/zoo-project/zoo-kernel/zoo_loader.c
===================================================================
--- trunk/zoo-project/zoo-kernel/zoo_loader.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/zoo_loader.c	(revision 962)
@@ -105,5 +105,4 @@
        int len=0;
        while((r=fread(buffer,sizeof(char),1,cgiIn))>0){
-	 fprintf(stderr,"%s",buffer);
 	 buffer[1]=0;
 	 if(res==NULL){
Index: trunk/zoo-project/zoo-kernel/zoo_service_loader.c
===================================================================
--- trunk/zoo-project/zoo-kernel/zoo_service_loader.c	(revision 961)
+++ trunk/zoo-project/zoo-kernel/zoo_service_loader.c	(revision 962)
@@ -2,5 +2,5 @@
  * Author : Gérald FENOY
  *
- *  Copyright 2008-2013 GeoLabs SARL. All rights reserved.
+ *  Copyright 2008-2020 GeoLabs SARL. All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -63,10 +63,10 @@
 #include <string.h>
 
-#include "service.h"
-
 #include "service_internal.h"
 #include "server_internal.h"
 #include "response_print.h"
 #include "request_parser.h"
+#include "service.h"
+
 #ifdef USE_JSON
 #include "caching.h"
@@ -106,5 +106,5 @@
 #endif
 
-#ifdef USE_CALLBACK
+#if defined(USE_CALLBACK) || defined(USE_JSON)
 #include "service_callback.h"
 #endif
@@ -417,6 +417,12 @@
 	     _("Unable to parse the ZCFG file: %s."),
 	     zcfg);
+  
   map* errormap = createMap("text", tmp01);
-  addToMap(errormap,"code", code);
+  map* tmpMap=getMapFromMaps(m,"lenv","executionType");
+  char* errorCode=(char*)code;
+  if(tmpMap!=NULL && strncasecmp(tmpMap->value,"json",4)==0)
+    errorCode="NoSuchProcess";
+
+  addToMap(errormap,"code", errorCode);
   addToMap(errormap,"locator", locator);
   funcError(m,errormap);
@@ -685,4 +691,5 @@
   fflush (stdout);
   zDup2 (saved_stdout, fileno (stdout));
+  zClose(saved_stdout);
   free (orig);
   return 0;
@@ -1870,10 +1877,20 @@
 #endif
   }
-  
+
+  int eres = SERVICE_STARTED;
+  int cpid = zGetpid ();
+  maps* bmap=NULL;
+  char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog;
+  FILE *f0, *f1;
+  HINTERNET hInternet;
+  service *s1;
+  maps *request_output_real_format = NULL;
+  maps *request_input_real_format = NULL;
+
   setMapInMaps(m,"lenv","executionType","xml");
-  if((strlen(cgiQueryString)>0 && cgiQueryString[0]=='/') && strstr(cgiAccept,"json")!=NULL){
-  //
-  // OGC API - Processing starts here
-  //
+  if((strlen(cgiQueryString)>0 && cgiQueryString[0]=='/') /*&& strstr(cgiAccept,"json")!=NULL*/){
+    //
+    // OGC API - Processing starts here
+    //
 #ifndef USE_JSON
     errorException (m, _("OGC API - Processing is not supported by this ZOO-Kernel."), "InternalError", NULL);
@@ -1904,5 +1921,24 @@
     addMapsToMaps(&m,m1);
     setMapInMaps(m,"lenv","executionType","json");
-
+    map* pmTmp0=getMapFromMaps(m,"openapi","full_html_support");
+    dumpMap(pmTmp0);
+    if(strstr(cgiQueryString,".html")==NULL && strstr(cgiAccept,"text/html")!=NULL && pmTmp0!=NULL && strncasecmp(pmTmp0->value,"true",4)==0){
+      map* pmTmpUrl=getMapFromMaps(m,"openapi","rootUrl");
+      char* pacTmpUrl=NULL;
+      if(strcmp(cgiQueryString,"/")!=0){
+	 pacTmpUrl=(char*)malloc((strlen(cgiQueryString)+strlen(pmTmpUrl->value)+6)*sizeof(char));
+	 sprintf(pacTmpUrl,"%s%s.html",pmTmpUrl->value,cgiQueryString);
+      }
+      else{
+	pacTmpUrl=(char*)malloc((strlen(pmTmpUrl->value)+6)*sizeof(char));
+	sprintf(pacTmpUrl,"%s/index.html",pmTmpUrl->value);
+      }
+      setMapInMaps(m,"headers","Location",pacTmpUrl);
+      printHeaders(m);
+      printf("Status: 302 Moved permanently \r\n\r\n");
+      fflush(stdout);
+      free(pacTmpUrl);
+      return 1;
+    }
     json_object *res=json_object_new_object();
     setMapInMaps(m,"headers","Content-Type","application/json;charset=UTF-8");
@@ -1917,20 +1953,58 @@
       for(int kk=0;kk<4;kk++){
 	maps* tmpMaps=getMaps(m,urls[kk]);
-	json_object *res2;
 	if(tmpMaps!=NULL){
+	  json_object *res2;
 	  res2=mapToJson(tmpMaps->content);
 	  char* tmpStr=(char*) malloc((strlen(tmpUrl->value)+strlen(urls[kk])+2)*sizeof(char));
 	  sprintf(tmpStr,"%s%s",tmpUrl->value,urls[kk]);
 	  json_object_object_add(res2,"href",json_object_new_string(tmpStr));
+	  free(tmpStr);
 	  json_object_array_add(res1,res2);
+
+	  map* pmTmp=getMap(tmpMaps->content,"title");
+	  char *pacTitle=NULL;
+	  if(pmTmp!=NULL)
+	    pacTitle=zStrdup(pmTmp->value);
+	  char* pacTmp=(char*) malloc((strlen(urls[kk])+6)*sizeof(char));
+	  sprintf(pacTmp,"%s.html",urls[kk]);
+	  tmpMaps=getMaps(m,pacTmp);
+	  if(tmpMaps==NULL && strncasecmp(pacTmp,"/.html",6)==0)
+	    tmpMaps=getMaps(m,"/index.html");
+	  if(tmpMaps!=NULL){
+	    json_object *res3;
+	    res3=mapToJson(tmpMaps->content);
+	    if(getMap(tmpMaps->content,"title")==NULL && pacTitle!=NULL){
+	      json_object_object_add(res3,"title",json_object_new_string(pacTitle));
+	    }
+	    char* tmpStr=NULL;
+	    if(strncasecmp(pacTmp,"/.html",6)==0){
+	      tmpStr=(char*) malloc((strlen(tmpUrl->value)+12)*sizeof(char));
+	      sprintf(tmpStr,"%s/index.html",tmpUrl->value);
+	    }else{
+	      tmpStr=(char*) malloc((strlen(tmpUrl->value)+strlen(urls[kk])+6)*sizeof(char));
+	      sprintf(tmpStr,"%s%s.html",tmpUrl->value,urls[kk]);
+	    }
+	    json_object_object_add(res3,"href",json_object_new_string(tmpStr));
+	    free(tmpStr);
+	    json_object_array_add(res1,res3);
+	  }
+	  free(pacTmp);
+	  if(pacTitle!=NULL)
+	    free(pacTitle);	  
 	}
       }
+      map* pmTmp=getMapFromMaps(m,"identification","title");
+      if(pmTmp!=NULL)
+	json_object_object_add(res,"title",json_object_new_string(pmTmp->value));
+      pmTmp=getMapFromMaps(m,"identification","abstract");
+      if(pmTmp!=NULL)
+	json_object_object_add(res,"description",json_object_new_string(pmTmp->value));
       json_object_object_add(res,"links",res1);
     }else if(strcmp(cgiQueryString,"/conformance")==0){
       /* - /conformance url */
-      map* rootUrl=getMapFromMaps(m,"conformTo","rootUrl");
+      map* rootUrl=getMapFromMaps(m,"conformsTo","rootUrl");
       json_object *res1=json_object_new_array();
-      map* length=getMapFromMaps(m,"conformTo","length");
-      maps* tmpMaps=getMaps(m,"conformTo");
+      map* length=getMapFromMaps(m,"conformsTo","length");
+      maps* tmpMaps=getMaps(m,"conformsTo");
       for(int kk=0;kk<atoi(length->value);kk++){
 	map* tmpMap1=getMapArray(tmpMaps->content,"link",kk);
@@ -1942,15 +2016,23 @@
 	}
       }
-      json_object_object_add(res,"conformTo",res1);
-    }else if(strcmp(cgiQueryString,"/api")==0){
-      /* - /api url */
-      produceApi(m,res);
+      json_object_object_add(res,"conformsTo",res1);
+    }else if(strncasecmp(cgiQueryString,"/api",4)==0){
+      if(strstr(cgiQueryString,".html")==NULL)
+	produceApi(m,res);
+      else{	
+	char* pacTmp=(char*)malloc(9*sizeof(char));
+	sprintf(pacTmp,"%s",cgiQueryString+1);
+	map* pmTmp=getMapFromMaps(m,pacTmp,"href");
+	free(pacTmp);
+	if(pmTmp!=NULL)
+	  setMapInMaps(m,"headers","Location",pmTmp->value);
+      }	
     }else if(strcmp(cgiQueryString,"/processes")==0 || strcmp(cgiQueryString,"/processes/")==0){
       /* - /processes */
+      setMapInMaps(m,"lenv","requestType","desc");
       json_object *res3=json_object_new_array();
       int saved_stdout = zDup (fileno (stdout));
       zDup2 (fileno (stderr), fileno (stdout));
-
-      if (int res =		  
+      if (int res0 =		  
           recursReaddirF (m, NULL, res3, NULL, ntmp, NULL, saved_stdout, 0,
 			  printGetCapabilitiesForProcessJ) < 0)
@@ -1959,6 +2041,6 @@
       zDup2 (saved_stdout, fileno (stdout));
       zClose(saved_stdout);
-      
-      json_object_object_add(res,"processes",res3);
+      res=res3;
+      //json_object_object_add(res,"processes",res3);
     }else{
       service* s1=NULL;
@@ -1984,4 +2066,5 @@
 	    orig[strlen(orig)-1]=0;
 	  json_object* res1=json_object_new_object();
+	  setMapInMaps(m,"lenv","requestType","GetCapabilities");
 	  int t=fetchServicesForDescription(NULL, m, orig,
 					    printGetCapabilitiesForProcessJ,
@@ -1991,6 +2074,6 @@
 	  if(t==1){
 	    /*map* error=createMap("code","BadRequest");
-	    addToMap(error,"message",_("Failed to acces the requested service"));
-	    printExceptionReportResponseJ(m,error);*/
+	      addToMap(error,"message",_("Failed to acces the requested service"));
+	      printExceptionReportResponseJ(m,error);*/
 	    return 1;
 	  }
@@ -2003,5 +2086,4 @@
 	  int cnt=0;
 	  for(int j=11;j<len1;j++){
-	    fprintf(stderr,"%s %c\n",cIdentifier,cgiQueryString[j]);
 	    cIdentifier[cnt]=cgiQueryString[j];
 	    cIdentifier[cnt+1]=0;
@@ -2009,5 +2091,4 @@
 	  }
 	  char tmps1[1024];
-
 	  map* import = getMapFromMaps (m, IMPORTSERVICE, cIdentifier); 
 	  if (import != NULL && import->value != NULL) { 
@@ -2023,4 +2104,5 @@
 	    if (strstr (cIdentifier, ".") != NULL)
 	      {
+		setMapInMaps (m, "lenv", "oIdentifier", cIdentifier);
 		char *identifier = zStrdup (cIdentifier);
 		parseIdentifier (m, ntmp, identifier, tmps1);
@@ -2071,5 +2153,5 @@
 		map* error=createMap("code","InternalError");
 		addToMap(error,"message",_("Unable to allocate memory"));
-		//setMapInMaps(conf,"lenv","status_code","404 Bad Request");
+		setMapInMaps(m,"lenv","status_code","404 Bad Request");
 		printExceptionReportResponseJ(m,error);
 
@@ -2091,49 +2173,166 @@
 	      free(zooRegistry);
 	    }
+	    fflush(stderr);
 	    fflush (stdout);
 	    zDup2 (saved_stdout, fileno (stdout));
+	    zClose (saved_stdout);
 	    if (t < 0)
 	      {
-		char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value));
-		sprintf (tmpMsg,
-			 _
-			 ("The value for <identifier> seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."),
-			 r_inputs->value);
-		map* error=createMap("code","InvalidParameterValue");
-		addToMap(error,"message",tmpMsg);
-		//setMapInMaps(conf,"lenv","status_code","404 Bad Request");
-		printExceptionReportResponseJ(m,error);
-
-		//errorException (m, tmpMsg, "InvalidParameterValue", "identifier");
-		free (tmpMsg);
-		free (s1);
-		freeMaps (&m);
-		free (m);
-		free (REQUEST);
-		free (SERVICE_URL);
-		return 0;
+		r_inputs = getMapFromMaps (m, "lenv", "oIdentifier");
+		if(r_inputs!=NULL){
+		  char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value));
+		  sprintf (tmpMsg,
+			   _
+			   ("The value for <identifier> seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."),
+			   r_inputs->value);
+		  map* error=createMap("code","NoSuchProcess");
+		  addToMap(error,"message",tmpMsg);
+		  //setMapInMaps(conf,"lenv","status_code","404 Bad Request");
+		  printExceptionReportResponseJ(m,error);
+
+		  //errorException (m, tmpMsg, "InvalidParameterValue", "identifier");
+		  free (tmpMsg);
+		  free (s1);
+		  freeMaps (&m);
+		  free (m);
+		  free (REQUEST);
+		  free (SERVICE_URL);
+		  return 0;
+		}
 	      }
-	    zClose (saved_stdout);
-	  
 #ifdef META_DB
 	  }
 #endif
-	  if(strstr(cgiQueryString,"/jobs/")!=NULL && strlen(strstr(cgiQueryString,"/jobs/"))>6){
+	  if(strstr(cgiQueryString,"/jobs/")!=NULL && strlen(strstr(cgiQueryString,"/jobs/"))>6) {
 	    /* - /jobs/{jobID} and /jobs/{jobID}/result urls */
-	    if(strstr(cgiQueryString,"/result")!=NULL && strlen(strstr(cgiQueryString,"/result"))>=7){
-	      fprintf(stderr,"For GetResult %s %d \n",__FILE__,__LINE__);
+	    if(strstr(cgiQueryString,"/results")!=NULL){
+	      // In case the service has run, then forward request to target result file
+	      char* jobId=zStrdup(strstr(cgiQueryString,"/jobs/")+6);
+	      jobId[strlen(jobId)-8]=0;
+	      char *sid=getStatusId(m,jobId);
+	      if(sid==NULL){
+		map* error=createMap("code","NoSuchJob");
+		addToMap(error,"message",_("The JobID from the request does not match any of the Jobs running on this server"));
+		printExceptionReportResponseJ(m,error);
+		return 1;
+	      }else{
+		if(isRunning(m,jobId)>0){
+		  map* error=createMap("code","ResultNotReady");
+		  addToMap(error,"message",_("The job is still running."));
+		  printExceptionReportResponseJ(m,error);
+		  return 1;
+		}else{
+		  char *Url0=getResultPath(m,jobId);
+		  map *cIdentifier = getMapFromMaps (m, "lenv", "oIdentifier");
+		  zStatStruct f_status;
+		  int s=zStat(Url0, &f_status);
+		  if(s==0 && f_status.st_size>0){
+		    if(f_status.st_size>15){
+		      json_object* pjoTmp=json_readFile(m,Url0);
+		      json_object* pjoCode=NULL;
+		      json_object* pjoMessage=NULL;
+		      if(pjoTmp!=NULL &&
+			 json_object_object_get_ex(pjoTmp,"code",&pjoCode)!=FALSE &&
+			 json_object_object_get_ex(pjoTmp,"description",&pjoMessage)!=FALSE){
+			map* error=createMap("code",json_object_get_string(pjoCode));
+			addToMap(error,"message",json_object_get_string(pjoMessage));
+			printExceptionReportResponseJ(m,error);
+			return 1;			
+		      }else{
+
+			map* tmpPath = getMapFromMaps (m, "main", "tmpUrl");
+			Url0=(char*) realloc(Url0,(strlen(tmpPath->value)+
+						   strlen(cIdentifier->value)+
+						   strlen(jobId)+8)*sizeof(char));
+			sprintf(Url0,"%s/%s_%s.json",tmpPath->value,
+				cIdentifier->value,jobId);
+			setMapInMaps(m,"headers","Location",Url0);
+		      }
+		      free(Url0);
+		    }else{
+		      // Service Failed
+		      map* statusInfo=createMap("JobID",jobId);
+		      readFinalRes(m,jobId,statusInfo);
+		      {
+			map* pmStatus=getMap(statusInfo,"status");
+			if(pmStatus!=NULL)
+			  setMapInMaps(m,"lenv","status",pmStatus->value);
+		      }
+		      char* tmpStr=_getStatus(m,jobId);
+		      if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
+			char *tmpStr1=zStrdup(tmpStr);
+			char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1);
+			free(tmpStr);
+			tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
+			addToMap(statusInfo,"PercentCompleted",tmpStr1);
+			addToMap(statusInfo,"Message",tmpStr0);
+			setMapInMaps(m,"lenv","PercentCompleted",tmpStr1);
+			setMapInMaps(m,"lenv","Message",tmpStr0);
+			free(tmpStr0);
+			free(tmpStr1);
+		      }
+		      map* error=createMap("code","NoApplicableCode");
+		      addToMap(error,"message",_("The service failed to execute."));
+		      printExceptionReportResponseJ(m,error);
+		      return 1;
+		    }
+
+		  }else{
+		    map* error=createMap("code","NoSuchJob");
+		    addToMap(error,"message",_("The JobID seem to be running on this server but not for this process id"));
+		    printExceptionReportResponseJ(m,error);
+		    return 1;
+		  }
+		}
+	      }
 	    }else{
 	      char* tmpUrl=strstr(cgiQueryString,"/jobs/");
 	      if(tmpUrl!=NULL && strlen(tmpUrl)>6){
-		char* jobId=zStrdup(strstr(cgiQueryString,"/jobs/")+6);
-		setMapInMaps(m,"lenv","gs_usid",jobId);
-		json_getStatusFile(m);
-		free(jobId);
-		return 1;	      
+		if(strncasecmp(cgiRequestMethod,"DELETE",6)==0){
+		  char* jobId=zStrdup(strstr(cgiQueryString,"/jobs/")+6);
+		  setMapInMaps(m,"lenv","gs_usid",jobId);
+		  setMapInMaps(m,"lenv","file.statusFile",json_getStatusFilePath(m));
+		  runDismiss(m,jobId);
+		  map* pmError=getMapFromMaps(m,"lenv","error");
+		  if(pmError!=NULL && strncasecmp(pmError->value,"true",4)==0){
+		    printExceptionReportResponseJ(m,getMapFromMaps(m,"lenv","code"));
+		    return 1;
+		  }
+		  else{
+		    setMapInMaps(m,"lenv","gs_location","false");
+		    res=createStatus(m,SERVICE_DISMISSED);
+		  }
+		}else{
+		  char* jobId=zStrdup(strstr(cgiQueryString,"/jobs/")+6);
+		  runGetStatus(m,jobId,"GetStatus");
+		  map* pmError=getMapFromMaps(m,"lenv","error");
+		  if(pmError!=NULL && strncasecmp(pmError->value,"true",4)==0){
+		    printExceptionReportResponseJ(m,getMapFromMaps(m,"lenv","code"));
+		    return 1;
+		  }else{
+		    map* pmStatus=getMapFromMaps(m,"lenv","status");
+		    setMapInMaps(m,"lenv","gs_location","false");
+		    setMapInMaps(m,"lenv","gs_usid",jobId);
+		    if(pmStatus!=NULL && strncasecmp(pmStatus->value,"Failed",6)==0)
+		      res=createStatus(m,SERVICE_FAILED);
+		    else
+		      if(pmStatus!=NULL  && strncasecmp(pmStatus->value,"Succeeded",9)==0)
+			res=createStatus(m,SERVICE_SUCCEEDED);
+		      else
+			if(pmStatus!=NULL  && strncasecmp(pmStatus->value,"Running",7)==0){
+			  map* tmpMap=getMapFromMaps(m,"lenv","Message");
+			  if(tmpMap!=NULL)
+			    setMapInMaps(m,"lenv","gs_message",tmpMap->value);
+			  res=createStatus(m,SERVICE_STARTED);
+			}
+			else
+			  res=createStatus(m,SERVICE_FAILED);
+		  }
+		  free(jobId);
+		}
 	      }
 	    }
 	  }else{
 	    /* - /jobs url */
-	    fprintf(stderr,"For Execute or Job list %s %d \n",__FILE__,__LINE__);
 	    if(strcasecmp(cgiRequestMethod,"get")==0){
 	      /* - /jobs List (GET) */
@@ -2141,6 +2340,5 @@
 	    }else if(strcasecmp(cgiRequestMethod,"post")==0){
 	      /* - /jobs Execution (POST) */
-	      int eres = SERVICE_STARTED;
-
+	      eres = SERVICE_STARTED;
 	      initAllEnvironment(m,request_inputs,ntmp,"jrequest");
 	      map* req=getMapFromMaps(m,"renv","jrequest");
@@ -2156,19 +2354,31 @@
 	      } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
 	      if (jerr != json_tokener_success) {
+		map* pamError=createMap("code","InvalidParameterValue");
+		const char* pcTmpErr=json_tokener_error_desc(jerr);
+		const char* pccErr=_("ZOO-Kernel cannot parse your POST data: %s");
+		char* pacMessage=(char*)malloc((strlen(pcTmpErr)+strlen(pccErr)+1)*sizeof(char));
+		sprintf(pacMessage,pccErr,pcTmpErr);
+		addToMap(pamError,"message",pacMessage);
+		printExceptionReportResponseJ(m,pamError);
 		fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
 		return 1;
 	      }
 	      if (tok->char_offset < slen){
+		map* pamError=createMap("code","InvalidParameterValue");
+		const char* pcTmpErr="None";
+		const char* pccErr=_("ZOO-Kernel cannot parse your POST data: %s");
+		char* pacMessage=(char*)malloc((strlen(pcTmpErr)+strlen(pccErr)+1)*sizeof(char));
+		sprintf(pacMessage,pccErr,pcTmpErr);
+		addToMap(pamError,"message",pacMessage);
+		printExceptionReportResponseJ(m,pamError);
+		fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
 		return 1;
 	      }
-	      fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
-	      // Success, use jobj here.
-	      maps* inputs_real_format=NULL, *outputs_real_format= NULL;
-	      parseJRequest(m,s1,jobj,&inputs_real_format,&outputs_real_format);
+	      //maps* inputs_real_format=NULL, *outputs_real_format= NULL;
+	      parseJRequest(m,s1,jobj,request_inputs,&request_input_real_format,&request_output_real_format);
 	      map* preference=getMapFromMaps(m,"renv","HTTP_PREFER");
-	      if(preference!=NULL && strcasecmp(preference->value,"respond-async")==0){
-		fprintf(stderr,"Asynchronous call!\n");
-		char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog;
-		FILE *f0, *f1;
+	      map* mode=getMap(request_inputs,"mode");
+	      if((preference!=NULL && strcasecmp(preference->value,"respond-async")==0) ||
+		 (mode!=NULL && strncasecmp(mode->value,"async",5)==0)) {
 		int pid;
 #ifdef DEBUG
@@ -2204,4 +2414,5 @@
 		    eres = SERVICE_ACCEPTED;
 		    createStatusFile(m,eres);
+		    //invokeBasicCallback(m,SERVICE_ACCEPTED);
 		    printHeaders(m);
 		    printf("Status: 201 Created \r\n\r\n");
@@ -2215,4 +2426,5 @@
 		    // process answer to http client.
 		    //
+		    map* oid = getMapFromMaps (m, "lenv", "oIdentifier");
 		    map* usid = getMapFromMaps (m, "lenv", "uusid");
 		    map* tmpm = getMapFromMaps (m, "lenv", "osid");
@@ -2228,5 +2440,5 @@
 			       strlen (usid->value) + 7) * sizeof (char));                    
 		    sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value);
-		    maps* bmap = createMaps("status");
+		    bmap = createMaps("status");
 		    bmap->content=createMap("usid",usid->value);
 		    addToMap(bmap->content,"sid",tmpm->value);
@@ -2248,5 +2460,5 @@
 		    fbkp =
 		      (char *)
-		      malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+		      malloc ((strlen (r_inputs->value) + strlen (oid->value) +
 			       strlen (usid->value) + 7) * sizeof (char));
 		    sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value);
@@ -2259,15 +2471,15 @@
 		    fbkp =
 		      (char *)
-		      malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+		      malloc ((strlen (r_inputs->value) + strlen (oid->value) +
 			       strlen (usid->value) + 7) * sizeof (char));
-		    sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value,
+		    sprintf (fbkp, "%s/%s_%s.json", r_inputs->value, oid->value,
 			     usid->value);
 		    setMapInMaps (m, "lenv", "file.responseInit", fbkp);
 		    flog =
 		      (char *)
-		      malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+		      malloc ((strlen (r_inputs->value) + strlen (oid->value) +
 			       strlen (usid->value) + 13) * sizeof (char));
 		    sprintf (flog, "%s/%s_%s_error.log", r_inputs->value,
-			     r_inputs1->value, usid->value);
+			     oid->value, usid->value);
 		    setMapInMaps (m, "lenv", "file.log", flog);
 #ifdef DEBUG
@@ -2291,16 +2503,12 @@
 		    invokeCallback(m,NULL,NULL,0,0);
 #endif
-		    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
-		    fflush(stderr);
-		    
-		    createStatusFile(m,eres);
-		    	  
-		  
+		    invokeBasicCallback(m,SERVICE_STARTED);
+		    createStatusFile(m,SERVICE_STARTED);
 		    fbkp1 =
 		      (char *)
-		      malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+		      malloc ((strlen (r_inputs->value) + strlen (oid->value) +
 			       strlen (usid->value) + 15) * sizeof (char));
 		    sprintf (fbkp1, "%s/%s_final_%s.json", r_inputs->value,
-			     r_inputs1->value, usid->value);
+			     oid->value, usid->value);
 		    setMapInMaps (m, "lenv", "file.responseFinal", fbkp1);
 
@@ -2317,32 +2525,31 @@
 		    sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value);
 		    maps* lenvMaps=getMaps(m,"lenv");
-		    dumpMapsToFile(lenvMaps,flenv,0);
+		    dumpMapsToFile(lenvMaps,flenv,1);
 		    free(flenv);
 
 		    map* testMap=getMapFromMaps(m,"main","memory");
-		    loadHttpRequests(m,inputs_real_format);
+		    loadHttpRequests(m,request_input_real_format);
+		    dumpMaps(request_input_real_format);
 		    loadServiceAndRun (&m, s1, request_inputs,
-				       &inputs_real_format,
-				       &outputs_real_format, &eres);
+				       &request_input_real_format,
+				       &request_output_real_format, &eres);
+		    setMapInMaps(m,"lenv","force","true");
 		    createStatusFile(m,eres);
-		    res=printJResult(m,s1,outputs_real_format,eres);
-		    char tmpUrl0[1024];
-		    const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN);
-		    printf(jsonStr);
-		    printf("\n");
-		    return 1;
-
+		    setMapInMaps(m,"lenv","force","false");
+		    setMapInMaps(m,"lenv","no-headers","true");
+		    fflush(stdout);
+		    rewind(stdout);
+		    res=printJResult(m,s1,request_output_real_format,eres);
+		    const char* jsonStr0=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN);
+		    if(getMapFromMaps(m,"lenv","jsonStr")==NULL)
+		      setMapInMaps(m,"lenv","jsonStr",jsonStr0);
+		    invokeBasicCallback(m,eres);
 		  }
 	      }else{
-		loadHttpRequests(m,inputs_real_format);
-		loadServiceAndRun (&m,s1,request_inputs,&inputs_real_format,&outputs_real_format,&eres);
-		res=printJResult(m,s1,outputs_real_format,eres);
-	      
-		printHeaders(m);
-		printf("Status: 201 Created \r\n\r\n");
-		const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN);
-		printf(jsonStr);
-		printf("\n");
-		return 1;
+		loadHttpRequests(m,request_input_real_format);
+		loadServiceAndRun (&m,s1,request_inputs,
+				   &request_input_real_format,
+				   &request_output_real_format,&eres);
+		res=printJResult(m,s1,request_output_real_format,eres);
 	      }
 
@@ -2353,184 +2560,358 @@
 	}
     }
-    printHeaders(m);
-    printf("Status: 200 OK \r\n\r\n");
-    const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN);
-    printf(jsonStr);
-    printf("\n");
-    return 1;
-#endif
-  }
-
-  //
-  // WPS 1.0.0 and 2.0.0 starts here
-  //
-  //Check for minimum inputs
-  map* version=getMap(request_inputs,"version");
-  if(version==NULL)
-    version=getMapFromMaps(m,"main","version");
-  setMapInMaps(m,"main","rversion",version->value);
-  int vid=getVersionId(version->value);
-  if(vid<0)
-    vid=0;
-  map* err=NULL;
-  const char **vvr=(const char**)requests[vid];
-  checkValidValue(request_inputs,&err,"request",vvr,1);
-  const char *vvs[]={
-    "WPS",
-    NULL
-  };
-  if(err!=NULL){
+    if(res!=NULL){
+      if(getMapFromMaps(m,"lenv","no-headers")==NULL){
+	printHeaders(m);
+	printf("Status: 200 OK \r\n\r\n");
+      }
+      const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN);
+      printf(jsonStr);
+      printf("\n");
+      fflush(stdout);
+    }
+    //return 1;
+#endif
+  }else{
+
+    //
+    // WPS 1.0.0 and 2.0.0 starts here
+    //
+    //Check for minimum inputs
+    map* version=getMap(request_inputs,"version");
+    if(version==NULL)
+      version=getMapFromMaps(m,"main","version");
+    setMapInMaps(m,"main","rversion",version->value);
+    int vid=getVersionId(version->value);
+    if(vid<0)
+      vid=0;
+    map* err=NULL;
+    const char **vvr=(const char**)requests[vid];
+    checkValidValue(request_inputs,&err,"request",vvr,1);
+    const char *vvs[]={
+      "WPS",
+      NULL
+    };
+    if(err!=NULL){
+      checkValidValue(request_inputs,&err,"service",(const char**)vvs,1);
+      printExceptionReportResponse (m, err);
+      freeMap(&err);
+      free(err);
+      if (count (request_inputs) == 1)
+	{
+	  freeMap (&request_inputs);
+	  free (request_inputs);
+	}
+      freeMaps (&m);
+      free (m);
+      return 1;
+    }
     checkValidValue(request_inputs,&err,"service",(const char**)vvs,1);
-    printExceptionReportResponse (m, err);
-    freeMap(&err);
-    free(err);
-    if (count (request_inputs) == 1)
-      {
-	freeMap (&request_inputs);
-	free (request_inputs);
-      }
-    freeMaps (&m);
-    free (m);
-    return 1;
-  }
-  checkValidValue(request_inputs,&err,"service",(const char**)vvs,1);
-
-  const char *vvv[]={
-    "1.0.0",
-    "2.0.0",
-    NULL
-  };
-  r_inputs = getMap (request_inputs, "Request");
-  if(r_inputs!=NULL)
-    REQUEST = zStrdup (r_inputs->value);
-  int reqId=-1;
-  if (strncasecmp (REQUEST, "GetCapabilities", 15) != 0){
-    checkValidValue(request_inputs,&err,"version",(const char**)vvv,1);
-    int j=0;
-    for(j=0;j<nbSupportedRequests;j++){
-      if(requests[vid][j]!=NULL && requests[vid][j+1]!=NULL){
-	if(j<nbReqIdentifier && strncasecmp(REQUEST,requests[vid][j+1],strlen(requests[vid][j+1]))==0){
-	  checkValidValue(request_inputs,&err,"identifier",NULL,1);
-	  reqId=j+1;
-	  break;
-	}
-	else
-	  if(j>=nbReqIdentifier && j<nbReqIdentifier+nbReqJob && 
-	     strncasecmp(REQUEST,requests[vid][j+1],strlen(requests[vid][j+1]))==0){
-	    checkValidValue(request_inputs,&err,"jobid",NULL,1);
+
+    const char *vvv[]={
+      "1.0.0",
+      "2.0.0",
+      NULL
+    };
+    r_inputs = getMap (request_inputs, "Request");
+    if(r_inputs!=NULL)
+      REQUEST = zStrdup (r_inputs->value);
+    int reqId=-1;
+    if (strncasecmp (REQUEST, "GetCapabilities", 15) != 0){
+      checkValidValue(request_inputs,&err,"version",(const char**)vvv,1);
+      int j=0;
+      for(j=0;j<nbSupportedRequests;j++){
+	if(requests[vid][j]!=NULL && requests[vid][j+1]!=NULL){
+	  if(j<nbReqIdentifier && strncasecmp(REQUEST,requests[vid][j+1],strlen(requests[vid][j+1]))==0){
+	    checkValidValue(request_inputs,&err,"identifier",NULL,1);
 	    reqId=j+1;
 	    break;
 	  }
-      }else
-	break;
-    }
-  }else{
-    checkValidValue(request_inputs,&err,"AcceptVersions",(const char**)vvv,-1);
-    map* version1=getMap(request_inputs,"AcceptVersions");
-    if(version1!=NULL){
-      if(strstr(version1->value,schemas[1][0])!=NULL){
-	addToMap(request_inputs,"version",schemas[1][0]);
-	setMapInMaps(m,"main","rversion",schemas[1][0]);
+	  else
+	    if(j>=nbReqIdentifier && j<nbReqIdentifier+nbReqJob && 
+	       strncasecmp(REQUEST,requests[vid][j+1],strlen(requests[vid][j+1]))==0){
+	      checkValidValue(request_inputs,&err,"jobid",NULL,1);
+	      reqId=j+1;
+	      break;
+	    }
+	}else
+	  break;
       }
-      else{
-	addToMap(request_inputs,"version",version1->value);
-	setMapInMaps(m,"main","rversion",version1->value);
+    }else{
+      checkValidValue(request_inputs,&err,"AcceptVersions",(const char**)vvv,-1);
+      map* version1=getMap(request_inputs,"AcceptVersions");
+      if(version1!=NULL){
+	if(strstr(version1->value,schemas[1][0])!=NULL){
+	  addToMap(request_inputs,"version",schemas[1][0]);
+	  setMapInMaps(m,"main","rversion",schemas[1][0]);
+	}
+	else{
+	  addToMap(request_inputs,"version",version1->value);
+	  setMapInMaps(m,"main","rversion",version1->value);
+	}
+	version=getMap(request_inputs,"version");
       }
-      version=getMap(request_inputs,"version");
-    }
-  }
-  if(err!=NULL){
-    printExceptionReportResponse (m, err);
-    freeMap(&err);
-    free(err);
-    if (count (request_inputs) == 1)
+    }
+    if(err!=NULL){
+      printExceptionReportResponse (m, err);
+      freeMap(&err);
+      free(err);
+      if (count (request_inputs) == 1)
+	{
+	  freeMap (&request_inputs);
+	  free (request_inputs);
+	}
+      free(REQUEST);
+      freeMaps (&m);
+      free (m);
+      return 1;
+    }
+
+    r_inputs = getMap (request_inputs, "serviceprovider");
+    if (r_inputs == NULL)
       {
-	freeMap (&request_inputs);
-	free (request_inputs);
+	addToMap (request_inputs, "serviceprovider", "");
       }
-    free(REQUEST);
-    freeMaps (&m);
-    free (m);
-    return 1;
-  }
-
-  r_inputs = getMap (request_inputs, "serviceprovider");
-  if (r_inputs == NULL)
-    {
-      addToMap (request_inputs, "serviceprovider", "");
-    }
-
-  maps *request_output_real_format = NULL;
-  map *tmpm = getMapFromMaps (m, "main", "serverAddress");
-  if (tmpm != NULL)
-    SERVICE_URL = zStrdup (tmpm->value);
-  else
-    SERVICE_URL = zStrdup (DEFAULT_SERVICE_URL);
-
-
-
-  service *s1;
-  int scount = 0;
-#ifdef DEBUG
-  dumpMap (r_inputs);
-#endif
-
-  if (strncasecmp (REQUEST, "GetCapabilities", 15) == 0)
-    {
-#ifdef DEBUG
-      dumpMap (r_inputs);
-#endif
-      xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
-      xmlNodePtr n=printGetCapabilitiesHeader(doc,m,(version!=NULL?version->value:"1.0.0"));
-      /**
-       * Here we need to close stdout to ensure that unsupported chars 
-       * has been found in the zcfg and then printed on stdout
-       */
-      int saved_stdout = zDup (fileno (stdout));
-      zDup2 (fileno (stderr), fileno (stdout));
-
-      maps* imports = getMaps(m, IMPORTSERVICE);
-      if (imports != NULL) {       
-        map* zcfg = imports->content;
+
+    map *tmpm = getMapFromMaps (m, "main", "serverAddress");
+    if (tmpm != NULL)
+      SERVICE_URL = zStrdup (tmpm->value);
+    else
+      SERVICE_URL = zStrdup (DEFAULT_SERVICE_URL);
+
+
+    int scount = 0;
+#ifdef DEBUG
+    dumpMap (r_inputs);
+#endif
+
+    if (strncasecmp (REQUEST, "GetCapabilities", 15) == 0)
+      {
+#ifdef DEBUG
+	dumpMap (r_inputs);
+#endif
+	xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
+	xmlNodePtr n=printGetCapabilitiesHeader(doc,m,(version!=NULL?version->value:"1.0.0"));
+	/**
+	 * Here we need to close stdout to ensure that unsupported chars 
+	 * has been found in the zcfg and then printed on stdout
+	 */
+	int saved_stdout = zDup (fileno (stdout));
+	zDup2 (fileno (stderr), fileno (stdout));
+
+	maps* imports = getMaps(m, IMPORTSERVICE);
+	if (imports != NULL) {       
+	  map* zcfg = imports->content;
         
-        while (zcfg != NULL) {
-	  if (zcfg->value != NULL) {
-	    service* svc = (service*) malloc(SERVICE_SIZE);
-	    if (svc == NULL || readServiceFile(m, zcfg->value, &svc, zcfg->name) < 0) {
-	      // pass over silently
-	      zcfg = zcfg->next;
-	      continue;
+	  while (zcfg != NULL) {
+	    if (zcfg->value != NULL) {
+	      service* svc = (service*) malloc(SERVICE_SIZE);
+	      if (svc == NULL || readServiceFile(m, zcfg->value, &svc, zcfg->name) < 0) {
+		// pass over silently
+		zcfg = zcfg->next;
+		continue;
+	      }
+	      inheritance(zooRegistry, &svc);
+	      printGetCapabilitiesForProcess(zooRegistry, m, doc, n, svc);
+	      freeService(&svc);
+	      free(svc);                             
 	    }
-	    inheritance(zooRegistry, &svc);
-	    printGetCapabilitiesForProcess(zooRegistry, m, doc, n, svc);
-	    freeService(&svc);
-	    free(svc);                             
+	    zcfg = zcfg->next;
+	  }            
+	}
+
+	if (int res =		  
+	    recursReaddirF (m, zooRegistry, doc, n, conf_dir, NULL, saved_stdout, 0,
+			    printGetCapabilitiesForProcess) < 0)
+	  {
+	    freeMaps (&m);
+	    free (m);
+	    if(zooRegistry!=NULL){
+	      freeRegistry(&zooRegistry);
+	      free(zooRegistry);
+	    }
+	    free (REQUEST);
+	    free (SERVICE_URL);
+	    fflush (stdout);
+	    return res;
 	  }
-	  zcfg = zcfg->next;
-        }            
+	fflush (stdout);
+	zDup2 (saved_stdout, fileno (stdout));
+#ifdef META_DB
+	fetchServicesFromDb(zooRegistry,m,doc,n,printGetCapabilitiesForProcess,1);
+	close_sql(m,0);
+#endif      
+	printDocument (m, doc, zGetpid ());
+	freeMaps (&m);
+	free (m);
+	if(zooRegistry!=NULL){
+	  freeRegistry(&zooRegistry);
+	  free(zooRegistry);
+	}
+	free (REQUEST);
+	free (SERVICE_URL);
+	fflush (stdout);
+	return 0;
       }
-
-      if (int res =		  
-          recursReaddirF (m, zooRegistry, doc, n, conf_dir, NULL, saved_stdout, 0,
-                          printGetCapabilitiesForProcess) < 0)
-        {
-          freeMaps (&m);
-          free (m);
-	  if(zooRegistry!=NULL){
-	    freeRegistry(&zooRegistry);
-	    free(zooRegistry);
+    else
+      {
+	r_inputs = getMap (request_inputs, "JobId");
+	if(reqId>nbReqIdentifier){
+	  if (strncasecmp (REQUEST, "GetStatus", 9) == 0 ||
+	      strncasecmp (REQUEST, "GetResult", 9) == 0){
+	    runGetStatus(m,r_inputs->value,REQUEST);
+#ifdef RELY_ON_DB
+	    map* dsNb=getMapFromMaps(m,"lenv","ds_nb");
+	    if(dsNb!=NULL && atoi(dsNb->value)>1)
+	      close_sql(m,1);
+	    close_sql(m,0);
+#endif
+	  
+	    freeMaps (&m);
+	    free(m);
+	    if(zooRegistry!=NULL){
+	      freeRegistry(&zooRegistry);
+	      free(zooRegistry);
+	    }
+	    free (REQUEST);
+	    free (SERVICE_URL);
+	    return 0;
 	  }
-          free (REQUEST);
-          free (SERVICE_URL);
-          fflush (stdout);
-          return res;
-        }
-      fflush (stdout);
-      zDup2 (saved_stdout, fileno (stdout));
+	  else
+	    if (strncasecmp (REQUEST, "Dismiss", strlen(REQUEST)) == 0){
+	      runDismiss(m,r_inputs->value);
+	      freeMaps (&m);
+	      free (m);
+	      if(zooRegistry!=NULL){
+		freeRegistry(&zooRegistry);
+		free(zooRegistry);
+	      }
+	      free (REQUEST);
+	      free (SERVICE_URL);
+	      return 0;
+	    
+	    }
+	  return 0;
+	}
+	if(reqId<=nbReqIdentifier){
+	  r_inputs = getMap (request_inputs, "Identifier");
+
+	  struct dirent *dp;
+	  DIR *dirp = opendir (conf_dir);
+	  if (dirp == NULL)
+	    {
+	      errorException (m, _("The specified path does not exist."),
+			      "InternalError", NULL);
+	      freeMaps (&m);
+	      free (m);
+	      if(zooRegistry!=NULL){
+		freeRegistry(&zooRegistry);
+		free(zooRegistry);
+	      }
+	      free (REQUEST);
+	      free (SERVICE_URL);
+	      return 0;
+	    }
+	  if (strncasecmp (REQUEST, "DescribeProcess", 15) == 0)
+	    {
+	      /**
+	       * Loop over Identifier list
+	       */
+	      xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
+	      r_inputs = NULL;
+	      r_inputs = getMap (request_inputs, "version");
+#ifdef DEBUG
+	      fprintf(stderr," ** DEBUG %s %d \n",__FILE__,__LINE__);
+	      fflush(stderr);
+#endif
+	      xmlNodePtr n = printWPSHeader(doc,m,"DescribeProcess",
+					    root_nodes[vid][1],(version!=NULL?version->value:"1.0.0"),1);
+
+	      r_inputs = getMap (request_inputs, "Identifier");
+
+	      fetchServicesForDescription(zooRegistry, m, r_inputs->value,
+					  printDescribeProcessForProcess,
+					  (void*) doc, (void*) n, conf_dir,
+					  request_inputs,printExceptionReportResponse);
+
+	      printDocument (m, doc, zGetpid ());
+	      freeMaps (&m);
+	      free (m);
+	      if(zooRegistry!=NULL){
+		freeRegistry(&zooRegistry);
+		free(zooRegistry);
+	      }
+	      free (REQUEST);
+	      free (SERVICE_URL);
+	      fflush (stdout);
 #ifdef META_DB
-      fetchServicesFromDb(zooRegistry,m,doc,n,printGetCapabilitiesForProcess,1);
-      close_sql(m,0);
-#endif      
-      printDocument (m, doc, zGetpid ());
+	      close_sql(m,0);
+	      //end_sql();
+#endif
+	      return 0;
+	    }
+	  else if (strncasecmp (REQUEST, "Execute", strlen (REQUEST)) != 0)
+	    {
+	      map* version=getMapFromMaps(m,"main","rversion");
+	      int vid=getVersionId(version->value);	    
+	      int len = 0;
+	      int j = 0;
+	      for(j=0;j<nbSupportedRequests;j++){
+		if(requests[vid][j]!=NULL)
+		  len+=strlen(requests[vid][j])+2;
+		else{
+		  len+=4;
+		  break;
+		}
+	      }
+	      char *tmpStr=(char*)malloc(len*sizeof(char));
+	      int it=0;
+	      for(j=0;j<nbSupportedRequests;j++){
+		if(requests[vid][j]!=NULL){
+		  if(it==0){
+		    sprintf(tmpStr,"%s",requests[vid][j]);
+		    it++;
+		  }else{
+		    char *tmpS=zStrdup(tmpStr);
+		    if(j+1<nbSupportedRequests && requests[vid][j+1]==NULL){
+		      sprintf(tmpStr,"%s and %s",tmpS,requests[vid][j]);
+		    }else{
+		      sprintf(tmpStr,"%s, %s",tmpS,requests[vid][j]);
+		  
+		    }
+		    free(tmpS);
+		  }
+		}
+		else{
+		  len+=4;
+		  break;
+		}
+	      }
+	      char* message=(char*)malloc((61+len)*sizeof(char));
+	      sprintf(message,"The <request> value was not recognized. Allowed values are %s.",tmpStr);
+	      errorException (m,_(message),"InvalidParameterValue", "request");
+#ifdef DEBUG
+	      fprintf (stderr, "No request found %s", REQUEST);
+#endif
+	      closedir (dirp);
+	      freeMaps (&m);
+	      free (m);
+	      if(zooRegistry!=NULL){
+		freeRegistry(&zooRegistry);
+		free(zooRegistry);
+	      }
+	      free (REQUEST);
+	      free (SERVICE_URL);
+	      fflush (stdout);
+	      return 0;
+	    }
+	  closedir (dirp);
+	}
+      }
+
+    map *postRequest = NULL;
+    postRequest = getMap (request_inputs, "xrequest");
+  
+    if(vid==1 && postRequest==NULL){
+      errorException (m,_("Unable to run Execute request using the GET HTTP method"),"InvalidParameterValue", "request");  
       freeMaps (&m);
       free (m);
@@ -2544,20 +2925,61 @@
       return 0;
     }
-  else
-    {
-      r_inputs = getMap (request_inputs, "JobId");
-      if(reqId>nbReqIdentifier){
-	if (strncasecmp (REQUEST, "GetStatus", 9) == 0 ||
-	    strncasecmp (REQUEST, "GetResult", 9) == 0){
-	  runGetStatus(m,r_inputs->value,REQUEST);
-#ifdef RELY_ON_DB
-	  map* dsNb=getMapFromMaps(m,"lenv","ds_nb");
-	  if(dsNb!=NULL && atoi(dsNb->value)>1)
-	    close_sql(m,1);
-	  close_sql(m,0);
-#endif
-	  
+    s1 = NULL;
+ 
+    r_inputs = getMap (request_inputs, "Identifier");
+    map* import = getMapFromMaps (m, IMPORTSERVICE, r_inputs->value); 
+    if (import != NULL && import->value != NULL) { 
+      strncpy(tmps1, import->value, 1024);
+      setMapInMaps (m, "lenv", "Identifier", r_inputs->value);
+      setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value);
+    } 
+    else {
+      snprintf (tmps1, 1024, "%s/%s.zcfg", conf_dir, r_inputs->value);
+#ifdef DEBUG
+      fprintf (stderr, "Trying to load %s\n", tmps1);
+#endif
+      if (strstr (r_inputs->value, ".") != NULL)
+	{
+	  char *identifier = zStrdup (r_inputs->value);
+	  parseIdentifier (m, conf_dir, identifier, tmps1);
+	  map *tmpMap = getMapFromMaps (m, "lenv", "metapath");
+	  if (tmpMap != NULL)
+	    addToMap (request_inputs, "metapath", tmpMap->value);
+	  free (identifier);
+	}
+      else
+	{
+	  setMapInMaps (m, "lenv", "Identifier", r_inputs->value);
+	  setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value);
+	}
+    }
+
+    r_inputs = getMapFromMaps (m, "lenv", "Identifier");
+  
+#ifdef META_DB
+    int metadb_id=_init_sql(m,"metadb");
+    //FAILED CONNECTING DB
+    if(getMapFromMaps(m,"lenv","dbIssue")!=NULL || metadb_id<0){
+      fprintf(stderr,"ERROR CONNECTING METADB\n");
+    }
+    if(metadb_id>=0)
+      s1=extractServiceFromDb(m,r_inputs->value,0);
+    //close_sql(m,0);
+    if(s1!=NULL){
+      inheritance(zooRegistry,&s1);
+#ifdef USE_HPC
+      addNestedOutputs(&s1);
+#endif
+      if(zooRegistry!=NULL){
+	freeRegistry(&zooRegistry);
+	free(zooRegistry);
+      }
+    }else /* Not found in MetaDB */{
+#endif
+      s1 = createService();
+      if (s1 == NULL)
+	{
 	  freeMaps (&m);
-	  free(m);
+	  free (m);
 	  if(zooRegistry!=NULL){
 	    freeRegistry(&zooRegistry);
@@ -2566,9 +2988,132 @@
 	  free (REQUEST);
 	  free (SERVICE_URL);
+	  return errorException (m, _("Unable to allocate memory"),
+				 "InternalError", NULL);
+	}
+
+      int saved_stdout = zDup (fileno (stdout));
+      zDup2 (fileno (stderr), fileno (stdout));
+      t = readServiceFile (m, tmps1, &s1, r_inputs->value);
+      if(t>=0){
+	inheritance(zooRegistry,&s1);
+#ifdef USE_HPC
+	addNestedOutputs(&s1);
+#endif
+      }
+      if(zooRegistry!=NULL){
+	freeRegistry(&zooRegistry);
+	free(zooRegistry);
+      }
+      fflush (stdout);
+      zDup2 (saved_stdout, fileno (stdout));
+      if (t < 0)
+	{
+	  char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value));
+	  sprintf (tmpMsg,
+		   _
+		   ("The value for <identifier> seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."),
+		   r_inputs->value);
+	  errorException (m, tmpMsg, "InvalidParameterValue", "identifier");
+	  free (tmpMsg);
+	  free (s1);
+	  freeMaps (&m);
+	  free (m);
+	  free (REQUEST);
+	  free (SERVICE_URL);
 	  return 0;
 	}
-	else
-	  if (strncasecmp (REQUEST, "Dismiss", strlen(REQUEST)) == 0){
-	    runDismiss(m,r_inputs->value);
+      zClose (saved_stdout);
+#ifdef META_DB
+    }
+#endif
+  
+#ifdef DEBUG
+    dumpService (s1);
+#endif
+    int j;
+
+
+    /**
+     * Create the input and output maps data structure
+     */
+    int i = 0;
+    HINTERNET res;
+    hInternet = InternetOpen (
+#ifndef WIN32
+			      (LPCTSTR)
+#endif
+			      "ZooWPSClient\0",
+			      INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
+
+#ifndef WIN32
+    if (!CHECK_INET_HANDLE (hInternet))
+      fprintf (stderr, "WARNING : hInternet handle failed to initialize");
+#endif
+    maps *tmpmaps = request_input_real_format;
+
+    if(parseRequest(&m,&request_inputs,s1,&request_input_real_format,&request_output_real_format,&hInternet)<0){
+      freeMaps (&m);
+      free (m);
+      free (REQUEST);
+      free (SERVICE_URL);
+      InternetCloseHandle (&hInternet);
+      freeService (&s1);
+      free (s1);
+      return 0;
+    }
+    //InternetCloseHandle (&hInternet);
+
+    initAllEnvironment(m,request_inputs,ntmp,"xrequest");
+
+
+#ifdef DEBUG
+    dumpMap (request_inputs);
+#endif
+
+    map *status = getMap (request_inputs, "status");
+    if(vid==0){
+      // Need to check if we need to fork to load a status enabled 
+      r_inputs = NULL;
+      map *store = getMap (request_inputs, "storeExecuteResponse");
+      /**
+       * 05-007r7 WPS 1.0.0 page 57 :
+       * 'If status="true" and storeExecuteResponse is "false" then the service 
+       * shall raise an exception.'
+       */
+      if (status != NULL && strcmp (status->value, "true") == 0 &&
+	  store != NULL && strcmp (store->value, "false") == 0)
+	{
+	  errorException (m,
+			  _
+			  ("The status parameter cannot be set to true if storeExecuteResponse is set to false. Please modify your request parameters."),
+			  "InvalidParameterValue", "storeExecuteResponse");
+	  freeService (&s1);
+	  free (s1);
+	  freeMaps (&m);
+	  free (m);
+	
+	  freeMaps (&request_input_real_format);
+	  free (request_input_real_format);
+	
+	  freeMaps (&request_output_real_format);
+	  free (request_output_real_format);
+
+	  free (REQUEST);
+	  free (SERVICE_URL);
+	  return 1;
+	}
+      r_inputs = getMap (request_inputs, "storeExecuteResponse");
+    }else{
+      // Define status depending on the WPS 2.0.0 mode attribute
+      status = getMap (request_inputs, "mode");
+      map* mode=getMap(s1->content,"mode");
+      if(strcasecmp(status->value,"async")==0){
+	if(mode!=NULL && strcasecmp(mode->value,"async")==0)
+	  addToMap(request_inputs,"status","true");
+	else{
+	  if(mode!=NULL){
+	    // see ref. http://docs.opengeospatial.org/is/14-065/14-065.html#61
+	    errorException (m,_("The process does not permit the desired execution mode."),"NoSuchMode", mode->value);  
+	    fflush (stdout);
 	    freeMaps (&m);
 	    free (m);
@@ -2577,649 +3122,304 @@
 	      free(zooRegistry);
 	    }
+	    freeMaps (&request_input_real_format);
+	    free (request_input_real_format);
+	    freeMaps (&request_output_real_format);
+	    free (request_output_real_format);
 	    free (REQUEST);
 	    free (SERVICE_URL);
 	    return 0;
-	    
+	  }else
+	    addToMap(request_inputs,"status","true");
+	}
+      }
+      else{
+	if(strcasecmp(status->value,"auto")==0){
+	  if(mode!=NULL){
+	    if(strcasecmp(mode->value,"async")==0)
+	      addToMap(request_inputs,"status","false");
+	    else
+	      addToMap(request_inputs,"status","true");
 	  }
-	return 0;
+	  else
+	    addToMap(request_inputs,"status","false");
+	}else
+	  addToMap(request_inputs,"status","false");
       }
-      if(reqId<=nbReqIdentifier){
-	r_inputs = getMap (request_inputs, "Identifier");
-
-	struct dirent *dp;
-	DIR *dirp = opendir (conf_dir);
-	if (dirp == NULL)
-	  {
-	    errorException (m, _("The specified path does not exist."),
-			    "InternalError", NULL);
-	    freeMaps (&m);
-	    free (m);
-	    if(zooRegistry!=NULL){
-	      freeRegistry(&zooRegistry);
-	      free(zooRegistry);
-	    }
-	    free (REQUEST);
-	    free (SERVICE_URL);
-	    return 0;
-	  }
-	if (strncasecmp (REQUEST, "DescribeProcess", 15) == 0)
-	  {
-	    /**
-	     * Loop over Identifier list
-	     */
-	    xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
-	    r_inputs = NULL;
-	    r_inputs = getMap (request_inputs, "version");
-#ifdef DEBUG
-	    fprintf(stderr," ** DEBUG %s %d \n",__FILE__,__LINE__);
-	    fflush(stderr);
-#endif
-	    xmlNodePtr n = printWPSHeader(doc,m,"DescribeProcess",
-					  root_nodes[vid][1],(version!=NULL?version->value:"1.0.0"),1);
-
-	    r_inputs = getMap (request_inputs, "Identifier");
-
-	    fetchServicesForDescription(zooRegistry, m, r_inputs->value,
-					printDescribeProcessForProcess,
-					(void*) doc, (void*) n, conf_dir,
-					request_inputs,printExceptionReportResponse);
-
-	    printDocument (m, doc, zGetpid ());
-	    freeMaps (&m);
-	    free (m);
-	    if(zooRegistry!=NULL){
-	      freeRegistry(&zooRegistry);
-	      free(zooRegistry);
-	    }
-	    free (REQUEST);
-	    free (SERVICE_URL);
-	    fflush (stdout);
-#ifdef META_DB
-	    close_sql(m,0);
-	    //end_sql();
-#endif
-	    return 0;
-	  }
-	else if (strncasecmp (REQUEST, "Execute", strlen (REQUEST)) != 0)
-	  {
-	    map* version=getMapFromMaps(m,"main","rversion");
-	    int vid=getVersionId(version->value);	    
-	    int len = 0;
-	    int j = 0;
-	    for(j=0;j<nbSupportedRequests;j++){
-	      if(requests[vid][j]!=NULL)
-		len+=strlen(requests[vid][j])+2;
-	      else{
-		len+=4;
-		break;
-	      }
-	    }
-	    char *tmpStr=(char*)malloc(len*sizeof(char));
-	    int it=0;
-	    for(j=0;j<nbSupportedRequests;j++){
-	      if(requests[vid][j]!=NULL){
-		if(it==0){
-		  sprintf(tmpStr,"%s",requests[vid][j]);
-		  it++;
-		}else{
-		  char *tmpS=zStrdup(tmpStr);
-		  if(j+1<nbSupportedRequests && requests[vid][j+1]==NULL){
-		    sprintf(tmpStr,"%s and %s",tmpS,requests[vid][j]);
-		  }else{
-		    sprintf(tmpStr,"%s, %s",tmpS,requests[vid][j]);
-		  
-		  }
-		  free(tmpS);
-		}
-	      }
-	      else{
-		len+=4;
-		break;
-	      }
-	    }
-	    char* message=(char*)malloc((61+len)*sizeof(char));
-	    sprintf(message,"The <request> value was not recognized. Allowed values are %s.",tmpStr);
-	    errorException (m,_(message),"InvalidParameterValue", "request");
-#ifdef DEBUG
-	    fprintf (stderr, "No request found %s", REQUEST);
-#endif
-	    closedir (dirp);
-	    freeMaps (&m);
-	    free (m);
-	    if(zooRegistry!=NULL){
-	      freeRegistry(&zooRegistry);
-	      free(zooRegistry);
-	    }
-	    free (REQUEST);
-	    free (SERVICE_URL);
-	    fflush (stdout);
-	    return 0;
-	  }
-	closedir (dirp);
-      }
-    }
-
-  map *postRequest = NULL;
-  postRequest = getMap (request_inputs, "xrequest");
-  
-  if(vid==1 && postRequest==NULL){
-    errorException (m,_("Unable to run Execute request using the GET HTTP method"),"InvalidParameterValue", "request");  
-    freeMaps (&m);
-    free (m);
-    if(zooRegistry!=NULL){
-      freeRegistry(&zooRegistry);
-      free(zooRegistry);
-    }
-    free (REQUEST);
-    free (SERVICE_URL);
-    fflush (stdout);
-    return 0;
-  }
-  s1 = NULL;
- 
-  r_inputs = getMap (request_inputs, "Identifier");
-  map* import = getMapFromMaps (m, IMPORTSERVICE, r_inputs->value); 
-  if (import != NULL && import->value != NULL) { 
-    strncpy(tmps1, import->value, 1024);
-    setMapInMaps (m, "lenv", "Identifier", r_inputs->value);
-    setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value);
-  } 
-  else {
-    snprintf (tmps1, 1024, "%s/%s.zcfg", conf_dir, r_inputs->value);
-#ifdef DEBUG
-    fprintf (stderr, "Trying to load %s\n", tmps1);
-#endif
-    if (strstr (r_inputs->value, ".") != NULL)
+      status = getMap (request_inputs, "status");
+    }
+
+    if (status != NULL)
+      if (strcasecmp (status->value, "false") == 0)
+	status = NULLMAP;
+    if (status == NULLMAP)
       {
-	char *identifier = zStrdup (r_inputs->value);
-	parseIdentifier (m, conf_dir, identifier, tmps1);
-	map *tmpMap = getMapFromMaps (m, "lenv", "metapath");
-	if (tmpMap != NULL)
-	  addToMap (request_inputs, "metapath", tmpMap->value);
-	free (identifier);
-      }
-    else
-      {
-	setMapInMaps (m, "lenv", "Identifier", r_inputs->value);
-	setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value);
-      }
-  }
-
-  r_inputs = getMapFromMaps (m, "lenv", "Identifier");
-  
-#ifdef META_DB
-  int metadb_id=_init_sql(m,"metadb");
-  //FAILED CONNECTING DB
-  if(getMapFromMaps(m,"lenv","dbIssue")!=NULL || metadb_id<0){
-    fprintf(stderr,"ERROR CONNECTING METADB\n");
-  }
-  if(metadb_id>=0)
-    s1=extractServiceFromDb(m,r_inputs->value,0);
-  //close_sql(m,0);
-  if(s1!=NULL){
-    inheritance(zooRegistry,&s1);
-#ifdef USE_HPC
-    addNestedOutputs(&s1);
-#endif
-    if(zooRegistry!=NULL){
-      freeRegistry(&zooRegistry);
-      free(zooRegistry);
-    }
-  }else /* Not found in MetaDB */{
-#endif
-    s1 = createService();
-    if (s1 == NULL)
-      {
-	freeMaps (&m);
-	free (m);
-	if(zooRegistry!=NULL){
-	  freeRegistry(&zooRegistry);
-	  free(zooRegistry);
-	}
-	free (REQUEST);
-	free (SERVICE_URL);
-	return errorException (m, _("Unable to allocate memory"),
-			       "InternalError", NULL);
-      }
-
-    int saved_stdout = zDup (fileno (stdout));
-    zDup2 (fileno (stderr), fileno (stdout));
-    t = readServiceFile (m, tmps1, &s1, r_inputs->value);
-    if(t>=0){
-      inheritance(zooRegistry,&s1);
-#ifdef USE_HPC
-      addNestedOutputs(&s1);
-#endif
-    }
-    if(zooRegistry!=NULL){
-      freeRegistry(&zooRegistry);
-      free(zooRegistry);
-    }
-    fflush (stdout);
-    zDup2 (saved_stdout, fileno (stdout));
-    if (t < 0)
-      {
-	char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value));
-	sprintf (tmpMsg,
-		 _
-		 ("The value for <identifier> seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."),
-		 r_inputs->value);
-	errorException (m, tmpMsg, "InvalidParameterValue", "identifier");
-	free (tmpMsg);
-	free (s1);
-	freeMaps (&m);
-	free (m);
-	free (REQUEST);
-	free (SERVICE_URL);
-	return 0;
-      }
-    zClose (saved_stdout);
-#ifdef META_DB
-  }
-#endif
-  
-#ifdef DEBUG
-  dumpService (s1);
-#endif
-  int j;
-
-
-  /**
-   * Create the input and output maps data structure
-   */
-  int i = 0;
-  HINTERNET hInternet;
-  HINTERNET res;
-  hInternet = InternetOpen (
-#ifndef WIN32
-			    (LPCTSTR)
-#endif
-			    "ZooWPSClient\0",
-			    INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
-
-#ifndef WIN32
-  if (!CHECK_INET_HANDLE (hInternet))
-    fprintf (stderr, "WARNING : hInternet handle failed to initialize");
-#endif
-  maps *request_input_real_format = NULL;
-  maps *tmpmaps = request_input_real_format;
-
-  if(parseRequest(&m,&request_inputs,s1,&request_input_real_format,&request_output_real_format,&hInternet)<0){
-    freeMaps (&m);
-    free (m);
-    free (REQUEST);
-    free (SERVICE_URL);
-    InternetCloseHandle (&hInternet);
-    freeService (&s1);
-    free (s1);
-    return 0;
-  }
-  //InternetCloseHandle (&hInternet);
-
-  initAllEnvironment(m,request_inputs,ntmp,"xrequest");
-
-
-#ifdef DEBUG
-  dumpMap (request_inputs);
-#endif
-
-  map *status = getMap (request_inputs, "status");
-  if(vid==0){
-    // Need to check if we need to fork to load a status enabled 
-    r_inputs = NULL;
-    map *store = getMap (request_inputs, "storeExecuteResponse");
-    /**
-     * 05-007r7 WPS 1.0.0 page 57 :
-     * 'If status="true" and storeExecuteResponse is "false" then the service 
-     * shall raise an exception.'
-     */
-    if (status != NULL && strcmp (status->value, "true") == 0 &&
-	store != NULL && strcmp (store->value, "false") == 0)
-      {
-	errorException (m,
-			_
-			("The status parameter cannot be set to true if storeExecuteResponse is set to false. Please modify your request parameters."),
-			"InvalidParameterValue", "storeExecuteResponse");
-	freeService (&s1);
-	free (s1);
-	freeMaps (&m);
-	free (m);
-	
-	freeMaps (&request_input_real_format);
-	free (request_input_real_format);
-	
-	freeMaps (&request_output_real_format);
-	free (request_output_real_format);
-
-	free (REQUEST);
-	free (SERVICE_URL);
-	return 1;
-      }
-    r_inputs = getMap (request_inputs, "storeExecuteResponse");
-  }else{
-    // Define status depending on the WPS 2.0.0 mode attribute
-    status = getMap (request_inputs, "mode");
-    map* mode=getMap(s1->content,"mode");
-    if(strcasecmp(status->value,"async")==0){
-      if(mode!=NULL && strcasecmp(mode->value,"async")==0)
-	addToMap(request_inputs,"status","true");
-      else{
-	if(mode!=NULL){
-	  // see ref. http://docs.opengeospatial.org/is/14-065/14-065.html#61
-	  errorException (m,_("The process does not permit the desired execution mode."),"NoSuchMode", mode->value);  
-	  fflush (stdout);
+	if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
+	  freeService (&s1);
+	  free (s1);
 	  freeMaps (&m);
 	  free (m);
-	  if(zooRegistry!=NULL){
-	    freeRegistry(&zooRegistry);
-	    free(zooRegistry);
-	  }
+	  free (REQUEST);
+	  free (SERVICE_URL);
 	  freeMaps (&request_input_real_format);
 	  free (request_input_real_format);
 	  freeMaps (&request_output_real_format);
 	  free (request_output_real_format);
-	  free (REQUEST);
-	  free (SERVICE_URL);
-	  return 0;
-	}else
-	  addToMap(request_inputs,"status","true");
+	  freeMaps (&tmpmaps);
+	  free (tmpmaps);
+	  return -1;
+	}
+	map* testMap=getMapFromMaps(m,"main","memory");
+	if(testMap==NULL || strcasecmp(testMap->value,"load")!=0)
+	  dumpMapsValuesToFiles(&m,&request_input_real_format);
+	loadServiceAndRun (&m, s1, request_inputs, &request_input_real_format,
+			   &request_output_real_format, &eres);	  
+
+#ifdef META_DB
+	close_sql(m,0);      
+#endif      
       }
-    }
-    else{
-      if(strcasecmp(status->value,"auto")==0){
-	if(mode!=NULL){
-	  if(strcasecmp(mode->value,"async")==0)
-	    addToMap(request_inputs,"status","false");
-	  else
-	    addToMap(request_inputs,"status","true");
-	}
+    else
+      {
+	int pid;
+#ifdef DEBUG
+	fprintf (stderr, "\nPID : %d\n", cpid);
+#endif
+#ifndef WIN32
+	pid = fork ();
+#else
+	if (cgiSid == NULL)
+	  {
+	    createProcess (m, request_inputs, s1, NULL, cpid,
+			   request_input_real_format,
+			   request_output_real_format);
+	    pid = cpid;
+	  }
 	else
-	  addToMap(request_inputs,"status","false");
-      }else
-	addToMap(request_inputs,"status","false");
-    }
-    status = getMap (request_inputs, "status");
-  }
-
-  int eres = SERVICE_STARTED;
-  int cpid = zGetpid ();
-
-  maps* bmap=NULL;
-  char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog;
-  FILE *f0, *f1;
-  if (status != NULL)
-    if (strcasecmp (status->value, "false") == 0)
-      status = NULLMAP;
-  if (status == NULLMAP)
-    {
-      if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
-	freeService (&s1);
-	free (s1);
-	freeMaps (&m);
-	free (m);
-	free (REQUEST);
-	free (SERVICE_URL);
-	freeMaps (&request_input_real_format);
-	free (request_input_real_format);
-	freeMaps (&request_output_real_format);
-	free (request_output_real_format);
-	freeMaps (&tmpmaps);
-	free (tmpmaps);
-	return -1;
-      }
-      map* testMap=getMapFromMaps(m,"main","memory");
-      if(testMap==NULL || strcasecmp(testMap->value,"load")!=0)
-	dumpMapsValuesToFiles(&m,&request_input_real_format);
-      loadServiceAndRun (&m, s1, request_inputs, &request_input_real_format,
-                         &request_output_real_format, &eres);	  
-
-#ifdef META_DB
-      close_sql(m,0);      
-#endif      
-    }
-  else
-    {
-      int pid;
-#ifdef DEBUG
-      fprintf (stderr, "\nPID : %d\n", cpid);
-#endif
+	  {
+	    pid = 0;
+	    cpid = atoi (cgiSid);
+	    updateStatus(m,0,_("Initializing"));
+	  }
+#endif
+	if (pid > 0)
+	  {
+	    //
+	    // dady :
+	    // set status to SERVICE_ACCEPTED
+	    //
+#ifdef DEBUG
+	    fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid,
+		     zGetpid ());
+#endif
+	    eres = SERVICE_ACCEPTED;
+	  }
+	else if (pid == 0)
+	  {
+	    eres = SERVICE_ACCEPTED;
+	    //
+	    // son : have to close the stdout, stdin and stderr to let the parent
+	    // process answer to http client.
+	    //
+	    map* usid = getMapFromMaps (m, "lenv", "uusid");
+	    map* tmpm = getMapFromMaps (m, "lenv", "osid");
+	    int cpid = atoi (tmpm->value);
+	    pid=cpid;
+	    r_inputs = getMapFromMaps (m, "main", "tmpPath");
+	    setMapInMaps (m, "lenv", "async","true");
+	    map* r_inputs1 = createMap("ServiceName", s1->name);
+
+	    // Create the filename for the result file (.res)
+	    fbkpres =
+	      (char *)
+	      malloc ((strlen (r_inputs->value) +
+		       strlen (usid->value) + 7) * sizeof (char));                    
+	    sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value);
+	    bmap = createMaps("status");
+	    bmap->content=createMap("usid",usid->value);
+	    addToMap(bmap->content,"sid",tmpm->value);
+	    addIntToMap(bmap->content,"pid",zGetpid());
+	  
+	    // Create PID file referencing the OS process identifier
+	    fbkpid =
+	      (char *)
+	      malloc ((strlen (r_inputs->value) +
+		       strlen (usid->value) + 7) * sizeof (char));
+	    sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value);
+	    setMapInMaps (m, "lenv", "file.pid", fbkpid);
+
+	    f0 = freopen (fbkpid, "w+",stdout);
+	    printf("%d",zGetpid());
+	    fflush(stdout);
+
+	    // Create SID file referencing the semaphore name
+	    fbkp =
+	      (char *)
+	      malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+		       strlen (usid->value) + 7) * sizeof (char));
+	    sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value);
+	    setMapInMaps (m, "lenv", "file.sid", fbkp);
+	    FILE* f2 = freopen (fbkp, "w+",stdout);
+	    printf("%s",tmpm->value);
+	    fflush(f2);
+	    free(fbkp);
+
+	    fbkp =
+	      (char *)
+	      malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+		       strlen (usid->value) + 7) * sizeof (char));
+	    sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value,
+		     usid->value);
+	    setMapInMaps (m, "lenv", "file.responseInit", fbkp);
+	    flog =
+	      (char *)
+	      malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+		       strlen (usid->value) + 13) * sizeof (char));
+	    sprintf (flog, "%s/%s_%s_error.log", r_inputs->value,
+		     r_inputs1->value, usid->value);
+	    setMapInMaps (m, "lenv", "file.log", flog);
+#ifdef DEBUG
+	    fprintf (stderr, "RUN IN BACKGROUND MODE \n");
+	    fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid,
+		     zGetpid ());
+	    fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value);
+#endif
+	    freopen (flog, "w+", stderr);
+	    fflush (stderr);
+	    f0 = freopen (fbkp, "w+", stdout);
+	    rewind (stdout);
 #ifndef WIN32
-      pid = fork ();
+	    fclose (stdin);
+#endif
+#ifdef RELY_ON_DB
+	    init_sql(m);
+	    recordServiceStatus(m);
+#endif
+#ifdef USE_CALLBACK
+	    invokeCallback(m,NULL,NULL,0,0);
+#endif
+	    if(vid==0){
+	      //
+	      // set status to SERVICE_STARTED and flush stdout to ensure full 
+	      // content was outputed (the file used to store the ResponseDocument).
+	      // Then, rewind stdout to restart writing from the begining of the file.
+	      // This way, the data will be updated at the end of the process run.
+	      //
+	      printProcessResponse (m, request_inputs, cpid, s1, r_inputs1->value,
+				    SERVICE_STARTED, request_input_real_format,
+				    request_output_real_format);
+	      fflush (stdout);
+#ifdef RELY_ON_DB
+	      recordResponse(m,fbkp);
+#endif
+	    }
+
+	    fflush (stderr);
+
+	    fbkp1 =
+	      (char *)
+	      malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+		       strlen (usid->value) + 13) * sizeof (char));
+	    sprintf (fbkp1, "%s/%s_final_%s.xml", r_inputs->value,
+		     r_inputs1->value, usid->value);
+	    setMapInMaps (m, "lenv", "file.responseFinal", fbkp1);
+
+	    f1 = freopen (fbkp1, "w+", stdout);
+
+	    map* serviceTypeMap=getMap(s1->content,"serviceType");
+	    if(serviceTypeMap!=NULL)
+	      setMapInMaps (m, "lenv", "serviceType", serviceTypeMap->value);
+
+	    char *flenv =
+	      (char *)
+	      malloc ((strlen (r_inputs->value) + 
+		       strlen (usid->value) + 12) * sizeof (char));
+	    sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value);
+	    maps* lenvMaps=getMaps(m,"lenv");
+	    dumpMapsToFile(lenvMaps,flenv,0);
+	    free(flenv);
+
+#ifdef USE_CALLBACK
+	    invokeCallback(m,request_input_real_format,NULL,1,0);
+#endif
+	    if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
+	      freeService (&s1);
+	      free (s1);
+	      fflush (stdout);
+	      fflush (stderr);
+	      fclose (f0);
+	      fclose (f1);
+	      if(dumpBackFinalFile(m,fbkp,fbkp1)<0)
+		return -1;
+#ifndef RELY_ON_DB
+	      dumpMapsToFile(bmap,fbkpres,1);
+	      removeShmLock (m, 1);
 #else
-      if (cgiSid == NULL)
-        {
-	  createProcess (m, request_inputs, s1, NULL, cpid,
-			 request_input_real_format,
-			 request_output_real_format);
-	  pid = cpid;
-        }
-      else
-        {
-	  pid = 0;
-	  cpid = atoi (cgiSid);
-	  updateStatus(m,0,_("Initializing"));
-        }
-#endif
-      if (pid > 0)
-	{
-	  //
-	  // dady :
-	  // set status to SERVICE_ACCEPTED
-	  //
-#ifdef DEBUG
-	  fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid,
-		   zGetpid ());
-#endif
-	  eres = SERVICE_ACCEPTED;
-	}
-      else if (pid == 0)
-	{
-	  eres = SERVICE_ACCEPTED;
-	  //
-	  // son : have to close the stdout, stdin and stderr to let the parent
-	  // process answer to http client.
-	  //
-	  map* usid = getMapFromMaps (m, "lenv", "uusid");
-	  map* tmpm = getMapFromMaps (m, "lenv", "osid");
-	  int cpid = atoi (tmpm->value);
-	  pid=cpid;
-	  r_inputs = getMapFromMaps (m, "main", "tmpPath");
-	  setMapInMaps (m, "lenv", "async","true");
-	  map* r_inputs1 = createMap("ServiceName", s1->name);
-
-	  // Create the filename for the result file (.res)
-	  fbkpres =
-	    (char *)
-	    malloc ((strlen (r_inputs->value) +
-		     strlen (usid->value) + 7) * sizeof (char));                    
-	  sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value);
-	  bmap = createMaps("status");
-	  bmap->content=createMap("usid",usid->value);
-	  addToMap(bmap->content,"sid",tmpm->value);
-	  addIntToMap(bmap->content,"pid",zGetpid());
-	  
-	  // Create PID file referencing the OS process identifier
-	  fbkpid =
-	    (char *)
-	    malloc ((strlen (r_inputs->value) +
-		     strlen (usid->value) + 7) * sizeof (char));
-	  sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value);
-	  setMapInMaps (m, "lenv", "file.pid", fbkpid);
-
-	  f0 = freopen (fbkpid, "w+",stdout);
-	  printf("%d",zGetpid());
-	  fflush(stdout);
-
-	  // Create SID file referencing the semaphore name
-	  fbkp =
-	    (char *)
-	    malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
-		     strlen (usid->value) + 7) * sizeof (char));
-	  sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value);
-	  setMapInMaps (m, "lenv", "file.sid", fbkp);
-	  FILE* f2 = freopen (fbkp, "w+",stdout);
-	  printf("%s",tmpm->value);
-	  fflush(f2);
-	  free(fbkp);
-
-	  fbkp =
-	    (char *)
-	    malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
-		     strlen (usid->value) + 7) * sizeof (char));
-	  sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value,
-		   usid->value);
-	  setMapInMaps (m, "lenv", "file.responseInit", fbkp);
-	  flog =
-	    (char *)
-	    malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
-		     strlen (usid->value) + 13) * sizeof (char));
-	  sprintf (flog, "%s/%s_%s_error.log", r_inputs->value,
-		   r_inputs1->value, usid->value);
-	  setMapInMaps (m, "lenv", "file.log", flog);
-#ifdef DEBUG
-	  fprintf (stderr, "RUN IN BACKGROUND MODE \n");
-	  fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid,
-		   zGetpid ());
-	  fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value);
-#endif
-	  freopen (flog, "w+", stderr);
-	  fflush (stderr);
-	  f0 = freopen (fbkp, "w+", stdout);
-	  rewind (stdout);
-#ifndef WIN32
-	  fclose (stdin);
-#endif
-#ifdef RELY_ON_DB
-	  init_sql(m);
-	  recordServiceStatus(m);
-#endif
+	      recordResponse(m,fbkp1);
 #ifdef USE_CALLBACK
-	  invokeCallback(m,NULL,NULL,0,0);
-#endif
-	  if(vid==0){
-	    //
-	    // set status to SERVICE_STARTED and flush stdout to ensure full 
-	    // content was outputed (the file used to store the ResponseDocument).
-	    // Then, rewind stdout to restart writing from the begining of the file.
-	    // This way, the data will be updated at the end of the process run.
-	    //
-	    printProcessResponse (m, request_inputs, cpid, s1, r_inputs1->value,
-				  SERVICE_STARTED, request_input_real_format,
-				  request_output_real_format);
-	    fflush (stdout);
-#ifdef RELY_ON_DB
-	    recordResponse(m,fbkp);
-#endif
-	  }
-
-	  fflush (stderr);
-
-	  fbkp1 =
-	    (char *)
-	    malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
-		     strlen (usid->value) + 13) * sizeof (char));
-	  sprintf (fbkp1, "%s/%s_final_%s.xml", r_inputs->value,
-		   r_inputs1->value, usid->value);
-	  setMapInMaps (m, "lenv", "file.responseFinal", fbkp1);
-
-	  f1 = freopen (fbkp1, "w+", stdout);
-
-	  map* serviceTypeMap=getMap(s1->content,"serviceType");
-	  if(serviceTypeMap!=NULL)
-	    setMapInMaps (m, "lenv", "serviceType", serviceTypeMap->value);
-
-	  char *flenv =
-	    (char *)
-	    malloc ((strlen (r_inputs->value) + 
-		     strlen (usid->value) + 12) * sizeof (char));
-	  sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value);
-	  maps* lenvMaps=getMaps(m,"lenv");
-	  dumpMapsToFile(lenvMaps,flenv,0);
-	  free(flenv);
-
-#ifdef USE_CALLBACK
-	  invokeCallback(m,request_input_real_format,NULL,1,0);
-#endif
-	  if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
-	    freeService (&s1);
-	    free (s1);
-	    fflush (stdout);
-	    fflush (stderr);
-	    fclose (f0);
-	    fclose (f1);
-	    if(dumpBackFinalFile(m,fbkp,fbkp1)<0)
-	      return -1;
-#ifndef RELY_ON_DB
-	    dumpMapsToFile(bmap,fbkpres,1);
-	    removeShmLock (m, 1);
-#else
-	    recordResponse(m,fbkp1);
-#ifdef USE_CALLBACK
-	    invokeCallback(m,NULL,NULL,7,0);
-#endif
-#endif
-	    zUnlink (fbkpid);
-	    unhandleStatus (m);
+	      invokeCallback(m,NULL,NULL,7,0);
+#endif
+#endif
+	      zUnlink (fbkpid);
+	      unhandleStatus (m);
 #ifdef RELY_ON_DB
 #ifdef META_DB
-	    cleanupCallbackThreads();
-	    close_sql(m,1);
-#endif
-	    close_sql(m,0);
-#endif
-	    freeMaps (&m);
-	    free (m);
-	    free (REQUEST);
-	    free (SERVICE_URL);
-	    freeMaps (&request_input_real_format);
-	    free (request_input_real_format);
-	    freeMaps (&request_output_real_format);
-	    free (request_output_real_format);
-	    freeMaps (&tmpmaps);
-	    free (tmpmaps);
-	    return -1;
+	      cleanupCallbackThreads();
+	      close_sql(m,1);
+#endif
+	      close_sql(m,0);
+#endif
+	      freeMaps (&m);
+	      free (m);
+	      free (REQUEST);
+	      free (SERVICE_URL);
+	      freeMaps (&request_input_real_format);
+	      free (request_input_real_format);
+	      freeMaps (&request_output_real_format);
+	      free (request_output_real_format);
+	      freeMaps (&tmpmaps);
+	      free (tmpmaps);
+	      return -1;
+	    }
+	    if(getMapFromMaps(m,"lenv","mapError")!=NULL){
+	      setMapInMaps(m,"lenv","message",_("Issue with geographic data"));
+#ifdef USE_CALLBACK
+	      invokeCallback(m,NULL,NULL,7,0);
+#endif
+	      eres=-1;//SERVICE_FAILED;
+	    }else{
+	      map* testMap=getMapFromMaps(m,"main","memory");
+	      if(testMap==NULL || strcasecmp(testMap->value,"load")!=0)
+		dumpMapsValuesToFiles(&m,&request_input_real_format);
+	      loadServiceAndRun (&m, s1, request_inputs,
+				 &request_input_real_format,
+				 &request_output_real_format, &eres);
+	    }
 	  }
-	  if(getMapFromMaps(m,"lenv","mapError")!=NULL){
-	    setMapInMaps(m,"lenv","message",_("Issue with geographic data"));
-#ifdef USE_CALLBACK
-	    invokeCallback(m,NULL,NULL,7,0);
-#endif
-	    eres=-1;//SERVICE_FAILED;
-	  }else{
-	    map* testMap=getMapFromMaps(m,"main","memory");
-	    if(testMap==NULL || strcasecmp(testMap->value,"load")!=0)
-	      dumpMapsValuesToFiles(&m,&request_input_real_format);
-	    loadServiceAndRun (&m, s1, request_inputs,
-			       &request_input_real_format,
-			       &request_output_real_format, &eres);
+	else
+	  {
+	    /**
+	     * error server don't accept the process need to output a valid 
+	     * error response here !!!
+	     */
+	    eres = -1;
+	    errorException (m, _("Unable to run the child process properly"),
+			    "InternalError", NULL);
 	  }
-	}
-      else
-        {
-	  /**
-	   * error server don't accept the process need to output a valid 
-	   * error response here !!!
-	   */
-	  eres = -1;
-	  errorException (m, _("Unable to run the child process properly"),
-			  "InternalError", NULL);
-        }
-    }
+      }
 	
 #ifdef DEBUG
-  fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__);
-  dumpMaps (request_output_real_format);
-  fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__);
-#endif
-  fflush(stdout);
-  rewind(stdout);
-
-  //fprintf(stderr,"%s %d %d\n",__FILE__,__LINE__,eres);  
-  if (eres != -1)
-    outputResponse (s1, request_input_real_format,
-                    request_output_real_format, request_inputs,
-                    cpid, m, eres);
-  fflush (stdout);
-  
+    fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__);
+    dumpMaps (request_output_real_format);
+    fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__);
+#endif
+    fflush(stdout);
+    rewind(stdout);
+
+    if (eres != -1)
+      outputResponse (s1, request_input_real_format,
+		      request_output_real_format, request_inputs,
+		      cpid, m, eres);
+    fflush (stdout);
+  }
   /**
    * Ensure that if error occurs when freeing memory, no signal will return
@@ -3248,4 +3448,5 @@
 
       fclose (f0);
+
       fclose (f1);
 
@@ -3278,7 +3479,10 @@
       zUnlink (fbkp1);
       unhandleStatus (m);
+#if defined(USE_JSON) || defined(USE_CALLBACK)
+      cleanupCallbackThreads();
+#endif
+
 #ifdef RELY_ON_DB
 #ifdef META_DB
-      cleanupCallbackThreads();
       close_sql(m,1);
 #endif
@@ -3287,9 +3491,11 @@
 #endif
       free(fbkpid);
-      free(fbkpres); 
+      free(fbkpres);
       free (fbkp1);
       if(cgiSid!=NULL)
 	free(cgiSid);
-      InternetCloseHandle (&hInternet);
+      map* tMap=getMapFromMaps(m,"lenv","executionType");
+      if(tMap!=NULL && strncasecmp(tMap->value,"xml",3)==0)
+	InternetCloseHandle (&hInternet);
       fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__);
       fflush(stderr);
Index: trunk/zoo-project/zoo-services/utils/open-api/cgi-env/display.zcfg
===================================================================
--- trunk/zoo-project/zoo-services/utils/open-api/cgi-env/display.zcfg	(revision 962)
+++ trunk/zoo-project/zoo-services/utils/open-api/cgi-env/display.zcfg	(revision 962)
@@ -0,0 +1,36 @@
+[display]
+ Title = Print Cheetah templates as HTML
+ Abstract = Print Cheetah templates as HTML.
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = service
+ serviceType = Python
+ <DataInputs>
+  [tmpl]
+   Title = Template name
+   Abstract = The name of the template to fill.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+      mimeType = application/json
+      encoding = utf-8
+    </Default>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The welcome message
+   Abstract = The HTML content out of the template.
+   <ComplexData>
+    <Default>
+     mimeType = text/html
+     encoding = utf-8
+    </Default>
+    <Supported>
+     mimeType = text/plain
+     encoding = utf-8
+    </Supported>
+   </ComplexData>
+ </DataOutputs>
Index: trunk/zoo-project/zoo-services/utils/open-api/cgi-env/service.py
===================================================================
--- trunk/zoo-project/zoo-services/utils/open-api/cgi-env/service.py	(revision 962)
+++ trunk/zoo-project/zoo-services/utils/open-api/cgi-env/service.py	(revision 962)
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#  Author:   Gérald Fenoy, gerald.fenoy@geolabs.fr
+#  Copyright (c) 2020, GeoLabs SARL. 
+############################################################################### 
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+# 
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+# 
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+################################################################################
+from Cheetah.Template import Template
+import configparser
+import zoo
+
+def display(conf,inputs,outputs):
+    config = configparser.ConfigParser()
+    config.read(conf["lenv"]["cwd"]+'/oas.cfg')
+    nameSpace = {'conf': conf,'inputs': inputs, 'outputs': outputs,"openapi": config}
+    t = Template(file=conf["main"]["templatesPath"]+"/index.html",searchList=nameSpace)
+    outputs["Result"]["value"]=t.__str__()
+    return zoo.SERVICE_SUCCEEDED
Index: trunk/zoo-project/zoo-services/utils/open-api/requirements.txt
===================================================================
--- trunk/zoo-project/zoo-services/utils/open-api/requirements.txt	(revision 962)
+++ trunk/zoo-project/zoo-services/utils/open-api/requirements.txt	(revision 962)
@@ -0,0 +1,6 @@
+aioredis
+appdirs
+hiredis
+websockets
+Cheetah3
+redis
Index: trunk/zoo-project/zoo-services/utils/open-api/server/.htaccess
===================================================================
--- trunk/zoo-project/zoo-services/utils/open-api/server/.htaccess	(revision 962)
+++ trunk/zoo-project/zoo-services/utils/open-api/server/.htaccess	(revision 962)
@@ -0,0 +1,4 @@
+RewriteRule ^ogc-api/api.html$ /cgi-bin3/zoo_loader.cgi?/api.html [L,QSA]
+RewriteRule ^ogc-api/index.html$ /cgi-bin3/zoo_loader.cgi?service=WPS&service=WPS&request=Execute&version=1.0.0&Identifier=display&RawDataOutput=Result&DataInputs=tmpl=@xlink:href=https://demo.mapmint.com/ogc-api/ [L,QSA]
+RewriteRule ^ogc-api(.*).html$ /cgi-bin3/zoo_loader.cgi?service=WPS&service=WPS&request=Execute&version=1.0.0&Identifier=display&RawDataOutput=Result&DataInputs=tmpl=@xlink:href=https://demo.mapmint.com/ogc-api$1 [L,QSA]
+RewriteRule ^ogc-api(.*)$ /cgi-bin3/zoo_loader.cgi?$1 [L,QSA]
Index: trunk/zoo-project/zoo-services/utils/open-api/server/publish.py
===================================================================
--- trunk/zoo-project/zoo-services/utils/open-api/server/publish.py	(revision 962)
+++ trunk/zoo-project/zoo-services/utils/open-api/server/publish.py	(revision 962)
@@ -0,0 +1,23 @@
+#!/usr/bin/python3
+import os
+import sys
+import redis
+data = sys.stdin.read();
+
+print('Content-Type: text/html')
+print('')
+print('Environment variables')
+for param in os.environ.keys():
+        print ("<b>%20s</b>: %s<br/>" % (param, os.environ[param]))
+
+print(data)
+
+from urllib import parse
+try:
+	params=parse.parse_qs(os.environ["QUERY_STRING"])
+	r = redis.Redis(host='localhost', port=6379, db=0)
+	print(params)
+	r.publish(params["jobid"][0],data)
+except Exception as e:
+	print(e)
+
Index: trunk/zoo-project/zoo-services/utils/open-api/server/subscriber.py
===================================================================
--- trunk/zoo-project/zoo-services/utils/open-api/server/subscriber.py	(revision 962)
+++ trunk/zoo-project/zoo-services/utils/open-api/server/subscriber.py	(revision 962)
@@ -0,0 +1,62 @@
+#!/usr/bin/python3
+# cf. https://github.com/joewalnes/websocketd/wiki/Simple-Python-Duplex-Example
+#
+# example usage:
+# websocketd --port=4430 --ssl --sslcert /ssl/fullchain.pem --sslkey /ssl/privkey.pem subscriber.py --devconsole
+#
+
+from sys import stdout, stdin
+import sys
+import threading
+import redis
+import json
+
+mThreads=[]
+r = redis.Redis(host='localhost', port=6379, db=0)
+
+def send(t):
+    # send string to web page
+    stdout.write(t+'\n')
+    stdout.flush()
+
+def listenMessages(jobID=None):
+    global r
+    p = r.pubsub()
+    p.subscribe(jobID)
+    hasSend=False
+    for raw_message in p.listen():
+        try:
+            send(str(raw_message["data"],'utf-8'))
+            hasSend=True
+            try:
+                tmp=json.loads(str(raw_message["data"],'utf-8'))
+                if tmp is not None and "outputs" in tmp:
+                    sys.exit()
+            except Exception as e:
+                print(str(e))
+                return
+        except:
+            if not(hasSend):
+                send(str(raw_message["data"]))
+
+
+def receive():
+    global n
+    global mThreads
+    while True:
+        t = stdin.readline().strip()
+        if not t:
+            break
+        t1 = t.split(" ")
+        if t1[0]=="SUB":
+            mThreads += [threading.Thread(target=listenMessages,kwargs={"jobID":t1[1]})]
+            mThreads[len(mThreads)-1].start()
+        else:
+            send(t)
+
+t0 = threading.Thread(target=receive)
+t0.start()
+
+t0.join()
+for i in range(len(mThreads)):
+    mThreads[i].join()
Index: trunk/zoo-project/zoo-services/utils/open-api/static/openapi.css
===================================================================
--- trunk/zoo-project/zoo-services/utils/open-api/static/openapi.css	(revision 962)
+++ trunk/zoo-project/zoo-services/utils/open-api/static/openapi.css	(revision 962)
@@ -0,0 +1,49 @@
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+  position: relative;
+  min-height: 100%;
+}
+body {
+  /* Margin bottom by footer height */
+  margin-bottom: 60px;
+}
+.footer {
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  /* Set the fixed height of the footer here */
+  height: 60px;
+  line-height: 60px; /* Vertically center the text there */
+  background-color: #f5f5f5;
+}
+
+
+/* Custom page CSS
+-------------------------------------------------- */
+/* Not required for template or sticky footer method. */
+
+body > .container-fluid {
+  padding: 60px 15px 0;
+}
+
+.footer > .container-fluid {
+  padding-right: 15px;
+  padding-left: 15px;
+}
+
+code {
+  font-size: 80%;
+}
+
+.bi::before {
+  display: inline-block;
+  content: "";
+  background-image: url("data:image/svg+xml,<svg viewBox='0 0 16 16' fill='%23333' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' d='M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z' clip-rule='evenodd'/></svg>");
+  background-repeat: no-repeat;
+  background-size: 1rem 1rem;
+}
+
+.bg-dark {
+  background-color: #663e05!important;
+}
Index: trunk/zoo-project/zoo-services/utils/open-api/templates/index.html
===================================================================
--- trunk/zoo-project/zoo-services/utils/open-api/templates/index.html	(revision 962)
+++ trunk/zoo-project/zoo-services/utils/open-api/templates/index.html	(revision 962)
@@ -0,0 +1,678 @@
+<!doctype html>
+#import zoo
+#import html,os
+#set removeCacheFile=False
+#set strUrl=$inputs["tmpl"]["xlink:href"]
+#set currentUrl=$strUrl.replace($openapi["openapi"]["rootUrl"],"")
+#if $currentUrl=="/"
+#set currentKey="root"
+#set $currentUrl="/index"
+#else
+#set currentKey=$currentUrl
+#end if
+#set urlCompnents=$currentUrl.split('/')
+#*
+* Load the JSON content from the API
+*#
+#try
+#import json
+#if "cache_file" in $inputs["tmpl"]
+#set values=json.load(open($inputs["tmpl"]["cache_file"]))
+#else
+#set values=$inputs["tmpl"]["value"]
+#end if
+#except Exception as e
+$e
+#end try
+<html lang="en">
+  <head>
+    <!-- Required meta tags -->
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+
+    <!-- Bootstrap CSS -->
+    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
+
+    <!-- Custom styles for this template -->
+    <link href="$openapi["openapi"]["rootUrl"]/../static/openapi.css" rel="stylesheet">
+
+    <title>#if "id" in $values#$values["id"]#else##if $currentKey in $openapi and "title" in $openapi[$currentKey]#$openapi[$currentKey]["title"]#else#Landing Page#end if##end if#</title>
+  </head>
+  <body itemscope itemtype="https://schema.org/DataCatalog">
+    <header>
+     <!-- Fixed navbar -->
+      <nav
+        class="navbar navbar-expand-md navbar-dark fixed-top bg-dark"
+        itemprop="creator"
+        itemscope itemtype="https://schema.org/Organization" >
+        <a class="navbar-brand" href="#">
+          <img itemprop="logo" src="http://zoo-project.org/img/zoo-sun-logo.png" width="55" height="30" class="d-inline-block align-top" alt="">
+           <span itemprop="name">$conf["provider"]["providerName"]</span>
+        </a>
+        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
+          <span class="navbar-toggler-icon"></span>
+        </button>
+        <div class="collapse navbar-collapse" id="navbarCollapse">
+	  <ul class="navbar-nav mr-auto"
+	    itemscope itemtype="https://schema.org/BreadcrumbList">
+	    <li class="nav-item #if $currentKey=="root"# active#end if#"
+	      itemprop="itemListElement" itemscope
+	      itemtype="https://schema.org/ListItem">
+	      <a itemprop="item" class="nav-link"
+	        href="$openapi["openapi"]["rootUrl"]/index.html">
+	        <span itemprop="name">Home #if $currentKey=="root"# <span class="sr-only">(current)</span>#end if#</span>
+	        <meta itemprop="position" content="1" />
+	      </a>
+	    </li>
+	    #if $currentKey!="root"
+	    #for i in range(1,len($urlCompnents))
+	    <li
+	      itemprop="itemListElement" itemscope
+	      itemtype="https://schema.org/ListItem"
+	      class="nav-item #if $i+1==len($urlCompnents)#active#end if#">
+	    #set prefix=""
+	    #for j in range(1,$i)
+	    #set $prefix+="/"+$urlCompnents[$j]
+	    #end for
+	      <a itemprop="item" class="nav-link" href="$openapi["openapi"]["rootUrl"]$(prefix)/$(urlCompnents[$i]).html">
+	        <span itemprop="name">
+	    #if $i==2
+	    $(urlCompnents[$i])
+	    #else
+	    $(urlCompnents[$i].title())
+	    #end if
+	    #if $i+1==len($urlCompnents)
+	    <span class="sr-only">(current)</span>
+	    #end if
+	        <meta itemprop="position" content="$(i+1)" />
+	        </span>
+	      </a>
+	    </li>
+	    #end for
+	    #end if
+	  </ul>
+	</div>
+       </nav>
+    </header>
+	<script>
+	var System={};
+	</script>
+
+#def printRel($o,$v)
+#if $v in $o
+$o[$v]
+#else
+View default (no title found for $v).
+#end if
+#end def
+#*
+	
+*#
+#def printControl(obj)
+#if "type" not in $obj
+#set oType="format"
+#else
+#set oType=$obj["type"]
+#end if	
+	<div class="input-group">
+	  <div class="input-group-prepend">
+	    <div class="input-group-text">$obj["title"]</div>
+	  </div>
+	  #if "ph" in $obj  
+	  <input type="text"
+	    #if "value" in $obj#value="$obj["value"]""#end if#
+	    #if "id" in $obj#data-id="$obj["id"]"#end if#
+	    class="form-control" data-name="$obj["title"]" name="$(oType)_$obj["name"]" placeholder="$obj["ph"]" #if "required" in $obj#required#end if#/>
+	  #else
+	  <select name="$(oType)_$obj["name"]" class="form-control" #if "required" in $obj#required#end if#>
+	  #for i in range(len($obj["options"]))
+	    <option>$obj["options"][$i]</option>
+	  #end for
+	  </select>
+	  #end if
+	  #if "required" in $obj
+	  <div class="invalid-feedback">
+	    Please set a value for $obj["id"].
+	  </div>
+	  #end if
+	</div>
+#end def
+#def printCard(obj)
+      <div class="card" #if "attrs" in $obj#$obj["attrs"]#end if#>
+        <div class="card-header" id="heading$(obj["id"])">
+	  <h4 class="mb-0">
+	    <button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#collapse$(obj["id"])" aria-expanded="true" aria-controls="collapse$(obj["id"])">
+	      $obj["title"]
+	    </button>
+	  </h4>
+	</div>
+	<div id="collapse$(obj["id"])" class="collapse #if "class" in $obj#$obj["class"]#end if#" aria-labelledby="heading$(obj["id"])">
+	  <div class="card-body">
+	    $obj["content"]
+	  </div>
+	</div>
+      </div>
+#end def
+#def printInputContent($obj)
+#set cName=$obj["id"].replace(".","_")
+#if "formats" in $obj["input"]
+ #set cFormats=[]
+  #for j in range(len($obj["input"]["formats"]))
+  #set $cFormats+=[$obj["input"]["formats"][$j]["mimeType"]]
+  #end for
+  $printControl({"title": "format","type": "input_format","name": $cName,"options":$cFormats})
+  #set largs={"id": $obj["id"],"title": "href","type": "input_value","name": $cName,"ph":"URL"}
+  #if $obj["minOccurs"]>0
+  #set $largs["required"]=True
+  #end if
+  $printControl($largs)
+#else
+ #if "literalDataDomains" in $obj["input"]
+  #set cDataDomain=$obj["input"]["literalDataDomains"][0]
+  #set largs={"id": $obj["id"],"title": $cDataDomain["dataType"]["name"],"type": "input_value", "name": $cName,}
+  #if $obj["minOccurs"]>0
+  #set $largs["required"]=True
+  #end if
+  #if "anyValue" in $cDataDomain["valueDefinition"]
+   #set $largs["ph"]="Value"
+      $printControl($largs)
+  #else
+   #if "allowedValues" in $cDataDomain["valueDefinition"]
+    #set $largs["options"]=$cDataDomain["valueDefinition"]["allowedValues"]
+    $printControl($largs)
+   #else
+    ELSE
+    $obj
+   #end if
+  #end if
+  #if "defaultValue" in $cDataDomain
+      <script>
+        System["function_$cName"]=function(){
+          try{
+            jQuery("input[name='input_value_$cName'],select[name='input_value_$cName]']").val($cDataDomain["defaultValue"]);
+          }catch(e){
+            jQuery("input[name='input_value_$cName'],select[name='input_value_$cName']").val("$cDataDomain["defaultValue"]");
+          }
+        }
+      </script>
+  #end if
+ #else
+  $obj 
+  ELSE
+ #end if
+#end if
+#end def
+#def printProvider(conf)
+#set provider=$conf["provider"]
+      <b itemprop="name">$provider["providerName"]</b>
+      <p><a itemprop="url" href="$provider["providerSite"]">$provider["providerSite"]</a></p>
+#end def
+#def printContact(conf)
+#set provider=$conf["provider"]
+#set alt=$openapi["provider_alt"]
+#set elements=list($alt.keys())
+      <b>Address</b>
+      #for i in ["addressDeliveryPoint","addressCity","addressAdministrativeArea","addressPostalCode","addressCountry","addressElectronicMailAddress","phoneVoice","phoneFacsimile"]
+      #if i!="addressElectronicMailAddress" and $provider[$i]!="False"
+      <p itemprop="$(alt[$i.lower()])">
+      #if i=="phoneVoice"
+      Phone
+      <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-telephone" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
+        <path fill-rule="evenodd" d="M3.654 1.328a.678.678 0 0 0-1.015-.063L1.605 2.3c-.483.484-.661 1.169-.45 1.77a17.568 17.568 0 0 0 4.168 6.608 17.569 17.569 0 0 0 6.608 4.168c.601.211 1.286.033 1.77-.45l1.034-1.034a.678.678 0 0 0-.063-1.015l-2.307-1.794a.678.678 0 0 0-.58-.122l-2.19.547a1.745 1.745 0 0 1-1.657-.459L5.482 8.062a1.745 1.745 0 0 1-.46-1.657l.548-2.19a.678.678 0 0 0-.122-.58L3.654 1.328zM1.884.511a1.745 1.745 0 0 1 2.612.163L6.29 2.98c.329.423.445.974.315 1.494l-.547 2.19a.678.678 0 0 0 .178.643l2.457 2.457a.678.678 0 0 0 .644.178l2.189-.547a1.745 1.745 0 0 1 1.494.315l2.306 1.794c.829.645.905 1.87.163 2.611l-1.034 1.034c-.74.74-1.846 1.065-2.877.702a18.634 18.634 0 0 1-7.01-4.42 18.634 18.634 0 0 1-4.42-7.009c-.362-1.03-.037-2.137.703-2.877L1.885.511z"/>
+      </svg>
+      #end if
+      $provider[$i]
+      </p>
+      #else
+      #if i=="addressElectronicMailAddress"
+      <b>Email</b>
+      <p itemprop="$(alt[$i.lower()])">
+      $provider[$i]
+      </p>
+      #end if
+      #end if
+      #end for
+#end def      
+#def printIndentification(conf)
+#set provider=$conf["provider"]
+$printCard({"id": "provider","title": "Provider","content": $printProvider($conf),"class": "show"})
+$printCard({"id": "contact","title": "Contact","content": $printContact($conf),"class": "show","attrs":'itemprop="address" itemscope itemtype="https://schema.org/PostalAddress"'})
+#end def
+      
+#if $currentKey=="root"
+  <div class="container-fluid">
+  <div class="row">
+      <div class="col-sm-8">
+#end if
+	<!-- $currentUrl -->
+      <!-- Begin page content -->      
+      <main #if $currentKey!="root"#class="container-fluid"#end if#>
+	<h1 itemprop="name">#if "id" in $values#$values["id"]: #end if##if "title" in $values#$html.escape($values["title"])#else##if len($urlCompnents)==2#$currentUrl[1:].title()#else#$currentUrl[1:]#end if##end if#</h1>
+	#if "description" in $values#<p itemprop="description">$html.escape($values["description"])</p>#end if#
+	#if $currentKey=="root"
+        <div class="keywords">
+	  #for i in $conf["identification"]["keywords"].split(',')
+	  <button type="button"
+	    class="btn btn-outline-info">$i</button>
+	  #end for
+	</div>
+	License: 
+	<a itemprop="license" href="$openapi["openapi"]["license_url"]">$openapi["openapi"]["license_name"]</a>
+	#end if
+    #if "inputs" in $values
+#set $cid="JOBSOCKET-"+$conf["lenv"]["usid"]
+	<form class="needs-validation" data-id="$cid" novalidate>
+    <h3>Inputs</h3>
+    <div class="accordion" id="accordionInputExample">
+      #for i in range(len(values["inputs"]))
+      #set cInput=$values["inputs"][$i]
+      #set cName=$cInput["id"].replace(".","_")
+      $printCard({"id": $cName, "title": $cInput["id"],"content":'<p>'+$cInput["description"]+'</p>'+$printInputContent($cInput)})
+      #end for    
+    </div>
+      
+    <h3>Outputs</h3>
+    <div class="accordion" id="accordionOutputExample">
+      #for i in range(len(values["outputs"]))
+      #set cOutput=$values["outputs"][$i]
+      #set cName=$cOutput["id"].replace(".","_")
+      #set cFormats=[]
+      #if "formats" in $cOutput["output"]
+      #for j in range(len($cOutput["output"]["formats"]))
+      #set cFormats+=[$cOutput["output"]["formats"][$j]["mimeType"]]
+      #end for
+      #end if
+      #set cTransmissions=[]
+      #for j in range(len($values["outputTransmission"]))
+      #set cTransmissions+=[$values["outputTransmission"][$j]]
+      #end for
+      #set cContent="<p>"+$cOutput["description"]+"</p>"
+      #if len(cFormats)>0
+      #set $cContent+=$printControl({"id": $cOutput["id"], "title": "format","type": "format","name": $cName,"options":$cFormats})
+      #end if
+      #if len(cTransmissions)>0
+      #set $cContent+=$printControl({"id": $cOutput["id"], "title": "transmission","type": "transmission","name": $cName,"options":$cTransmissions})
+      #end if
+      $printCard({"id": $cName+"_"+str($i),"title": $cOutput["id"],"content": $cContent})
+      #end for
+    </div>
+    
+    <h3>Execution options</h3>
+    <div class="accordion" id="accordionExampleExecutionMode">
+      #set cContent=""
+      #set cUrl=$openapi["openapi"]["publisherurl"]+cid+"&type="
+      #for a in ["successUri","inProgressUri","failedUri"]
+      #set $cContent+=$printControl({"title": $a,"type": "main_value","name": $a,"ph":"URL","value":$cUrl+$a.replace("Uri","")})
+      #end for
+      $printCard({"id":"ModeOne","title":"Subscribers","content": $cContent})
+      $printCard({"id":"ModeTwo","title":"Response","content": $printControl({"title":"format","type": "main_value","name": "format","options":["document","raw"]})})
+      $printCard({"id":"ModeThree","title":"Mode","content": $printControl({"title":"mode","type": "main_value","name": "mode","options":["async","sync"]})})
+    </div>
+    <button type="submit" class="btn btn-primary" >Submit</button>
+    </form>
+    <div class="modal" tabindex="-1" id="exampleModal">
+      <div class="modal-dialog modal-xl">
+        <div class="modal-content">
+	  <div class="modal-header">
+	    <h5 class="modal-title">Your request</h5>
+	    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+	      <span aria-hidden="true">&times;</span>
+	    </button>
+	  </div>
+	  <div class="modal-body">
+	    <textarea name="modalText" class="form-control" style="min-height:300px"></textarea>
+	    <pre id="result"></pre>
+	    <div id="progress_details" style="display:none">
+	      <p id="prgress_description"></p>
+	      <div class="progress">
+	        <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%"></div>
+              </div>
+	    </div>
+	  </div>
+	  <div class="modal-footer">
+	    <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+	    <button type="button" class="btn btn-primary">Submit Job</button>
+	  </div>
+	</div>
+      </div>
+    </div>
+    <script>
+      var socket;
+      function loadRequest(){
+        var requestObject={
+          "inputs":[],
+          "outputs":[],
+          "subscriber":{},
+          "mode": \$("select[name='main_value_mode']").val(),
+          "response": \$("select[name='main_value_format']").val()
+        }
+        for(var i=0;i < System["JSON_STR"]["inputs"].length;i++){
+          var cInput={"id": System["JSON_STR"]["inputs"][i]["id"]};
+          var cName=System["JSON_STR"]["inputs"][i]["id"].replace(".","_");
+          var selector="input[name='input_value_"+cName+"'],"+
+                       "select[name='input_value_"+cName+"']";
+          if(\$(selector).val()!=""){
+            cInput["input"]={};
+          if(System["JSON_STR"]["inputs"][i]["input"]["formats"]){
+            var selector1="input[name='input_format_"+cName+"'],"+
+              "select[name='input_format_"+cName+"']";
+            cInput["input"]["format"]={
+              "mimeType": \$(selector1).val()
+            };
+            cInput["input"]["value"]={
+              "href": \$(selector).val()
+            };
+          }
+          else{
+            if(System["JSON_STR"]["inputs"][i]["input"]["literalDataDomains"]){
+              console.log(System["JSON_STR"]["inputs"][i]["input"]["literalDataDomains"]);
+              cInput["input"]["dataType"]={
+                "name": System["JSON_STR"]["inputs"][i]["input"]["literalDataDomains"][0]["dataType"]["name"]
+              };
+              cInput["input"]["value"]=\$(selector).val();
+            }
+            }
+            requestObject["inputs"].push(cInput);
+          }
+        }
+        console.log(System["JSON_STR"]["outputs"]);
+        for(var i=0;i < System["JSON_STR"]["outputs"].length;i++){
+          var cOutput={"id": System["JSON_STR"]["outputs"][i]["id"]};
+          var cName=System["JSON_STR"]["outputs"][i]["id"].replace(/\./g,"_");
+          if(System["JSON_STR"]["outputs"][i]["output"]["formats"]){
+            var selector="select[name='format_"+cName+"']";
+            cOutput["format"]={
+              "mimeType": \$(selector).val()
+            };
+          }
+          else{
+            if(System["JSON_STR"]["outputs"][i]["output"]["literalDataDomains"]){
+              cOutput["dataType"]={
+                "name": System["JSON_STR"]["outputs"][i]["output"]["literalDataDomains"][0]["dataType"]["name"]
+              };
+            }
+          }
+          var selector1="select[name='transmission_"+cName+"']";
+          cOutput["transmissionMode"]=\$(selector1).val();
+          requestObject["outputs"].push(cOutput);
+        }
+        if(\$("input[name='main_value_successUri']").val()!="")
+          requestObject["subscriber"]["successUri"]=\$("input[name='main_value_successUri']").val();
+        if(\$("input[name='main_value_inProgressUri']").val()!="")
+          requestObject["subscriber"]["inProgressUri"]=\$("input[name='main_value_inProgressUri']").val();
+        if(\$("input[name='main_value_failedUri']").val()!="")
+          requestObject["subscriber"]["failedUri"]=\$("input[name='main_value_failedUri']").val();
+        \$(".modal").find("textarea").first().val(js_beautify(JSON.stringify(requestObject)));
+        \$("#exampleModal").modal('toggle');
+        \$('#result').html("");
+        \$("#exampleModal").find(".btn-primary").off('click');
+        \$("#exampleModal").find(".btn-primary").click(function(){
+          \$('#result').html("");
+          if(!socket && requestObject["mode"]!="sync")
+            socket = new WebSocket("$openapi["openapi"]["wsurl"]");
+          else
+              \$.ajax({
+                contentType: "application/json",
+                data: \$("textarea").val(),
+                type: "POST",
+                url: "$openapi["openapi"]["rootUrl"]$(currentUrl)/jobs",
+                success: function (msg) {
+                  console.log(msg);
+                  var cObj=msg;
+                  \$('#result').html(js_beautify(JSON.stringify(msg["outputs"])));
+                },
+                error: function(){
+                  console.log(arguments);
+                },
+              });
+          if(requestObject["mode"]=="sync"){
+           return;
+          }
+          socket.onopen = function () {
+            console.log('Connected!');
+            socket.send("SUB $cid");
+          };
+          socket.onmessage = function(event) {
+            console.log('MESSAGE: ' + event.data);
+            if(event.data=="1")
+              \$.ajax({
+                contentType: "application/json",
+                data: \$("textarea").val(),
+                type: "POST",
+                url: "$openapi["openapi"]["rootUrl"]$(currentUrl)/jobs",
+                success: function (msg) {
+                  console.log(msg);
+                },
+                error: function(){
+                  console.log(arguments);
+                },
+              });
+            else{
+              //progressBar
+              \$("#progress_details").show();
+              var cObj=JSON.parse(event.data);
+              if(cObj["jobID"]){
+                \$("#prgress_description").html(cObj["jobID"]+": "+cObj["message"]);
+                \$(".progress-bar").attr("aria-valuenow",cObj["progress"]);
+                \$(".progress-bar").css("width",cObj["progress"]+"%");
+              }else{
+                \$("#progress_details").hide();
+                if(cObj["outputs"])
+                  \$('#result').html(js_beautify(JSON.stringify(cObj["outputs"])));
+                else
+                  \$('#result').html(cObj["message"]);
+              }
+            }
+          };
+        });
+      }
+    </script>
+    #end if
+    
+    #try
+    #if "links" in $values
+    #for i in range(len($values["links"]))
+    #if $i%2==0    
+    <h2>$values["links"][$i]["title"]</h2>
+    <p>
+      <a href="$values["links"][$i]["href"]">$printRel($openapi["links_title"],$values["links"][$i]["rel"])</a>
+    </p>
+    #if $i+1<=len($values["links"]) and len($values["links"])>1 and not($values["links"][$i+1]["rel"]=="alternate" and $openapi["openapi"]["full_html_support"]=="true")
+    <p><a href="$values["links"][$i+1]["href"]">$printRel($openapi["links_title"],$values["links"][$i+1]["rel"])</a></p>
+    #end if
+    #end if
+    #end for
+    #end if
+    #except Exception as e
+    $e
+    #end try
+    #if "conformsTo" in $values
+    <ul>
+      #for i in range(len($values["conformsTo"]))
+      <li>
+      <a href="$values["conformsTo"][$i]">$values["conformsTo"][$i]</a>
+      </li>
+      #end for
+    </ul>
+    #end if
+    #if "jobs" in $urlCompnents
+    #set $removeCacheFile=True
+    #end if
+    #if hasattr($values, "__len__") and isinstance($values,list) and len($values)>0
+    <table class="table table-striped">
+      <thead>
+	<tr>
+	  #if "jobs" not in $urlCompnents
+	  #*
+	  * Processes list
+	  *#
+	  <th scope="col">#</th>
+	  <th scope="col">Title</th>
+	  <th scope="col">Version</th>
+	  #else
+	  #*
+	  * Jobs list
+	  *#
+	  <th scope="col">#</th>
+	  <th scope="col">Message</th>
+	  <th scope="col">Links</th>
+	  #end if
+	</tr>
+      </thead>
+      <tbody>	
+	#for i in range(len($values))
+	<tr>
+	  #if "jobs" not in $urlCompnents
+	  #*
+	  * Processes list
+	  *#
+	  <th scope="row">
+	    <a href="$(values[$i]["links"][0]["href"][:-1]).html">
+	      <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-link-45deg" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
+	        <path d="M4.715 6.542L3.343 7.914a3 3 0 1 0 4.243 4.243l1.828-1.829A3 3 0 0 0 8.586 5.5L8 6.086a1.001 1.001 0 0 0-.154.199 2 2 0 0 1 .861 3.337L6.88 11.45a2 2 0 1 1-2.83-2.83l.793-.792a4.018 4.018 0 0 1-.128-1.287z"/>
+	        <path d="M6.586 4.672A3 3 0 0 0 7.414 9.5l.775-.776a2 2 0 0 1-.896-3.346L9.12 3.55a2 2 0 0 1 2.83 2.83l-.793.792c.112.42.155.855.128 1.287l1.372-1.372a3 3 0 0 0-4.243-4.243L6.586 4.672z"/>
+	      </svg>
+	    $values[$i]["id"]
+	    </a>
+	  </th>
+	  <td>$values[$i]["title"]</td>
+	  <td>#if "version" in $values[$i]#$values[$i]["version"]#else#1.0.0#end if#</td>
+	  #else
+	  #*
+	  * Jobs list
+	  *#
+	  #set cValue=$values[$i]["infos"]
+	  <th scope="row">
+	    #if "status" in $cValue and $cValue["status"]=="successful"
+	    <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-check-circle-fill text-success" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
+	      <path fill-rule="evenodd" d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
+	    </svg>
+	    #else
+	    #if "status" in $cValue and $cValue["status"]=="failed"
+	    <svg width="1.0625em" height="1em" viewBox="0 0 17 16" class="bi bi-exclamation-triangle-fill text-error" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
+	      <path fill-rule="evenodd" d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 5zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/>
+	    </svg>
+	    #end if
+	    #end if
+	    $cValue["jobID"]
+	  </th>
+	  <td>$cValue["message"]</td>
+	  <td>
+	  <div class="dropdown">
+	    <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+	    Action
+	    </button>
+	    <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
+	      #for j in range(len($cValue["links"]))
+	      #set $cValueLink=$cValue["links"][$j]
+	      #if $cValueLink["href"].count("result")==0
+	      <a class="dropdown-item delete"
+	        href="#"
+	        data-value="$(cValueLink["href"])">Delete</a>
+	      #end if
+	      <a class="dropdown-item" href="$(cValueLink["href"]).html">$cValueLink["title"]</a>
+	      #end for	      
+	    </div>
+	  </div>
+	  </td>
+	  #end if
+	</tr>	
+	#end for
+      </tbody>
+    </table>
+    <script>
+    System["jobListDelete"]=function(){
+      \$(".delete").each(function(){
+        \$(this).off("click");
+        \$(this).click(function(){
+          console.log("OK");
+          \$.ajax({
+            url: \$(this).data("value"),
+            type: "DELETE",
+            success: function(){
+              console.log(arguments);
+            }
+          });
+        });
+      });
+    }
+    </script>
+    #end if
+
+      <div class="microlight">$json.dumps(values)</div>
+      <textarea class="form-control" style="height: 300px;"></textarea>
+      <script>
+      window.onload = function(){
+        var jsContent=\$(".microlight").html();
+        var tmpStr=js_beautify(jsContent);
+        \$("textarea").last().val(tmpStr);
+        \$(".microlight").remove();
+        for(var i in System){
+          System[i]();
+        }
+         System["JSON_STR"]=JSON.parse(tmpStr);
+         var forms = document.getElementsByClassName('needs-validation');
+         // Loop over them and prevent submission
+         var validation = Array.prototype.filter.call(forms, function(form) {
+      form.addEventListener('submit', function(event) {
+             event.preventDefault();
+             event.stopPropagation();
+             if (form.checkValidity() === false) {
+               event.preventDefault();
+      event.stopPropagation();
+      alert('ok');
+             }else{
+               loadRequest();
+             }
+             form.classList.add('was-validated');
+           }, false);
+         });
+      
+      }
+      </script>
+      <hr>
+      <address>$openapi["openapi"]["rootUrl"]$(currentUrl).html</address>
+      <!-- hhmts start -->Last modified: Wed Oct 21 17:23:48 CEST 2020 <!-- hhmts end -->
+    </main>
+#if $currentKey=="root"
+    </div>  
+    <div class="col-sm-4"
+      itemprop="provider"
+      itemscope itemtype="https://schema.org/Organization">
+      $printIndentification($conf)
+    </div>
+   </div>
+  </div>
+#end if
+      
+
+    <footer class="footer" itemscope itemtype="https://schema.org/SoftwareApplication">
+      <div class="container-fluid">
+	<span class="text-muted">
+	  Powered by
+	  <a target="_blank" itemprop="url"
+	    href="http://www.zoo-project.org/"><span itemprop="name">ZOO-Project</span></a>
+	  <span itemprop="version">$zoo.VERSION</span>.
+	  <meta itemprop="applicationCategory" content="WebService" />
+	#try
+	#set sysname=$os.uname()
+	#except Exception as e
+	#set sysname=["Unknown"]
+	#end try
+	  <meta itemprop="operatingSystem" content="$sysname[0]" />
+	</span>
+      </div>
+    </footer>
+
+    <!-- JS, Popper.js, and jQuery -->
+    <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
+    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
+    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.13.0/beautify.min.js" integrity="sha512-84xqGKD+OW9ElGeIq5RkXhsKveQx+kAjahn9r7f/Vm9J0bDrwEabW3MQNgYdTzLBnwfrTGs0nuPx3pZxh6itNg==" crossorigin="anonymous"></script>
+  </body>
+</html>
+#if "cache_file" in $inputs["tmpl"] and $removeCacheFile
+<!-- REMOVED ! -->      
+#import os
+$(os.remove($inputs["tmpl"]["cache_file"]))
+#end if
