Index: /trunk/thirds/otb2zcfg/CMakeLists.txt
===================================================================
--- /trunk/thirds/otb2zcfg/CMakeLists.txt	(revision 550)
+++ /trunk/thirds/otb2zcfg/CMakeLists.txt	(revision 550)
@@ -0,0 +1,14 @@
+PROJECT(otb2zcfg)  
+ 
+cmake_minimum_required(VERSION 2.6)  
+ 
+FIND_PACKAGE(OTB)  
+IF(OTB_FOUND)  
+  INCLUDE(${OTB_USE_FILE})  
+ELSE(OTB_FOUND)  
+  MESSAGE(FATAL_ERROR  
+      "Cannot build OTB project without OTB.  Please set OTB_DIR.")  
+ENDIF(OTB_FOUND)  
+ 
+ADD_EXECUTABLE(otb2zcfg otb2zcfg.cxx )  
+TARGET_LINK_LIBRARIES(otb2zcfg OTBCommon OTBApplicationEngine OTBIO ${ITK_LIBRARIES}) 
Index: /trunk/thirds/otb2zcfg/README.txt
===================================================================
--- /trunk/thirds/otb2zcfg/README.txt	(revision 550)
+++ /trunk/thirds/otb2zcfg/README.txt	(revision 550)
@@ -0,0 +1,18 @@
+To build the otb2zcfg utility you should run the following command:
+
+ mkdir build
+ cd build
+ ccmake ..
+ make
+
+ 
+To generate the zcfgs for the OTB Applications available, you should run the following:
+
+ mkdir zcfgs
+ cd zcfgs
+ ../build/otb2zcfg
+ cp *zcfg /location/to/your/cgi-bin
+ export ITK_AUTOLOAD_PATH=/your/path/to/otb/applications
+ ../build/otb2zcfg
+
+This ITK_AUTOLOAD_PATH environment variable will be required in the [env] section of your main.cfg.
Index: /trunk/thirds/otb2zcfg/otb2zcfg.cxx
===================================================================
--- /trunk/thirds/otb2zcfg/otb2zcfg.cxx	(revision 550)
+++ /trunk/thirds/otb2zcfg/otb2zcfg.cxx	(revision 550)
@@ -0,0 +1,382 @@
+#include "otbWrapperApplicationRegistry.h"
+#include "otbWrapperApplication.h"
+#include "otbImage.h" 
+#include <iostream> 
+
+using namespace otb::Wrapper;
+
+std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
+    size_t start_pos = 0;
+    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
+        str.replace(start_pos, from.length(), to);
+        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
+    }
+    return str;
+}
+
+void printDefaultOutput(){
+  std::cout << "  [Result]" << std::endl;
+  std::cout << "   Title = the result message" << std::endl;
+  std::cout << "   Abstract = the result message" << std::endl;
+  std::cout << "   <LiteralData>" << std::endl;
+  std::cout << "    dataType = string" << std::endl;
+  std::cout << "    <Default />" << std::endl;
+  std::cout << "   </LiteralData>" << std::endl;
+}
+
+void printAscii(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/plain" << std::endl;
+  std::cout << "     encoding = ascii" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+}
+
+void printXml(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/xml" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+}
+
+void printGeoid(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = application/octet-stream" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+}
+
+void printCSV(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/csv" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+}
+
+void printUnknown(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/xml" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = text/plain" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+}
+
+void printImages(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = image/tiff" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+#if defined(OTB_USE_JPEG2000)
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = image/jp2" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+#endif
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = image/jpeg" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = image/png" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+}
+
+void printVector(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/xml" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = application/vnd.google-earth.kml+xml" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = application/zip" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+}
+
+void printOutputImage(){
+  std::cout << "   <LiteralData>" << std::endl;
+  std::cout << "    dataType = string" << std::endl;
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     value = float" << std::endl;
+  std::cout << "     AllowedValues = uint8,uint16,int16n,int32,int32,float,double" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+  std::cout << "   </LiteralData>" << std::endl;
+}
+
+void printOutputComplexImage(){
+  std::cout << "   <LiteralData>" << std::endl;
+  std::cout << "    dataType = string" << std::endl;
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     value = cfloat" << std::endl;
+  std::cout << "     AllowedValues = cfloat,cdouble" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+  std::cout << "   </LiteralData>" << std::endl;
+}
+
+int main(int itkNotUsed(argc), char * itkNotUsed(argv)[]) 
+{ 
+  typedef otb::Image<unsigned short, 2> ImageType; 
+ 
+  ImageType::Pointer image = ImageType::New(); 
+ 
+  const char * ITK_AUTOLOAD_PATH = itksys::SystemTools::GetEnv("ITK_AUTOLOAD_PATH");
+  std::cerr << "ERROR: Module search path: " << (ITK_AUTOLOAD_PATH ? ITK_AUTOLOAD_PATH : "none (check ITK_AUTOLOAD_PATH)") << std::endl;
+
+  std::vector<std::string> list = ApplicationRegistry::GetAvailableApplications();
+  if (list.size() == 0)
+    std::cerr << "ERROR: Available modules : none." << std::endl;
+  else{
+    std::cerr << "ERROR: Available modules :" << std::endl;
+    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it){
+      std::string filename= *it + ".zcfg";
+      std::ofstream out(filename);
+      std::streambuf *coutbuf = std::cout.rdbuf();
+      std::cout.rdbuf(out.rdbuf());
+
+      std::cerr << *it << std::endl;
+      std::cout << "[" << *it << "]" << std::endl;
+      Application::Pointer m_Application=ApplicationRegistry::CreateApplication(*it);
+      std::string s0 = m_Application->GetDescription();
+      s0=ReplaceAll(ReplaceAll(s0,std::string("\n"),std::string("")),std::string("\t"),std::string(""));
+      std::cout << " Title = " << s0 << std::endl;
+      s0 = m_Application->GetDocLongDescription();
+      s0=ReplaceAll(ReplaceAll(s0,std::string("\n"),std::string("")),std::string("\t"),std::string(""));
+      std::cout << " Abstract = " << s0 << std::endl;
+      const std::vector<std::string> appKeyList = m_Application->GetParametersKeys(true);
+      std::cout << " storeSupported = true"<< std::endl;
+      std::cout << " statusSupported = true" << std::endl;
+      std::cout << " serviceProvider = " << *it << std::endl;
+      std::cout << " serviceType = OTB" << std::endl;
+      std::cout << " <DataInputs>" << std::endl;
+      for (unsigned int i = 0; i < appKeyList.size(); i++){
+	const std::string paramKey(appKeyList[i]);
+	Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+	ParameterType type = m_Application->GetParameterType(paramKey);
+	Role role = m_Application->GetParameterRole(paramKey);
+      
+	if(paramKey!="inxml" && paramKey!="outxml" && role==0 && type!=17 
+	   && type!=ParameterType_OutputFilename && type!=ParameterType_OutputVectorData){
+	  std::vector<std::string> values;
+	  std::string s = m_Application->GetParameterDescription(paramKey);
+	  s=ReplaceAll(ReplaceAll(ReplaceAll(s,std::string("\n"),std::string("")),std::string("\t"),std::string("")),std::string("<"),std::string("&lt;"));
+	  std::cout << "  [" << paramKey << "]" << std::endl;
+	  if(s.length()>0){
+	    std::cout << "   Title = " << s << std::endl;
+	    std::cout << "   Abstract = " << s << std::endl;
+	  }else{
+	    std::cout << "   Title = " << paramKey << std::endl;
+	    std::cout << "   Abstract = " << paramKey << std::endl;
+	  }
+	  std::cout << "   minOccurs = " << m_Application->IsMandatory(paramKey) << std::endl;
+	  /* Bounded and unbounded parameters */
+	  if(type == ParameterType_StringList || type == ParameterType_InputImageList
+	     || type == ParameterType_InputVectorDataList || type == ParameterType_InputFilenameList)
+	    std::cout << "   maxOccurs = 1024" << std::endl;
+	  else
+	    std::cout << "   maxOccurs = 1" << std::endl;
+	  std::replace( s.begin(), s.end(), '\n', ' ');
+	  
+	  if(type == ParameterType_StringList || type == ParameterType_String || type == ParameterType_Float
+	     || type == ParameterType_Int || type == ParameterType_Choice || type == ParameterType_ListView
+	     || type == ParameterType_RAM || type == ParameterType_Empty || type == ParameterType_Directory){
+	    std::cout << "   <LiteralData>" << std::endl;
+	    std::string lt;
+	    if(type == ParameterType_Int || type == ParameterType_RAM)
+	      lt="integer";
+	    if(type == ParameterType_Float)
+	      lt="float";
+	    if(type == ParameterType_String || type == ParameterType_StringList
+	       || type == ParameterType_Choice || type == ParameterType_Directory
+	       || type == ParameterType_ListView)
+	      lt="string";
+	    if(type == ParameterType_Empty)
+	      lt="boolean";
+	    std::cout << "    dataType = " << lt << std::endl;
+	    if(type == ParameterType_Choice || type == ParameterType_ListView){
+	      const std::vector<std::string> nList = m_Application->GetChoiceNames(paramKey);
+	      const std::vector<std::string> keysList = m_Application->GetChoiceKeys(paramKey);
+	      if(keysList.size()==0){
+		std::cout << "    <Default />" << std::endl;
+	      }
+	      for (unsigned int j = 0; j < keysList.size(); j++){
+		const std::string key(keysList[j]);
+		if(j==0){
+		  std::cout << "    <Default>" << std::endl;
+		  if(m_Application->HasValue(paramKey))
+		    std::cout << "    value = " << m_Application->GetParameterAsString(paramKey) << std::endl;
+		  else
+		    std::cout << "    value = " << key << std::endl;
+		}
+		else{
+		  if(j==1){
+		    std::cout << "    AllowedValues = "+keysList[0]+",";
+		  }
+		  std::cout << keysList[j];
+		  if(j+1>=keysList.size()){
+		    std::cout << std::endl;
+		    std::cout << "    </Default>" << std::endl;
+		  }
+		  else
+		    std::cout << ",";
+		}
+	      }
+	    }
+	    else{
+	      if(type!=17 && m_Application->HasValue(paramKey)){
+		std::cout << "    <Default>" << std::endl;
+		std::cout << "     value = " << m_Application->GetParameterAsString(paramKey) << std::endl;
+		std::cout << "    </Default>" << std::endl;
+	      }
+	      else
+		std::cout << "    <Default />" << std::endl;
+	    }
+	    std::cout << "   </LiteralData>" << std::endl;
+	  }
+	  else{
+	    if(type == ParameterType_OutputImage)
+	      printOutputImage();
+	    else{
+	      if(type == ParameterType_ComplexOutputImage){
+		printOutputComplexImage();
+	      }else{
+		std::cout << "   <ComplexData>" << std::endl;
+		if(type == ParameterType_InputImage || type == ParameterType_InputImageList || type == ParameterType_ComplexInputImage){
+		  printImages();
+		}
+		else
+		  if(type == ParameterType_InputVectorData || type == ParameterType_InputVectorDataList){
+		    printVector();
+		  }
+		  else
+		    if(type == ParameterType_InputFilename || type == ParameterType_OutputFilename){
+		      
+		      std::string geoid("geoid");
+		      if(paramKey.find(geoid)!= std::string::npos)
+			printGeoid();
+		      else{
+			std::string dtype("vector");
+			std::string descr(m_Application->GetParameterDescription(paramKey));
+			if(descr.find(dtype)!= std::string::npos)
+			  printVector();
+			else{
+			  std::string dtype1("ASCII");
+			  if(descr.find(dtype1)!= std::string::npos)
+			    printAscii();
+			  else{
+			    std::string dtype2("XML");
+			    std::string dtype3("xml");
+			    if(descr.find(dtype2)!= std::string::npos || descr.find(dtype3)!= std::string::npos)
+			      printXml();
+			    else
+			      printImages();
+			  }
+			}
+		      }
+		    }
+		std::cout << "   </ComplexData>" << std::endl;
+	      }
+	    }
+	  }
+
+
+	}
+      }
+      std::cout << " <DataInputs>" << std::endl;
+      std::cout << " <DataOutputs>" << std::endl;
+      int hasOutput=-1;
+      for (unsigned int i = 0; i < appKeyList.size(); i++){
+	const std::string paramKey(appKeyList[i]);
+	std::vector<std::string> values;
+	Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+	ParameterType type = m_Application->GetParameterType(paramKey);
+	Role role = m_Application->GetParameterRole(paramKey);
+	
+	if(paramKey!="inxml" && paramKey!="outxml" &&
+	   ((type == ParameterType_OutputVectorData || type == ParameterType_OutputImage
+	     || type == ParameterType_OutputImage || type == ParameterType_ComplexOutputImage
+	     || type == ParameterType_OutputFilename) || role==1) && type != ParameterType_Group){
+	  hasOutput=1;
+	  std::vector<std::string> values;
+	  Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+	  ParameterType type = m_Application->GetParameterType(paramKey);
+	  Role role = m_Application->GetParameterRole(paramKey);
+	  std::cout << "  [" << paramKey << "]" << std::endl;
+	  std::string s=m_Application->GetParameterDescription(paramKey);
+	  if(s.length()>0){
+	    std::cout << "   Title = " << s << std::endl;
+	    std::cout << "   Abstract = " << s << std::endl;
+	  }else{
+	    std::cout << "   Title = " << paramKey << std::endl;
+	    std::cout << "   Abstract = " << paramKey << std::endl;
+	  }
+
+	  if(type == ParameterType_OutputImage || type == ParameterType_ComplexOutputImage){
+	    std::cout << "   <ComplexData>" << std::endl;
+	    printImages();
+	    std::cout << "   </ComplexData>" << std::endl;
+	  }
+	  else
+	    if(type == ParameterType_OutputVectorData || type == ParameterType_OutputImage){
+	      std::cout << "   <ComplexData>" << std::endl;
+	      if(type == ParameterType_OutputImage)
+		printImages();
+	      else
+		printVector();
+	      std::cout << "   </ComplexData>" << std::endl;
+	    }
+	    else
+	      if(type == ParameterType_String || type == ParameterType_StringList
+		 || type == ParameterType_Float || type == ParameterType_Int){
+		std::cout << "   <LiteralData>" << std::endl;
+		std::string lt;
+		if(type == ParameterType_Int)
+		  lt="integer";
+		if(type == ParameterType_Float)
+		  lt="float";
+		if(type == ParameterType_String || type == ParameterType_StringList)
+		  lt="string";
+		std::cout << "    dataType = " << lt << std::endl;
+		std::cout << "    <Default />" << std::endl;
+		std::cout << "   </LiteralData>" << std::endl;
+	      }
+	      else
+		if(type == ParameterType_OutputFilename){
+		  std::cout << "   <ComplexData>" << std::endl;
+		  std::string descr(m_Application->GetParameterDescription(paramKey));
+		  std::string dtype("csv");
+		  std::string dtype1("CSV");
+		  if(descr.find(dtype)!= std::string::npos || descr.find(dtype1)!= std::string::npos)
+		    printCSV();
+		  else{
+		    std::string dtype2("text file");
+		    if(descr.find(dtype2)!= std::string::npos)
+		      printAscii();
+		    else{
+		      std::string dtype2("XML");
+		      std::string dtype3("xml");
+		      if(descr.find(dtype2)!= std::string::npos || descr.find(dtype3)!= std::string::npos)
+			printXml();
+		      else{
+			std::string dtype4("vector");
+			std::string dtype5("Vector");
+			if(descr.find(dtype4)!= std::string::npos || descr.find(dtype5)!= std::string::npos)
+			  printVector();
+			else
+			  printUnknown();
+		      }
+		    }
+		  }
+		  std::cout << "   </ComplexData>" << std::endl;
+		}
+	}
+      }
+      if(hasOutput<0)
+	printDefaultOutput();
+      std::cout << " </DataOutputs>" << std::endl;
+      std::cout.rdbuf(coutbuf);
+    }
+  }
+ 
+  return EXIT_SUCCESS; 
+}
+
Index: /trunk/zoo-project/HISTORY.txt
===================================================================
--- /trunk/zoo-project/HISTORY.txt	(revision 549)
+++ /trunk/zoo-project/HISTORY.txt	(revision 550)
@@ -1,2 +1,9 @@
+Version 1.5.0-dev
+  * Add Orfeo Toolbox support for applications as a service
+  * Add the otb2zcfg utility to produce zcfg for otb applications
+  * Fix maxOccurs handling
+  * Fix gesture of downloaded inputs when multiple values are given
+  * Add detection of generated_file key in outputs to read the file generated by a service
+
 Version 1.4.0
   * Small fix for mimeType of results for CGAL services
Index: /trunk/zoo-project/zoo-kernel/Makefile.in
===================================================================
--- /trunk/zoo-project/zoo-kernel/Makefile.in	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/Makefile.in	(revision 550)
@@ -45,4 +45,13 @@
 	g++ ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} -c service_internal_python.c
 
+service_internal_otb.o: service_internal_otb.c service.h
+	g++ ${OTBCFLAGS} ${CFLAGS} -c service_internal_otb.c
+
+otbRunner.o: otbRunner.cxx otbRunner.h service.h
+	g++ ${OTBCFLAGS} ${CFLAGS} -c otbRunner.cxx
+
+otbZooWatcher.o: otbZooWatcher.cxx otbZooWatcher.h  service.h
+	g++ ${OTBCFLAGS} ${CFLAGS} -c otbZooWatcher.cxx
+
 service_internal_php.o: service_internal_php.c service.h
 	g++ -c ${XML2CFLAGS} ${PHPCFLAGS} ${CFLAGS}  ${PHP_ENABLED} service_internal_php.c
@@ -64,9 +73,9 @@
 
 zoo_service_loader.o: zoo_service_loader.c service.h
-	g++ -g -O2 ${XML2CFLAGS} ${CFLAGS} ${PYTHONCFLAGS} ${JAVACFLAGS} ${JSCFLAGS} ${PERLCFLAGS} ${PHPCFLAGS} ${PYTHON_ENABLED} ${JS_ENABLED} ${PHP_ENABLED} ${PERL_ENABLED} ${JAVA_ENABLED} -c zoo_service_loader.c  -fno-common -DPIC -o zoo_service_loader.o
+	g++ -g -O2 ${XML2CFLAGS} ${CFLAGS} ${OTBCFLAGS} ${PYTHONCFLAGS} ${JAVACFLAGS} ${JSCFLAGS} ${PERLCFLAGS} ${PHPCFLAGS} ${OTB_ENABLED} ${PYTHON_ENABLED} ${JS_ENABLED} ${PHP_ENABLED} ${PERL_ENABLED} ${JAVA_ENABLED} -c zoo_service_loader.c  -fno-common -DPIC -o zoo_service_loader.o
 
-zoo_loader.cgi: version.h zoo_loader.c zoo_service_loader.o  ulinet.o service.h lex.sr.o service_conf.tab.o service_conf.y ulinet.o main_conf_read.tab.o lex.cr.o service_internal.o ${MS_FILE} ${PYTHON_FILE} ${PHP_FILE} ${JAVA_FILE} ${JS_FILE} ${PERL_FILE} ${RUBY_FILE} ${YAML_FILE}
+zoo_loader.cgi: version.h zoo_loader.c zoo_service_loader.o  ulinet.o service.h lex.sr.o service_conf.tab.o service_conf.y ulinet.o main_conf_read.tab.o lex.cr.o service_internal.o ${MS_FILE} ${PYTHON_FILE} ${PHP_FILE} ${JAVA_FILE} ${JS_FILE} ${PERL_FILE} ${RUBY_FILE} ${YAML_FILE} ${OTB_FILE}
 	g++ -g -O2 ${JSCFLAGS} ${PHPCFLAGS}  ${PERLCFLAGS} ${RUBYCFLAGS}  ${JAVACFLAGS} ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} -c zoo_loader.c  -fno-common -DPIC -o zoo_loader.o
-	g++  ${JSCFLAGS} ${GDAL_CFLAGS} ${XML2CFLAGS} ${PHPCFLAGS} ${PERLCFLAGS} ${JAVACFLAGS} ${PYTHONCFLAGS} ${CFLAGS} zoo_loader.o zoo_service_loader.o service_internal.o ${MS_FILE} ${PYTHON_FILE}  ${PERL_FILE} ${PHP_FILE}  ${JS_FILE} ${JAVA_FILE} ${YAML_FILE} ulinet.o lex.cr.o lex.sr.o service_conf.tab.o main_conf_read.tab.o -o zoo_loader.cgi ${LDFLAGS}
+	g++  ${JSCFLAGS} ${OTBCFLAGS} ${GDAL_CFLAGS} ${XML2CFLAGS} ${PHPCFLAGS} ${PERLCFLAGS} ${JAVACFLAGS} ${PYTHONCFLAGS} ${CFLAGS} zoo_loader.o zoo_service_loader.o service_internal.o ${MS_FILE} ${PYTHON_FILE}  ${PERL_FILE} ${PHP_FILE}  ${JS_FILE} ${JAVA_FILE} ${YAML_FILE} ${OTB_FILE} ulinet.o lex.cr.o lex.sr.o service_conf.tab.o main_conf_read.tab.o -o zoo_loader.cgi ${LDFLAGS}
 
 zcfg2yaml: zcfg2yaml.c  ulinet.o service.h lex.sr.o service_conf.tab.o service_conf.y ulinet.o main_conf_read.tab.o lex.cr.o service_internal.o ${MS_FILE} ${JS_FILE} ${RUBY_FILE}  ${YAML_FILE}
Index: /trunk/zoo-project/zoo-kernel/ZOOMakefile.opts.in
===================================================================
--- /trunk/zoo-project/zoo-kernel/ZOOMakefile.opts.in	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/ZOOMakefile.opts.in	(revision 550)
@@ -69,5 +69,10 @@
 PERL_FILE=@PERL_FILE@
 
+OTBCFLAGS=@OTB_CPPFLAGS@
+OTBLDFLAGS=@OTB_LDFLAGS@
+OTB_ENABLED=@OTB_ENABLED@
+OTB_FILE=@OTB_FILE@
+
 CFLAGS=@DEB_DEF@ -fpic ${YAML_CFLAGS} ${MACOS_CFLAGS} ${MS_CFLAGS} -I../../thirds/cgic206 -I. -DLINUX_FREE_ISSUE #-DDEBUG #-DDEBUG_SERVICE_CONF
-LDFLAGS=-lcurl -L../../thirds/cgic206 -lcgic ${GDAL_LIBS} ${XML2LDFLAGS} ${PYTHONLDFLAGS} ${PERLLDFLAGS}  ${PHPLDFLAGS} ${JAVALDFLAGS} ${JSLDFLAGS} -lfcgi -lcrypto ${MS_LDFLAGS} ${MACOS_LD_FLAGS} ${MACOS_LD_NET_FLAGS} ${YAML_LDFLAGS} 
+LDFLAGS=-lcurl -L../../thirds/cgic206 -lcgic ${GDAL_LIBS} ${XML2LDFLAGS} ${PYTHONLDFLAGS} ${PERLLDFLAGS}  ${PHPLDFLAGS} ${JAVALDFLAGS} ${JSLDFLAGS} -lfcgi -lcrypto ${MS_LDFLAGS} ${MACOS_LD_FLAGS} ${MACOS_LD_NET_FLAGS} ${YAML_LDFLAGS} ${OTBLDFLAGS}
 
Index: /trunk/zoo-project/zoo-kernel/configure.ac
===================================================================
--- /trunk/zoo-project/zoo-kernel/configure.ac	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/configure.ac	(revision 550)
@@ -1,3 +1,3 @@
-AC_INIT([ZOO Kernel], [1.5.0], [bugs@zoo-project.org])
+AC_INIT([ZOO Kernel], [1.5.0-dev], [bugs@zoo-project.org])
 
 # Checks for programs.
@@ -84,9 +84,48 @@
 
 # ===========================================================================
+# Detect if otb is available
+# ===========================================================================
+
+AC_ARG_WITH([otb],
+        [AS_HELP_STRING([--with-otb=PATH], [specify an alternative location for the otb library])],
+        [OTBPATH="$withval"], [OTBPATH=""])
+
+if test -z "$OTBPATH"
+then
+	OTB_LDFLAGS=""
+	OTB_CPPFLAGS=""
+	OTB_FILE=""
+	OTB_ENABLED=""
+else
+
+	OTB_ENABLED="-DUSE_OTB"
+	OTB_LDFLAGS="-L$OTBPATH/lib/otb -lOTBIO -lOTBCommon -lOTBApplicationEngine -lITKBiasCorrection-4.5 -lITKCommon-4.5 -lITKIOImageBase-4.5 -lITKKLMRegionGrowing-4.5 -lITKLabelMap-4.5 -lITKMesh-4.5 -lITKMetaIO-4.5 -lITKOptimizers-4.5 -lITKPath-4.5 -lITKPolynomials-4.5 -lITKQuadEdgeMesh-4.5 -lITKSpatialObjects-4.5 -lITKStatistics-4.5 -lITKVNLInstantiation-4.5 -lITKWatersheds-4.5 -litkNetlibSlatec-4.5 -litksys-4.5 -litkdouble-conversion-4.5 -litkv3p_lsqr-4.5 -litkv3p_netlib-4.5 -litkvcl-4.5 -litkvnl-4.5 -litkvnl_algo-4.5 -litkzlib-4.5"
+	OTB_CPPFLAGS="-I$OTBPATH/include/otb/ApplicationEngine -I$OTBPATH/include/otb/Common -I$OTBPATH/include/otb/Utilities/ITK -I$OTBPATH/include/otb/ -I$OTBPATH/include/otb/IO -I$OTBPATH/include/otb/UtilitiesAdapters/OssimAdapters -I$OTBPATH/include/otb/UtilitiesAdapters/CurlAdapters -I$OTBPATH/include/otb/Utilities/BGL -I$OTBPATH/include/otb/UtilitiesAdapters/ITKPendingPatches -I$OTBPATH/include/otb/Utilities/otbconfigfile"
+	OTB_FILE="service_internal_otb.o" #otbZooWatcher.o otbRunner.o"
+	
+	AC_LANG_PUSH([C++])
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$OTB_CPPFLAGS"
+	LDFLAGS_SAVE="$LDFLAGS"
+	LDFLAGS="$OTB_LDFLAGS"
+	for i in otbWrapperApplication.h otbWrapperInputImageListParameter.h otbWrapperApplicationRegistry.h; do
+	    AC_CHECK_HEADERS([$i],
+			[], [AC_MSG_ERROR([could not find header file $i related to OTB])])
+	done
+	AC_LANG_POP([C++])
+	##,otbWrapperInputImageListParameter,otbFilterWatcherBase.h,itksys/SystemTools.hxx,itkCommand.h,itkProcessObject.h,itkTimeProbe.h
+fi
+AC_SUBST([OTB_CPPFLAGS])
+AC_SUBST([OTB_LDFLAGS])
+AC_SUBST([OTB_FILE])
+AC_SUBST([OTB_ENABLED])
+
+# ===========================================================================
 # Detect if libyaml is available
 # ===========================================================================
 
 AC_ARG_WITH([yaml],
-        [AS_HELP_STRING([--with-yaml=PATH], [specify an alternative location for the fastcgi library])],
+        [AS_HELP_STRING([--with-yaml=PATH], [specify an alternative location for the yaml library])],
         [YAMLPATH="$withval"], [YAMLPATH=""])
 
Index: /trunk/zoo-project/zoo-kernel/service.h
===================================================================
--- /trunk/zoo-project/zoo-kernel/service.h	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/service.h	(revision 550)
@@ -566,4 +566,47 @@
   }
 
