1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <Ice/Ice.h>
6 #include <IceXML/Parser.h>
7 #include <IcePatch2Lib/Util.h>
8 #include <IceGrid/Admin.h>
9 #include <IceGrid/DescriptorParser.h>
10 #include <IceGrid/DescriptorBuilder.h>
11 #include <IceGrid/Util.h>
12
13 #include <stack>
14 #include <fstream>
15
16 using namespace std;
17 using namespace Ice;
18 using namespace IceGrid;
19
20 namespace IceGrid
21 {
22
23 class DescriptorHandler : public IceXML::Handler
24 {
25 public:
26
27 DescriptorHandler(const string&, const Ice::CommunicatorPtr&);
28
29 void setAdmin(const IceGrid::AdminPrx&);
30 void setVariables(const map<string, string>&, const vector<string>&);
31
32 virtual void startElement(const string&, const IceXML::Attributes&, int, int);
33 virtual void endElement(const string&, int, int);
34 virtual void characters(const string&, int, int);
35 virtual void error(const string&, int, int);
36
37 const ApplicationDescriptor& getApplicationDescriptor() const;
38
39 private:
40
41 bool isCurrentTargetDeployable() const;
42 string elementValue();
43 vector<string> getTargets(const string&) const;
44 void error(const string&) const;
45 bool isTargetDeployable(const string&) const;
46
47 const Ice::CommunicatorPtr _communicator;
48 IceGrid::AdminPrx _admin;
49 string _filename;
50 map<string, string> _overrides;
51 vector<string> _targets;
52 string _data;
53 string _previousElementName;
54 int _targetCounter;
55 bool _isCurrentTargetDeployable;
56 int _line;
57 int _column;
58
59 IceInternal::UniquePtr<ApplicationDescriptorBuilder> _currentApplication;
60 IceInternal::UniquePtr<NodeDescriptorBuilder> _currentNode;
61 IceInternal::UniquePtr<TemplateDescriptorBuilder> _currentTemplate;
62 IceInternal::UniquePtr<ServerInstanceDescriptorBuilder> _currentServerInstance;
63 IceInternal::UniquePtr<ServiceInstanceDescriptorBuilder> _currentServiceInstance;
64 IceInternal::UniquePtr<ServerDescriptorBuilder> _currentServer;
65 IceInternal::UniquePtr<ServiceDescriptorBuilder> _currentService;
66 CommunicatorDescriptorBuilder* _currentCommunicator;
67 IceInternal::UniquePtr<PropertySetDescriptorBuilder> _currentPropertySet;
68
69 bool _isTopLevel;
70 bool _inAdapter;
71 bool _inReplicaGroup;
72 bool _inDbEnv;
73 bool _inDistrib;
74 };
75
76 }
77
DescriptorHandler(const string & filename,const Ice::CommunicatorPtr & communicator)78 DescriptorHandler::DescriptorHandler(const string& filename, const Ice::CommunicatorPtr& communicator) :
79 _communicator(communicator),
80 _filename(filename),
81 _isCurrentTargetDeployable(true),
82 _currentCommunicator(0),
83 _isTopLevel(true),
84 _inAdapter(false),
85 _inReplicaGroup(false),
86 _inDbEnv(false)
87 {
88 }
89
90 void
setAdmin(const AdminPrx & admin)91 DescriptorHandler::setAdmin(const AdminPrx& admin)
92 {
93 _admin = admin;
94 }
95
96 void
setVariables(const map<string,string> & variables,const vector<string> & targets)97 DescriptorHandler::setVariables(const map<string, string>& variables, const vector<string>& targets)
98 {
99 _overrides = variables;
100 _targets = targets;
101 }
102
103 void
startElement(const string & name,const IceXML::Attributes & attrs,int line,int column)104 DescriptorHandler::startElement(const string& name, const IceXML::Attributes& attrs, int line, int column)
105 {
106 _line = line;
107 _column = column;
108 XmlAttributesHelper attributes(attrs, _communicator->getLogger(), _filename, line);
109
110 try
111 {
112 if(name == "icegrid")
113 {
114 if(!_isTopLevel)
115 {
116 error("element <icegrid> is a top level element");
117 }
118 _isTopLevel = false;
119 }
120 else if(_isTopLevel)
121 {
122 error("only the <icegrid> element is allowed at the top-level");
123 }
124 else if(name == "target")
125 {
126 if(!_isCurrentTargetDeployable)
127 {
128 ++_targetCounter;
129 }
130 else
131 {
132 _isCurrentTargetDeployable = isTargetDeployable(attributes("name"));
133 _targetCounter = 1;
134 return;
135 }
136 }
137 else if(!isCurrentTargetDeployable())
138 {
139 //
140 // We don't bother to parse the elements if the elements are enclosed in a target element
141 // which won't be deployed.
142 //
143 attributes.asMap();
144 return;
145 }
146 else if(name == "include")
147 {
148 string targets = attributes("targets", "");
149 string file = attributes("file");
150 if(file[0] != '/')
151 {
152 string::size_type end = _filename.find_last_of('/');
153 if(end != string::npos)
154 {
155 file = _filename.substr(0, end) + "/" + file;
156 }
157 }
158
159 string oldFileName = _filename;
160 vector<string> oldTargets = _targets;
161 _isTopLevel = true;
162 _filename = file;
163 _targets = getTargets(targets);
164
165 IceXML::Parser::parse(file, *this);
166
167 _filename = oldFileName;
168 _targets = oldTargets;
169 }
170 else if(name == "application")
171 {
172 if(_currentApplication.get())
173 {
174 error("only one <application> element is allowed");
175 }
176
177 bool importTemplates = attributes.asBool("import-default-templates", false);
178
179 //
180 // TODO: is ignoring importTemplates the desired behavior when _admin == 0?
181 //
182 if(importTemplates && _admin != 0)
183 {
184 try
185 {
186 ApplicationDescriptor application = _admin->getDefaultApplicationDescriptor();
187 _currentApplication.reset(new ApplicationDescriptorBuilder(_communicator, application,
188 attributes, _overrides));
189 }
190 catch(const DeploymentException& ex)
191 {
192 throw runtime_error(ex.reason);
193 }
194 }
195 else
196 {
197 _currentApplication.reset(new ApplicationDescriptorBuilder(_communicator, attributes, _overrides));
198 }
199 }
200 else if(name == "node")
201 {
202 if(!_currentApplication.get() || _currentNode.get())
203 {
204 error("the <node> element can only be a child of an <application> element");
205 }
206 _currentNode.reset(_currentApplication->createNode(attributes));
207 }
208 else if(name == "server-instance")
209 {
210 if(!_currentNode.get() || _currentServer.get() || _currentServerInstance.get())
211 {
212 error("the <server-instance> element can only be a child of a <node> element");
213 }
214 _currentServerInstance.reset(_currentNode->createServerInstance(attributes));
215 }
216 else if(name == "server")
217 {
218 if((!_currentNode.get() && !_currentTemplate.get()) || _currentServer.get() || _currentServerInstance.get())
219 {
220 error("the <server> element can only be a child of a <node> or <server-template> element");
221 }
222 if(_currentNode.get())
223 {
224 _currentServer.reset(_currentNode->createServer(attributes));
225 }
226 else
227 {
228 _currentServer.reset(_currentTemplate->createServer(attributes));
229 }
230 _currentCommunicator = _currentServer.get();
231 }
232 else if(name == "icebox")
233 {
234 if((!_currentNode.get() && !_currentTemplate.get()) || _currentServer.get() || _currentServerInstance.get())
235 {
236 error("the <icebox> element can only be a child of a <node> or <server-template> element");
237 }
238 if(_currentNode.get())
239 {
240 _currentServer.reset(_currentNode->createIceBox(attributes));
241 }
242 else
243 {
244 _currentServer.reset(_currentTemplate->createIceBox(attributes));
245 }
246 _currentCommunicator = _currentServer.get();
247 }
248 else if(name == "server-template")
249 {
250 if(!_currentApplication.get() || _currentTemplate.get() || _currentNode.get())
251 {
252 error("the <server-template> element can only be a child of an <application> element");
253 }
254 _currentTemplate.reset(_currentApplication->createServerTemplate(attributes));
255 }
256 else if(name == "service-instance")
257 {
258 if(!_currentServer.get() || _currentServiceInstance.get())
259 {
260 error("the <service-instance> element can only be a child of an <icebox> element");
261 }
262 _currentServiceInstance.reset(_currentServer->createServiceInstance(attributes));
263 }
264 else if(name == "service")
265 {
266 if((!_currentServer.get() && !_currentTemplate.get()) || _currentService.get() ||
267 _currentServiceInstance.get())
268 {
269 error("the <service> element can only be a child of an <icebox> or <service-template> element");
270 }
271
272 if(_currentServer.get())
273 {
274 _currentService.reset(_currentServer->createService(attributes));
275 }
276 else
277 {
278 _currentService.reset(_currentTemplate->createService(attributes));
279 }
280 _currentCommunicator = _currentService.get();
281 }
282 else if(name == "service-template")
283 {
284 if(!_currentApplication.get() || _currentNode.get() || _currentTemplate.get())
285 {
286 error("the <service-template> element can only be a child of an <application> element");
287 }
288
289 _currentTemplate.reset(_currentApplication->createServiceTemplate(attributes));
290 }
291 else if(name == "replica-group")
292 {
293 if(!_currentApplication.get())
294 {
295 error("the <replica-group> element can only be a child of an <application> element");
296 }
297 _currentApplication->addReplicaGroup(attributes);
298 _inReplicaGroup = true;
299 }
300 else if(name == "load-balancing")
301 {
302 if(!_inReplicaGroup)
303 {
304 error("the <load-balancing> element can only be a child of a <replica-group> element");
305 }
306 _currentApplication->setLoadBalancing(attributes);
307 }
308 else if(name == "variable")
309 {
310 if(_currentNode.get())
311 {
312 _currentNode->addVariable(attributes);
313 }
314 else if(_currentApplication.get())
315 {
316 _currentApplication->addVariable(attributes);
317 }
318 else
319 {
320 error("the <variable> element can only be a child of an <application> or <node> element");
321 }
322 }
323 else if(name == "parameter")
324 {
325 if(!_currentTemplate.get())
326 {
327 error("the <parameter> element can only be a child of a <template> element");
328 }
329 _currentTemplate->addParameter(attributes);
330 }
331 else if(name == "properties")
332 {
333 if(_currentPropertySet.get())
334 {
335 _currentPropertySet->addPropertySet(attributes);
336 }
337 else if(_currentServiceInstance.get())
338 {
339 _currentPropertySet.reset(_currentServiceInstance->createPropertySet());
340 }
341 else if(_currentServerInstance.get())
342 {
343 _currentPropertySet.reset(_currentServerInstance->createPropertySet(attributes));
344 }
345 else if(_currentCommunicator)
346 {
347 _currentPropertySet.reset(_currentCommunicator->createPropertySet());
348 }
349 else if(_currentNode.get())
350 {
351 _currentPropertySet.reset(_currentNode->createPropertySet(attributes));
352 }
353 else if(_currentApplication.get() && !_currentTemplate.get())
354 {
355 _currentPropertySet.reset(_currentApplication->createPropertySet(attributes));
356 }
357 else
358 {
359 error("the <properties> element is not allowed here");
360 }
361 }
362 else if(name == "property")
363 {
364 if(_currentPropertySet.get())
365 {
366 _currentPropertySet->addProperty(attributes);
367 }
368 else if(_currentCommunicator)
369 {
370 _currentCommunicator->addProperty(attributes);
371 }
372 else
373 {
374 error("the <property> element can only be a child of a <properties>, <icebox>, <server> or <service> "
375 "element");
376 }
377 }
378 else if(name == "adapter")
379 {
380 if(!_currentCommunicator)
381 {
382 error("the <adapter> element can only be a child of a <server> or <service> element");
383 }
384 _currentCommunicator->addAdapter(attributes);
385 _inAdapter = true;
386 }
387 else if(name == "object")
388 {
389 if(!_inAdapter && !_inReplicaGroup)
390 {
391 error("the <object> element can only be a child of an <adapter> or <replica-group> element");
392 }
393 if(_inReplicaGroup)
394 {
395 _currentApplication->addObject(attributes);
396 }
397 else
398 {
399 _currentCommunicator->addObject(attributes);
400 }
401 }
402 else if(name == "allocatable")
403 {
404 if(!_inAdapter)
405 {
406 error("the <allocatable> element can only be a child of an <adapter> element");
407 }
408 _currentCommunicator->addAllocatable(attributes);
409 }
410 else if(name == "distrib")
411 {
412 if(!_currentApplication.get() ||
413 ((_currentNode.get() || _currentTemplate.get()) && !_currentServer.get()) ||
414 _currentServer.get() != _currentCommunicator)
415 {
416 error("the <distrib> element can only be a child of an <application>, <server> or <icebox> element");
417 }
418 if(!_currentServer.get())
419 {
420 _currentApplication->addDistribution(attributes);
421 }
422 else
423 {
424 _currentServer->addDistribution(attributes);
425 }
426 _inDistrib = true;
427 }
428 else if(name == "dbenv")
429 {
430 if(!_currentCommunicator)
431 {
432 error("the <dbenv> element can only be a child of a <server> or <service> element");
433 }
434 _currentCommunicator->addDbEnv(attributes);
435 _inDbEnv = true;
436 }
437 else if(name == "log")
438 {
439 if(!_currentCommunicator)
440 {
441 error("the <log> element can only be a child of a <server> or <service> element");
442 }
443 _currentCommunicator->addLog(attributes);
444 }
445 else if(name == "dbproperty")
446 {
447 if(!_inDbEnv)
448 {
449 error("the <dbproperty> element can only be a child of a <dbenv> element");
450 }
451 _currentCommunicator->addDbEnvProperty(attributes);
452 }
453 else if(name == "description" || name == "option" || name == "env" || name == "directory")
454 {
455 //
456 // Nothing to do.
457 //
458 }
459 else
460 {
461 error("unknown element `" + name + "'");
462 }
463
464 attributes.checkUnknownAttributes();
465 }
466 catch(const exception& ex)
467 {
468 error(ex.what());
469 }
470
471 //
472 // Check if the previous element value has been consumed and if not make
473 // sure it's "empty".
474 //
475 string value = elementValue();
476 if(!value.empty() && value.find_first_not_of(" \t\r\n") != string::npos)
477 {
478 error("invalid element value for element `" + _previousElementName + "'");
479 }
480 _previousElementName = name;
481 }
482
483 void
endElement(const string & name,int line,int column)484 DescriptorHandler::endElement(const string& name, int line, int column)
485 {
486 _line = line;
487 _column = column;
488
489 try
490 {
491 if(name == "target")
492 {
493 if(!_isCurrentTargetDeployable && --_targetCounter == 0)
494 {
495 _isCurrentTargetDeployable = true;
496 _targetCounter = 0;
497 }
498 return;
499 }
500 else if(!isCurrentTargetDeployable())
501 {
502 //
503 // We don't bother to parse the elements if the elements are enclosed in a target element
504 // which won't be deployed.
505 //
506 return;
507 }
508 else if(name == "node")
509 {
510 _currentApplication->addNode(_currentNode->getName(), _currentNode->getDescriptor());
511 _currentNode.reset(0);
512 }
513 else if(name == "server" || name == "icebox")
514 {
515 assert(_currentServer.get());
516 if(_currentTemplate.get())
517 {
518 _currentTemplate->setDescriptor(_currentServer->getDescriptor());
519 }
520 else
521 {
522 assert(_currentNode.get());
523 _currentNode->addServer(_currentServer->getDescriptor());
524 }
525 _currentServer->finish();
526 _currentServer.reset(0);
527 _currentCommunicator = 0;
528 }
529 else if(name == "server-template")
530 {
531 assert(_currentApplication.get());
532 _currentApplication->addServerTemplate(_currentTemplate->getId(), _currentTemplate->getDescriptor());
533 _currentTemplate.reset(0);
534 }
535 else if(name == "service")
536 {
537 assert(_currentService.get());
538 if(_currentServer.get())
539 {
540 _currentServer->addService(_currentService->getDescriptor());
541 }
542 else
543 {
544 _currentTemplate->setDescriptor(_currentService->getDescriptor());
545 }
546 _currentService->finish();
547 _currentService.reset(0);
548 _currentCommunicator = _currentServer.get();
549 }
550 else if(name == "service-template")
551 {
552 assert(_currentTemplate.get());
553 _currentApplication->addServiceTemplate(_currentTemplate->getId(), _currentTemplate->getDescriptor());
554 _currentTemplate.reset(0);
555 }
556 else if(name == "server-instance")
557 {
558 assert(_currentNode.get() && _currentServerInstance.get());
559 _currentNode->addServerInstance(_currentServerInstance->getDescriptor());
560 _currentServerInstance.reset(0);
561 }
562 else if(name == "service-instance")
563 {
564 assert(_currentServer.get() && _currentServiceInstance.get());
565 _currentServer->addServiceInstance(_currentServiceInstance->getDescriptor());
566 _currentServiceInstance.reset(0);
567 }
568 else if(name == "properties")
569 {
570 assert(_currentPropertySet.get());
571 if(_currentPropertySet->finish())
572 {
573 if(_currentServiceInstance.get())
574 {
575 _currentServiceInstance->addPropertySet(_currentPropertySet->getDescriptor());
576 }
577 else if(_currentServerInstance.get())
578 {
579 _currentServerInstance->addPropertySet(_currentPropertySet->getService(),
580 _currentPropertySet->getDescriptor());
581 }
582 else if(_currentCommunicator)
583 {
584 _currentCommunicator->addPropertySet(_currentPropertySet->getDescriptor());
585 }
586 else if(_currentNode.get())
587 {
588 _currentNode->addPropertySet(_currentPropertySet->getId(),
589 _currentPropertySet->getDescriptor());
590 }
591 else if(_currentApplication.get())
592 {
593 _currentApplication->addPropertySet(_currentPropertySet->getId(),
594 _currentPropertySet->getDescriptor());
595 }
596 else
597 {
598 assert(false);
599 }
600 _currentPropertySet.reset(0);
601 }
602 }
603 else if(name == "description")
604 {
605 if(_inAdapter)
606 {
607 _currentCommunicator->setAdapterDescription(elementValue());
608 }
609 else if(_inReplicaGroup)
610 {
611 _currentApplication->setReplicaGroupDescription(elementValue());
612 }
613 else if(_inDbEnv)
614 {
615 assert(_currentCommunicator);
616 _currentCommunicator->setDbEnvDescription(elementValue());
617 }
618 else if(_currentCommunicator)
619 {
620 _currentCommunicator->setDescription(elementValue());
621 }
622 else if(_currentNode.get())
623 {
624 _currentNode->setDescription(elementValue());
625 }
626 else if(_currentApplication.get())
627 {
628 _currentApplication->setDescription(elementValue());
629 }
630 else
631 {
632 error("element <description> is not allowed here");
633 }
634 }
635 else if(name == "option")
636 {
637 if(!_currentServer.get())
638 {
639 error("element <option> can only be the child of a <server> element");
640 }
641 _currentServer->addOption(elementValue());
642 }
643 else if(name == "env")
644 {
645 if(!_currentServer.get())
646 {
647 error("element <env> can only be the child of a <server> element");
648 }
649 _currentServer->addEnv(elementValue());
650 }
651 else if(name == "directory")
652 {
653 if(!_inDistrib)
654 {
655 error("the <directory> element can only be a child of a <distrib> element");
656 }
657 if(!_currentServer.get())
658 {
659 _currentApplication->addDistributionDirectory(elementValue());
660 }
661 else
662 {
663 _currentServer->addDistributionDirectory(elementValue());
664 }
665 }
666 else if(name == "adapter")
667 {
668 _inAdapter = false;
669 }
670 else if(name == "replica-group")
671 {
672 _currentApplication->finishReplicaGroup();
673 _inReplicaGroup = false;
674 }
675 else if(name == "dbenv")
676 {
677 _inDbEnv = false;
678 }
679 else if(name == "distrib")
680 {
681 _inDistrib = false;
682 }
683 }
684 catch(const exception& ex)
685 {
686 error(ex.what());
687 }
688
689 //
690 // Check if the element value has been consumed and if not make
691 // sure it's "empty".
692 //
693 string value = elementValue();
694 if(!value.empty() && value.find_first_not_of(" \t\r\n") != string::npos)
695 {
696 error("invalid element value for element `" + name + "'");
697 }
698 }
699
700 void
characters(const string & chars,int,int)701 DescriptorHandler::characters(const string& chars, int, int)
702 {
703 if(isCurrentTargetDeployable())
704 {
705 _data += chars;
706 }
707 }
708
709 void
error(const string & msg,int line,int column)710 DescriptorHandler::error(const string& msg, int line, int column)
711 {
712 ostringstream os;
713 os << "error in <" << _filename << "> descriptor, line " << line << ", column " << column << ":\n" << msg;
714 throw IceXML::ParserException(__FILE__, __LINE__, os.str());
715 }
716
717 const ApplicationDescriptor&
getApplicationDescriptor() const718 DescriptorHandler::getApplicationDescriptor() const
719 {
720 if(!_currentApplication.get())
721 {
722 error("no application descriptor defined in this file");
723 }
724 return _currentApplication->getDescriptor();
725 }
726
727 bool
isCurrentTargetDeployable() const728 DescriptorHandler::isCurrentTargetDeployable() const
729 {
730 return _isCurrentTargetDeployable;
731 }
732
733 vector<string>
getTargets(const string & targets) const734 DescriptorHandler::getTargets(const string& targets) const
735 {
736 vector<string> result;
737
738 if(!targets.empty())
739 {
740 const string delim = " \t\n\r";
741
742 string::size_type beg = 0;
743 string::size_type end = 0;
744 do
745 {
746 end = targets.find_first_of(delim, end);
747 if(end == string::npos)
748 {
749 end = targets.size();
750 }
751
752 result.push_back(targets.substr(beg, end - beg));
753 beg = ++end;
754 }
755 while(end < targets.size());
756 }
757
758 copy(_targets.begin(), _targets.end(), back_inserter(result));
759
760 return result;
761 }
762
763 void
error(const string & msg) const764 DescriptorHandler::error(const string& msg) const
765 {
766 ostringstream os;
767 os << "error in <" << _filename << "> descriptor, line " << _line << ", column " << _column << ":\n" << msg;
768 throw IceXML::ParserException(__FILE__, __LINE__, os.str());
769 }
770
771 string
elementValue()772 DescriptorHandler::elementValue()
773 {
774 string tmp;
775 tmp = _data;
776 _data = "";
777 return tmp;
778 }
779
780 bool
isTargetDeployable(const string & target) const781 DescriptorHandler::isTargetDeployable(const string& target) const
782 {
783 string application = _currentApplication.get() ? _currentApplication->getDescriptor().name : string("");
784 string node = _currentNode.get() ? _currentNode->getName() : string("");
785 string server = _currentServer.get() ? _currentServer->getDescriptor()->id : string("");
786 string service = _currentService.get() ? _currentService->getDescriptor()->name : string("");
787
788 //
789 // Compute the current fully qualified name of the communicator.
790 //
791 string fqn;
792 if(!application.empty())
793 {
794 fqn += (fqn.empty() ? "" : ".") + application;
795 }
796 if(!node.empty())
797 {
798 fqn += (fqn.empty() ? "" : ".") + node;
799 }
800 if(!server.empty())
801 {
802 fqn += (fqn.empty() ? "" : ".") + server;
803 }
804 if(!service.empty())
805 {
806 fqn += (fqn.empty() ? "" : ".") + service;
807 }
808
809 //
810 // Go through the list of supplied targets and see if we can match one with the current communicator + target.
811 //
812 for(vector<string>::const_iterator p = _targets.begin(); p != _targets.end(); ++p)
813 {
814 if((*p) == target)
815 {
816 //
817 // A supplied target without any communicator prefix is matching the target.
818 //
819 return true;
820 }
821 else
822 {
823 string communicatorTarget;
824 string::size_type end = 0;
825 while(end != string::npos)
826 {
827 //
828 // Add the first communicator name from the communicator fully qualified name to the
829 // target and see if matches.
830 //
831 end = fqn.find('.', end);
832 if(end == string::npos)
833 {
834 communicatorTarget = fqn + "." + target;
835 }
836 else
837 {
838 communicatorTarget = fqn.substr(0, end) + "." + target;
839 ++end;
840 }
841
842 if((*p) == communicatorTarget)
843 {
844 return true;
845 }
846 }
847 }
848 }
849
850 return false;
851 }
852
853 ApplicationDescriptor
parseDescriptor(const string & descriptor,const Ice::StringSeq & targets,const map<string,string> & variables,const Ice::CommunicatorPtr & communicator,const IceGrid::AdminPrx & admin)854 DescriptorParser::parseDescriptor(const string& descriptor,
855 const Ice::StringSeq& targets,
856 const map<string, string>& variables,
857 const Ice::CommunicatorPtr& communicator,
858 const IceGrid::AdminPrx& admin)
859 {
860 string filename = IcePatch2Internal::simplify(descriptor);
861 DescriptorHandler handler(filename, communicator);
862 handler.setAdmin(admin);
863 handler.setVariables(variables, targets);
864 IceXML::Parser::parse(filename, handler);
865 return handler.getApplicationDescriptor();
866 }
867
868 ApplicationDescriptor
parseDescriptor(const string & descriptor,const Ice::CommunicatorPtr & communicator)869 DescriptorParser::parseDescriptor(const string& descriptor, const Ice::CommunicatorPtr& communicator)
870 {
871 string filename = IcePatch2Internal::simplify(descriptor);
872 DescriptorHandler handler(filename, communicator);
873 IceXML::Parser::parse(filename, handler);
874 return handler.getApplicationDescriptor();
875 }
876