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
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
00092 if(mServiceMap.find(service_name) != mServiceMap.end())
00093 {
00094
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
00117 if(!service_url.empty() && option_map.isMap())
00118 {
00119
00120
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
00138
00139
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
00170
00171
00172
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
00219 #if 0
00220
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