+  static void loadMapBinary(map** out,map* in,int pos){
+    map* size=getMap(in,"size");
+    map *lout=*out;
+    if(size!=NULL && pos>0){
+      char tmp[11];
+      sprintf(tmp,"size_%d",pos);
+      size=getMap(in,tmp);
+      sprintf(tmp,"value_%d",pos);
+      map* tmpVin=getMap(in,tmp);
+      map* tmpVout=getMap(lout,tmp);
+      free(tmpVout->value);
+      tmpVout->value=(char*)malloc((atoi(size->value)+1)*sizeof(char));
+      memmove(tmpVout->value,tmpVin->value,atoi(size->value)*sizeof(char));
+      tmpVout->value[atoi(size->value)]=0;
+    }else{
+      if(size!=NULL){
+	map* tmpVin=getMap(in,"value");
+	map* tmpVout=getMap(lout,"value");
+	free(tmpVout->value);
+	tmpVout->value=(char*)malloc((atoi(size->value)+1)*sizeof(char));
+	memmove(tmpVout->value,tmpVin->value,atoi(size->value)*sizeof(char));
+	tmpVout->value[atoi(size->value)]=0;
+      }
+    }
+  }
+  
+  static void loadMapBinaries(map** out,map* in){
+    map* size=getMap(in,"size");
+    map* length=getMap(in,"length");
+    if(length!=NULL){
+      int len=atoi(length->value);
+      int i=0;
+      for(i=0;i<len;i++){
+	loadMapBinary(out,in,i);
+      }
+    }
+    else
+      if(size!=NULL)
+	loadMapBinary(out,in,-1);
+    char* tmpSized=NULL;
+    
+  }
+
   static maps* dupMaps(maps** mo){
     maps* _cursor=*mo;
@@ -575,21 +618,7 @@
       res->next=NULL;
       map* mc=_cursor->content;
-      map* tmp=getMap(mc,"size");
-      char* tmpSized=NULL;
-      if(tmp!=NULL){
-	map* tmpV=getMap(mc,"value");
-	tmpSized=(char*)malloc((atoi(tmp->value)+1)*sizeof(char));
-	memmove(tmpSized,tmpV->value,atoi(tmp->value)*sizeof(char));
-      }
       if(mc!=NULL){
 	addMapToMap(&res->content,mc);
-      }
-      if(tmp!=NULL){
-	map* tmpV=getMap(res->content,"value");
-	free(tmpV->value);
-	tmpV->value=(char*)malloc((atoi(tmp->value)+1)*sizeof(char));
-	memmove(tmpV->value,tmpSized,atoi(tmp->value)*sizeof(char));
-	tmpV->value[atoi(tmp->value)]=0;
-	free(tmpSized);
+	loadMapBinaries(&res->content,mc);
       }
       res->next=dupMaps(&_cursor->next);
@@ -643,5 +672,5 @@
     else
       sprintf(tmp,"%s",key);
-    map* tmpSize=getMapArray(m,(char*)"size",index);
+    map* tmpSize=getMapArray(m,"size",index);
     if(tmpSize!=NULL && strncasecmp(key,"value",5)==0){
 #ifdef DEBUG
@@ -685,18 +714,21 @@
     }
 
-    char *tmpV[8]={
+    char *tmpV[11]={
       (char*)"size",
       (char*)"value",
       (char*)"uom",
       (char*)"Reference",
+      (char*)"cache_file",
+      (char*)"fmimeType",
       (char*)"xlink:href",
       typ,
       (char*)"schema",
-      (char*)"encoding"
+      (char*)"encoding",
+      (char*)"isCached"
     };
     sprintf(tmpLen,"%d",len+1);
     addToMap(_cursor->content,"length",tmpLen);
     int i=0;
-    for(i=0;i<8;i++){
+    for(i=0;i<11;i++){
       map* tmpVI=getMap(tmp->content,tmpV[i]);
       if(tmpVI!=NULL){
@@ -704,8 +736,8 @@
 	fprintf(stderr,"%s = %s\n",tmpV[i],tmpVI->value);
 #endif
-	if(i<5)
+	if(i<7)
 	  setMapArray(_cursor->content,tmpV[i],len,tmpVI->value);
 	else
-	  if(strncasecmp(tmpV[5],"mimeType",8)==0)
+	  if(strncasecmp(tmpV[7],"mimeType",8)==0)
 	    setMapArray(_cursor->content,tmpV[i],len,tmpVI->value);
       }
Index: /trunk/zoo-project/zoo-kernel/service_conf.l
===================================================================
--- /trunk/zoo-project/zoo-kernel/service_conf.l	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/service_conf.l	(revision 550)
@@ -40,6 +40,6 @@
 chardata	[^<]*
 
-attname	[a-zA-Z0-9_\-]+
-attvalue1	[\^\*\+,;@a-zA-Z0-9%_\-::.:" "\"\'/\\\(\)\t\|\$\&>\[\]]+
+attname	[a-zA-Z0-9._\-]+
+attvalue1	[°²θé#\^\*\+,;@a-zA-Z0-9%_\-::.:" "\"\'/\\\(\)\t\|\$\&>\[\]]+
 
 attvalue		\"[^"]*\"|\'[^']*\'\(\)
Index: /trunk/zoo-project/zoo-kernel/service_internal.c
===================================================================
--- /trunk/zoo-project/zoo-kernel/service_internal.c	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/service_internal.c	(revision 550)
@@ -2432,5 +2432,6 @@
   nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
   if(tmp!=NULL){
-    xmlNodeSetContent(nc1, BAD_CAST tmp->value);
+    xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
+    xmlAddChild(nc1,txt);
   }
   else{
@@ -2442,4 +2443,40 @@
 }
 
+/************************************************************************/
+/*                          readGeneratedFile()                         */
+/************************************************************************/
+
+/**
+ * Read a file generated by a service.
+ * 
+ * @param m the conf maps
+ * @param content the output item
+ * @param filename the file to read
+ */
+void readGeneratedFile(maps* m,map* content,char* filename){
+  FILE * file=fopen(filename,"rb");
+  fseek(file, 0, SEEK_END);
+  long count = ftell(file);
+  rewind(file);
+  struct stat file_status; 
+  stat(filename, &file_status);
+  if(file==NULL){
+    fprintf(stderr,"Failed to open file %s for reading purpose.\n",filename);
+    setMapInMaps(m,"lenv","message","Unable to read produced file. Please try again later");
+    return ;
+  }
+  map* tmpMap1=getMap(content,"value");
+  if(tmpMap1==NULL){
+    addToMap(content,"value","");
+    tmpMap1=getMap(content,"value");
+  }
+  free(tmpMap1->value);
+  tmpMap1->value=(char*) malloc((count+1)*sizeof(char));  
+  fread(tmpMap1->value,1,count*sizeof(char),file);
+  fclose(file);
+  char rsize[100];
+  sprintf(rsize,"%d",count*sizeof(char));
+  addToMap(tmpMap1,"size",rsize);
+}
 
 void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
@@ -2503,4 +2540,27 @@
   }
   
+    if(res==SERVICE_FAILED){
+      map * errormap;
+      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,_("Unable to run the Service. No more information was returned back by the Service."));
+      }
+      errormap = createMap("text",tmp0);
+      free(tmp0);
+      addToMap(errormap,"code", "InternalError");
+      dumpMap(errormap);
+      printExceptionReportResponse(m,errormap);
+      freeMap(&errormap);
+      free(errormap);
+      return;
+    }
+
 
   if(asRaw==0){
@@ -2521,92 +2581,108 @@
 #endif
 	{
-	elements* in=getElements(s->outputs,tmpI->name);
-	char *format=NULL;
-	if(in!=NULL){
-	  format=strdup(in->format);
-	}else
-	  format=strdup("LiteralData");
-	if(strcasecmp(format,"BoundingBoxData")==0){
-	  addToMap(tmpI->content,"extension","xml");
-	  addToMap(tmpI->content,"mimeType","text/xml");
-	  addToMap(tmpI->content,"encoding","UTF-8");
-	  addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
-	}
-	map *ext=getMap(tmpI->content,"extension");
-	map *tmp1=getMapFromMaps(m,"main","tmpPath");
-	char *file_name,*file_path;
-	bool hasExt=true;
-	if(ext==NULL){
-	  // We can fallback to a default list of supported formats using
-	  // mimeType information if present here. Maybe we can add more formats
-	  // here.
-	  // If mimeType was not found, we then set txt as the default extension
-	  map* mtype=getMap(tmpI->content,"mimeType");
-	  if(mtype!=NULL){
-	    if(strcasecmp(mtype->value,"text/xml")==0)
-	      ext=createMap("extension","xml");
-	    else if(strcasecmp(mtype->value,"application/json")==0)
-	      ext=createMap("extension","js");
-	    else if(strncmp(mtype->value,"application/vnd.google-earth.kml",32)==0)
-	      ext=createMap("extension","kml");
-	    else if(strncmp(mtype->value,"image/",6)==0)
-	      ext=createMap("extension",strstr(mtype->value,"/")+1);
-	    else
-	      ext=createMap("extension","txt");
+	  elements* in=getElements(s->outputs,tmpI->name);
+	  char *format=NULL;
+	  if(in!=NULL){
+	    format=strdup(in->format);
+	  }else
+	    format=strdup("LiteralData");
+	  if(strcasecmp(format,"BoundingBoxData")==0){
+	    addToMap(tmpI->content,"extension","xml");
+	    addToMap(tmpI->content,"mimeType","text/xml");
+	    addToMap(tmpI->content,"encoding","UTF-8");
+	    addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
 	  }
-	  else
-	    ext=createMap("extension","txt");
-	  hasExt=false;
-	}
-	file_name=(char*)malloc((strlen(s->name)+strlen(ext->value)+strlen(tmpI->name)+1024)*sizeof(char));
-	int cpid0=cpid+time(NULL);
-	sprintf(file_name,"%s_%s_%i.%s",s->name,tmpI->name,cpid0,ext->value);
-	file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
-	sprintf(file_path,"%s/%s",tmp1->value,file_name);
-	FILE *ofile=fopen(file_path,"wb");
-	if(ofile==NULL){
-	  char tmpMsg[1024];
-	  sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the %s final result."),file_name,tmpI->name);
-	  map * errormap = createMap("text",tmpMsg);
-	  addToMap(errormap,"code", "InternalError");
-	  printExceptionReportResponse(m,errormap);
-	  freeMap(&errormap);
-	  free(errormap);
+
+	  map *tmp1=getMapFromMaps(m,"main","tmpPath");
+
+	  map *gfile=getMap(tmpI->content,"generated_file");
+	  char *file_name;
+	  if(gfile!=NULL){
+	    readGeneratedFile(m,tmpI->content,gfile->value);	    
+	    file_name=(char*)malloc((strlen(gfile->value)+strlen(tmp1->value)+1)*sizeof(char));
+	    for(int i=0;i<strlen(gfile->value);i++)
+	      file_name[i]=gfile->value[i+strlen(tmp1->value)];
+	  }
+	  else{
+	    map *ext=getMap(tmpI->content,"extension");
+	    char *file_path;
+	    bool hasExt=true;
+	    if(ext==NULL){
+	      // We can fallback to a default list of supported formats using
+	      // mimeType information if present here. Maybe we can add more formats
+	      // here.
+	      // If mimeType was not found, we then set txt as the default extension
+	      map* mtype=getMap(tmpI->content,"mimeType");
+	      if(mtype!=NULL) {
+		if(strncasecmp(mtype->value,"text/xml",8)==0)
+		  ext=createMap("extension","xml");
+		else if(strncasecmp(mtype->value,"application/zip",15)==0)
+		  ext=createMap("extension","zip");
+		else if(strncasecmp(mtype->value,"application/json",16)==0)
+		  ext=createMap("extension","js");
+		else if(strncmp(mtype->value,"application/vnd.google-earth.kml",32)==0)
+		  ext=createMap("extension","kml");
+		else if(strncmp(mtype->value,"image/",6)==0)
+		  ext=createMap("extension",strstr(mtype->value,"/")+1);
+		else
+		  ext=createMap("extension","txt");
+	      }
+	      else
+		ext=createMap("extension","txt");
+	      hasExt=false;
+	    }
+	    file_name=(char*)malloc((strlen(s->name)+strlen(ext->value)+strlen(tmpI->name)+1024)*sizeof(char));
+	    int cpid0=cpid+time(NULL);
+	    sprintf(file_name,"%s_%s_%i.%s",s->name,tmpI->name,cpid0,ext->value);
+	    file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
+	    sprintf(file_path,"%s/%s",tmp1->value,file_name);
+	    FILE *ofile=fopen(file_path,"wb");
+	    if(ofile==NULL){
+	      char tmpMsg[1024];
+	      sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the %s final result."),file_name,tmpI->name);
+	      map * errormap = createMap("text",tmpMsg);
+	      addToMap(errormap,"code", "InternalError");
+	      printExceptionReportResponse(m,errormap);
+	      freeMap(&errormap);
+	      free(errormap);
+	      free(file_name);
+	      free(file_path);
+	      return;
+	    }
+	    free(file_path);
+	    if(!hasExt){
+	      freeMap(&ext);
+	      free(ext);
+	    }
+	    toto=getMap(tmpI->content,"value");
+	    if(strcasecmp(format,"BoundingBoxData")!=0){
+	      map* size=getMap(tmpI->content,"size");
+	      if(size!=NULL && toto!=NULL)
+		fwrite(toto->value,1,atoi(size->value)*sizeof(char),ofile);
+	      else
+		if(toto!=NULL && toto->value!=NULL)
+		  fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
+	    }else{
+	      printBoundingBoxDocument(m,tmpI,ofile);
+	    }
+	    fclose(ofile);
+
+	  }
+	  map *tmp2=getMapFromMaps(m,"main","tmpUrl");
+	  map *tmp3=getMapFromMaps(m,"main","serverAddress");
+	  char *file_url;
+	  if(strncasecmp(tmp2->value,"http://",7)==0 ||
+	     strncasecmp(tmp2->value,"https://",8)==0){
+	    file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
+	    sprintf(file_url,"%s/%s",tmp2->value,file_name);
+	  }else{
+	    file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
+	    sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
+	  }
+	  addToMap(tmpI->content,"Reference",file_url);
+	  free(format);
 	  free(file_name);
-	  free(file_path);
-	  return;
-	}
-	free(file_path);
-	map *tmp2=getMapFromMaps(m,"main","tmpUrl");
-	map *tmp3=getMapFromMaps(m,"main","serverAddress");
-	char *file_url;
-	if(strncasecmp(tmp2->value,"http://",7)==0 ||
-	   strncasecmp(tmp2->value,"https://",8)==0){
-	  file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
-	  sprintf(file_url,"%s/%s",tmp2->value,file_name);
-	}else{
-	  file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
-	  sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
-	}
-	addToMap(tmpI->content,"Reference",file_url);
-	if(!hasExt){
-	  freeMap(&ext);
-	  free(ext);
-	}
-	toto=getMap(tmpI->content,"value");
-	if(strcasecmp(format,"BoundingBoxData")!=0){
-	  map* size=getMap(tmpI->content,"size");
-	  if(size!=NULL && toto!=NULL)
-	    fwrite(toto->value,1,atoi(size->value)*sizeof(char),ofile);
-	  else
-	    if(toto!=NULL && toto->value!=NULL)
-	      fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
-	}else{
-	  printBoundingBoxDocument(m,tmpI,ofile);
-	}
-	free(format);
-	fclose(ofile);
-	free(file_name);
-	free(file_url);	
+	  free(file_url);	
+	  
 	}
 #ifdef USE_MS
@@ -2628,22 +2704,31 @@
 			 request_inputs,
 			 request_outputs);
-    }
-    else{
-      if(res==SERVICE_FAILED){
-	map * errormap;
-	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,_("Unable to run the Service. No more information was returned back by the Service."));
-	}
-	errormap = createMap("text",tmp0);
-	free(tmp0);
-	addToMap(errormap,"code", "InternalError");
+  }
+  else{
+    /**
+     * We get the requested output or fallback to the first one if the 
+     * requested one is not present in the resulting outputs maps.
+     */
+    maps* tmpI=NULL;
+    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
+    if(tmpIV!=NULL){
+      tmpI=getMaps(request_outputs,tmpIV->value);
+    }
+    if(tmpI==NULL)
+      tmpI=request_outputs;
+    elements* e=getElements(s->outputs,tmpI->name);
+    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
+      printBoundingBoxDocument(m,tmpI,NULL);
+    }else{
+      map *gfile=getMap(tmpI->content,"generated_file");
+      if(gfile!=NULL){
+	readGeneratedFile(m,tmpI->content,gfile->value);
+      }
+      toto=getMap(tmpI->content,"value");
+      if(toto==NULL){
+	char tmpMsg[1024];
+	sprintf(tmpMsg,_("Wrong RawDataOutput parameter, unable to fetch any result for the name your provided : \"%s\"."),tmpI->name);
+	map * errormap = createMap("text",tmpMsg);
+	addToMap(errormap,"code", "InvalidParameterValue");
 	printExceptionReportResponse(m,errormap);
 	freeMap(&errormap);
@@ -2651,66 +2736,40 @@
 	return;
       }
-      /**
-       * We get the requested output or fallback to the first one if the 
-       * requested one is not present in the resulting outputs maps.
-       */
-      maps* tmpI=NULL;
-      map* tmpIV=getMap(request_inputs1,"RawDataOutput");
-      if(tmpIV!=NULL){
-	tmpI=getMaps(request_outputs,tmpIV->value);
-      }
-      if(tmpI==NULL)
-	tmpI=request_outputs;
-      elements* e=getElements(s->outputs,tmpI->name);
-      if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
-	printBoundingBoxDocument(m,tmpI,NULL);
-      }else{
-	toto=getMap(tmpI->content,"value");
-	if(toto==NULL){
-	  char tmpMsg[1024];
-	  sprintf(tmpMsg,_("Wrong RawDataOutput parameter, unable to fetch any result for the name your provided : \"%s\"."),tmpI->name);
-	  map * errormap = createMap("text",tmpMsg);
-	  addToMap(errormap,"code", "InvalidParameterValue");
-	  printExceptionReportResponse(m,errormap);
-	  freeMap(&errormap);
-	  free(errormap);
-	  return;
-	}
-	map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
-	if(fname!=NULL)
-	  printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
-	map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
-	if(rs!=NULL)
-	  printf("Content-Length: %s\r\n",rs->value);
-	printHeaders(m);
-	char mime[1024];
-	map* mi=getMap(tmpI->content,"mimeType");
-#ifdef DEBUG
-	fprintf(stderr,"SERVICE OUTPUTS\n");
-	dumpMaps(request_outputs);
-	fprintf(stderr,"SERVICE OUTPUTS\n");
-#endif
-	map* en=getMap(tmpI->content,"encoding");
-	if(mi!=NULL && en!=NULL)
+      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
+      if(fname!=NULL)
+	printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
+      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
+      if(rs!=NULL)
+	printf("Content-Length: %s\r\n",rs->value);
+      printHeaders(m);
+      char mime[1024];
+      map* mi=getMap(tmpI->content,"mimeType");
+#ifdef DEBUG
+      fprintf(stderr,"SERVICE OUTPUTS\n");
+      dumpMaps(request_outputs);
+      fprintf(stderr,"SERVICE OUTPUTS\n");
+#endif
+      map* en=getMap(tmpI->content,"encoding");
+      if(mi!=NULL && en!=NULL)
+	sprintf(mime,
+		"Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
+		mi->value,en->value);
+      else
+	if(mi!=NULL)
 	  sprintf(mime,
-		  "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
-		  mi->value,en->value);
+		  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
+		  mi->value);
 	else
-	  if(mi!=NULL)
-	    sprintf(mime,
-		    "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
-		    mi->value);
-	  else
-	    sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
-	printf("%s",mime);
-	if(rs!=NULL)
-	  fwrite(toto->value,1,atoi(rs->value),stdout);
-	else
-	  fwrite(toto->value,1,strlen(toto->value),stdout);
-#ifdef DEBUG
-	dumpMap(toto);
-#endif
-      }
-    }
+	  sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
+      printf("%s",mime);
+      if(rs!=NULL)
+	fwrite(toto->value,1,atoi(rs->value),stdout);
+      else
+	fwrite(toto->value,1,strlen(toto->value),stdout);
+#ifdef DEBUG
+      dumpMap(toto);
+#endif
+    }
+  }
 }
 
