(file) Return to provreg.c CVS log (file) (dir) Up to [OMI] / omi / provreg

  1 mike  1.1 /*
  2           **==============================================================================
  3           **
  4           ** Open Management Infrastructure (OMI)
  5           **
  6           ** Copyright (c) Microsoft Corporation
  7           ** 
  8           ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
  9           ** use this file except in compliance with the License. You may obtain a copy 
 10           ** of the License at 
 11           **
 12           **     http://www.apache.org/licenses/LICENSE-2.0 
 13           **
 14           ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15           ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
 16           ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
 17           ** MERCHANTABLITY OR NON-INFRINGEMENT. 
 18           **
 19           ** See the Apache 2 License for the specific language governing permissions 
 20           ** and limitations under the License.
 21           **
 22 mike  1.1 **==============================================================================
 23           */
 24           
 25           #include <stdio.h>
 26           #include <ctype.h>
 27           #include <base/strings.h>
 28           #include <base/io.h>
 29           #include <base/dir.h>
 30           #include <base/paths.h>
 31           #include "provreg.h"
 32           #include "regfile.h"
 33           
 34           typedef struct _ProvRegNamespaceNode
 35           {
 36               struct _ProvRegNamespaceNode* next;
 37               MI_ConstString  ns;
 38               struct _ProvRegClassInheritanceNode* tree;
 39           }
 40           ProvRegNamespaceNode;
 41           
 42           typedef struct _ProvRegAssocBackLinkNode
 43 mike  1.1 {
 44               struct _ProvRegAssocBackLinkNode* next;
 45               struct _ProvRegClassInheritanceNode* assocClass;
 46           }
 47           ProvRegAssocBackLinkNode;
 48           
 49           typedef struct _ProvRegClassInheritanceNode
 50           {
 51               MI_ConstString  cn;
 52               struct _ProvRegClassInheritanceNode* parent;
 53               struct _ProvRegClassInheritanceNode* nextSibling;
 54               struct _ProvRegClassInheritanceNode* firstChild;
 55               /* assoc support */
 56               /* left/right are not-null only for assoc class */
 57               struct _ProvRegClassInheritanceNode* left;
 58               struct _ProvRegClassInheritanceNode* right;
 59           
 60               /* linked list of all assoc classes that refer this class */
 61               ProvRegAssocBackLinkNode* associatorClasses;
 62           }
 63           ProvRegClassInheritanceNode;
 64 mike  1.1 
 65           #if (MI_CHAR_TYPE == 1)
 66           #define MI_ScasecmpChar_MIChar Zcasecmp
 67           #else
 68           static int MI_ScasecmpChar_MIChar(
 69               const char* str1,
 70               const MI_Char* str2 )
 71           {
 72               /* assuming str2 is ascii char-set only */
 73               for(;;)
 74               {
 75                   int c1 = tolower((unsigned char)*str1);
 76                   int c2 = tolower((unsigned char)*str2);
 77           
 78                   if (c1 != c2 )
 79                   {
 80                       return c1 < c2 ? -1 : 1;
 81                   }
 82                   if (!c1)
 83                       break;
 84           
 85 mike  1.1         str1++;
 86                   str2++;
 87               }
 88           
 89               return 0;
 90           }
 91           #endif
 92           
 93           /* returns last segment from the string or string itself; 
 94               for example, for string abc,edf,ghk  function returns 'ghk', 'edf' and 'abc' */
 95           static char* _GetNextReverse(char** text, char delim)
 96           {
 97               char* start = *text;
 98               char* end;
 99               size_t len;
100           
101               /* If at end of string */
102               if (!*start)
103                   return NULL;
104           
105               len = strlen(start);
106 mike  1.1 
107               /* end of string */
108               end = start + len;
109           
110               /* Remove trailing whitespace */
111               for (; end != start && isspace((unsigned char)end[-1]);)
112                   *--end = '\0';
113           
114               /* Skip non-colon character characters */
115               for (; end != start && *end != delim; end--)
116                   ;
117           
118               if ( end == start )
119               {   /* last block - move position to the end to point to \0 */
120                   *text = start + len;
121               }
122               else
123               {  /* skip delimiter*/
124                   *end = 0;
125                   end++;
126               }
127 mike  1.1 
128               /* Skip leading whitespace */
129               while (*end && isspace((unsigned char)*end))
130                   end++;
131           
132               return end;
133           }
134           
135           static char* _Strdup(Batch* batch, const char* s)
136           {
137               size_t size = strlen(s) + 1;
138               char* p;
139               size_t i;
140           
141               p = Batch_Get(batch, size * sizeof(char));
142           
143               if (!p)
144                   return NULL;
145           
146               for (i = 0; i < size; i++)
147                   p[i] = s[i];
148 mike  1.1 
149               return p;
150           }
151           
152           static MI_Char* _Strdup2(Batch* batch, const char* s)
153           {
154               size_t size = strlen(s) + 1;
155               MI_Char* p;
156               size_t i;
157           
158               p = Batch_Get(batch, size * sizeof(MI_Char));
159           
160               if (!p)
161                   return NULL;
162           
163               for (i = 0; i < size; i++)
164                   p[i] = (MI_Char)s[i];
165           
166               return p;
167           }
168           
169 mike  1.1 /* ********************************************************* */
170           /* ***           namespace operations                    *** */
171           /* ********************************************************* */
172           
173           ProvRegNamespaceNode* _FindNamespace(
174               ProvReg* self,
175               MI_ConstString ns)
176           {
177               /* find namespace node in the list */
178               ProvRegNamespaceNode* current = self->namespaces;
179           
180               while (current && Zcasecmp(ns,current->ns) != 0)
181                   current = current->next;
182           
183               return current;
184           }
185           
186           ProvRegNamespaceNode* _FindOrCreateNamespace(
187               ProvReg* self,
188               MI_ConstString ns)
189           {
190 mike  1.1     ProvRegNamespaceNode* item = _FindNamespace(self,ns);
191           
192               if (item)
193                   return item;
194           
195               item = (ProvRegNamespaceNode*)Batch_GetClear(
196                   &self->batch, sizeof(ProvRegNamespaceNode));
197           
198               if (item)
199               {
200                   item->ns = ns; /* no need to strdup, since it's already in batch*/
201                   item->next = self->namespaces;
202                   self->namespaces = item;
203               }
204           
205               return item;
206           }
207           
208           /* ********************************************************* */
209           /* ***                tree operations                    *** */
210           /* ********************************************************* */
211 mike  1.1 ProvRegClassInheritanceNode* _GetNextTreeNodeLimittedBy(
212               ProvRegClassInheritanceNode* item,
213               ProvRegClassInheritanceNode* subtreeRoot)
214           {
215               /* first-child */
216               if (item->firstChild)
217                   return item->firstChild;
218           
219               /* sibling */
220               if (item->nextSibling)
221                   return item->nextSibling;
222           
223               /* sibling of direct or indirect parent*/
224               while (item && item->parent != subtreeRoot)
225               {
226                   item = item->parent;
227           
228                   if (item->nextSibling)
229                       return item->nextSibling;
230               }
231           
232 mike  1.1     /* end of tree */
233               return 0;
234           }
235           
236           ProvRegClassInheritanceNode* _GetNextTreeNode(
237               ProvRegClassInheritanceNode* item)
238           {
239               return _GetNextTreeNodeLimittedBy(item,0);
240           }
241           
242           ProvRegClassInheritanceNode* _FindClassNodeInTreeByChar(
243               ProvRegClassInheritanceNode* root,
244               const char* cn)
245           {
246               while (root)
247               {
248                   if (MI_ScasecmpChar_MIChar(cn,root->cn)==0)
249                   {
250                       return root;
251                   }
252                   root = _GetNextTreeNode(root);
253 mike  1.1     }
254               return root;
255           }
256           
257           ProvRegClassInheritanceNode* _FindClassNodeInTree(
258               ProvRegClassInheritanceNode* root,
259               const MI_Char* cn)
260           {
261               while (root)
262               {
263                   if (Zcasecmp(cn,root->cn)==0)
264                   {
265                       return root;
266                   }
267                   root = _GetNextTreeNode(root);
268               }
269               return root;
270           }
271           
272           MI_Boolean _ValidateTreeNodes(
273               ProvRegClassInheritanceNode* derivedNode,
274 mike  1.1     ProvRegClassInheritanceNode* baseNode)
275           {
276               /* if we have no nodes - it's fine - no info yet*/
277               if ( !derivedNode && !baseNode )
278                   return MI_TRUE;
279           
280               /* if we have both nodes - check they are child/parent */
281               if ( derivedNode && baseNode )
282                   return derivedNode->parent == baseNode;
283           
284               /* base must be specified */
285               if ( derivedNode && !baseNode )
286                   return MI_FALSE;
287           
288               /* only one node is known - ok */
289               return MI_TRUE;
290           }
291           
292           static MI_Result _AddClassInheritanceInfo( 
293               ProvReg* self,
294               MI_ConstString ns,
295 mike  1.1     const char* derivedClass, /* can be null */
296               const char* baseClass )
297           {
298               /* get (or create if needed) namespace item */
299               ProvRegNamespaceNode* namespaceNode = _FindOrCreateNamespace(self,ns);
300               ProvRegClassInheritanceNode* derivedNode, *baseNode;
301           
302               if (!namespaceNode)
303                   return MI_RESULT_FAILED;
304           
305               /* find classes' nodes */
306               derivedNode = derivedClass ? _FindClassNodeInTreeByChar(namespaceNode->tree, derivedClass) : 0;
307               baseNode = _FindClassNodeInTreeByChar(namespaceNode->tree, baseClass);
308           
309               /* validate nodes */
310               if (!_ValidateTreeNodes(derivedNode,baseNode))
311                   return MI_RESULT_INVALID_CLASS_HIERARCHY;
312           
313               /* create missing nodes and insert them into tree */
314               if ( !baseNode )
315               {
316 mike  1.1         baseNode = (ProvRegClassInheritanceNode*)Batch_GetClear(
317                           &self->batch, sizeof(ProvRegClassInheritanceNode));
318           
319                   if ( !baseNode )
320                       return MI_RESULT_FAILED;
321           
322                   baseNode->cn = _Strdup2(&self->batch, baseClass);
323           
324                   if ( !baseNode->cn )
325                       return MI_RESULT_FAILED;
326           
327                   /* insert into tree */
328                   baseNode->nextSibling = namespaceNode->tree;
329                   namespaceNode->tree = baseNode;
330               }
331           
332               if ( !derivedNode && derivedClass)
333               {
334                   derivedNode = (ProvRegClassInheritanceNode*)Batch_GetClear(
335                           &self->batch, sizeof(ProvRegClassInheritanceNode));
336           
337 mike  1.1         if ( !derivedNode )
338                       return MI_RESULT_FAILED;
339           
340                   derivedNode->cn = _Strdup2(&self->batch, derivedClass);
341           
342                   if ( !derivedNode->cn )
343                       return MI_RESULT_FAILED;
344           
345                   /* add as a child */
346                   derivedNode->parent = baseNode;
347                   derivedNode->nextSibling = baseNode->firstChild;
348                   baseNode->firstChild = derivedNode;
349               }
350           
351               return MI_RESULT_OK;
352           }
353           
354           static MI_Result _AddAssociation( 
355               ProvReg* self,
356               MI_ConstString ns,
357               const char* assoc, 
358 mike  1.1     const char* left,
359               const char* right)
360           {
361               /* find all related nodes */
362               ProvRegNamespaceNode* namespaceNode;
363               ProvRegClassInheritanceNode  *leftNode, *rightNode, *assocNode;
364           
365               /* check namespace */
366               namespaceNode = _FindNamespace(self,ns);
367           
368               if (!namespaceNode)
369                   return MI_RESULT_INVALID_NAMESPACE;
370           
371               /* find class */
372               leftNode = _FindClassNodeInTreeByChar(namespaceNode->tree, left);
373               rightNode = _FindClassNodeInTreeByChar(namespaceNode->tree, right);
374               assocNode = _FindClassNodeInTreeByChar(namespaceNode->tree, assoc);
375           
376               if (!leftNode || !rightNode || !assocNode)
377                   return MI_RESULT_INVALID_CLASS;
378           
379 mike  1.1     /* add cross-links */
380               assocNode->left = leftNode;
381               assocNode->right = rightNode;
382           
383               {
384                   ProvRegAssocBackLinkNode* newLinkItemLeft;
385                   newLinkItemLeft = (ProvRegAssocBackLinkNode*)Batch_GetClear(
386                       &self->batch, sizeof(ProvRegAssocBackLinkNode));
387           
388                   if (!newLinkItemLeft)
389                       return MI_RESULT_FAILED;
390           
391                   newLinkItemLeft->assocClass = assocNode;
392                   newLinkItemLeft->next = leftNode->associatorClasses;
393                   leftNode->associatorClasses = newLinkItemLeft;
394               }
395           
396               /* check if assoc links different classes */
397               if (leftNode != rightNode)
398               {
399                   ProvRegAssocBackLinkNode* newLinkItemRight;
400 mike  1.1         newLinkItemRight = (ProvRegAssocBackLinkNode*)Batch_GetClear(
401                       &self->batch, sizeof(ProvRegAssocBackLinkNode));
402                   if (!newLinkItemRight)
403                       return MI_RESULT_FAILED;
404           
405                   newLinkItemRight->assocClass = assocNode;
406                   newLinkItemRight->next = rightNode->associatorClasses;
407                   rightNode->associatorClasses = newLinkItemRight;
408               }
409           
410               return MI_RESULT_OK;
411           }
412           
413           static MI_Result _GetSubclasses2(
414               ProvReg* self,
415               ProvRegEntry* e,
416               char* p)
417           {
418               /* get all sub-classes */
419               char* baseClass = _GetNextReverse(&p, ':');
420               char* derivedClass = _GetNextReverse(&p, ':');
421 mike  1.1     MI_Result r;
422           
423               /* expecting to find at least one class */
424               if (!baseClass)
425                   return MI_RESULT_INVALID_CLASS;
426           
427               while ( derivedClass )
428               {
429                   r = _AddClassInheritanceInfo(self, e->nameSpace, derivedClass, 
430                       baseClass);
431           
432                   if ( MI_RESULT_OK != r )
433                       return r;
434           
435                   baseClass = derivedClass;
436                   derivedClass = _GetNextReverse(&p, ':');
437               }
438           
439               /* add base class with no parent */
440               r = _AddClassInheritanceInfo(self, e->nameSpace, derivedClass, baseClass);
441               if (MI_RESULT_OK != r)
442 mike  1.1         return r;
443           
444               e->className = _Strdup2(&self->batch, baseClass);
445               if (!e->className)
446               {
447                   return MI_RESULT_FAILED;
448               }
449           
450               return MI_RESULT_OK;
451           }
452           
453           static int _AddEntry(
454               ProvReg* self,
455               const char* nameSpace,
456               RegFile* regFile,
457               RegClass* regClass)
458           {
459               ProvRegEntry* e;
460           
461           #if 0
462               RegFile_Print(regFile, stdout);
463 mike  1.1 #endif
464           
465               /* Allocate new provider register entry */
466               e = (ProvRegEntry*)Batch_GetClear(&self->batch, sizeof(ProvRegEntry));
467               if (!e)
468                   return -1;
469           
470               /* ProvRegEntry.provInterface */
471               e->provInterface = PROV_INTERFACE_STATIK;
472           
473               /* ProvRegEntry.nameSpace */
474               e->nameSpace = _Strdup2(&self->batch, nameSpace);
475           
476               /* ProvRegEntry.libraryName */
477               e->libraryName = _Strdup(&self->batch, regFile->library);
478           
479               /* ProvRegEntry.hosting*/
480               e->hosting = PROV_HOSTING_INPROC;
481           
482               if (regClass->hosting)
483               {
484 mike  1.1         char hosting[64];
485                   Strlcpy(hosting, regClass->hosting, sizeof(hosting));
486           
487                   /* it either user name or one of two special values: 
488                    *  @inproc@
489                    *  @requestor@ 
490                    */
491                   if (strcmp(hosting, PROV_REG_HOSTING_INPROC) == 0)
492                   {
493                       e->hosting = PROV_HOSTING_INPROC;
494                   }
495                   else if (strcmp(hosting, PROV_REG_HOSTING_REQUESTOR) == 0)
496                   {
497                       e->hosting = PROV_HOSTING_REQUESTOR;
498                   }
499                   else
500                   {
501                       e->hosting = PROV_HOSTING_USER;
502                       e->user =  _Strdup(&self->batch, hosting);
503                       if (!e->user)
504                           return -1;
505 mike  1.1         }
506               }
507           
508               /* If an association */
509               if (regClass->refName1 && regClass->refName2)
510               {
511                   if (_GetSubclasses2(self, e, regClass->refName1) != MI_RESULT_OK)
512                       return -1;
513           
514                   if (_GetSubclasses2(self, e, regClass->refName2) != MI_RESULT_OK)
515                       return -1;
516           
517                   if (_GetSubclasses2(self, e, regClass->name) != MI_RESULT_OK)
518                       return -1;
519           
520                   if (_AddAssociation(self, e->nameSpace, regClass->name,
521                       regClass->refName1, regClass->refName2) != MI_RESULT_OK)
522                   {
523                       return -1;
524                   }
525               }
526 mike  1.1     else
527               {
528                   if (_GetSubclasses2(self, e, regClass->name) != MI_RESULT_OK)
529                       return -1;
530               }
531           
532               /* Add entry to end of list */
533               {
534                   e->next = NULL;
535           
536                   if (self->tail)
537                   {
538                       self->tail->next = e;
539                       self->tail = e;
540                   }
541                   else
542                   {
543                       self->tail = e;
544                       self->head = e;
545                   }
546               }
547 mike  1.1 
548               return 0;
549           }
550           
551           MI_Result ProvReg_Init2(ProvReg* self)
552           {
553               Dir* dir = NULL;
554               Dir* dir2 = NULL;
555               RegFile* reg = NULL;
556               Batch* b = NULL;
557           
558               /* Zero-fill self */
559               memset(self, 0, sizeof(*self));
560           
561               /* Initialize batch allocator */
562               Batch_Init(&self->batch, BATCH_MAX_PAGES);
563               b = &self->batch;
564           
565               /* Open the 'omiregister' directory */
566               dir = Dir_Open(GetPath(ID_REGISTERDIR));
567               if (!dir)
568 mike  1.1         return MI_RESULT_FAILED;
569           
570               /* For each namespace directory in 'omirgister' */
571               for (;;)
572               {
573                   DirEnt* ent = Dir_Read(dir);
574                   if (!ent)
575                       break;
576           
577                   /* Ignore system directories */
578                   if (strcmp(ent->name, ".") == 0 || strcmp(ent->name, "..") == 0)
579                       continue;
580           
581                   /* Skip 'CVS' directories */
582                   if (strcmp(ent->name, "CVS") == 0)
583                       continue;
584           
585                   /* Scan .reg files in the current namespace directory */
586                   {
587                       char path[MAX_PATH_SIZE];
588           
589 mike  1.1             Strlcpy(path, GetPath(ID_REGISTERDIR), sizeof(path));
590                       Strlcat(path, "/", sizeof(path));
591                       Strlcat(path, ent->name, sizeof(path));
592           
593                       dir2 = Dir_Open(path);
594                       if (!dir2)
595                       {
596                           goto failed;
597                       }
598           
599                       for (;;)
600                       {
601                           DirEnt* ent2 = Dir_Read(dir2);
602                           if (!ent2)
603                               break;
604           
605                           /* Ignore system directories */
606                           if (strcmp(ent2->name,".") == 0 || strcmp(ent2->name,"..") == 0)
607                               continue;
608           
609                           /* Load the reg file */
610 mike  1.1                 {
611                               char regPath[MAX_PATH_SIZE];
612           
613                               /* Form path to .reg file */
614                               Strlcpy(regPath, path, sizeof(regPath));
615                               Strlcat(regPath, "/", sizeof(regPath));
616                               Strlcat(regPath, ent2->name, sizeof(regPath));
617           
618                               /* Create new reg file object */
619                               reg = RegFile_New(regPath);
620                               if (!reg)
621                               {
622                                   goto failed;
623                               }
624           
625                               /* For each class in the reg file */
626                               {
627                                   RegClass* rc;
628           
629                                   for (rc = reg->classesHead; rc; rc = rc->next)
630                                   {
631 mike  1.1                             char* p = ent->name;
632           
633                                       /* Transpose '#' characters to '/' characters */
634                                       while (*p)
635                                       {
636                                           if (*p == '#')
637                                               *p = '/';
638                                           p++;
639                                       }
640           
641                                       if (_AddEntry(self, ent->name, reg, rc) != 0)
642                                       {
643                                           goto failed;
644                                       }
645                                   }
646                               }
647           
648                               /* Delete the current entry */
649                               RegFile_Delete(reg);
650                               reg = NULL;
651                           }
652 mike  1.1             }
653           
654                       /* Close the directory */
655                       Dir_Close(dir2);
656                       dir2 = NULL;
657                   }
658               }
659           
660               /* Close directory */
661               Dir_Close(dir);
662           
663               return MI_RESULT_OK;
664           
665           failed:
666           
667               if (dir)
668                   Dir_Close(dir);
669           
670               if (dir2)
671                   Dir_Close(dir2);
672           
673 mike  1.1     return MI_RESULT_FAILED;
674           }
675           
676           void ProvReg_Destroy(
677               ProvReg* self)
678           {
679               Batch_Destroy(&self->batch);
680           }
681           
682           void ProvReg_Dump(
683               ProvReg* self,
684               FILE* os)
685           {
686               ProvRegEntry* p;
687           
688               for (p = self->head; p; p = p->next)
689               {
690                   fprintf(os, "==== ProvRegEntry\n");
691                   fprintf(os, "provInterface[%u]\n", p->provInterface);
692                   Fzprintf(os, MI_T("nameSpace[%s]\n"), p->nameSpace);
693                   Fzprintf(os, MI_T("className[%s]\n"), p->className);
694 mike  1.1         fprintf(os, "libraryName[%s]\n", p->libraryName);
695               }
696           }
697           
698           const ProvRegEntry* ProvReg_FindProviderForClass(
699               ProvReg* self,
700               const MI_Char* nameSpace,
701               const MI_Char* className)
702           {
703               ProvRegEntry* p;
704           
705               for (p = self->head; p; p = p->next)
706               {
707                   if (Zcasecmp(p->className, className) == 0 &&
708                       Zcasecmp(p->nameSpace, nameSpace) == 0)
709                       return p;
710               }
711           
712               /* Not found */
713               return NULL;
714           }
715 mike  1.1 
716           /* returns ok or not-found; baseClass will be null if no base class exist */
717           MI_Result ProvReg_GetDirectBaseClass(
718               ProvReg* self,
719               const MI_Char* nameSpace,
720               const MI_Char* className,
721               const MI_Char** baseClass)
722           {
723               ProvRegClassInheritanceNode* classNode;
724               ProvRegNamespaceNode* namespaceNode;
725           
726               /* clear out param */
727               *baseClass = 0;
728           
729               /* check namespace */
730               namespaceNode = _FindNamespace(self,nameSpace);
731           
732               if (!namespaceNode)
733                   return MI_RESULT_INVALID_NAMESPACE;
734           
735               /* find class */
736 mike  1.1     classNode = _FindClassNodeInTree(namespaceNode->tree, className);
737           
738               if (!classNode)
739                   return MI_RESULT_INVALID_CLASS;
740           
741               if (classNode->parent)
742               {
743                   *baseClass = classNode->parent->cn;
744               }
745           
746               return MI_RESULT_OK;
747           }
748           
749           /* enumerates classes derived classes:
750            - if deep == false and className == null, returns all root classes
751            - if deep == true and className == null, returns all classes
752            - if deep == false and className provided, returns all classes directly derived from given
753            - if deep == true and className provided, returns all classes derived from given
754           */
755           MI_Result ProvReg_BeginClasses(
756               ProvReg* self,
757 mike  1.1     const MI_Char* nameSpace,
758               const MI_Char* className,
759               MI_Boolean deep,
760               ProvRegPosition* pos)
761           {
762               ProvRegNamespaceNode* namespaceNode;
763           
764               /* clear pos */
765               memset( pos, 0, sizeof(*pos));
766               pos->deep = deep;
767           
768               /* check namespace */
769               namespaceNode = _FindNamespace(self,nameSpace);
770           
771               if (!namespaceNode)
772                   return MI_RESULT_INVALID_NAMESPACE;
773           
774               /* find class */
775               if (className)
776               {
777                   pos->start = _FindClassNodeInTree(namespaceNode->tree, className);
778 mike  1.1 
779                   if (!pos->start)
780                       return MI_RESULT_INVALID_CLASS;
781           
782                   pos->current = pos->start->firstChild;
783               }
784               else
785               {
786                   pos->start = 0;
787                   pos->current = namespaceNode->tree;
788               }
789           
790               return MI_RESULT_OK;
791           }
792           
793           MI_Result ProvReg_NextClass(
794               ProvRegPosition* pos,
795               const MI_Char** className,
796               MI_Boolean* done)
797           {
798               if (!pos->current)
799 mike  1.1     {
800                   *className = 0;
801           
802                   if (done)
803                       *done = MI_TRUE;
804           
805                   return MI_RESULT_OK;
806               }
807           
808               *className = pos->current->cn;
809           
810               if (pos->deep)
811               {
812                   pos->current = _GetNextTreeNodeLimittedBy(pos->current,pos->start);
813               }
814               else
815               {
816                   pos->current = pos->current->nextSibling;
817               }
818           
819               if (done)
820 mike  1.1         *done = MI_FALSE;
821           
822               return MI_RESULT_OK;
823           }
824           
825           MI_Result ProvReg_EndClasses(
826               ProvRegPosition* pos)
827           {
828               memset( pos, -1, sizeof(*pos));
829               return MI_RESULT_OK;
830           }
831           
832           
833           
834           /* returns enumerator to all registered association classes by given instance class
835             and (optionally) assoc/result classes */
836           MI_EXPORT MI_Result ProvReg_BeginAssocClasses(
837               ProvReg* self,
838               const MI_Char* nameSpace,
839               const MI_Char* className,
840               const MI_Char* assocClassName,  /* can be NULL */
841 mike  1.1     const MI_Char* resultClassName, /* can be NULL */
842               ProvRegAssocPosition* pos)
843           {
844               ProvRegNamespaceNode* namespaceNode;
845           
846               if (!nameSpace || !className || !pos)
847                   return MI_RESULT_INVALID_PARAMETER;
848           
849               /* clear pos */
850               memset( pos, 0, sizeof(*pos));
851           
852               /* check namespace */
853               namespaceNode = _FindNamespace(self,nameSpace);
854           
855               if (!namespaceNode)
856                   return MI_RESULT_INVALID_NAMESPACE;
857           
858               /* find class */
859               pos->currentLeft = _FindClassNodeInTree(namespaceNode->tree, className);
860           
861               if (!pos->currentLeft)
862 mike  1.1         return MI_RESULT_INVALID_CLASS;
863           
864               //pos->currentAssoc = pos->currentLeft->associatorClasses;
865           
866               /* validate optional parameters */
867               if (assocClassName)
868               {
869                   ProvRegClassInheritanceNode* assocClassNode = _FindClassNodeInTree(namespaceNode->tree, assocClassName);
870           
871                   if (!assocClassNode)
872                       return MI_RESULT_INVALID_CLASS;
873           
874                   /* store node pointer */
875                   pos->assocClass = assocClassNode;
876               }
877           
878               if (resultClassName)
879               {
880                   ProvRegClassInheritanceNode* resultClassNode = _FindClassNodeInTree(namespaceNode->tree, resultClassName);
881           
882                   if (!resultClassNode)
883 mike  1.1             return MI_RESULT_INVALID_CLASS;
884           
885                   /* store node pointer */
886                   pos->resultClass = resultClassNode;
887               }
888           
889               return MI_RESULT_OK;
890           }
891           
892           static MI_Boolean _GetNextAssoc(
893               ProvRegAssocPosition* pos)
894           {
895               /* check if we are at new node */
896               if (!pos->currentAssoc || !pos->currentLeft)
897               {
898                   /* find class with assoc link */
899                   while (pos->currentLeft && !pos->currentLeft->associatorClasses)
900                       pos->currentLeft = pos->currentLeft->parent;
901           
902                   if (!pos->currentLeft)
903                       return MI_FALSE;
904 mike  1.1 
905                   pos->currentAssoc = pos->currentLeft->associatorClasses;
906                   return MI_TRUE;
907               }
908           
909               pos->currentAssoc = pos->currentAssoc->next;
910           
911               if (pos->currentAssoc)
912                   return MI_TRUE;
913           
914               /* skip to parent */
915               pos->currentLeft = pos->currentLeft->parent;
916               return _GetNextAssoc(pos);
917           }
918           
919           static MI_Boolean _IsNodeOrParentOf(
920               ProvRegClassInheritanceNode* parent,
921               ProvRegClassInheritanceNode* node)
922           {
923               while (node)
924               {
925 mike  1.1         if (node == parent)
926                       return MI_TRUE;
927           
928                   node = node->parent;
929               }
930               return MI_FALSE;
931           }
932           
933           MI_EXPORT MI_Result ProvReg_NextAssocClass(
934               ProvRegAssocPosition* pos,
935               const MI_Char** className,
936               MI_Boolean* done)
937           {
938               /* navigate to next */
939               if (!pos->currentLeft)
940               {
941                   if (done)
942                       *done = MI_TRUE;
943 mike  1.2 
944 mike  1.1         return MI_RESULT_OK;
945               }
946           
947               while (_GetNextAssoc(pos))
948               {
949                   /* check filters */
950                   if ( (!pos->assocClass || _IsNodeOrParentOf(pos->assocClass, pos->currentAssoc->assocClass)) 
951                       && (!pos->resultClass || _IsNodeOrParentOf(pos->resultClass, 
952                           pos->currentAssoc->assocClass->left != pos->currentLeft ? pos->currentAssoc->assocClass->left : pos->currentAssoc->assocClass->right)
953                           || _IsNodeOrParentOf(
954                           pos->currentAssoc->assocClass->left != pos->currentLeft ? pos->currentAssoc->assocClass->left : pos->currentAssoc->assocClass->right,
955                           pos->resultClass)) )
956                   {
957                       *className = pos->currentAssoc->assocClass->cn;
958 mike  1.2 
959 mike  1.1             if (done)
960                           *done = MI_FALSE;
961 mike  1.2 
962 mike  1.1             return MI_RESULT_OK;
963                   }
964               }
965           
966               if (done)
967                   *done = MI_TRUE;
968 mike  1.2 
969 mike  1.1     return MI_RESULT_OK;
970           }
971           
972           MI_EXPORT MI_Result ProvReg_EndAssocClasses(
973               ProvRegAssocPosition* pos)
974           {
975               memset( pos, -1, sizeof(*pos));
976               return MI_RESULT_OK;
977           }
978           

ViewCVS 0.9.2