// ********************************************************************** // // Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #include #include #include #include #include #include #include #include using namespace std; using namespace Ice; using namespace IceGrid; namespace IceGrid { class DescriptorHandler : public IceXML::Handler { public: DescriptorHandler(const string&); void setCommunicator(const Ice::CommunicatorPtr&); void setVariables(const std::map&); void setTargets(const std::vector&); virtual void startElement(const string&, const IceXML::Attributes&, int, int); virtual void endElement(const string&, int, int); virtual void characters(const string&, int, int); virtual void error(const string&, int, int); const ApplicationDescriptorPtr& getApplicationDescriptor() const; const ServerDescriptorPtr& getServerDescriptor() const; private: std::string getAttributeValue(const IceXML::Attributes&, const std::string&) const; std::string getAttributeValueWithDefault(const IceXML::Attributes&, const std::string&, const std::string&) const; bool isCurrentTargetDeployable() const; std::string elementValue() const; std::vector getTargets(const std::string&) const; void error(const string&) const; bool isTargetDeployable(const std::string&) const; Ice::CommunicatorPtr _communicator; string _filename; std::vector _targets; DescriptorVariablesPtr _variables; std::stack _elements; std::map _serverTemplates; std::map _serviceTemplates; std::map _templates; int _targetCounter; bool _isCurrentTargetDeployable; int _line; int _column; auto_ptr _currentApplication; auto_ptr _currentServer; std::string _currentServerTemplate; auto_ptr _currentService; std::string _currentServiceTemplate; ComponentDescriptorHelper* _currentComponent; bool _isTopLevel; bool _inProperties; bool _inAdapters; bool _inAdapter; bool _inDbEnv; }; } DescriptorHandler::DescriptorHandler(const string& filename) : _filename(filename), _variables(new DescriptorVariables()), _isCurrentTargetDeployable(true), _isTopLevel(true), _inProperties(false), _inAdapters(false), _inAdapter(false), _inDbEnv(false) { _variables->push(); } void DescriptorHandler::setCommunicator(const Ice::CommunicatorPtr& communicator) { _communicator = communicator; } void DescriptorHandler::setVariables(const std::map& variables) { _variables->reset(variables); } void DescriptorHandler::setTargets(const vector& targets) { _targets = targets; } void DescriptorHandler::startElement(const string& name, const IceXML::Attributes& attrs, int line, int column) { _line = line; _column = column; XmlAttributesHelper attributes(_variables, attrs); try { if(name == "icegrid") { if(!_isTopLevel) { error("element is a top level element"); } _isTopLevel = false; } else if(_isTopLevel) { error("only the element is allowed at the top-level"); } else if(name == "target") { if(!_isCurrentTargetDeployable) { ++_targetCounter; } else { _isCurrentTargetDeployable = isTargetDeployable(getAttributeValue(attrs, "name")); _targetCounter = 1; return; } } else if(!isCurrentTargetDeployable()) { // // We don't bother to parse the elements if the elements are enclosed in a target element // which won't be deployed. // return; } else if(name == "include") { _variables->push(); string file; string targets; for(IceXML::Attributes::const_iterator p = attrs.begin(); p != attrs.end(); ++p) { if(p->first == "descriptor") { file = _variables->substitute(p->second); } else if(p->first == "targets") { targets = _variables->substitute(p->second); } else { string v = _variables->substitute(p->second); (*_variables)[p->first] = v; } } if(file.empty()) { error("attribute `descriptor' is mandatory in element "); } if(file[0] != '/') { string::size_type end = _filename.find_last_of('/'); if(end != string::npos) { file = _filename.substr(0, end) + "/" + file; } } string oldFileName = _filename; vector oldTargets = _targets; _isTopLevel = true; _filename = file; _targets = getTargets(targets); IceXML::Parser::parse(file, *this); _variables->pop(); _filename = oldFileName; _targets = oldTargets; } else if(name == "application") { if(_currentApplication.get()) { error("only one element is allowed"); } _currentApplication.reset(new ApplicationDescriptorHelper(_communicator, _variables, attrs)); (*_variables)["application"] = _currentApplication->getDescriptor()->name; } else if(name == "node") { (*_variables)["node"] = attributes("name"); } else if(name == "server") { if(_currentServer.get()) { error("element inside a server definition"); } if(!_variables->hasVariable("node")) { error("the element can only be a child of a element"); } if(!_currentApplication.get()) { _currentServer.reset(new ServerDescriptorHelper(_communicator, _variables, attrs)); } else { _currentServer.reset(_currentApplication->addServer(attrs)); } _currentComponent = _currentServer.get(); (*_variables)["server"] = _currentServer->getDescriptor()->name; } else if(name == "server-template") { if(_currentServer.get()) { error("element inside a server definition"); } _variables->ignoreMissing(true); _currentServer.reset(_currentApplication->addServerTemplate(attrs)); _currentComponent = _currentServer.get(); (*_variables)["server"] = _currentServer->getDescriptor()->name; } else if(name == "service") { if(_currentService.get()) { error("element inside a service definition"); } _currentService.reset(_currentServer->addService(attrs)); _currentComponent = _currentService.get(); (*_variables)["service"] = _currentService->getDescriptor()->name; } else if(name == "service-template") { if(_currentService.get()) { error("element inside a service definition"); } _variables->ignoreMissing(true); _currentService.reset(_currentApplication->addServiceTemplate(attrs)); _currentComponent = _currentService.get(); (*_variables)["server"] = "${server}"; (*_variables)["service"] = _currentService->getDescriptor()->name; } else if(name == "variable") { (*_variables)[attributes("name")] = attributes("value", ""); } else if(name == "properties") { if(!_currentComponent) { error("the element can only be a child of a or element"); } _inProperties = true; } else if(name == "property") { if(!_inProperties) { error("the element can only be a child of a element"); } _currentComponent->addProperty(attrs); } else if(name == "adapters") { if(!_currentComponent) { error("the element can only be a child of a or element"); } _inAdapters = true; } else if(name == "adapter") { if(!_inAdapters) { error("the element can only be a child of an element"); } _currentComponent->addAdapter(attrs); } else if(name == "object") { if(_inAdapter) { error("the element can only be a child of an element"); } _currentComponent->addObject(attrs); } else if(name == "dbenv") { if(!_currentComponent) { error("the element can only be a child of a or element"); } _currentComponent->addDbEnv(attrs); _inDbEnv = true; } else if(name == "dbproperty") { if(!_inDbEnv) { error("the element can only be a child of a element"); } _currentComponent->addDbEnvProperty(attrs); } } catch(const string& reason) { error(reason); } _elements.push(""); } void DescriptorHandler::endElement(const string& name, int line, int column) { _line = line; _column = column; if(name == "target") { if(!_isCurrentTargetDeployable && --_targetCounter == 0) { _isCurrentTargetDeployable = true; _targetCounter = 0; } return; } else if(!isCurrentTargetDeployable()) { // // We don't bother to parse the elements if the elements are enclosed in a target element // which won't be deployed. // return; } else if(name == "application") { _variables->remove("application"); } else if(name == "node") { _variables->remove("node"); } else if(name == "server" || name == "server-template") { if(_currentApplication.get()) { _currentServer.reset(0); } _currentComponent = 0; _variables->ignoreMissing(false); _variables->remove("server"); } else if(name == "service" || name == "service-template") { _currentService.reset(0); _currentComponent = _currentServer.get(); _variables->ignoreMissing(false); _variables->remove("service"); _variables->remove("server"); } else if(name == "comment") { if(_currentComponent) { _currentComponent->setComment(elementValue()); } else if(_currentApplication.get()) { _currentApplication->setComment(elementValue()); } } else if(name == "option") { if(!_currentServer.get()) { error("element