@@ -3220,46 +3279,98 @@
     int index=0;
     while(content!=NULL){
-      if((tmp1=getMap(content->content,"href")) || 
-	 (tmp1=getMap(content->content,"xlink:href"))){
-	if(getMap(content->content,"isCached")==NULL){
-	  char* fcontent;
-	  char *mimeType=NULL;
-	  int fsize=0;
-
-	  fcontent=(char*)malloc((hInternet->ihandle[index].nDataLen+1)*sizeof(char));
-	  if(fcontent == NULL){
-	    return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
+      
+      map* length=getMap(content->content,"length");
+      int shouldClean=-1;
+      if(length==NULL){
+	length=createMap("length","1");
+	shouldClean=1;
+      }
+      for(int i=0;i<atoi(length->value);i++){
+	
+	char* fcontent;
+	char *mimeType=NULL;
+	int fsize=0;
+	char cname[15];
+	char vname[11];
+	char vname1[11];
+	char sname[9];
+	char icname[14];
+	char xname[16];
+	if(index>0)
+	  sprintf(vname1,"value_%d",index);
+	else
+	  sprintf(vname1,"value");
+
+	if(i>0){
+	  tmp1=getMap(content->content,cname);
+	  sprintf(cname,"cache_file_%d",i);
+	  sprintf(vname,"value_%d",i);
+	  sprintf(sname,"size_%d",i);
+	  sprintf(icname,"isCached_%d",i);
+	  sprintf(xname,"Reference_%d",i);
+	}else{
+	  sprintf(cname,"cache_file");
+	  sprintf(vname,"value");
+	  sprintf(icname,"isCached");
+	  sprintf(sname,"size");
+	  sprintf(xname,"Reference");
+	}
+
+	map* tmap=getMapFromMaps(*m,"orequests",vname1);
+	if((tmp1=getMap(content->content,xname))!=NULL && strcasecmp(tmap->value,tmp1->value)==0 ){
+	  if(getMap(content->content,icname)==NULL){
+	    
+	    fcontent=(char*)malloc((hInternet->ihandle[index].nDataLen+1)*sizeof(char));
+	    if(fcontent == NULL){
+	      return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
+	    }
+	    size_t dwRead;
+	    InternetReadFile(hInternet->ihandle[index], 
+			     (LPVOID)fcontent, 
+			     hInternet->ihandle[index].nDataLen, 
+			     &dwRead);
+	    fcontent[hInternet->ihandle[index].nDataLen]=0;
+	    fsize=hInternet->ihandle[index].nDataLen;
+	    if(hInternet->ihandle[index].mimeType==NULL)
+	      mimeType=strdup("none");
+	    else
+	      mimeType=strdup((char*)hInternet->ihandle[index].mimeType);
+	    
+	    map* tmpMap=getMapOrFill(&content->content,vname,"");
+	    free(tmpMap->value);
+	    tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
+	    if(tmpMap->value==NULL){
+	      return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
+	    }
+	    memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
+	    
+	    char ltmp1[256];
+	    sprintf(ltmp1,"%d",fsize);
+	    map* tmp=getMapFromMaps(*m,"main","cacheDir");
+	    if(tmp!=NULL){
+	      char* md5str=getMd5(tmp1->value);
+	      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
+	      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
+	      addToMap(content->content,cname,fname);
+	      free(fname);
+	    }
+	    addToMap(content->content,sname,ltmp1);
+	    addToCache(*m,tmp1->value,fcontent,mimeType,fsize);
+	    free(fcontent);
+	    free(mimeType);
+	    dumpMaps(content);
+	    index++;
+
 	  }
-	  size_t dwRead;
-	  InternetReadFile(hInternet->ihandle[index], 
-			   (LPVOID)fcontent, 
-			   hInternet->ihandle[index].nDataLen, 
-			   &dwRead);
-	  fcontent[hInternet->ihandle[index].nDataLen]=0;
-	  fsize=hInternet->ihandle[index].nDataLen;
-	  if(hInternet->ihandle[index].mimeType==NULL)
-	    mimeType=strdup("none");
-	  else
-	    mimeType=strdup((char*)hInternet->ihandle[index].mimeType);
-	  
-	  map* tmpMap=getMapOrFill(&content->content,"value","");
-	  free(tmpMap->value);
-	  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
-	  if(tmpMap->value==NULL){
-	    return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
-	  }
-	  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
-	  
-	  char ltmp1[256];
-	  sprintf(ltmp1,"%d",fsize);
-	  addToMap(content->content,"size",ltmp1);
-	  addToCache(*m,tmp1->value,fcontent,mimeType,fsize);
-	  free(fcontent);
-	  free(mimeType);
 	}
-	index++;
-      }
+      }
+      if(shouldClean>0){
+	freeMap(&length);
+	free(length);
+      }
+      
       content=content->next;
     }
+    
   }
 }
