// ********************************************************************** // // Copyright (c) 2003-2006 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&, const Ice::CommunicatorPtr&); void setAdmin(const IceGrid::AdminPrx&); void setVariables(const map&, const 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 ApplicationDescriptor& getApplicationDescriptor() const; private: bool isCurrentTargetDeployable() const; string elementValue(); vector getTargets(const string&) const; void error(const string&) const; bool isTargetDeployable(const string&) const; const Ice::CommunicatorPtr _communicator; IceGrid::AdminPrx _admin; string _filename; map _overrides; vector _targets; string _data; string _previousElementName; int _targetCounter; bool _isCurrentTargetDeployable; int _line; int _column; auto_ptr _currentApplication; auto_ptr _currentNode; auto_ptr _currentTemplate; auto_ptr _currentServerInstance; auto_ptr _currentServiceInstance; auto_ptr _currentServer; auto_ptr _currentService; CommunicatorDescriptorBuilder* _currentCommunicator; auto_ptr _currentPropertySet; bool _isTopLevel; bool _inAdapter; bool _inReplicaGroup; bool _inDbEnv; bool _inDistrib; }; } DescriptorHandler::DescriptorHandler(const string& filename, const Ice::CommunicatorPtr& communicator) : _communicator(communicator), _filename(filename), _isCurrentTargetDeployable(true), _currentCommunicator(0), _isTopLevel(true), _inAdapter(false), _inReplicaGroup(false), _inDbEnv(false) { } void DescriptorHandler::setAdmin(const AdminPrx& admin) { _admin = admin; } void DescriptorHandler::setVariables(const map& variables, const vector& targets) { _overrides = variables; _targets = targets; } void DescriptorHandler::startElement(const string& name, const IceXML::Attributes& attrs, int line, int column) { _line = line; _column = column; XmlAttributesHelper attributes(attrs, _communicator->getLogger(), _filename, line); 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(attributes("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. // attributes.asMap(); return; } else if(name == "include") { string targets = attributes("targets", ""); string file = attributes("file"); 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); _filename = oldFileName; _targets = oldTargets; } else if(name == "application") { if(_currentApplication.get()) { error("only one element is allowed"); } bool importTemplates = attributes.asBool("import-default-templates", false); // // TODO: is ignoring importTemplates the desired behavior when _admin == 0? // if(importTemplates && _admin != 0) { try { ApplicationDescriptor application = _admin->getDefaultApplicationDescriptor(); _currentApplication.reset(new ApplicationDescriptorBuilder(_communicator, application, attributes, _overrides)); } catch(const DeploymentException& ex) { throw ex.reason; } } else { _currentApplication.reset(new ApplicationDescriptorBuilder(_communicator, attributes, _overrides)); } } else if(name == "node") { if(!_currentApplication.get()) { error("the element can only be a child of a element"); } _currentNode.reset(_currentApplication->createNode(attributes)); } else if(name == "server-instance") { if(!_currentNode.get() || _currentServer.get()) { error("the element can only be a child of a element"); } _currentServerInstance.reset(_currentNode->createServerInstance(attributes)); } else if(name == "server") { if(!_currentNode.get() && !_currentTemplate.get() || _currentServer.get()) { error("the element can only be a child of a or element"); } if(_currentNode.get()) { _currentServer.reset(_currentNode->createServer(attributes)); } else { _currentServer.reset(_currentTemplate->createServer(attributes)); } _currentCommunicator = _currentServer.get(); } else if(name == "icebox") { if(!_currentNode.get() && !_currentTemplate.get() || _currentServer.get()) { error("the element can only be a child of a or element"); } if(_currentNode.get()) { _currentServer.reset(_currentNode->createIceBox(attributes)); } else { _currentServer.reset(_currentTemplate->createIceBox(attributes)); } _currentCommunicator = _currentServer.get(); } else if(name == "server-template") { if(_currentTemplate.get() || _currentNode.get()) { error("element can only be a child of an element"); } _currentTemplate.reset(_currentApplication->createServerTemplate(attributes)); } else if(name == "service-instance") { if(!_currentServer.get()) { error("the element can only be a child of an element"); } _currentServiceInstance.reset(_currentServer->createServiceInstance(attributes)); } else if(name == "service") { if(!_currentServer.get() && !_currentTemplate.get() || _currentService.get()) { error("the element can only be a child of an or element"); } if(_currentServer.get()) { _currentService.reset(_currentServer->createService(attributes)); } else { _currentService.reset(_currentTemplate->createService(attributes)); } _currentCommunicator = _currentService.get(); } else if(name == "service-template") { if(_currentNode.get() || _currentTemplate.get()) { error("element can only be a child of an element"); } _currentTemplate.reset(_currentApplication->createServiceTemplate(attributes)); } else if(name == "replica-group") { if(!_currentApplication.get()) { error("the element can only be a child of a element"); } _currentApplication->addReplicaGroup(attributes); _inReplicaGroup = true; } else if(name == "load-balancing") { if(!_inReplicaGroup) { error("the element can only be a child of a element"); } _currentApplication->setLoadBalancing(attributes); } else if(name == "variable") { if(_currentNode.get()) { _currentNode->addVariable(attributes); } else if(_currentApplication.get()) { _currentApplication->addVariable(attributes); } else { error("the element can only be a child of an or element"); } } else if(name == "parameter") { if(!_currentTemplate.get()) { error("the element can only be a child of a