/* * 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. * * See Ref: http://hg.orfeo-toolbox.org/OTB/ Copyright * Some parts of this code are derived from ITK. See ITKCopyright.txt for * details. */ #include "service_internal_otb.h" #include "response_print.h" #include "server_internal.h" using namespace otb::Wrapper; /** * Global OTB counter */ int otbCounter=0; /** * The ZooWatcher list */ WatcherListType m_WatcherList; /** * A pointer to the conf maps containing the main.cfg settings */ maps* m_Conf; /** * The command to create a ZooWatcher and add it to the global m_WatcherList */ class MyCommand : public itk::Command { public: itkNewMacro( MyCommand ); public: /** * The method that defines the action to be taken by the command. * * @param caller an itk::Object pointer * @param event an itk::EventObject pointer */ void Execute(itk::Object *caller, const itk::EventObject & event) { Execute( (const itk::Object *)caller, event); } /** * The method that defines the action to be taken by the command. * Create a new ZooWatcher instance then add it to the m_WatcherList. * * @param caller a const itk::Object pointer * @param event an itk::EventObject pointer * @see ZooWatcher,ZooWatcher::SetConf */ void Execute(const itk::Object *caller, const itk::EventObject & event) { const AddProcessToWatchEvent* eventToWatch = dynamic_cast< const AddProcessToWatchEvent*> ( &event ); std::string m_CurrentDescription = eventToWatch->GetProcessDescription(); ZooWatcher * watch = new ZooWatcher(eventToWatch->GetProcess(), eventToWatch->GetProcessDescription()); watch->SetConf(&m_Conf); m_WatcherList.push_back(watch); } }; /** * Replace all occurence of from by to in a str string * * @param str the string to transform * @param from the string to replace * @param to the string used as replacement * @return the resulting string */ 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; } /** * Load and run an OTB Application corresponding to the service by using inputs parameters. * Define the m_Conf * * @param main_conf the conf maps containing the main.cfg settings * @param request the map containing the HTTP request * @param s the service structure * @param real_inputs the maps containing the inputs * @param real_outputs the maps containing the outputs */ int zoo_otb_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){ 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; int saved_stdout = zDup (fileno (stdout)); zDup2 (fileno (stderr), fileno (stdout)); std::vector 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); free(tmps); res=-1; return res; } else{ dumpMapsValuesToFiles(main_conf,real_inputs); for (std::vector::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"); zDup2 (saved_stdout, fileno (stdout)); zClose(saved_stdout); printExceptionReportResponse(m,tmps); freeMap(&tmps); free(tmps); res=-1; }else{ // Create Observer on AddProcessToWatchEvent m_Conf=m; MyCommand::Pointer myCommand = MyCommand::New(); m_Application->AddObserver(AddProcessToWatchEvent(), myCommand); char tmpS[1024]; const std::vector appKeyList = m_Application->GetParametersKeys(true); 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); 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"); map* tmpPath=getMapFromMaps(m,"main","tmpPath"); map* tmpSid=getMapFromMaps(m,"lenv","usid"); char tmp[1024]; map* tmpVal=getMapFromMaps(outputs,paramKey.c_str(),"mimeType"); maps* tmpMaps=getMaps(outputs,paramKey.c_str()); if(tmpMaps!=NULL && 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; const 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_%d_%s.%s",tmpPath->value,s->name,otbCounter,tmpSid->value,ext); otbCounter++; m_Application->SetParameterString(paramKey, tmp); setMapInMaps(inputs,paramKey.c_str(),"generated_file",tmp); dynamic_cast (param.GetPointer())->SetPixelType(outPixType); } else{ if(test!=NULL && test->value!=NULL) m_Application->SetParameterString(paramKey, test->value); } }else{ if(type == ParameterType_OutputVectorData){ const 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_%d_%s.%s",tmpPath->value,s->name,otbCounter,tmpSid->value,ext); otbCounter++; m_Application->SetParameterString(paramKey, tmp); setMapInMaps(inputs,paramKey.c_str(),"generated_file",tmp); } else if(type == ParameterType_OutputFilename){ const 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"; else if(strncasecmp(tmpVal->value,"application/vnd.google-earth.kmz",32)==0){ ext="kmz"; sprintf(tmp,"%s/%s_%d_%sxt.%s",tmpPath->value,s->name,otbCounter,tmpSid->value,ext); m_Application->SetParameterString(paramKey, tmp); setMapInMaps(outputs,paramKey.c_str(),"expected_generated_file",tmp); } } sprintf(tmp,"%s/%s_%d_%s.%s",tmpPath->value,s->name,otbCounter,tmpSid->value,ext); otbCounter++; m_Application->SetParameterString(paramKey, tmp); setMapInMaps(inputs,paramKey.c_str(),"generated_file",tmp); } else{ test=getMapFromMaps(inputs,paramKey.c_str(),"value"); if(test!=NULL && type!=ParameterType_ListView){ m_Application->SetParameterString(paramKey, test->value); } else if(type==ParameterType_ListView){ std::vector values; values.push_back(test->value); map* tmpLength=getMapFromMaps(inputs,paramKey.c_str(),"length"); if(tmpLength!=NULL){ int len=atoi(tmpLength->value); for(int k=1;kvalue); } } } dynamic_cast (param.GetPointer())->SetSelectedItems(values); } } } }else{ if(type == ParameterType_InputImageList){ std::vector values; 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;kvalue); } } } dynamic_cast (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"); const char* ext="json"; if(tmpVal!=NULL){ if(strncasecmp(tmpVal->value,"application/zip",14)==0){ char *tmpName=(char*)malloc((strlen(test->value)+9)*sizeof(char)); std::string test0(test->value); if(test0.find(".zca")!=std::string::npos){ symlink(test->value,ReplaceAll(test->value,".zca",".zip").c_str()); sprintf(tmpName,"/vsizip/%s",ReplaceAll(test->value,".zca",".zip").c_str()); }else sprintf(tmpName,"/vsizip/%s",test->value); char **files=VSIReadDir(tmpName); int nFiles = CSLCount( files ); char *tmpSSName=(char*)malloc((strlen(tmpPath->value)+strlen(paramKey.c_str())+strlen(tmpSid->value)+9)*sizeof(char)); sprintf(tmpSSName,"%s/Input_%s_%s",tmpPath->value,paramKey.c_str(),tmpSid->value); mkdir(tmpSSName,0777); for(int kk=0;kkSetParameterString(paramKey, test->value); } else if(type == ParameterType_InputImage || 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 > paramList; paramList = m_Application->GetOutputParametersSumUp(); if(paramList.size()>0) for( unsigned int i=0; i appKeyList = m_Application->GetParametersKeys(true); for (unsigned int i = 0; i < appKeyList.size(); i++){ const std::string paramKey(appKeyList[i]); std::vector 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; const 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()); zDup2 (saved_stdout, fileno (stdout)); zClose(saved_stdout); return SERVICE_FAILED; } catch(...){ setMapInMaps(m,"lenv","message","An unknown exception has been raised during application execution"); res=SERVICE_FAILED; } break; } } } } for (unsigned int i = 0; i < m_WatcherList.size(); i++){ m_WatcherList[i]->FreeConf(); delete m_WatcherList[i]; m_WatcherList[i] = NULL; } m_WatcherList.clear(); fflush(stdout); zDup2 (saved_stdout, fileno (stdout)); zClose(saved_stdout); return res; }