@@ -3274,5 +3385,13 @@
   char *mimeType=NULL;
   int fsize=0;
+
+  map* t=getMap(*content,"xlink:href");
+  if(t==NULL){
+    t=getMap((*content),"href");
+    addToMap(*content,"xlink:href",url);
+  }
+
   if(cached!=NULL){
+
     struct stat f_status;
     int s=stat(cached, &f_status);
@@ -3284,4 +3403,5 @@
       fcontent[fsize]=0;
       fclose(f);
+      addToMap(*content,"cache_file",cached);
     }
     cached[strlen(cached)-1]='m';
@@ -3294,7 +3414,20 @@
       fclose(f);
     }
+
   }else{
     hInternet->waitingRequests[hInternet->nb]=strdup(url);
     InternetOpenUrl(hInternet,hInternet->waitingRequests[hInternet->nb],NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
+    maps *oreq=getMaps(*m,"orequests");
+    if(oreq==NULL){
+      oreq=(maps*)malloc(MAPS_SIZE);
+      oreq->name=zStrdup("orequests");
+      oreq->content=createMap("value",url);
+      oreq->next=NULL;
+      addMapsToMaps(m,oreq);
+      freeMaps(&oreq);
+      free(oreq);
+    }else{
+      setMapArray(oreq->content,"value",hInternet->nb-1,url);
+    }
     return 0;
   }
@@ -3309,16 +3442,29 @@
     
   free(tmpMap->value);
+
   tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
   if(tmpMap->value==NULL)
     return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
   memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
-  
+
   char ltmp1[256];
   sprintf(ltmp1,"%d",fsize);
   addToMap(*content,"size",ltmp1);
-  if(cached==NULL)
+  if(cached==NULL){
     addToCache(*m,url,fcontent,mimeType,fsize);
-  else
+  }
+  else{
     addToMap(*content,"isCached","true");
+
+    map* tmp=getMapFromMaps(*m,"main","cacheDir");
+    if(tmp!=NULL){
+      map *c=getMap((*content),"xlink:href");
+      char* md5str=getMd5(c->value);
+      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
+      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
+      addToMap(*content,"cache_file",fname);
+      free(fname);
+    }
+  }
   free(fcontent);
   free(mimeType);
Index: /trunk/zoo-project/zoo-kernel/service_internal.h
===================================================================
--- /trunk/zoo-project/zoo-kernel/service_internal.h	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/service_internal.h	(revision 550)
@@ -120,4 +120,6 @@
 #endif
   
+  void readGeneratedFile(maps*,map*,char*);
+
   void URLDecode(char *);
   char *url_encode(char *);
Index: /trunk/zoo-project/zoo-kernel/service_internal_ms.c
===================================================================
--- /trunk/zoo-project/zoo-kernel/service_internal_ms.c	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/service_internal_ms.c	(revision 550)
@@ -931,4 +931,8 @@
   sprintf(pszDataSource,"%s/ZOO_DATA_%s_%s.%s",tmpMap->value,outputs->name,sidMap->value,ext); 
   int f=zOpen(pszDataSource,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+  map *gfile=getMap(outputs->content,"generated_file");
+  if(gfile!=NULL){
+    readGeneratedFile(conf,outputs->content,gfile->value);	    
+  }
   map* sizeMap=getMap(outputs->content,"size");
   map* vData=getMap(outputs->content,"value");
Index: /trunk/zoo-project/zoo-kernel/service_internal_otb.c
===================================================================
--- /trunk/zoo-project/zoo-kernel/service_internal_otb.c	(revision 550)
+++ /trunk/zoo-project/zoo-kernel/service_internal_otb.c	(revision 550)
@@ -0,0 +1,363 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2015 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.
+ */
+
+#include "service_internal_otb.h"
+#include "otbWrapperInputImageListParameter.h"
+#include <vector>
+#include <string>
+
+using namespace otb::Wrapper;
+
+std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
+    size_t start_pos = 0;
+    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
+        str.replace(start_pos, from.length(), to);
+        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
+    }
+    return str;
+}
+
+int zoo_otb_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
+  char *pythonpath;
+  char *python_path;
+  maps* m=*main_conf;
+  maps* inputs=*real_inputs;
+  maps* outputs=*real_outputs;
+  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
+  char *ntmp=tmp0->value;
+  map* tmp=NULL;
+  int res=-1;
+
+  std::vector<std::string> list = ApplicationRegistry::GetAvailableApplications();
+  if (list.size() == 0){
+    map* tmps=createMap("text","No OTB Application found.");
+    addToMap(tmps,"code","InternalError");
+    printExceptionReportResponse(m,tmps);
+    freeMap(&tmps);
+    free(tmps);
+    res=-1;
+  }
+  else{
+    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it){
+      if(s->name==*it){
+	Application::Pointer m_Application=ApplicationRegistry::CreateApplication(*it);
+	if (m_Application.IsNull()){
+	  char tmpS[1024];
+	  sprintf(tmpS, "The OTB Application %s cannot be loaded.", (*it).c_str());
+	  map* tmps=createMap("text",tmpS);
+	  addToMap(tmps,"code","InternalError");
+	  printExceptionReportResponse(m,tmps);
+	  freeMap(&tmps);
+	  free(tmps);
+	  res=-1;
+	}else{
+	  char tmpS[1024];
+	  sprintf(tmpS, "The OTB Application %s was loaded correctly.", (*it).c_str());
+	  const std::vector<std::string> appKeyList = m_Application->GetParametersKeys(true);
+	  for (unsigned int i = 0; i < appKeyList.size(); i++){
+	    const std::string paramKey(appKeyList[i]);
+	    std::vector<std::string> values;
+	    Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+	    ParameterType type = m_Application->GetParameterType(paramKey);
+	    if (type != ParameterType_Group && paramKey!="inxml" && paramKey!="outxml"){
+	      map* test=getMapFromMaps(inputs,paramKey.c_str(),"cache_file");
+	      if(test==NULL){
+		test=getMapFromMaps(inputs,paramKey.c_str(),"inRequest");
+		if(test!=NULL && test->value!=NULL && strncasecmp(test->value,"true",4)==0){
+		  test=getMapFromMaps(inputs,paramKey.c_str(),"value");
+		  if(type == ParameterType_OutputImage){
+		    ImagePixelType outPixType = ImagePixelType_float;
+		    if (strncasecmp(test->value,"uint8",5)==0)
+		      outPixType = ImagePixelType_uint8;
+		    else if (strncasecmp(test->value,"int16",5)==0)
+		      outPixType = ImagePixelType_int16;
+		    else if (strncasecmp(test->value,"uint16",6)==0)
+		      outPixType = ImagePixelType_uint16;
+		    else if (strncasecmp(test->value,"int32",5)==0)
+		      outPixType = ImagePixelType_int32;
+		    else if (strncasecmp(test->value,"uint32",6)==0)
+		      outPixType = ImagePixelType_uint32;
+		    else if (strncasecmp(test->value,"double",6)==0)
+		      outPixType = ImagePixelType_double;
+		    map* tmpPath=getMapFromMaps(m,"main","tmpPath");
+		    map* tmpSid=getMapFromMaps(m,"lenv","sid");
+		    char tmp[1024];
+		    map* tmpVal=getMapFromMaps(outputs,paramKey.c_str(),"mimeType");
+		    char* ext="tiff";
+		    if(tmpVal!=NULL){
+		      if(strncasecmp(tmpVal->value,"image/jp2",9)==0)
+			 ext="j2k";
+		      else
+			if(strncasecmp(tmpVal->value,"image/png",9)==0)
+			 ext="png";
+			else
+			  if(strncasecmp(tmpVal->value,"image/jpeg",10)==0)
+			    ext="jpeg";
+		    }
+		    sprintf(tmp,"%s/%s_%s.%s",tmpPath->value,s->name,tmpSid->value,ext);
+		    m_Application->SetParameterString(paramKey, tmp);
+		    setMapInMaps(inputs,paramKey.c_str(),"generated_file",tmp);
+		    dynamic_cast<OutputImageParameter *> (param.GetPointer())->SetPixelType(outPixType);
+		  }else{
+		    if(test->value!=NULL)
+		      m_Application->SetParameterString(paramKey, test->value);
+		  }
+
+		}else{
+		  if(type == ParameterType_OutputVectorData){
+		      map* tmpPath=getMapFromMaps(m,"main","tmpPath");
+		      map* tmpSid=getMapFromMaps(m,"lenv","sid");
+		      char tmp[1024];
+		      map* tmpVal=getMapFromMaps(outputs,paramKey.c_str(),"mimeType");
+		      char* ext="json";
+		      if(tmpVal!=NULL){
+			if(strncasecmp(tmpVal->value,"text/xml",8)==0)
+			ext="gml";
+		      else
+			if(strncasecmp(tmpVal->value,"applicaton/json",15)==0)
+			  ext="json";
+			else
+			  if(strncasecmp(tmpVal->value,"application/zip",14)==0)
+			    ext="shp";
+			  else
+			    if(strncasecmp(tmpVal->value,"application/vnd.google-earth.kml+xml",36)==0)
+			      ext="kml";
+		      }
+		      sprintf(tmp,"%s/%s_%s.%s",tmpPath->value,s->name,tmpSid->value,ext);
+		      m_Application->SetParameterString(paramKey, tmp);
+		      setMapInMaps(inputs,paramKey.c_str(),"generated_file",tmp);
+		  }
+		  else
+		    if(type == ParameterType_OutputFilename){
+		      map* tmpPath=getMapFromMaps(m,"main","tmpPath");
+		      map* tmpSid=getMapFromMaps(m,"lenv","sid");
+		      char tmp[1024];
+		      map* tmpVal=getMapFromMaps(outputs,paramKey.c_str(),"mimeType");
+		      char* ext="txt";
+		      if(tmpVal!=NULL){
+			if(strncasecmp(tmpVal->value,"text/xml",8)==0)
+			  ext="xml";
+			else
+			  if(strncasecmp(tmpVal->value,"text/csv",15)==0)
+			    ext="csv";
+			  else
+			    if(strncasecmp(tmpVal->value,"application/zip",14)==0)
+			      ext="shp";
+			    else
+			    if(strncasecmp(tmpVal->value,"application/vnd.google-earth.kml+xml",36)==0)
+			      ext="kml";
+		      }
+		      sprintf(tmp,"%s/%s_%s.%s",tmpPath->value,s->name,tmpSid->value,ext);
+		      m_Application->SetParameterString(paramKey, tmp);
+		      setMapInMaps(inputs,paramKey.c_str(),"generated_file",tmp);
+		    }
+
+		}
+	      }else{
+		if(type == ParameterType_InputImageList){
+		  values.push_back(test->value);
+		  map* tmpPath=getMapFromMaps(inputs,paramKey.c_str(),"length");
+		  if(tmpPath!=NULL){
+		    int len=atoi(tmpPath->value);
+		    for(int k=1;k<len;k++){
+		      char tmp[10];
+		      sprintf(tmp,"cache_file_%d",k);
+		      map* tmpVal=getMapFromMaps(inputs,paramKey.c_str(),tmp);
+		      if(tmpVal!=NULL){
+			values.push_back(tmpVal->value);
+		      }
+		    }
+		  }
+		  dynamic_cast<InputImageListParameter *> (param.GetPointer())->SetListFromFileName(values);
+		}
+		else
+		  if(type == ParameterType_InputVectorData || type == ParameterType_InputFilename){
+		    map* tmpPath=getMapFromMaps(m,"main","tmpPath");
+		    map* tmpSid=getMapFromMaps(m,"lenv","sid");
+		    char tmp[1024];
+		    map* tmpVal=getMapFromMaps(inputs,paramKey.c_str(),"mimeType");
+		    char* ext="json";
+		    if(tmpVal!=NULL){
+		      if(strncasecmp(tmpVal->value,"application/zip",14)==0){
+			char tmpName[1024];
+			symlink(test->value,ReplaceAll(test->value,".zca",".zip").c_str());
+			sprintf(tmpName,"/vsizip/%s",ReplaceAll(test->value,".zca",".zip").c_str());
+			char **files=VSIReadDir(tmpName);
+			int nFiles = CSLCount( files );
+			char tmpSSName[1024];
+			sprintf(tmpSSName,"%s/Input_%s_%s",tmpPath->value,s->name,tmpSid->value);
+			mkdir(tmpSSName,0777);
+			    
+			char tmpSName[1024];
+			for(int kk=0;kk<nFiles;kk++){
+			  sprintf(tmpSName,"%s/%s",tmpName,files[kk]);
+			  VSILFILE* fmain=VSIFOpenL(tmpSName, "rb");
+			  if(fmain!=NULL){
+			    VSIFSeekL(fmain,0,SEEK_END);
+			    long count=VSIFTellL(fmain);
+			    VSIRewindL(fmain);
+
+			    char *content=(char*) malloc((count+1)*sizeof(char));  
+			    VSIFReadL(content,1,count*sizeof(char),fmain);
+			  
+			    char tmpSSSName[1024];
+			    sprintf(tmpSSSName,"%s/%s",tmpSSName,files[kk]);
+			    
+			    FILE* fx=fopen(tmpSSSName, "wb");
+			    fwrite(content,1,count,fx);
+			    fclose(fx);
+			    VSIFCloseL(fmain);
+			    free(content);
+			    std::string test1(tmpSSSName);
+			    if(test1.find(".shp")!=std::string::npos){
+			      setMapInMaps(inputs,paramKey.c_str(),"cache_file",tmpSSSName);
+			      test=getMapFromMaps(inputs,paramKey.c_str(),"cache_file");
+			    }
+			  }
+			}
+		      }
+		    }
+		    
+		    m_Application->SetParameterString(paramKey, test->value);
+		  }
+		  else
+		    if(type == ParameterType_InputImage
+		       || type == ParameterType_ComplexInputImage || type == ParameterType_InputVectorData
+		       || type == ParameterType_InputFilename){
+		      m_Application->SetParameterString(paramKey, test->value);
+		  }		  
+	      }
+	    }
+	    param->SetUserValue(true);
+	    m_Application->UpdateParameters();
+	  }
+
+	  try{
+	    if( m_Application->ExecuteAndWriteOutput() == 0 ){
+	      std::vector< std::pair<std::string, std::string> > paramList;
+	      paramList = m_Application->GetOutputParametersSumUp();
+	      if(paramList.size()>0)
+		for( unsigned int i=0; i<paramList.size(); i++){
+		  setMapInMaps(outputs,paramList[i].first.c_str(),"value",paramList[i].second.c_str());
+		}
+	      else{
+		const std::vector<std::string> appKeyList = m_Application->GetParametersKeys(true);
+		for (unsigned int i = 0; i < appKeyList.size(); i++){
+		  const std::string paramKey(appKeyList[i]);
+		  std::vector<std::string> values;
+		  Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+		  ParameterType type = m_Application->GetParameterType(paramKey);
+		  if (type != ParameterType_Group && paramKey!="inxml" && paramKey!="outxml"
+		      && (type == ParameterType_OutputImage || type == ParameterType_OutputFilename
+			  || type == ParameterType_OutputVectorData ) ){
+		    if(type == ParameterType_OutputImage || type == ParameterType_OutputFilename || type == ParameterType_OutputVectorData){
+		      map* test=getMapFromMaps(outputs,paramKey.c_str(),"mimeType");
+		      if(test!=NULL && strncasecmp(test->value,"application/zip",15)==0){
+			
+			test=getMapFromMaps(inputs,paramKey.c_str(),"generated_file");
+			char tmpName[1024];
+			sprintf(tmpName,"/vsizip/%s",ReplaceAll(test->value,".shp",".zip").c_str());
+			VSILFILE* fmain=VSIFOpenL(tmpName, "w");
+			FILE * file;
+			char *tmp;
+			char tmpSName[1024];
+			long count;
+			
+			char *exts[4];
+			exts[0]=".shp";
+			exts[1]=".shx";
+			exts[2]=".dbf";
+			exts[3]=".prj";
+			for(int c=0;c<4;c++){
+			  sprintf(tmpSName,"%s/result%s",tmpName,exts[c]);
+			  
+			  file=fopen(ReplaceAll(test->value,".shp",exts[c]).c_str(),"rb");
+			  if(file!=NULL){
+			    fseek(file, 0, SEEK_END);
+			    count = ftell(file);
+			    rewind(file);
+			    
+			    tmp=(char*) malloc((count+1)*sizeof(char));  
+			    fread(tmp,1,count*sizeof(char),file);
+			    
+			    VSILFILE* fx=VSIFOpenL(tmpSName, "wb");
+			    VSIFWriteL(tmp,1,count,fx);
+			    VSIFCloseL(fx);
+			    fclose(file);
+			    free(tmp);
+			  }
+			}
+			
+			VSIFCloseL(fmain);
+			
+			FILE* file1=fopen(ReplaceAll(test->value,".shp",".zip").c_str(), "rb");
+			fseek(file1, 0, SEEK_END);
+			count=ftell(file1);
+			rewind(file1);
+			
+			tmp=(char*) malloc((count+1)*sizeof(char));  
+			fread(tmp,1,count*sizeof(char),file1);
+			
+			file=fopen(ReplaceAll(test->value,".shp",".zip").c_str(),"wb");
+			fwrite(tmp,1,count,file);
+			fclose(file);
+			free(tmp);
+			fclose(file1);
+			setMapInMaps(inputs,paramKey.c_str(),"generated_file",ReplaceAll(test->value,".shp",".zip").c_str());
+		      }
+		      test=getMapFromMaps(inputs,paramKey.c_str(),"generated_file");
+
+		      if(test!=NULL){
+			setMapInMaps(outputs,paramKey.c_str(),"generated_file",test->value);
+		      }
+
+		    }
+		  }
+		}
+	      }
+	      res=3;
+	      break;
+	    }
+	    else{
+	      sprintf(tmpS, "The OTB Application %s cannot be run.", s->name);
+	      setMapInMaps(m,"lenv","message",tmpS);
+	      res=SERVICE_FAILED;
+	    }
+	  }
+	  catch(std::exception& err){
+	    setMapInMaps(m,"lenv","message",err.what());
+	    return SERVICE_FAILED;
+	    
+	  }
+	  catch(...){
+	    setMapInMaps(m,"lenv","message","An unknown exception has been raised during application execution");
+	    res=SERVICE_FAILED;
+	  }
+	  break;
+	}
+      }
+    }
+  }
+  return res;
+}
Index: /trunk/zoo-project/zoo-kernel/service_internal_otb.h
===================================================================
--- /trunk/zoo-project/zoo-kernel/service_internal_otb.h	(revision 550)
+++ /trunk/zoo-project/zoo-kernel/service_internal_otb.h	(revision 550)
@@ -0,0 +1,42 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2015 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.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_OTB_H
+#define ZOO_SERVICE_INTERNAL_OTB_H 1
+
+#pragma once 
+
+#include "otbWrapperApplication.h"
+#include "otbWrapperApplicationRegistry.h"
+#include "service_internal.h"
+#include "service.h"
+#include "cgic.h"
+#ifdef WIN32
+#include <windows.h>
+#include <direct.h>
+#endif
+
+int zoo_otb_support(maps**,map*,service*,maps**,maps**);
+
+#endif
Index: /trunk/zoo-project/zoo-kernel/zcfg2yaml.c
===================================================================
--- /trunk/zoo-project/zoo-kernel/zcfg2yaml.c	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/zcfg2yaml.c	(revision 550)
@@ -23,6 +23,6 @@
  */
 
