// ********************************************************************** // // Copyright (c) 2003-2004 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 using namespace std; using namespace Ice; using namespace IcePack; namespace IcePack { 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 substitute(const std::string&) const; std::string elementValue() const; std::vector getTargets(const std::string&) const; void error(const string&) const; const std::string& getVariable(const std::string&) const; bool hasVariable(const std::string&) const; bool isTargetDeployable(const std::string&) const; Ice::CommunicatorPtr _communicator; string _filename; std::vector _targets; std::vector< std::map > _variables; std::stack _elements; int _targetCounter; bool _isCurrentTargetDeployable; int _line; int _column; ApplicationDescriptorPtr _currentApplication; ServerDescriptorPtr _currentServer; ServiceDescriptorPtr _currentService; ComponentDescriptorPtr _currentComponent; AdapterDescriptor _currentAdapter; DbEnvDescriptor _currentDbEnv; bool _isTopLevel; bool _inProperties; bool _inAdapters; }; } DescriptorHandler::DescriptorHandler(const string& filename) : _filename(filename), _isCurrentTargetDeployable(true), _isTopLevel(true), _inProperties(false), _inAdapters(false) { _variables.push_back(map()); } void DescriptorHandler::setCommunicator(const Ice::CommunicatorPtr& communicator) { _communicator = communicator; } void DescriptorHandler::setVariables(const std::map& variables) { _variables.clear(); _variables.push_back(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; if(name == "icepack") { 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_back(map()); string file; string targets; for(IceXML::Attributes::const_iterator p = attrs.begin(); p != attrs.end(); ++p) { if(p->first == "descriptor") { file = substitute(p->second); } else if(p->first == "targets") { targets = substitute(p->second); } else { string v = substitute(p->second); _variables.back()[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_back(); _filename = oldFileName; _targets = oldTargets; } else if(name == "application") { if(_currentApplication) { error("only one element is allowed"); } _currentApplication = new ApplicationDescriptor(); _currentApplication->name = getAttributeValue(attrs, "name"); _variables.back()["application"] = _currentApplication->name; } else if(name == "node") { _variables.back()["node"] = getAttributeValue(attrs, "name"); } else if(name == "server") { if(!hasVariable("node")) { error("the element can only be a child of a element"); } string kind = getAttributeValue(attrs, "kind"); if(kind == "cpp" || kind == "cs") { _currentServer = new ServerDescriptor(); _currentServer->exe = getAttributeValue(attrs, "exe"); } else if(kind == "java") { JavaServerDescriptorPtr descriptor = new JavaServerDescriptor(); _currentServer = descriptor; _currentServer->exe = getAttributeValueWithDefault(attrs, "exe", "java"); descriptor->className = getAttributeValue(attrs, "classname"); } else if(kind == "cpp-icebox") { _currentServer = new CppIceBoxDescriptor(); _currentServer->exe = getAttributeValueWithDefault(attrs, "exe", "icebox"); } else if(kind == "java-icebox") { JavaIceBoxDescriptorPtr descriptor = new JavaIceBoxDescriptor(); _currentServer = descriptor; _currentServer->exe = getAttributeValueWithDefault(attrs, "exe", "java"); descriptor->className = getAttributeValueWithDefault(attrs, "classname", "IceBox.Server"); } _currentServer->name = getAttributeValue(attrs, "name"); _currentServer->node = getVariable("node"); _currentServer->pwd = getAttributeValueWithDefault(attrs, "pwd", ""); _currentServer->activation = getAttributeValueWithDefault(attrs, "activation", "manual") == "on-demand" ? OnDemand : Manual; if(_currentApplication) { _currentServer->application = _currentApplication->name; } if(kind == "cpp-icebox" || kind == "java-icebox") { CppIceBoxDescriptorPtr cppIceBox = CppIceBoxDescriptorPtr::dynamicCast(_currentServer); if(cppIceBox) { cppIceBox->endpoints = getAttributeValue(attrs, "endpoints"); } JavaIceBoxDescriptorPtr javaIceBox = JavaIceBoxDescriptorPtr::dynamicCast(_currentServer); if(javaIceBox) { javaIceBox->endpoints = getAttributeValue(attrs, "endpoints"); } PropertyDescriptor prop; prop.name = "IceBox.ServiceManager.Identity"; prop.value = _currentServer->name + "/ServiceManager"; _currentServer->properties.push_back(prop); AdapterDescriptor adapter; adapter.name = "IceBox.ServiceManager"; adapter.endpoints = getAttributeValue(attrs, "endpoints"); adapter.id = _currentServer->name + "." + adapter.name; adapter.registerProcess = true; _currentServer->adapters.push_back(adapter); } _currentComponent = _currentServer; _variables.back()["server"] = _currentServer->name; } else if(name == "service") { if(!CppIceBoxDescriptorPtr::dynamicCast(_currentServer) && !JavaIceBoxDescriptorPtr::dynamicCast(_currentServer)) { error("element can only be a child of an IceBox element"); } _currentService = new ServiceDescriptor(); _currentService->name = getAttributeValue(attrs, "name"); _currentService->entry = getAttributeValue(attrs, "entry"); _currentComponent = _currentService; _variables.back()["service"] = _currentService->name; } else if(name == "variable") { _variables.back()[getAttributeValue(attrs, "name")] = getAttributeValueWithDefault(attrs, "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"); } PropertyDescriptor prop; prop.name = getAttributeValue(attrs, "name"); prop.value = getAttributeValueWithDefault(attrs, "value", ""); _currentComponent->properties.push_back(prop); } 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"); } _currentAdapter.name = getAttributeValue(attrs, "name"); _currentAdapter.id = getAttributeValueWithDefault(attrs, "id", ""); if(_currentAdapter.id.empty()) { string service = getVariable("service"); const string fqn = getVariable("server") + (service.empty() ? "" : ".") + service; _currentAdapter.id = fqn + "." + _currentAdapter.name; } _currentAdapter.endpoints = getAttributeValue(attrs, "endpoints"); _currentAdapter.registerProcess = getAttributeValueWithDefault(attrs, "register", "false") == "true"; } else if(name == "object") { if(_currentAdapter.name.empty()) { error("the element can only be a child of an element"); } ObjectDescriptor object; object.type = getAttributeValueWithDefault(attrs, "type", ""); object.proxy = _communicator->stringToProxy(getAttributeValue(attrs, "identity") + "@" + _currentAdapter.id); object.adapterId = _currentAdapter.id; _currentAdapter.objects.push_back(object); } else if(name == "dbenv") { if(!_currentComponent) { error("the element can only be a child of a or element"); } _currentDbEnv.name = getAttributeValue(attrs, "name"); DbEnvDescriptorSeq::iterator p; for(p = _currentComponent->dbEnvs.begin(); p != _currentComponent->dbEnvs.end(); ++p) { // // We are re-opening the dbenv element to define more properties. // if(p->name == _currentDbEnv.name) { break; } } if(p != _currentComponent->dbEnvs.end()) { // // Remove the previously defined dbenv, we'll add it back again when // the dbenv element end tag is reached. // _currentDbEnv = *p; _currentComponent->dbEnvs.erase(p); } if(_currentDbEnv.dbHome.empty()) { _currentDbEnv.dbHome = getAttributeValueWithDefault(attrs, "home", ""); } } else if(name == "dbproperty") { if(_currentDbEnv.name.empty()) { error("the element can only be a child of a element"); } PropertyDescriptor prop; prop.name = getAttributeValue(attrs, "name"); prop.value = getAttributeValueWithDefault(attrs, "value", ""); _currentDbEnv.properties.push_back(prop); } _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.back()["application"] = ""; } else if(name == "node") { _variables.back()["node"] = ""; } else if(name == "server") { if(_currentApplication) { _currentApplication->servers.push_back(_currentServer); _currentServer = 0; } _currentComponent = 0; _variables.back()["server"] = ""; } else if(name == "service") { CppIceBoxDescriptorPtr cppIceBox = CppIceBoxDescriptorPtr::dynamicCast(_currentServer); if(cppIceBox) { cppIceBox->services.push_back(_currentService); } JavaIceBoxDescriptorPtr javaIceBox = JavaIceBoxDescriptorPtr::dynamicCast(_currentServer); if(javaIceBox) { javaIceBox->services.push_back(_currentService); } _currentService = 0; _currentComponent = _currentServer; _variables.back()["service"] = ""; } else if(name == "comment") { if(_currentComponent) { _currentComponent->comment = elementValue(); } else if(_currentApplication) { _currentApplication->comment = elementValue(); } } else if(name == "option") { if(!_currentServer) { error("element