Back to index

nordugrid-arc-nox  1.1.0~rc6
MCCLoader.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <arc/Logger.h>
00006 #include <arc/StringConv.h>
00007 
00008 #include "MCCLoader.h"
00009 
00010 namespace Arc {
00011 
00012   MCCLoader::MCCLoader(Config& cfg):Loader(cfg),valid_(false) {
00013     context_ = new ChainContext(*this);
00014     valid_ = make_elements(cfg);
00015     if(!valid_)
00016       MCCLoader::logger.msg(ERROR, "Chain(s) configuration failed");
00017   }
00018 
00019   MCCLoader::~MCCLoader(void) {
00020     // TODO: stop any processing on those MCCs or mark them for
00021     // self-destruction or break links first or use semaphors in
00022     // MCC destructors
00023     // Unlink all objects
00024     for(mcc_container_t::iterator mcc_i = mccs_.begin();
00025         mcc_i != mccs_.end(); ++mcc_i) {
00026       MCC* mcc = mcc_i->second;
00027       if(mcc) mcc->Unlink();
00028     }
00029     for(plexer_container_t::iterator plexer_i = plexers_.begin();
00030         plexer_i != plexers_.end(); ++plexer_i) {
00031       Plexer* plexer = plexer_i->second;
00032       if(plexer) plexer->Unlink();
00033     }
00034     // Destroy all objects
00035     for(mcc_container_t::iterator mcc_i = mccs_.begin();
00036         mcc_i != mccs_.end(); mcc_i = mccs_.begin()) {
00037       MCC* mcc = mcc_i->second;
00038       mccs_.erase(mcc_i);
00039       if(mcc) delete mcc;
00040     }
00041     for(service_container_t::iterator service_i = services_.begin();
00042         service_i != services_.end(); service_i = services_.begin()) {
00043       Service* service = service_i->second;
00044       services_.erase(service_i);
00045       if(service) delete service;
00046     }
00047     for(plexer_container_t::iterator plexer_i = plexers_.begin();
00048         plexer_i != plexers_.end(); plexer_i = plexers_.begin()) {
00049       Plexer* plexer = plexer_i->second;
00050       plexers_.erase(plexer_i);
00051       if(plexer) delete plexer;
00052     }
00053     for(sechandler_container_t::iterator sechandler_i = sechandlers_.begin();
00054         sechandler_i != sechandlers_.end();
00055         sechandler_i = sechandlers_.begin()) {
00056       ArcSec::SecHandler* sechandler = sechandler_i->second;
00057       sechandlers_.erase(sechandler_i);
00058       if(sechandler) delete sechandler;
00059     }
00060 
00061     if(context_) delete context_;
00062   }
00063 
00064   class mcc_connector_t {
00065   public:
00066     MCCLoader::mcc_container_t::iterator mcc;
00067     std::string name;
00068     std::map<std::string, std::string> nexts;
00069     mcc_connector_t(MCCLoader::mcc_container_t::iterator mcc) : mcc(mcc) {};
00070   };
00071 
00072   std::ostream& operator<<(std::ostream& o, const mcc_connector_t& mcc) {
00073     o << mcc.name;
00074     o << "(" << mcc.mcc->first << ")";
00075     return o;
00076   }
00077 
00078   class plexer_connector_t {
00079   public:
00080     MCCLoader::plexer_container_t::iterator plexer;
00081     std::map<std::string, std::string> nexts;
00082     plexer_connector_t(MCCLoader::plexer_container_t::iterator plexer) :
00083       plexer(plexer) {};
00084   };
00085 
00086   class mcc_connectors_t : public std::list<mcc_connector_t> {};
00087   class plexer_connectors_t : public std::list<plexer_connector_t> {};
00088 
00089   static XMLNode FindElementByID(XMLNode node, const std::string& id, const std::string& name) {
00090     for(int n = 0;; ++n) {
00091       XMLNode cn = node.Child(n);
00092       if(!cn) break;
00093 
00094       if(MatchXMLName(cn, "ArcConfig")) {
00095         XMLNode result = FindElementByID(cn, id, name);
00096         if(result) return result;
00097         continue;
00098       }
00099 
00100       if(MatchXMLName(cn, "Chain")) {
00101         XMLNode result = FindElementByID(cn, id, name);
00102         if(result) return result;
00103       continue;
00104       }
00105 
00106       if(MatchXMLName(cn, name)) {
00107         if((std::string)(cn.Attribute("id")) == id) return cn;
00108       }
00109     }
00110     return XMLNode();
00111   }
00112 
00113   static ArcSec::SecHandler* MakeSecHandler(Config& cfg, ChainContext *ctx,
00114                                             MCCLoader::sechandler_container_t& sechandlers,
00115                                             PluginsFactory *factory, XMLNode& node) {
00116     if(!node) {
00117       // Normally should not happen
00118       MCCLoader::logger.msg(ERROR, "SecHandler configuration is not defined");
00119       return NULL;
00120     }
00121     XMLNode desc_node;
00122     std::string refid = node.Attribute("refid");
00123     if(refid.empty()) {
00124       desc_node = node;
00125       refid = (std::string)node.Attribute("id");
00126       if(refid.empty()) {
00127         refid = "__arc_sechandler_" + tostring(sechandlers.size()) + "__";
00128       }
00129     }
00130     else {
00131       // Maybe it's already created
00132       MCCLoader::sechandler_container_t::iterator phandler = sechandlers.find(refid);
00133       if(phandler != sechandlers.end()) {
00134         return phandler->second;
00135       }
00136       // Look for it's configuration
00137       desc_node = FindElementByID(cfg, refid, "SecHandler");
00138     }
00139     if(!desc_node) {
00140       MCCLoader::logger.msg(ERROR, "SecHandler has no configuration");
00141       return NULL;
00142     }
00143     std::string name = desc_node.Attribute("name");
00144     if(name.empty()) {
00145       MCCLoader::logger.msg(ERROR, "SecHandler has no name attribute defined");
00146       return NULL;
00147     }
00148     // Create new security handler
00149     Config cfg_(desc_node, cfg.getFileName());
00150     ArcSec::SecHandlerPluginArgument arg(&cfg_,ctx);
00151     Plugin* plugin = factory->get_instance(SecHandlerPluginKind, name, &arg);
00152     ArcSec::SecHandler* sechandler = plugin?dynamic_cast<ArcSec::SecHandler*>(plugin):NULL;
00153     if(!sechandler) {
00154       Loader::logger.msg(ERROR, "Security Handler %s(%s) could not be created", name, refid);
00155     } else {
00156       Loader::logger.msg(INFO, "SecHandler: %s(%s)", name, refid);
00157       sechandlers[refid] = sechandler;
00158     }
00159     return sechandler;
00160   }
00161 
00162   bool MCCLoader::make_elements(Config& cfg, int level,
00163                                 mcc_connectors_t *mcc_connectors,
00164                                 plexer_connectors_t *plexer_connectors) {
00165     bool success = true;
00166     if(mcc_connectors == NULL) mcc_connectors = new mcc_connectors_t;
00167     if(plexer_connectors == NULL) plexer_connectors = new plexer_connectors_t;
00168     // 1st stage - creating all elements.
00169     // Configuration is parsed recursively - going deeper at ArcConfig
00170     // and Chain elements
00171     for(int n = 0;; ++n) {
00172       XMLNode cn = cfg.Child(n);
00173       if(!cn) break;
00174       Config cfg_(cn, cfg.getFileName());
00175 
00176       if(MatchXMLName(cn, "ArcConfig")) {
00177         if(!make_elements(cfg_, level + 1, mcc_connectors, plexer_connectors))
00178           success = false;
00179         continue;
00180       }
00181 
00182       if(MatchXMLName(cn, "Chain")) {
00183         if(!make_elements(cfg_, level + 1, mcc_connectors, plexer_connectors))
00184           success = false;
00185         continue;
00186       }
00187 
00188       if(MatchXMLName(cn, "Component")) {
00189         // Create new MCC
00190         std::string name = cn.Attribute("name");
00191         if(name.empty()) {
00192           logger.msg(ERROR, "Component has no name attribute defined");
00193           success = false;
00194           continue;
00195         }
00196         std::string id = cn.Attribute("id");
00197         if(id.empty()) {
00198           logger.msg(ERROR, "Component has no id attribute defined");
00199           success = false;
00200           continue;
00201         }
00202         MCCPluginArgument arg(&cfg_,context_);
00203         Plugin* plugin = factory_->get_instance(MCCPluginKind ,name, &arg);
00204         MCC* mcc = plugin?dynamic_cast<MCC*>(plugin):NULL;
00205         if(!mcc) {
00206           logger.msg(ERROR, "Component %s(%s) could not be created", name, id);
00207           success = false;
00208           continue;
00209         }
00210         mccs_[id] = mcc;
00211 
00212         // Configure security plugins
00213         XMLNode an = cn["SecHandler"];
00214         for(int n = 0;; ++n) {
00215           XMLNode can = an[n];
00216           if(!can) break;
00217           ArcSec::SecHandler* sechandler = MakeSecHandler(cfg, context_,
00218                                         sechandlers_, factory_, can);
00219           if(!sechandler) {
00220             success = false;
00221             continue;
00222           };
00223           std::string event = can.Attribute("event");
00224           mcc->AddSecHandler(&cfg_, sechandler, event);
00225         }
00226 
00227         // Add to chain list
00228         std::string entry = cn.Attribute("entry");
00229         if(!entry.empty()) mccs_exposed_[entry] = mcc;
00230         mcc_connector_t mcc_connector(mccs_.find(id));
00231         for(int nn = 0;; ++nn) {
00232           XMLNode cnn = cn["next"][nn];
00233           if(!cnn) break;
00234           std::string nid = cnn.Attribute("id");
00235           if(nid.empty()) {
00236             logger.msg(ERROR, "Component's %s(%s) next has no id "
00237                  "attribute defined", name, id);
00238             success = false;
00239             continue;
00240           }
00241           std::string label = cnn;
00242           mcc_connector.nexts[label] = nid;
00243         }
00244         mcc_connector.name = name;
00245         mcc_connectors->push_back(mcc_connector);
00246         logger.msg(INFO, "Loaded MCC %s(%s)", name, id);
00247         continue;
00248       }
00249 
00250       if(MatchXMLName(cn, "Plexer")) {
00251         std::string id = cn.Attribute("id");
00252         if(id.empty()) id = "plexer";
00253         Plexer* plexer = new Plexer(&cfg_);
00254         plexers_[id] = plexer;
00255         plexer_connector_t plexer_connector(plexers_.find(id));
00256         for(int nn = 0;; ++nn) {
00257           XMLNode cnn = cn["next"][nn];
00258           if(!cnn) break;
00259           std::string nid = cnn.Attribute("id");
00260           if(nid.empty()) {
00261             logger.msg(ERROR, "Plexer's (%s) next has no id "
00262                  "attribute defined", id);
00263             success = false;
00264             continue;
00265           }
00266           std::string label = cnn;
00267           plexer_connector.nexts[label] = nid;
00268         }
00269         plexer_connectors->push_back(plexer_connector);
00270         logger.msg(INFO, "Loaded Plexer %s", id);
00271         continue;
00272       }
00273 
00274       if(MatchXMLName(cn, "Service")) {
00275         std::string name = cn.Attribute("name");
00276         if(name.empty()) {
00277           logger.msg(ERROR, "Service has no name attribute defined");
00278           success = false;
00279           continue;
00280         }
00281         std::string id = cn.Attribute("id");
00282         if(id.empty()) {
00283           logger.msg(ERROR, "Service has no id attribute defined");
00284           success = false;
00285           continue;
00286         }
00287         ServicePluginArgument arg(&cfg_,context_);
00288         Plugin* plugin = factory_->get_instance(ServicePluginKind, name, &arg);
00289               Service* service = plugin?dynamic_cast<Service*>(plugin):NULL;
00290         if(!service) {
00291           logger.msg(ERROR, "Service %s(%s) could not be created", name, id);
00292           success = false;
00293           continue;
00294         }
00295         services_[id] = service;
00296         logger.msg(INFO, "Loaded Service %s(%s)", name, id);
00297 
00298         // Configure security plugins
00299         XMLNode an;
00300 
00301         an = cn["SecHandler"];
00302         for(int n = 0;; ++n) {
00303           XMLNode can = an[n];
00304           if(!can) break;
00305           ArcSec::SecHandler* sechandler = MakeSecHandler(cfg, context_,
00306                                         sechandlers_, factory_, can);
00307           if(!sechandler) {
00308             success = false;
00309             continue;
00310           }
00311           std::string event = can.Attribute("event");
00312           service->AddSecHandler(&cfg_, sechandler, event);
00313         }
00314         continue;
00315       }
00316 
00317       // Configuration processing is split to multiple functions - hence
00318       // ignoring all unknown elements.
00319       //logger.msg(WARNING, "Unknown element \"%s\" - ignoring", cn.Name());
00320     }
00321 
00322     if(level != 0) return true;
00323 
00324     // 2nd stage - making links between elements.
00325 
00326     // Making links from MCCs
00327     for(mcc_connectors_t::iterator mcc = mcc_connectors->begin();
00328         mcc != mcc_connectors->end(); ++mcc) {
00329       for(std::map<std::string, std::string>::iterator next =
00330           mcc->nexts.begin();
00331           next != mcc->nexts.end(); next = mcc->nexts.begin()) {
00332         std::string label = next->first;
00333         std::string id = next->second;
00334         mcc_container_t::iterator mcc_l = mccs_.find(id);
00335         if(mcc_l != mccs_.end()) {
00336           // Make link MCC->MCC
00337           mcc->mcc->second->Next(mcc_l->second, label);
00338           logger.msg(INFO, "Linking MCC %s(%s) to MCC (%s) under %s",
00339                mcc->name, mcc->mcc->first, id, label);
00340           mcc->nexts.erase(next);
00341           continue;
00342         }
00343         service_container_t::iterator service_l = services_.find(id);
00344         if(service_l != services_.end()) {
00345           // Make link MCC->Service
00346           mcc->mcc->second->Next(service_l->second, label);
00347           logger.msg(INFO, "Linking MCC %s(%s) to Service (%s) under %s",
00348                mcc->name, mcc->mcc->first, id, label);
00349           mcc->nexts.erase(next);
00350           continue;
00351         }
00352         plexer_container_t::iterator plexer_l = plexers_.find(id);
00353         if(plexer_l != plexers_.end()) {
00354           // Make link MCC->Plexer
00355           mcc->mcc->second->Next(plexer_l->second, label);
00356           logger.msg(INFO, "Linking MCC %s(%s) to Plexer (%s) under %s",
00357                mcc->name, mcc->mcc->first, id, label);
00358           mcc->nexts.erase(next);
00359           continue;
00360         }
00361         logger.msg(ERROR, "MCC %s(%s) - next %s(%s) has no target",
00362                    mcc->name, mcc->mcc->first, label, id);
00363         success = false;
00364         mcc->nexts.erase(next);
00365       }
00366     }
00367     // Making links from Plexers
00368     for(plexer_connectors_t::iterator plexer = plexer_connectors->begin();
00369         plexer != plexer_connectors->end(); ++plexer) {
00370       for(std::map<std::string, std::string>::iterator next =
00371           plexer->nexts.begin();
00372           next != plexer->nexts.end(); next = plexer->nexts.begin()) {
00373         std::string label = next->first;
00374         std::string id = next->second;
00375         mcc_container_t::iterator mcc_l = mccs_.find(id);
00376         if(mcc_l != mccs_.end()) {
00377           // Make link Plexer->MCC
00378           plexer->plexer->second->Next(mcc_l->second, label);
00379           logger.msg(INFO, "Linking Plexer %s to MCC (%s) under %s",
00380                plexer->plexer->first, id, label);
00381           plexer->nexts.erase(next);
00382           continue;
00383         }
00384         service_container_t::iterator service_l = services_.find(id);
00385         if(service_l != services_.end()) {
00386           // Make link Plexer->Service
00387           plexer->plexer->second->Next(service_l->second, label);
00388           logger.msg(INFO, "Linking Plexer %s to Service (%s) under %s",
00389                plexer->plexer->first, id, label);
00390           plexer->nexts.erase(next);
00391           continue;
00392         }
00393         plexer_container_t::iterator plexer_l = plexers_.find(id);
00394         if(plexer_l != plexers_.end()) {
00395           // Make link Plexer->Plexer
00396           plexer->plexer->second->Next(plexer_l->second, label);
00397           logger.msg(INFO, "Linking Plexer %s to Plexer (%s) under %s",
00398                plexer->plexer->first, id, label);
00399           plexer->nexts.erase(next);
00400           continue;
00401         }
00402 
00403         logger.msg(ERROR, "Plexer (%s) - next %s(%s) has no target",
00404                    plexer->plexer->first, label, id);
00405         success = false;
00406         plexer->nexts.erase(next);
00407       }
00408     }
00409     if(mcc_connectors) delete mcc_connectors;
00410     if(plexer_connectors) delete plexer_connectors;
00411     return success;
00412   }
00413 
00414   MCC* MCCLoader::operator[](const std::string& id) {
00415     mcc_container_t::iterator mcc = mccs_exposed_.find(id);
00416     if(mcc != mccs_exposed_.end()) return mcc->second;
00417     return NULL;
00418   }
00419 
00420 } // namespace Arc