Move config logic into an "XML" SP plugin, divorce shibd and modules from old libs.
[shibboleth/cpp-sp.git] / shib-target / shib-ini.cpp
index b09d090..edf5908 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2005 Internet2
+ *  Copyright 2001-2007 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
 #include <log4cpp/PropertyConfigurator.hh>
 #include <shibsp/RequestMapper.h>
 #include <shibsp/SPConfig.h>
+#include <shibsp/TransactionLog.h>
 #include <shibsp/security/PKIXTrustEngine.h>
 #include <shibsp/util/DOMPropertySet.h>
 #include <saml/SAMLConfig.h>
@@ -36,6 +37,7 @@
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/security/ChainingTrustEngine.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/ReplayCache.h>
 
 using namespace shibsp;
 using namespace shibtarget;
@@ -50,11 +52,13 @@ using xmlsignature::CredentialResolver;
 
 namespace {
 
+    vector<const Handler*> g_noHandlers;
+
     // Application configuration wrapper
     class XMLApplication : public virtual IApplication, public DOMPropertySet, public DOMNodeFilter
     {
     public:
-        XMLApplication(const IConfig*, const DOMElement* e, const XMLApplication* base=NULL);
+        XMLApplication(const ServiceProvider*, const DOMElement* e, const XMLApplication* base=NULL);
         ~XMLApplication() { cleanup(); }
     
         // PropertySet
@@ -68,11 +72,9 @@ namespace {
         // IApplication
         const char* getId() const {return getString("id").second;}
         const char* getHash() const {return m_hash.c_str();}
-        Iterator<SAMLAttributeDesignator*> getAttributeDesignators() const;
-        Iterator<IAAP*> getAAPProviders() const;
         MetadataProvider* getMetadataProvider() const;
         TrustEngine* getTrustEngine() const;
-        Iterator<const XMLCh*> getAudiences() const;
+        const vector<const XMLCh*>& getAudiences() const;
         const PropertySet* getCredentialUse(const EntityDescriptor* provider) const;
 
         const SAMLBrowserProfile* getBrowserProfile() const {return m_profile;}
@@ -89,7 +91,7 @@ namespace {
         const Handler* getSessionInitiatorById(const char* id) const;
         const Handler* getDefaultAssertionConsumerService() const;
         const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const;
-        Iterator<const Handler*> getAssertionConsumerServicesByBinding(const XMLCh* binding) const;
+        const vector<const Handler*>& getAssertionConsumerServicesByBinding(const XMLCh* binding) const;
         const Handler* getHandler(const char* path) const;
         
         // Provides filter to exclude special config elements.
@@ -97,11 +99,9 @@ namespace {
     
     private:
         void cleanup();
-        const IConfig* m_ini;   // this is ok because its locking scope includes us
+        const ServiceProvider* m_sp;   // this is ok because its locking scope includes us
         const XMLApplication* m_base;
         string m_hash;
-        vector<SAMLAttributeDesignator*> m_designators;
-        vector<IAAP*> m_aaps;
         MetadataProvider* m_metadata;
         TrustEngine* m_trust;
         vector<const XMLCh*> m_audiences;
@@ -175,11 +175,11 @@ namespace {
     #pragma warning( disable : 4250 )
 #endif
 
-    class XMLConfig : public IConfig, public ReloadableXMLFile
+    class XMLConfig : public ServiceProvider, public ReloadableXMLFile
     {
     public:
         XMLConfig(const DOMElement* e)
-            : ReloadableXMLFile(e), m_impl(NULL), m_listener(NULL), m_sessionCache(NULL), m_replayCache(NULL) {
+            : ReloadableXMLFile(e), m_impl(NULL), m_listener(NULL), m_sessionCache(NULL) {
         }
         
         void init() {
@@ -189,8 +189,10 @@ namespace {
         ~XMLConfig() {
             delete m_impl;
             delete m_sessionCache;
-            delete m_replayCache;
             delete m_listener;
+            delete m_tranLog;
+            XMLToolingConfig::getConfig().setReplayCache(NULL);
+            for_each(m_storage.begin(), m_storage.end(), xmltooling::cleanup_pair<string,StorageService>());
         }
 
         // PropertySet
@@ -203,15 +205,39 @@ namespace {
         const DOMElement* getElement() const {return m_impl->getElement();}
 
         // ServiceProvider
+        TransactionLog* getTransactionLog() const {
+            if (m_tranLog)
+                return m_tranLog;
+            throw ConfigurationException("No TransactionLog available.");
+        }
+
+        StorageService* getStorageService(const char* id) const {
+            if (id) {
+                map<string,StorageService*>::const_iterator i=m_storage.find(id);
+                if (i!=m_storage.end())
+                    return i->second;
+            }
+            return NULL;
+        }
+
         ListenerService* getListenerService(bool required=true) const {
             if (required && !m_listener)
                 throw ConfigurationException("No ListenerService available.");
             return m_listener;
         }
 
-        ISessionCache* getSessionCache() const {return m_sessionCache;}
-        IReplayCache* getReplayCache() const {return m_replayCache;}
-        RequestMapper* getRequestMapper() const {return m_impl->m_requestMapper;}
+        SessionCache* getSessionCache(bool required=true) const {
+            if (required && !m_sessionCache)
+                throw ConfigurationException("No SessionCache available.");
+            return m_sessionCache;
+        }
+
+        RequestMapper* getRequestMapper(bool required=true) const {
+            if (required && !m_impl->m_requestMapper)
+                throw ConfigurationException("No RequestMapper available.");
+            return m_impl->m_requestMapper;
+        }
+
         const Application* getApplication(const char* applicationId) const {
             map<string,Application*>::const_iterator i=m_impl->m_appmap.find(applicationId);
             return (i!=m_impl->m_appmap.end()) ? i->second : NULL;
@@ -233,8 +259,9 @@ namespace {
         friend class XMLConfigImpl;
         XMLConfigImpl* m_impl;
         mutable ListenerService* m_listener;
-        mutable ISessionCache* m_sessionCache;
-        mutable IReplayCache* m_replayCache;
+        mutable SessionCache* m_sessionCache;
+        mutable TransactionLog* m_tranLog;
+        mutable map<string,StorageService*> m_storage;
     };
 
 #if defined (_MSC_VER)
@@ -262,10 +289,11 @@ namespace {
     static const XMLCh MemoryListener[] =       UNICODE_LITERAL_14(M,e,m,o,r,y,L,i,s,t,e,n,e,r);
     static const XMLCh MemorySessionCache[] =   UNICODE_LITERAL_18(M,e,m,o,r,y,S,e,s,s,i,o,n,C,a,c,h,e);
     static const XMLCh RelyingParty[] =         UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y);
-    static const XMLCh ReplayCache[] =          UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e);
+    static const XMLCh _ReplayCache[] =         UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e);
     static const XMLCh RequestMapProvider[] =   UNICODE_LITERAL_18(R,e,q,u,e,s,t,M,a,p,P,r,o,v,i,d,e,r);
-    static const XMLCh SessionCache[] =         UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);
+    static const XMLCh _SessionCache[] =        UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);
     static const XMLCh SessionInitiator[] =     UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);
+    static const XMLCh _StorageService[] =      UNICODE_LITERAL_14(S,t,o,r,a,g,e,S,e,r,v,i,c,e);
     static const XMLCh OutOfProcess[] =         UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s);
     static const XMLCh TCPListener[] =          UNICODE_LITERAL_11(T,C,P,L,i,s,t,e,n,e,r);
     static const XMLCh TrustProvider[] =        UNICODE_LITERAL_13(T,r,u,s,t,P,r,o,v,i,d,e,r);
@@ -282,10 +310,10 @@ ServiceProvider* shibtarget::XMLServiceProviderFactory(const DOMElement* const &
 }
 
 XMLApplication::XMLApplication(
-    const IConfig* ini,
+    const ServiceProvider* sp,
     const DOMElement* e,
     const XMLApplication* base
-    ) : m_ini(ini), m_base(base), m_metadata(NULL), m_trust(NULL), m_profile(NULL), m_binding(NULL), m_bindingHook(NULL),
+    ) : m_sp(sp), m_base(base), m_metadata(NULL), m_trust(NULL), m_profile(NULL), m_binding(NULL), m_bindingHook(NULL),
         m_credDefault(NULL), m_sessionInitDefault(NULL), m_acsDefault(NULL)
 {
 #ifdef _DEBUG
@@ -416,40 +444,18 @@ XMLApplication::XMLApplication(
             m_acsDefault=h2;
         }
         
-        // Process general configuration elements.
-        XMLSize_t i;
-        DOMNodeList* nlist=e->getElementsByTagNameNS(samlconstants::SAML1_NS,AttributeDesignator::LOCAL_NAME);
-        for (i=0; nlist && i<nlist->getLength(); i++)
-            if (nlist->item(i)->getParentNode()->isSameNode(e))
-                m_designators.push_back(new SAMLAttributeDesignator(static_cast<DOMElement*>(nlist->item(i))));
-
-        nlist=e->getElementsByTagNameNS(samlconstants::SAML1_NS,Audience::LOCAL_NAME);
-        for (i=0; nlist && i<nlist->getLength(); i++)
+        DOMNodeList* nlist=e->getElementsByTagNameNS(samlconstants::SAML1_NS,Audience::LOCAL_NAME);
+        for (XMLSize_t i=0; nlist && i<nlist->getLength(); i++)
             if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
                 m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
 
         // Always include our own providerId as an audience.
         m_audiences.push_back(getXMLString("providerId").second);
 
-        if (conf.isEnabled(SPConfig::AAP)) {
+        if (conf.isEnabled(SPConfig::AttributeResolver)) {
             child = XMLHelper::getFirstChildElement(e,AAPProvider);
             while (child) {
-                xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                log.info("building AAP provider of type %s...",type.get());
-                try {
-                    IPlugIn* plugin=shibConf.getPlugMgr().newPlugin(type.get(),child);
-                    IAAP* aap=dynamic_cast<IAAP*>(plugin);
-                    if (aap)
-                        m_aaps.push_back(aap);
-                    else {
-                        delete plugin;
-                        log.crit("plugin was not an AAP provider");
-                    }
-                }
-                catch (exception& ex) {
-                    log.crit("error building AAP provider: %s", ex.what());
-                }
-
+                // TODO: some kind of compatibility
                 child = XMLHelper::getNextSiblingElement(child,AAPProvider);
             }
         }
@@ -574,8 +580,6 @@ void XMLApplication::cleanup()
 #else
     for_each(m_credMap.begin(),m_credMap.end(),xmltooling::cleanup_pair<const XMLCh*,PropertySet>());
 #endif
-    for_each(m_designators.begin(),m_designators.end(),xmltooling::cleanup<SAMLAttributeDesignator>());
-    for_each(m_aaps.begin(),m_aaps.end(),xmltooling::cleanup<IAAP>());
 
     delete m_trust;
     delete m_metadata;
@@ -585,6 +589,8 @@ short XMLApplication::acceptNode(const DOMNode* node) const
 {
     if (XMLHelper::isNodeNamed(node,samlconstants::SAML1_NS,AttributeDesignator::LOCAL_NAME))
         return FILTER_REJECT;
+    else if (XMLHelper::isNodeNamed(node,samlconstants::SAML20_NS,opensaml::saml1::Attribute::LOCAL_NAME))
+        return FILTER_REJECT;
     else if (XMLHelper::isNodeNamed(node,samlconstants::SAML1_NS,Audience::LOCAL_NAME))
         return FILTER_REJECT;
     const XMLCh* name=node->getLocalName();
@@ -651,18 +657,6 @@ const PropertySet* XMLApplication::getPropertySet(const char* name, const char*
     return m_base->getPropertySet(name,ns);
 }
 
-Iterator<SAMLAttributeDesignator*> XMLApplication::getAttributeDesignators() const
-{
-    if (!m_designators.empty() || !m_base)
-        return m_designators;
-    return m_base->getAttributeDesignators();
-}
-
-Iterator<IAAP*> XMLApplication::getAAPProviders() const
-{
-    return (m_aaps.empty() && m_base) ? m_base->getAAPProviders() : m_aaps;
-}
-
 MetadataProvider* XMLApplication::getMetadataProvider() const
 {
     return (!m_metadata && m_base) ? m_base->getMetadataProvider() : m_metadata;
@@ -673,7 +667,7 @@ TrustEngine* XMLApplication::getTrustEngine() const
     return (!m_trust && m_base) ? m_base->getTrustEngine() : m_trust;
 }
 
-Iterator<const XMLCh*> XMLApplication::getAudiences() const
+const vector<const XMLCh*>& XMLApplication::getAudiences() const
 {
     return (m_audiences.empty() && m_base) ? m_base->getAudiences() : m_audiences;
 }
@@ -801,7 +795,7 @@ const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short
     return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : NULL;
 }
 
-Iterator<const Handler*> XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
+const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
 {
 #ifdef HAVE_GOOD_STL
     ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);
@@ -811,7 +805,7 @@ Iterator<const Handler*> XMLApplication::getAssertionConsumerServicesByBinding(c
 #endif
     if (i!=m_acsBindingMap.end())
         return i->second;
-    return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : EMPTY(const Handler*);
+    return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers;
 }
 
 const Handler* XMLApplication::getHandler(const char* path) const
@@ -825,7 +819,8 @@ const Handler* XMLApplication::getHandler(const char* path) const
 
 short XMLConfigImpl::acceptNode(const DOMNode* node) const
 {
-    if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB1SPCONFIG_NS))
+    if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB1SPCONFIG_NS) &&
+        !XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB2SPCONFIG_NS))
         return FILTER_ACCEPT;
     const XMLCh* name=node->getLocalName();
     if (XMLString::equals(name,Applications) ||
@@ -838,8 +833,9 @@ short XMLConfigImpl::acceptNode(const DOMNode* node) const
         XMLString::equals(name,MemoryListener) ||
         XMLString::equals(name,MemorySessionCache) ||
         XMLString::equals(name,RequestMapProvider) ||
-        XMLString::equals(name,ReplayCache) ||
-        XMLString::equals(name,SessionCache) ||
+        XMLString::equals(name,_ReplayCache) ||
+        XMLString::equals(name,_SessionCache) ||
+        XMLString::equals(name,_StorageService) ||
         XMLString::equals(name,TCPListener) ||
         XMLString::equals(name,UnixListener))
         return FILTER_REJECT;
@@ -884,8 +880,8 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
     Category& log=Category::getInstance(SHIBT_LOGCAT".Config");
 
     try {
-        SAMLConfig& shibConf=SAMLConfig::getConfig();
         SPConfig& conf=SPConfig::getConfig();
+        XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
         const DOMElement* SHAR=XMLHelper::getFirstChildElement(e,OutOfProcess);
         if (!SHAR)
             SHAR=XMLHelper::getFirstChildElement(e,Global);
@@ -907,6 +903,9 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
                 log.debug("loading new logging configuration from (%s), check log destination for status of configuration",logpath.get());
                 XMLToolingConfig::getConfig().log_config(logpath.get());
             }
+            
+            if (first)
+                m_outer->m_tranLog = new TransactionLog();
         }
         
         // First load any property sets.
@@ -916,11 +915,14 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
         load(e,log,this,&root_remap);
 
         const DOMElement* child;
-        IPlugIn* plugin=NULL;
         string plugtype;
 
         // Much of the processing can only occur on the first instantiation.
         if (first) {
+            // Set clock skew.
+            pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");
+            if (skew.first)
+                xmlConf.clock_skew_secs=skew.second;
 
             // Extensions
             doExtensions(e, "global", log);
@@ -967,47 +969,73 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
                 // TODO: This code's a mess, due to a very bad config layout for the caches...
                 // Needs rework with the new config file.
                 const DOMElement* container=conf.isEnabled(SPConfig::OutOfProcess) ? SHAR : SHIRE;
-                child=XMLHelper::getFirstChildElement(container,MemorySessionCache);
+
+                // First build any StorageServices.
+                string inmemID;
+                child=XMLHelper::getFirstChildElement(container,_StorageService);
+                while (child) {
+                    xmltooling::auto_ptr_char id(child->getAttributeNS(NULL,Id));
+                    xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type));
+                    if (id.get() && type.get()) {
+                        try {
+                            log.info("building StorageService (%s) of type %s...", id.get(), type.get());
+                            m_outer->m_storage[id.get()] = xmlConf.StorageServiceManager.newPlugin(type.get(),child);
+                            if (!strcmp(type.get(),MEMORY_STORAGE_SERVICE))
+                                inmemID = id.get();
+                        }
+                        catch (exception& ex) {
+                            log.crit("failed to instantiate StorageService (%s): %s", id.get(), ex.what());
+                        }
+                    }
+                    child=XMLHelper::getNextSiblingElement(container,_StorageService);
+                }
+                
+                child=XMLHelper::getFirstChildElement(container,_SessionCache);
                 if (child) {
-                    log.info("building Session Cache of type %s...",MEMORY_SESSIONCACHE);
-                    plugin=shibConf.getPlugMgr().newPlugin(MEMORY_SESSIONCACHE,child);
+                    xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type));
+                    log.info("building Session Cache of type %s...",type.get());
+                    m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(type.get(),child);
                 }
