llservicebuilder.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 #include "llapp.h"
00034 #include "llfile.h"
00035 #include "llservicebuilder.h"
00036 #include "llsd.h"
00037 #include "llsdserialize.h"
00038 
00039 void LLServiceBuilder::loadServiceDefinitionsFromFile(
00040         const std::string& service_filename)
00041 {
00042         llifstream service_file(service_filename.c_str(), std::ios::binary);
00043         if(service_file.is_open())
00044         {
00045                 LLSD service_data;
00046                 LLSDSerialize::fromXML(service_data, service_file);
00047                 service_file.close();
00048                 // Load service 
00049                 LLSD service_map = service_data["services"];
00050                 for(LLSD::array_iterator array_itr = service_map.beginArray();
00051                         array_itr != service_map.endArray();
00052                         ++array_itr)
00053                 {       
00054                         LLSD service_llsd = (*array_itr)["service-builder"];
00055                         std::string service_name = (*array_itr)["name"].asString();
00056                         createServiceDefinition(service_name, service_llsd);
00057                 }
00058                 llinfos << "loaded config file: " << service_filename << llendl;
00059         }
00060         else
00061         {
00062                 llwarns << "unable to find config file: " << service_filename << llendl;
00063         }
00064 }
00065 
00066 void LLServiceBuilder::createServiceDefinition(
00067         const std::string& service_name,
00068         LLSD& service_llsd)
00069 {
00070         if(service_llsd.isString())
00071         {
00072                 mServiceMap[ service_name ] = service_llsd.asString();
00073         }                       
00074         else if(service_llsd.isMap())
00075         {
00076                 for(LLSD::map_iterator map_itr = service_llsd.beginMap();
00077                         map_itr != service_llsd.endMap();
00078                         ++map_itr)
00079                 {
00080                         std::string compound_builder_name = service_name;
00081                         compound_builder_name.append("-");
00082                         compound_builder_name.append((*map_itr).first);
00083                         mServiceMap[ compound_builder_name ] = (*map_itr).second.asString();
00084                 }
00085         }
00086 }
00087 
00088 std::string LLServiceBuilder::buildServiceURI(const std::string& service_name)
00089 {
00090         std::ostringstream service_url;
00091         // Find the service builder
00092         if(mServiceMap.find(service_name) != mServiceMap.end())
00093         {
00094                 // construct the service builder url
00095                 LLApp* app = LLApp::instance();
00096                 if(app)
00097                 {
00098                         LLSD base_url = app->getOption("services-base-url");
00099                         service_url << base_url.asString();
00100                 }
00101                 service_url << mServiceMap[service_name];
00102         }
00103         else
00104         {
00105                 llwarns << "Cannot find service " << service_name << llendl;
00106         }
00107         return service_url.str();
00108 }
00109 
00110 std::string LLServiceBuilder::buildServiceURI(
00111         const std::string& service_name,
00112         const LLSD& option_map)
00113 {
00114         std::string service_url = buildServiceURI(service_name);
00115     
00116         // Find the Service Name
00117         if(!service_url.empty() && option_map.isMap())
00118         {
00119                 // throw in a ridiculously large limiter to make sure we don't
00120                 // loop forever with bad input.
00121                 int iterations = 100;
00122                 bool keep_looping = true;
00123                 while(keep_looping)
00124                 {
00125                         if(0 == --iterations)
00126                         {
00127                                 keep_looping = false;
00128                         }
00129 
00130                         int depth = 0;
00131                         int deepest = 0;
00132                         bool find_match = false;
00133                         std::string::iterator iter(service_url.begin());
00134                         std::string::iterator end(service_url.end());
00135                         std::string::iterator deepest_node(service_url.end());
00136                         std::string::iterator deepest_node_end(service_url.end());
00137                         //parse out the variables to replace by going through {}s one at a time,
00138                         // starting with the "deepest" in series {{}},
00139                         // and otherwise replacing right-to-left
00140                         for(; iter != end; ++iter)
00141                         {
00142                                 switch(*iter)
00143                                 {
00144                                 case '{':
00145                                         ++depth;
00146                                         if(depth > deepest)
00147                                         {
00148                                                 deepest = depth;
00149                                                 deepest_node = iter;
00150                                                 find_match = true;
00151                                         }
00152                                         break;
00153                                 case '}':
00154                                         --depth;
00155                                         if(find_match)
00156                                         {
00157                                                 deepest_node_end = iter;
00158                                                 find_match = false;
00159                                         }
00160                                         break;
00161                                 default:
00162                                         break;
00163                                 }
00164                         }
00165                         if((deepest_node == end) || (deepest_node_end == end))
00166                         {
00167                                 break;
00168                         }
00169                         //replace the variable we found in the {} above.
00170                         // *NOTE: since the c++ implementation only understands
00171                         // params and straight string substitution, so it's a
00172                         // known distance of 2 to skip the directive.
00173                         std::string key(deepest_node + 2, deepest_node_end);
00174                         LLSD value = option_map[key];
00175                         switch(*(deepest_node + 1))
00176                         {
00177                         case '$':
00178                                 if(value.isDefined())
00179                                 {
00180                                         service_url.replace(
00181                                                 deepest_node,
00182                                                 deepest_node_end + 1,
00183                                                 value.asString());
00184                                 }
00185                                 else
00186                                 {
00187                                         llwarns << "Unknown key: " << key << " in option map: " << LLSDOStreamer<LLSDNotationFormatter>(option_map) << llendl;
00188                                         keep_looping = false;
00189                                 }
00190                                 break;
00191                         case '%':
00192                                 {
00193                                         std::string query_str = LLURI::mapToQueryString(value);
00194                                         service_url.replace(
00195                                                 deepest_node,
00196                                                 deepest_node_end + 1,
00197                                                 query_str);
00198                                 }
00199                                 break;
00200                         default:
00201                                 llinfos << "Unknown directive: " << *(deepest_node + 1)
00202                                         << llendl;
00203                                 keep_looping = false;
00204                                 break;
00205                         }
00206                 }
00207         }
00208         if (service_url.find('{') != std::string::npos)
00209         {
00210                 llwarns << "Constructed a likely bogus service URL: " << service_url
00211                         << llendl;
00212         }
00213         return service_url;
00214 }
00215 
00216 
00217 
00218 // Old, not as good implementation. Phoenix 2007-10-15
00219 #if 0
00220                 // Do brace replacements - NOT CURRENTLY RECURSIVE
00221                 for(LLSD::map_const_iterator option_itr = option_map.beginMap();
00222                         option_itr != option_map.endMap();
00223                         ++option_itr)
00224                 {
00225                         std::string variable_name = "{$";
00226                         variable_name.append((*option_itr).first);
00227                         variable_name.append("}");
00228                         std::string::size_type find_pos = service_url.find(variable_name);
00229                         if(find_pos != std::string::npos)
00230                         {
00231                                 service_url.replace(
00232                                         find_pos,
00233                                         variable_name.length(),
00234                                         (*option_itr).second.asString());
00235                                 continue;
00236                         }
00237                         variable_name.assign("{%");
00238                         variable_name.append((*option_itr).first);
00239                         variable_name.append("}");
00240                         find_pos = service_url.find(variable_name);
00241                         if(find_pos != std::string::npos)
00242                         {
00243                                 std::string query_str = LLURI::mapToQueryString(
00244                                         (*option_itr).second);
00245                                 service_url.replace(
00246                                         find_pos,
00247                                         variable_name.length(),
00248                                         query_str);
00249                         }
00250                 }
00251         }
00252 
00253         if (service_url.find('{') != std::string::npos)
00254         {
00255                 llwarns << "Constructed a likely bogus service URL: " << service_url
00256                                 << llendl;
00257         }
00258 
00259         return service_url;
00260 }
00261 #endif

Generated on Fri May 16 08:32:30 2008 for SecondLife by  doxygen 1.5.5