+#include "service_internal.h"
 #include "service.h"
-#include "service_internal.h"
 
 extern   int getServiceFromFile(maps*,const char*,service**);
Index: /trunk/zoo-project/zoo-kernel/zoo_service_loader.c
===================================================================
--- /trunk/zoo-project/zoo-kernel/zoo_service_loader.c	(revision 549)
+++ /trunk/zoo-project/zoo-kernel/zoo_service_loader.c	(revision 550)
@@ -23,8 +23,14 @@
  */
 
-#define length(x) (sizeof(x) / sizeof(x[0]))
+
 
 extern "C" int yylex ();
 extern "C" int crlex ();
+
+#ifdef USE_OTB
+#include "service_internal_otb.h"
+#else
+#define length(x) (sizeof(x) / sizeof(x[0]))
+#endif
 
 #include "cgic.h"
@@ -177,10 +183,11 @@
           && atoi (testMap->value) > 1)
         {
-          if (addMapsArrayToMaps (&mo, mi, tmap->name) < 0)
+	  addMapsArrayToMaps (&mo, mi, tmap->name);
+	  map* nb=getMapFromMaps(mo,mi->name,"length");
+          if (nb!=NULL && atoi(nb->value)>atoi(testMap->value))
             {
               char emsg[1024];
               sprintf (emsg,
-                       _
-                       ("You set maximum occurences for <%s> as %i but you tried to use it more than the limit you set. Please correct your ZCFG file or your request."),
+                       _("You set maximum occurences for <%s> as %i but you tried to use it more than the limit you set. Please correct your ZCFG file or your request."),
                        mi->name, atoi (testMap->value));
               errorException (m, emsg, "InternalError", NULL);
@@ -609,4 +616,16 @@
     }
   else
+
+#ifdef USE_OTB
+  if (strncasecmp (r_inputs->value, "OTB", 6) == 0)
+    {
+      *eres =
+        zoo_otb_support (&m, request_inputs, s1,
+                            &request_input_real_format,
+                            &request_output_real_format);
+    }
+  else
+#endif
+
 #ifdef USE_PYTHON
   if (strncasecmp (r_inputs->value, "PYTHON", 6) == 0)