-                else {
-                    child=XMLHelper::getFirstChildElement(container,SessionCache);
-                    if (child) {
-                        xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                        log.info("building Session Cache of type %s...",type.get());
-                        plugin=shibConf.getPlugMgr().newPlugin(type.get(),child);
-                    }
-                    else {
-                        log.info("custom SessionCache unspecified or no longer supported, building SessionCache of type %s...",MEMORY_SESSIONCACHE);
-                        plugin=shibConf.getPlugMgr().newPlugin(MEMORY_SESSIONCACHE,child);
+                else if (conf.isEnabled(SPConfig::OutOfProcess)) {
+                    log.warn("custom SessionCache unspecified or no longer supported, building SessionCache of type %s...",STORAGESERVICE_SESSION_CACHE);
+                    if (inmemID.empty()) {
+                        inmemID = "memory";
+                        log.info("no StorageServices configured, providing in-memory version for legacy config");
+                        m_outer->m_storage[inmemID] = xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE,NULL);
                     }
+                    child = container->getOwnerDocument()->createElementNS(NULL,_SessionCache);
+                    xmltooling::auto_ptr_XMLCh ssid(inmemID.c_str());
+                    const_cast<DOMElement*>(child)->setAttributeNS(NULL,_StorageService,ssid.get());
+                    m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(STORAGESERVICE_SESSION_CACHE,child);
                 }
-                if (plugin) {
-                    ISessionCache* cache=dynamic_cast<ISessionCache*>(plugin);
-                    if (cache)
-                        m_outer->m_sessionCache=cache;
-                    else {
-                        delete plugin;
-                        log.fatal("plugin was not a Session Cache object");
-                        throw UnknownExtensionException("plugin was not a Session Cache object");
-                    }
+                else {
+                    log.warn("custom SessionCache unspecified or no longer supported, building SessionCache of type %s...",REMOTED_SESSION_CACHE);
+                    m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(REMOTED_SESSION_CACHE,NULL);
                 }
                 
                 // Replay cache.
-                // TODO: switch to new cache interface
-                child=XMLHelper::getFirstChildElement(container,ReplayCache);
+                StorageService* replaySS=NULL;
+                child=XMLHelper::getFirstChildElement(container,_ReplayCache);
                 if (child) {
-                    xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                    log.info("building ReplayCache of type %s...",type.get());
-                    m_outer->m_replayCache=IReplayCache::getInstance(type.get(),child);
+                    xmltooling::auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService));
+                    if (ssid.get() && *ssid.get()) {
+                        replaySS = m_outer->m_storage[ssid.get()];
+                        if (replaySS)
+                            log.info("building ReplayCache on top of StorageService (%s)...", ssid.get());
+                        else
+                            log.crit("unable to locate StorageService (%s) in configuration", ssid.get());
+                    }
                 }
