(file) Return to InheritanceTree.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Repository

  1 karl  1.35 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.16 //
  3 karl  1.27 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.23 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.27 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.29 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.35 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.16 //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15 kumpf 1.20 // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18 mike  1.16 // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20 karl  1.38 //
 21 kumpf 1.20 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 mike  1.16 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24 kumpf 1.20 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27 mike  1.16 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29            //
 30            //==============================================================================
 31            //
 32            //%/////////////////////////////////////////////////////////////////////////////
 33            
 34            #include <Pegasus/Common/String.h>
 35            #include <Pegasus/Common/HashTable.h>
 36            #include <Pegasus/Common/Dir.h>
 37 chuck 1.24 #include <Pegasus/Common/CommonUTF.h>
 38 r.kieninger 1.33 #include <Pegasus/Common/CIMNameUnchecked.h>
 39 mike        1.16 #include "InheritanceTree.h"
 40                  
 41 schuur      1.25 #if 0
 42                  #undef PEG_METHOD_ENTER
 43                  #undef PEG_METHOD_EXIT
 44                  #define PEG_METHOD_ENTER(x,y)  cout<<"--- Enter: "<<y<<endl;
 45                  #define PEG_METHOD_EXIT()
 46                  #endif
 47                  
 48 mike        1.16 PEGASUS_NAMESPACE_BEGIN
 49                  
 50                  PEGASUS_USING_STD;
 51                  
 52                  ////////////////////////////////////////////////////////////////////////////////
 53                  //
 54                  // NoCaseEqualFunc
 55                  //
 56                  ////////////////////////////////////////////////////////////////////////////////
 57                  
 58                  struct NoCaseEqualFunc
 59                  {
 60                      static Boolean equal(const String& x, const String& y)
 61                      {
 62                          return String::equalNoCase(x, y);
 63                      }
 64                  };
 65                  
 66                  ////////////////////////////////////////////////////////////////////////////////
 67                  //
 68 schuur      1.25 // InheritanceTreeRep
 69                  //
 70                  ////////////////////////////////////////////////////////////////////////////////
 71                  
 72 marek       1.26 struct InheritanceTreeNode;
 73 schuur      1.25 
 74                  struct InheritanceTreeRep
 75                  {
 76 mike        1.32     typedef HashTable<
 77 kumpf       1.37         String, InheritanceTreeNode*, NoCaseEqualFunc, HashLowerCaseFunc> Table;
 78 schuur      1.25     Table table;
 79 mike        1.32 
 80                      // Tradeoff: chosing a larger value decreases hash lookup time but
 81                      // increases iteration (which seems to be the dominant operations).
 82                      // This power of two (256) seems to produce the best results.
 83                  
 84                      InheritanceTreeRep() : table(256)
 85                      {
 86                      }
 87 schuur      1.25 };
 88                  
 89                  ////////////////////////////////////////////////////////////////////////////////
 90                  //
 91 mike        1.16 // InheritanceTreeNode
 92                  //
 93                  ////////////////////////////////////////////////////////////////////////////////
 94                  
 95 schuur      1.25 class NameSpace;
 96                  
 97                  struct InheritanceTreeExt
 98                  {
 99                      InheritanceTreeExt(NameSpace* t, InheritanceTreeNode* itn)
100                         : tag(t), node(itn) {}
101                      NameSpace* tag;
102                      InheritanceTreeNode* node;
103                  };
104                  
105                  
106 mike        1.16 struct InheritanceTreeNode
107                  {
108 kumpf       1.22     InheritanceTreeNode(const CIMName& className);
109 venkat.puvvada 1.39     ~InheritanceTreeNode();
110 mike           1.16 
111                         void addSubClass(InheritanceTreeNode* subClass);
112                     
113                         Boolean removeSubClass(InheritanceTreeNode* subClass);
114                     
115                         void getSubClassNames(
116 kumpf          1.37         Array<CIMName>& subClassNames,
117                             Boolean deepInheritance,
118                             NameSpace* tag = 0);
119 mike           1.16 
120 kumpf          1.22     void getSuperClassNames(Array<CIMName>& superClassNames);
121 mike           1.16 
122                         void print(PEGASUS_STD(ostream)& os) const;
123 schuur         1.25 #if 0
124 kumpf          1.22     Boolean isSubClass(const CIMName& className) const;
125 schuur         1.25 #endif
126 kumpf          1.22     CIMName className;
127 mike           1.16     InheritanceTreeNode* superClass;
128                         InheritanceTreeNode* sibling;
129 schuur         1.25     union {
130 mike           1.16     InheritanceTreeNode* subClasses;
131 schuur         1.25        Array<InheritanceTreeExt*>* extNodes;
132                         };
133 mike           1.16     Boolean provisional;
134 schuur         1.25     Boolean extension;
135 mike           1.16 };
136                     
137 kumpf          1.37 InheritanceTreeNode::InheritanceTreeNode(const CIMName& className)
138                         : className(className), superClass(0),
139 schuur         1.25     sibling(0), subClasses(0), provisional(true), extension(false)
140 mike           1.16 {
141                     }
142                     
143 venkat.puvvada 1.39 InheritanceTreeNode::~InheritanceTreeNode()
144                     {
145                         if (extension)
146                         {
147                             for(Uint32 i = 0, size = extNodes->size(); i < size; i++)
148                             {
149                                 delete (*extNodes)[i];
150                             }
151                             delete extNodes;
152                         }
153                     }
154                     
155 mike           1.16 void InheritanceTreeNode::addSubClass(InheritanceTreeNode* subClass)
156                     {
157                         subClass->superClass = this;
158                         subClass->sibling = subClasses;
159                         subClasses = subClass;
160                     }
161                     
162                     Boolean InheritanceTreeNode::removeSubClass(InheritanceTreeNode* subClass)
163                     {
164                         InheritanceTreeNode* prev = 0;
165                     
166                         for (InheritanceTreeNode* p = subClasses; p; p = p->sibling)
167                         {
168 kumpf          1.37         if (p == subClass)
169                             {
170                                 if (prev)
171                                     prev->sibling = subClass->sibling;
172                                 else
173                                     subClasses = subClass->sibling;
174                     
175                                 return true;
176                             }
177                             prev = p;
178 mike           1.16     }
179                     
180                         return false;
181                     }
182                     
183                     void InheritanceTreeNode::getSubClassNames(
184 schuur         1.25     Array<CIMName>& subClassNames,
185                         Boolean deepInheritance,
186 kumpf          1.37     NameSpace* ns)
187 mike           1.16 {
188                         // For each subClass:
189                     
190 kumpf          1.37     for (InheritanceTreeNode* p = subClasses; p; p = p->sibling)
191                         {
192                             if (p->extension)
193                             {
194                                 for (int j = 0, m = p->extNodes->size(); j < m; j++)
195                                 {
196                                     InheritanceTreeExt* itx = (*(p->extNodes))[j];
197                                     subClassNames.append(p->className);
198                                     if (!ns)
199                                     {
200                                         InheritanceTreeNode* itn=itx->node;
201                                         itn->getSubClassNames(subClassNames, deepInheritance, ns);
202                                     }
203                                     else if (itx->tag == ns)
204                                     {
205                                         InheritanceTreeNode* itn=itx->node;
206                                         itn->getSubClassNames(subClassNames, deepInheritance, ns);
207                                         break;
208                                     }
209                                 }
210                             }
211 kumpf          1.37         else
212                             {
213                                 subClassNames.append(p->className);
214                                 if (deepInheritance)
215                                 {
216                                     p->getSubClassNames(subClassNames, true, ns);
217                                 }
218                             }
219 mike           1.16     }
220                     }
221                     
222 schuur         1.25 #if 0
223 kumpf          1.22 Boolean InheritanceTreeNode::isSubClass(const CIMName& className_) const
224 mike           1.16 {
225 kumpf          1.22     if (className.equal (className_))
226 kumpf          1.37         return true;
227 mike           1.16 
228                         for (InheritanceTreeNode* p = subClasses; p; p = p->sibling)
229                         {
230 kumpf          1.37         if (p->className.equal (className_))
231                                 return true;
232 mike           1.16     }
233                     
234                         return false;
235                     }
236 schuur         1.25 #endif
237 mike           1.16 
238 kumpf          1.22 void InheritanceTreeNode::getSuperClassNames(Array<CIMName>& superClassNames)
239 mike           1.16 {
240                         // For each superClass:
241                     
242                         for (InheritanceTreeNode* p = superClass; p; p = p->superClass)
243                         {
244 kumpf          1.37         superClassNames.append(p->className);
245                             // p->getSuperClassNames(superClassNames);
246 mike           1.16     }
247                     }
248                     
249                     void InheritanceTreeNode::print(PEGASUS_STD(ostream)& os) const
250                     {
251 kumpf          1.40     os << className.getString() << " : " ;
252                         os << (superClass ? superClass->className : CIMName()).getString();
253 mike           1.16 
254                         os << " { ";
255                     
256                         for (InheritanceTreeNode* p = subClasses; p; p = p->sibling)
257 kumpf          1.40         os << p->className.getString() << ' ';
258 mike           1.16 
259                         os << "}" << endl;
260                     }
261                     
262                     ////////////////////////////////////////////////////////////////////////////////
263                     //
264                     // InheritanceTree
265                     //
266                     ////////////////////////////////////////////////////////////////////////////////
267                     
268                     InheritanceTree::InheritanceTree()
269                     {
270                         _rep = new InheritanceTreeRep;
271                     }
272                     
273                     InheritanceTree::~InheritanceTree()
274                     {
275 sage           1.18     for (InheritanceTreeRep::Table::Iterator i = _rep->table.start(); i; i++)
276                             delete i.value();
277                     
278 mike           1.16     delete _rep;
279                     }
280 schuur         1.25 void InheritanceTree::insert(
281                         const String& className,
282                         const String& superClassName,
283                         InheritanceTree& parentTree,
284 kumpf          1.37     NameSpace* tag)
285 schuur         1.25 {
286                         InheritanceTreeNode* superClassNode = 0;
287                     
288 kumpf          1.37     if (superClassName.size() &&
289                             !parentTree._rep->table.lookup(superClassName, superClassNode))
290                         {
291                             superClassNode =
292                                 new InheritanceTreeNode(CIMNameUnchecked(superClassName));
293                             parentTree._rep->table.insert(superClassName, superClassNode);
294 schuur         1.25     }
295                     
296                         InheritanceTreeNode* extNode = 0;
297                     
298 kumpf          1.37     if (!parentTree._rep->table.lookup(className, extNode))
299                         {
300                             extNode = new InheritanceTreeNode(CIMNameUnchecked(className));
301                             parentTree._rep->table.insert(className, extNode);
302                             extNode->extension=true;
303                             extNode->extNodes=new Array<InheritanceTreeExt*>;
304 schuur         1.25     }
305                     
306                         extNode->provisional = false;
307                     
308                         if (superClassNode)
309 kumpf          1.37         superClassNode->addSubClass(extNode);
310 schuur         1.25 
311                         InheritanceTreeNode* classNode = 0;
312                     
313 kumpf          1.37     if (!_rep->table.lookup(className, classNode))
314                         {
315                             classNode = new InheritanceTreeNode(className);
316                             _rep->table.insert(className, classNode);
317 schuur         1.25     }
318                     
319                         extNode->extNodes->append(new InheritanceTreeExt(tag,classNode));
320                     
321                         classNode->superClass = superClassNode;
322                     }
323 mike           1.16 
324                     void InheritanceTree::insert(
325 kumpf          1.37     const String& className,
326 mike           1.16     const String& superClassName)
327                     {
328                         // ATTN: need found flag!
329                     
330                         // -- Insert superclass:
331                     
332                         InheritanceTreeNode* superClassNode = 0;
333                     
334 kumpf          1.37     if (superClassName.size() &&
335                             !_rep->table.lookup(superClassName, superClassNode))
336 mike           1.16     {
337 kumpf          1.37         superClassNode =
338                                 new InheritanceTreeNode(CIMNameUnchecked(superClassName));
339                             _rep->table.insert(superClassName, superClassNode);
340 mike           1.16     }
341                     
342                         // -- Insert class:
343 kumpf          1.37 
344 mike           1.16     InheritanceTreeNode* classNode = 0;
345                     
346                         if (!_rep->table.lookup(className, classNode))
347                         {
348 kumpf          1.37         classNode = new InheritanceTreeNode(CIMNameUnchecked(className));
349                             _rep->table.insert(className, classNode);
350 mike           1.16     }
351                     
352                         classNode->provisional = false;
353                     
354                         // -- Link the class and superclass nodes:
355                     
356                         if (superClassNode)
357 kumpf          1.37         superClassNode->addSubClass(classNode);
358 mike           1.16 }
359                     
360 schuur         1.25 void InheritanceTree::insertFromPath(const String& path,
361                           InheritanceTree* parentTree,
362 kumpf          1.37       NameSpace* ns)
363 mike           1.16 {
364                         for (Dir dir(path); dir.more(); dir.next())
365                         {
366 kumpf          1.37         String fileName = dir.getName();
367 mike           1.16 
368 kumpf          1.37         // Ignore the current and parent directories.
369 mike           1.16 
370 kumpf          1.37         if (fileName == "." || fileName == "..")
371                                 continue;
372 mike           1.16 
373 kumpf          1.37         Uint32 dot = fileName.find('.');
374 mike           1.16 
375 kumpf          1.37         // Ignore files without dots in them:
376 mike           1.16 
377 kumpf          1.37         if (dot == PEG_NOT_FOUND)
378                                 continue;
379 mike           1.16 
380 kumpf          1.37         String className = fileName.subString(0, dot);
381                             String superClassName = fileName.subString(dot + 1);
382 mike           1.16 
383 kumpf          1.37         if (superClassName == "#")
384                                 superClassName.clear();
385 mike           1.16 
386 bafna.mukesh   1.28 
387 chuck          1.24 #ifdef PEGASUS_REPOSITORY_ESCAPE_UTF8
388 kumpf          1.37         if (ns)
389                                 insert(
390                                     escapeStringDecoder(className),
391                                     escapeStringDecoder(superClassName),
392                                     *parentTree, ns);
393                             else
394                                 insert(
395                                     escapeStringDecoder(className),
396                                     escapeStringDecoder(superClassName));
397 chuck          1.24 #else
398 kumpf          1.37         if (ns)
399                                 insert(className, superClassName, *parentTree, ns);
400                             else
401                                 insert(className, superClassName);
402 chuck          1.24 #endif
403 mike           1.16     }
404                     }
405                     
406                     void InheritanceTree::check() const
407                     {
408                         for (InheritanceTreeRep::Table::Iterator i = _rep->table.start(); i; i++)
409                         {
410 kumpf          1.37         if (i.value()->provisional)
411                                 throw InvalidInheritanceTree(i.value()->className.getString());
412 mike           1.16     }
413                     }
414                     
415                     Boolean InheritanceTree::getSubClassNames(
416 kumpf          1.22     const CIMName& className,
417 mike           1.16     Boolean deepInheritance,
418 schuur         1.25     Array<CIMName>& subClassNames,
419 kumpf          1.37     NameSpace* ns) const
420 mike           1.16 {
421 kumpf          1.37     // -- Case 1: className is empty: get all class names (if deepInheritance)
422                         // -- or just root class names (if not deepInheritance).
423 mike           1.16 
424 kumpf          1.37     if (className.isNull())
425                         {
426                             for (InheritanceTreeRep::Table::Iterator i = _rep->table.start();i;i++)
427                             {
428                                 InheritanceTreeNode* itn=i.value();
429                                 if (itn->extension)
430                                 {
431                                     if (!ns)
432                                         continue;
433                                     for (int j=0,m=itn->extNodes->size(); j<m; j++)
434                                     {
435                                         InheritanceTreeExt* itx=(*(itn->extNodes))[j];
436                                         if (itx->tag==ns)
437                                         {
438                                             InheritanceTreeNode* itn=itx->node;
439                                             if (deepInheritance)
440                                             {
441                                                 subClassNames.append(CIMNameUnchecked(i.key()));
442                                                 itn->getSubClassNames(
443                                                     subClassNames, deepInheritance, ns);
444                                             }
445 kumpf          1.37                         else if (!i.value()->superClass)
446                                                 subClassNames.append(CIMNameUnchecked(i.key()));
447                                             break;
448                                         }
449                                     }
450                                 }
451                                 else if (deepInheritance)
452                                 {
453                                     // Append all classes:
454                                     subClassNames.append(CIMNameUnchecked(i.key()));
455                                 }
456                                 else if (!i.value()->superClass)
457                                 {
458                                     // Just append root classes:
459                                     subClassNames.append(CIMNameUnchecked(i.key()));
460                                 }
461                             }
462                             return true;
463                         }
464 schuur         1.25 
465 kumpf          1.37     // -- Case 2: className non-empty: get names of classes descendent from
466                         // -- the given class.
467 schuur         1.25 
468 kumpf          1.37     for (InheritanceTreeRep::Table::Iterator i = _rep->table.start(); i; i++)
469                         {
470                             if (className.equal (CIMNameUnchecked(i.key())))
471                             {
472                                 i.value()->getSubClassNames(subClassNames, deepInheritance, ns);
473                                 return true;
474                             }
475                         }
476 schuur         1.25 
477 kumpf          1.37     // Not found!
478                         return false;
479 mike           1.16 }
480 kumpf          1.37 
481 schuur         1.25 #if 0
482 mike           1.17 Boolean InheritanceTree::isSubClass(
483 kumpf          1.37     const CIMName& class1,
484 kumpf          1.22     const CIMName& class2) const
485 mike           1.16 {
486 kumpf          1.37     InheritanceTreeNode* node = 0;
487 mike           1.16 
488 kumpf          1.22     if (!_rep->table.lookup(class1.getString(), node))
489 kumpf          1.37         return false;
490 mike           1.16 
491 kumpf          1.22     return node->isSubClass(class2.getString());
492 mike           1.16 }
493 schuur         1.25 #endif
494 mike           1.16 
495                     Boolean InheritanceTree::getSuperClassNames(
496 kumpf          1.22     const CIMName& className,
497                         Array<CIMName>& superClassNames) const
498 mike           1.16 {
499                         InheritanceTreeNode* classNode;
500                     
501 kumpf          1.22     if (_rep->table.lookup(className.getString(), classNode))
502 mike           1.16     {
503 kumpf          1.37         classNode->getSuperClassNames(superClassNames);
504                             return true;
505 mike           1.16     }
506                     
507                         return false;
508                     }
509                     
510                     Boolean InheritanceTree::getSuperClass(
511 kumpf          1.22     const CIMName& className,
512                         CIMName& superClassName) const
513 mike           1.16 {
514                         InheritanceTreeNode* classNode;
515                     
516 kumpf          1.22     if (_rep->table.lookup(className.getString(), classNode))
517 mike           1.16     {
518 kumpf          1.37         if (classNode->superClass)
519                             {
520                                 superClassName = classNode->superClass->className;
521                             }
522                             else
523                             {
524                                 superClassName.clear();
525                             }
526 mike           1.16 
527 kumpf          1.37         return true;
528 mike           1.16     }
529                     
530                         return false;
531                     }
532                     
533                     Boolean InheritanceTree::hasSubClasses(
534 kumpf          1.22     const CIMName& className,
535 mike           1.16     Boolean& hasSubClasses) const
536                     {
537 kumpf          1.37     InheritanceTreeNode* node = 0;
538 mike           1.16 
539 kumpf          1.22     if (!_rep->table.lookup(className.getString(), node))
540 kumpf          1.37         return false;
541 mike           1.16 
542                         hasSubClasses = node->subClasses != 0;
543                         return true;
544                     }
545                     
546 kumpf          1.22 Boolean InheritanceTree::containsClass(const CIMName& className) const
547 mike           1.16 {
548 kumpf          1.22     return _rep->table.contains(className.getString());
549 mike           1.16 }
550                     
551 kumpf          1.37 void InheritanceTree::remove(
552                         const CIMName& className,
553                         InheritanceTree& parentTree,
554                         NameSpace* tag)
555 mike           1.16 {
556                         // -- Lookup the node:
557                     
558 kumpf          1.37     InheritanceTreeNode* node = 0;
559 mike           1.16 
560 kumpf          1.22     if (!_rep->table.lookup(className.getString(), node))
561 kumpf          1.37         throw PEGASUS_CIM_EXCEPTION(
562                                 CIM_ERR_INVALID_CLASS, className.getString());
563 mike           1.16 
564                         // -- Disallow if is has any subclasses:
565                     
566                         if (node->subClasses)
567 kumpf          1.37         throw PEGASUS_CIM_EXCEPTION(
568                                 CIM_ERR_CLASS_HAS_CHILDREN, className.getString());
569 mike           1.16 
570                         // -- Remove as child of superclass:
571                     
572                         InheritanceTreeNode* superClass = node->superClass;
573                     
574 kumpf          1.37     if (tag)
575                         {
576                             InheritanceTreeNode* itn = 0;
577                             if (parentTree._rep->table.lookup(className.getString(), itn))
578                             {
579                                 if (itn->extension)
580                                 {
581                                     for (int j = 0, m = itn->extNodes->size(); j < m; j++)
582                                     {
583                                         if ((*(itn->extNodes))[j]->tag == tag)
584                                         {
585                                             itn->extNodes->remove(j);
586                                             break;
587                                         }
588                                     }
589                                     if (itn->extNodes->size() == 0)
590                                     {
591                                         delete itn->extNodes;
592                                         parentTree._rep->table.remove(className.getString());
593 schuur         1.25                 }
594 kumpf          1.37             }
595                             }
596                             else
597                             {
598                                 Boolean result = superClass->removeSubClass(node);
599                                 PEGASUS_ASSERT(result);
600                             }
601 schuur         1.25     }
602                         else if (superClass)
603 mike           1.16     {
604 kumpf          1.37         Boolean result = superClass->removeSubClass(node);
605                             PEGASUS_ASSERT(result);
606 mike           1.16     }
607                     
608 schuur         1.25 
609 mike           1.16     // -- Remove from the hash table and delete:
610                     
611 kumpf          1.22     Boolean result = _rep->table.remove(className.getString());
612 mike           1.16     PEGASUS_ASSERT(result);
613                         delete node;
614                     }
615                     
616                     void InheritanceTree::print(PEGASUS_STD(ostream)& os) const
617                     {
618                         for (InheritanceTreeRep::Table::Iterator i = _rep->table.start(); i; i++)
619 kumpf          1.37         i.value()->print(os);
620 mike           1.16 }
621                     
622                     PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2