// ********************************************************************** // // 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&, 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; 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; 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, const vector& targets) { _variables->reset(variables, 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 { _variables->addVariable(p->first, _variables->substitute(p->second)); } } 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)); } else if(name == "node") { _currentApplication->addNode(attrs); } else if(name == "server" || name == "server-instance") { if(!_currentApplication.get()) { error("the element can only be a child of a element"); } 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(name == "server-instance") { _currentApplication->addServer(attributes("template"), attrs); } else { _currentServer = _currentApplication->addServerTemplate("", attrs); _currentComponent = _currentServer.get(); } } else if(name == "server-template") { if(_currentServer.get()) { error("element inside a server definition"); } _currentServer = _currentApplication->addServerTemplate(attributes("id"), attrs); _currentComponent = _currentServer.get(); } else if(name == "service" || name == "service-instance") { if(!_currentServer.get()) { error("the element can only be a child of a element"); } if(_currentService.get()) { error("element inside a service definition"); } if(name == "service-instance") { _currentServer->addService(attributes("template"), attrs); } else { _currentService = _currentServer->addServiceTemplate("", attrs); _currentComponent = _currentService.get(); } } else if(name == "service-template") { if(_currentService.get()) { error("element inside a service definition"); } _currentService = _currentApplication->addServiceTemplate(attributes("id"), attrs); _currentComponent = _currentService.get(); } else if(name == "variable") { _variables->addVariable(attributes("name"), attributes("value", "")); } else if(name == "parameter") { _variables->addParameter(attributes("name")); } 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") { _currentApplication->endParsing(); } else if(name == "node") { _currentApplication->endNodeParsing(); } else if(name == "server" || name == "server-template") { assert(_currentServer.get()); _currentServer->endParsing(); if(name == "server") { _currentApplication->addServer(_currentServer->getDescriptor()); } _currentServer.reset(0); _currentComponent = 0; } else if(name == "service" || name == "service-template") { assert(_currentService.get()); _currentService->endParsing(); if(name == "service") { _currentServer->addService(_currentService->getDescriptor()); } _currentService.reset(0); _currentComponent = _currentServer.get(); } else if(name == "comment") { if(_currentComponent) { _currentComponent->setComment(elementValue()); } else if(_currentApplication.get()) { _currentApplication->setComment(elementValue()); } else { error("element can only be the child of an , or element"); } } else if(name == "option") { if(!_currentServer.get()) { error("element