-                else {
-                    // OpenSAML default provider.
-                    log.info("custom ReplayCache unspecified or no longer supported, building default ReplayCache...");
-                    m_outer->m_replayCache=IReplayCache::getInstance();
+                if (!replaySS) {
+                    log.info("building ReplayCache using in-memory StorageService...");
+                    if (inmemID.empty()) {
+                        inmemID = "memory";
+                        log.info("no StorageServices configured, providing in-memory version for legacy config");
+                        m_outer->m_storage[inmemID] = xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE,NULL);
+                    }
+                    replaySS = m_outer->m_storage[inmemID];
                 }
+                xmlConf.setReplayCache(new ReplayCache(replaySS));
             }
         } // end of first-time-only stuff
         
@@ -1067,34 +1095,6 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
             }
         }
 
-        // Now we load any attribute factories
-        child = XMLHelper::getFirstChildElement(e,AttributeFactory);
-        while (child) {
-            xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type));
-            log.info("building Attribute factory of type %s...",type.get());
-            try {
-                plugin=shibConf.getPlugMgr().newPlugin(type.get(),child);
-                if (plugin) {
-                    IAttributeFactory* fact=dynamic_cast<IAttributeFactory*>(plugin);
-                    if (fact) {
-                        m_attrFactories.push_back(fact);
-                        ShibConfig::getConfig().regAttributeMapping(
-                            child->getAttributeNS(NULL,Attribute::ATTRIBUTENAME_ATTRIB_NAME), fact
-                            );
-                    }
-                    else {
-                        delete plugin;
-                        log.crit("plugin was not an Attribute factory");
-                    }
-                }
-            }
-            catch (exception& ex) {
-                log.crit("error building Attribute factory: %s", ex.what());
-            }
-
-            child = XMLHelper::getNextSiblingElement(child,AttributeFactory);
-        }
-
         // Load the default application. This actually has a fixed ID of "default". ;-)
         child=XMLHelper::getFirstChildElement(e,Applications);
         if (!child) {