(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 krisbash 1.4 #include <pal/strings.h>
  28              #include <pal/format.h>
  29              #include <base/log.h>
  30 mike     1.1 #include <base/paths.h>
  31 krisbash 1.4 #include <base/naming.h>
  32 mike     1.1 #include "provreg.h"
  33              #include "regfile.h"
  34              
  35 krisbash 1.4 
  36 mike     1.1 typedef struct _ProvRegNamespaceNode
  37              {
  38                  struct _ProvRegNamespaceNode* next;
  39                  MI_ConstString  ns;
  40                  struct _ProvRegClassInheritanceNode* tree;
  41              }
  42              ProvRegNamespaceNode;
  43              
  44              typedef struct _ProvRegAssocBackLinkNode
  45              {
  46                  struct _ProvRegAssocBackLinkNode* next;
  47                  struct _ProvRegClassInheritanceNode* assocClass;
  48              }
  49              ProvRegAssocBackLinkNode;
  50              
  51              typedef struct _ProvRegClassInheritanceNode
  52              {
  53                  MI_ConstString  cn;
  54 krisbash 1.4     const char*  library;
  55                  ProvHosting hosting;
  56                  const char*     user;
  57 mike     1.1     struct _ProvRegClassInheritanceNode* parent;
  58                  struct _ProvRegClassInheritanceNode* nextSibling;
  59                  struct _ProvRegClassInheritanceNode* firstChild;
  60                  /* assoc support */
  61                  /* left/right are not-null only for assoc class */
  62                  struct _ProvRegClassInheritanceNode* left;
  63                  struct _ProvRegClassInheritanceNode* right;
  64              
  65                  /* linked list of all assoc classes that refer this class */
  66                  ProvRegAssocBackLinkNode* associatorClasses;
  67              }
  68              ProvRegClassInheritanceNode;
  69              
  70              #if (MI_CHAR_TYPE == 1)
  71 krisbash 1.4 #define MI_ScasecmpChar_MIChar Tcscasecmp
  72 mike     1.1 #else
  73              static int MI_ScasecmpChar_MIChar(
  74                  const char* str1,
  75 krisbash 1.4     const ZChar* str2 )
  76 mike     1.1 {
  77                  /* assuming str2 is ascii char-set only */
  78                  for(;;)
  79                  {
  80                      int c1 = tolower((unsigned char)*str1);
  81                      int c2 = tolower((unsigned char)*str2);
  82              
  83                      if (c1 != c2 )
  84                      {
  85                          return c1 < c2 ? -1 : 1;
  86                      }
  87                      if (!c1)
  88                          break;
  89              
  90                      str1++;
  91                      str2++;
  92                  }
  93              
  94                  return 0;
  95              }
  96              #endif
  97 mike     1.1 
  98              /* returns last segment from the string or string itself; 
  99                  for example, for string abc,edf,ghk  function returns 'ghk', 'edf' and 'abc' */
 100 krisbash 1.4 static char* _GetNextReverse(_Inout_ CharPtr* text, char delim)
 101 mike     1.1 {
 102                  char* start = *text;
 103                  char* end;
 104                  size_t len;
 105              
 106                  /* If at end of string */
 107                  if (!*start)
 108                      return NULL;
 109              
 110                  len = strlen(start);
 111              
 112                  /* end of string */
 113                  end = start + len;
 114              
 115                  /* Remove trailing whitespace */
 116                  for (; end != start && isspace((unsigned char)end[-1]);)
 117                      *--end = '\0';
 118              
 119                  /* Skip non-colon character characters */
 120                  for (; end != start && *end != delim; end--)
 121                      ;
 122 mike     1.1 
 123                  if ( end == start )
 124                  {   /* last block - move position to the end to point to \0 */
 125                      *text = start + len;
 126                  }
 127                  else
 128                  {  /* skip delimiter*/
 129                      *end = 0;
 130                      end++;
 131                  }
 132 krisbash 1.4 #ifdef _MSC_VER
 133              #pragma prefast(push)
 134              #pragma prefast (disable: 26016)
 135              #endif
 136 mike     1.1 
 137                  /* Skip leading whitespace */
 138                  while (*end && isspace((unsigned char)*end))
 139                      end++;
 140              
 141 krisbash 1.4 #ifdef _MSC_VER
 142              #pragma prefast(pop)
 143              #endif
 144              
 145 mike     1.1     return end;
 146              }
 147              
 148              /* ********************************************************* */
 149              /* ***           namespace operations                    *** */
 150              /* ********************************************************* */
 151              
 152              ProvRegNamespaceNode* _FindNamespace(
 153                  ProvReg* self,
 154 krisbash 1.4     MI_ConstString ns,
 155                  MI_Boolean extraClass)
 156 mike     1.1 {
 157                  /* find namespace node in the list */
 158 krisbash 1.4     ProvRegNamespaceNode* current;
 159                  if(extraClass)
 160                      current = self->namespacesForExtraClasses;
 161                  else
 162                      current = self->namespaces;
 163 mike     1.1 
 164 krisbash 1.4     while (current && Tcscasecmp(ns,current->ns) != 0)
 165 mike     1.1         current = current->next;
 166              
 167                  return current;
 168              }
 169              
 170              ProvRegNamespaceNode* _FindOrCreateNamespace(
 171                  ProvReg* self,
 172 krisbash 1.4     MI_ConstString ns,
 173                  MI_Boolean extraClass)
 174 mike     1.1 {
 175 krisbash 1.4     ProvRegNamespaceNode* item = _FindNamespace(self,ns, extraClass);
 176 mike     1.1 
 177                  if (item)
 178                      return item;
 179              
 180                  item = (ProvRegNamespaceNode*)Batch_GetClear(
 181                      &self->batch, sizeof(ProvRegNamespaceNode));
 182              
 183                  if (item)
 184                  {
 185 krisbash 1.4         if(extraClass)
 186                      {
 187                          size_t size;
 188                          size = Tcslen(ns) + 1;
 189              
 190                          {
 191                              ZChar* nameSpace = Batch_Get(&self->batch, size * sizeof(ZChar));
 192                              if(nameSpace == NULL)
 193                              {
 194                                  trace_OutOfMemory();
 195                                  return NULL;
 196                              }
 197                              Tcslcpy(nameSpace, ns, size);
 198                              
 199                              item->ns = nameSpace;
 200                              item->next = self->namespacesForExtraClasses;
 201                              self->namespacesForExtraClasses = item;
 202                          }
 203                      }
 204                      else
 205                      {
 206 krisbash 1.4             item->ns = ns; /* no need to strdup, since it's already in batch*/
 207                          item->next = self->namespaces;
 208                          self->namespaces = item;
 209                      }
 210 mike     1.1     }
 211              
 212                  return item;
 213              }
 214              
 215              /* ********************************************************* */
 216              /* ***                tree operations                    *** */
 217              /* ********************************************************* */
 218              ProvRegClassInheritanceNode* _GetNextTreeNodeLimittedBy(
 219                  ProvRegClassInheritanceNode* item,
 220                  ProvRegClassInheritanceNode* subtreeRoot)
 221              {
 222                  /* first-child */
 223                  if (item->firstChild)
 224                      return item->firstChild;
 225              
 226                  /* sibling */
 227                  if (item->nextSibling)
 228                      return item->nextSibling;
 229              
 230                  /* sibling of direct or indirect parent*/
 231 mike     1.1     while (item && item->parent != subtreeRoot)
 232                  {
 233                      item = item->parent;
 234              
 235 krisbash 1.4         if (item && item->nextSibling)
 236 mike     1.1             return item->nextSibling;
 237                  }
 238              
 239                  /* end of tree */
 240                  return 0;
 241              }
 242              
 243              ProvRegClassInheritanceNode* _GetNextTreeNode(
 244                  ProvRegClassInheritanceNode* item)
 245              {
 246                  return _GetNextTreeNodeLimittedBy(item,0);
 247              }
 248              
 249              ProvRegClassInheritanceNode* _FindClassNodeInTreeByChar(
 250                  ProvRegClassInheritanceNode* root,
 251                  const char* cn)
 252              {
 253                  while (root)
 254                  {
 255                      if (MI_ScasecmpChar_MIChar(cn,root->cn)==0)
 256                      {
 257 mike     1.1             return root;
 258                      }
 259                      root = _GetNextTreeNode(root);
 260                  }
 261                  return root;
 262              }
 263              
 264              ProvRegClassInheritanceNode* _FindClassNodeInTree(
 265                  ProvRegClassInheritanceNode* root,
 266 krisbash 1.4     const ZChar* cn)
 267 mike     1.1 {
 268                  while (root)
 269                  {
 270 krisbash 1.4         if (Tcscasecmp(cn,root->cn)==0)
 271 mike     1.1         {
 272                          return root;
 273                      }
 274                      root = _GetNextTreeNode(root);
 275                  }
 276                  return root;
 277              }
 278              
 279              MI_Boolean _ValidateTreeNodes(
 280                  ProvRegClassInheritanceNode* derivedNode,
 281                  ProvRegClassInheritanceNode* baseNode)
 282              {
 283                  /* if we have no nodes - it's fine - no info yet*/
 284                  if ( !derivedNode && !baseNode )
 285                      return MI_TRUE;
 286              
 287                  /* if we have both nodes - check they are child/parent */
 288                  if ( derivedNode && baseNode )
 289                      return derivedNode->parent == baseNode;
 290              
 291                  /* base must be specified */
 292 mike     1.1     if ( derivedNode && !baseNode )
 293                      return MI_FALSE;
 294              
 295                  /* only one node is known - ok */
 296                  return MI_TRUE;
 297              }
 298              
 299              static MI_Result _AddClassInheritanceInfo( 
 300                  ProvReg* self,
 301                  MI_ConstString ns,
 302                  const char* derivedClass, /* can be null */
 303 krisbash 1.4     const char* baseClass,
 304                  const char* library,
 305                  ProvHosting hosting,
 306                  const char*     user,
 307                  MI_Boolean extraClass)
 308 mike     1.1 {
 309                  /* get (or create if needed) namespace item */
 310 krisbash 1.4     ProvRegNamespaceNode* namespaceNode = _FindOrCreateNamespace(self,ns, extraClass);
 311 mike     1.1     ProvRegClassInheritanceNode* derivedNode, *baseNode;
 312              
 313                  if (!namespaceNode)
 314                      return MI_RESULT_FAILED;
 315              
 316                  /* find classes' nodes */
 317                  derivedNode = derivedClass ? _FindClassNodeInTreeByChar(namespaceNode->tree, derivedClass) : 0;
 318                  baseNode = _FindClassNodeInTreeByChar(namespaceNode->tree, baseClass);
 319              
 320                  /* validate nodes */
 321                  if (!_ValidateTreeNodes(derivedNode,baseNode))
 322                      return MI_RESULT_INVALID_CLASS_HIERARCHY;
 323              
 324                  /* create missing nodes and insert them into tree */
 325                  if ( !baseNode )
 326                  {
 327                      baseNode = (ProvRegClassInheritanceNode*)Batch_GetClear(
 328                              &self->batch, sizeof(ProvRegClassInheritanceNode));
 329              
 330                      if ( !baseNode )
 331                          return MI_RESULT_FAILED;
 332 mike     1.1 
 333 krisbash 1.4         baseNode->cn = Batch_StrTcsdup(&self->batch, baseClass);
 334                      baseNode->library = Batch_Strdup(&self->batch, library);
 335                      baseNode->hosting = hosting;
 336                      if(user)
 337                      {
 338                          baseNode->user = Batch_Strdup(&self->batch, user);
 339                          if(!baseNode->user)
 340                              return MI_RESULT_FAILED;
 341                      }
 342 mike     1.1 
 343 krisbash 1.4         if ( !baseNode->cn || !baseNode->library)
 344 mike     1.1             return MI_RESULT_FAILED;
 345              
 346                      /* insert into tree */
 347                      baseNode->nextSibling = namespaceNode->tree;
 348                      namespaceNode->tree = baseNode;
 349                  }
 350              
 351                  if ( !derivedNode && derivedClass)
 352                  {
 353                      derivedNode = (ProvRegClassInheritanceNode*)Batch_GetClear(
 354                              &self->batch, sizeof(ProvRegClassInheritanceNode));
 355              
 356                      if ( !derivedNode )
 357                          return MI_RESULT_FAILED;
 358              
 359 krisbash 1.4         derivedNode->cn = Batch_StrTcsdup(&self->batch, derivedClass);
 360                      derivedNode->library = Batch_Strdup(&self->batch, library);
 361                      derivedNode->hosting = hosting;
 362                      if(user)
 363                      {
 364                          derivedNode->user = Batch_Strdup(&self->batch, user);
 365                          if(!derivedNode->user)
 366                              return MI_RESULT_FAILED;
 367                      }
 368 mike     1.1 
 369 krisbash 1.4         if ( !derivedNode->cn || !derivedNode->library)
 370 mike     1.1             return MI_RESULT_FAILED;
 371              
 372                      /* add as a child */
 373                      derivedNode->parent = baseNode;
 374                      derivedNode->nextSibling = baseNode->firstChild;
 375                      baseNode->firstChild = derivedNode;
 376                  }
 377              
 378                  return MI_RESULT_OK;
 379              }
 380              
 381              static MI_Result _AddAssociation( 
 382                  ProvReg* self,
 383                  MI_ConstString ns,
 384                  const char* assoc, 
 385                  const char* left,
 386                  const char* right)
 387              {
 388                  /* find all related nodes */
 389                  ProvRegNamespaceNode* namespaceNode;
 390                  ProvRegClassInheritanceNode  *leftNode, *rightNode, *assocNode;
 391 mike     1.1 
 392                  /* check namespace */
 393 krisbash 1.4     namespaceNode = _FindNamespace(self,ns, MI_FALSE);
 394 mike     1.1 
 395                  if (!namespaceNode)
 396                      return MI_RESULT_INVALID_NAMESPACE;
 397              
 398                  /* find class */
 399                  leftNode = _FindClassNodeInTreeByChar(namespaceNode->tree, left);
 400                  rightNode = _FindClassNodeInTreeByChar(namespaceNode->tree, right);
 401                  assocNode = _FindClassNodeInTreeByChar(namespaceNode->tree, assoc);
 402              
 403                  if (!leftNode || !rightNode || !assocNode)
 404                      return MI_RESULT_INVALID_CLASS;
 405              
 406                  /* add cross-links */
 407                  assocNode->left = leftNode;
 408                  assocNode->right = rightNode;
 409              
 410                  {
 411                      ProvRegAssocBackLinkNode* newLinkItemLeft;
 412                      newLinkItemLeft = (ProvRegAssocBackLinkNode*)Batch_GetClear(
 413                          &self->batch, sizeof(ProvRegAssocBackLinkNode));
 414              
 415 mike     1.1         if (!newLinkItemLeft)
 416                          return MI_RESULT_FAILED;
 417              
 418                      newLinkItemLeft->assocClass = assocNode;
 419                      newLinkItemLeft->next = leftNode->associatorClasses;
 420                      leftNode->associatorClasses = newLinkItemLeft;
 421                  }
 422              
 423                  /* check if assoc links different classes */
 424                  if (leftNode != rightNode)
 425                  {
 426                      ProvRegAssocBackLinkNode* newLinkItemRight;
 427                      newLinkItemRight = (ProvRegAssocBackLinkNode*)Batch_GetClear(
 428                          &self->batch, sizeof(ProvRegAssocBackLinkNode));
 429                      if (!newLinkItemRight)
 430                          return MI_RESULT_FAILED;
 431              
 432                      newLinkItemRight->assocClass = assocNode;
 433                      newLinkItemRight->next = rightNode->associatorClasses;
 434                      rightNode->associatorClasses = newLinkItemRight;
 435                  }
 436 mike     1.1 
 437                  return MI_RESULT_OK;
 438              }
 439              
 440              static MI_Result _GetSubclasses2(
 441                  ProvReg* self,
 442                  ProvRegEntry* e,
 443 krisbash 1.4     _Inout_ CharPtr p)
 444 mike     1.1 {
 445                  /* get all sub-classes */
 446                  char* baseClass = _GetNextReverse(&p, ':');
 447                  char* derivedClass = _GetNextReverse(&p, ':');
 448                  MI_Result r;
 449              
 450                  /* expecting to find at least one class */
 451                  if (!baseClass)
 452                      return MI_RESULT_INVALID_CLASS;
 453              
 454                  while ( derivedClass )
 455                  {
 456                      r = _AddClassInheritanceInfo(self, e->nameSpace, derivedClass, 
 457 krisbash 1.4             baseClass, e->libraryName, e->hosting, e->user, MI_FALSE);
 458 mike     1.1 
 459                      if ( MI_RESULT_OK != r )
 460                          return r;
 461              
 462                      baseClass = derivedClass;
 463                      derivedClass = _GetNextReverse(&p, ':');
 464                  }
 465              
 466                  /* add base class with no parent */
 467 krisbash 1.4     r = _AddClassInheritanceInfo(self, e->nameSpace, derivedClass, baseClass, e->libraryName, e->hosting, e->user, MI_FALSE);
 468 mike     1.1     if (MI_RESULT_OK != r)
 469                      return r;
 470              
 471 krisbash 1.4     e->className = Batch_StrTcsdup(&self->batch, baseClass);
 472 mike     1.1     if (!e->className)
 473                  {
 474                      return MI_RESULT_FAILED;
 475                  }
 476 krisbash 1.4     e->classNameHash = Hash(e->className);
 477 mike     1.1 
 478                  return MI_RESULT_OK;
 479              }
 480              
 481              static int _AddEntry(
 482                  ProvReg* self,
 483                  const char* nameSpace,
 484                  RegFile* regFile,
 485                  RegClass* regClass)
 486              {
 487                  ProvRegEntry* e;
 488              
 489              #if 0
 490                  RegFile_Print(regFile, stdout);
 491              #endif
 492              
 493                  /* Allocate new provider register entry */
 494                  e = (ProvRegEntry*)Batch_GetClear(&self->batch, sizeof(ProvRegEntry));
 495                  if (!e)
 496                      return -1;
 497              
 498 mike     1.1     /* ProvRegEntry.provInterface */
 499                  e->provInterface = PROV_INTERFACE_STATIK;
 500              
 501                  /* ProvRegEntry.nameSpace */
 502 krisbash 1.4     e->nameSpace = Batch_StrTcsdup(&self->batch, nameSpace);
 503                  if (!e->nameSpace)
 504                      return -1;
 505              
 506                  e->nameSpaceHash = Hash(e->nameSpace);
 507 mike     1.1 
 508                  /* ProvRegEntry.libraryName */
 509 krisbash 1.4     e->libraryName = Batch_Strdup(&self->batch, regFile->library);
 510                  if (!e->libraryName)
 511                  {
 512                      trace_ProvReg_ProvRegEntry_NULLLibraryName(nameSpace, regClass->name);
 513                      return -1;
 514                  }
 515              
 516              #if defined(CONFIG_ENABLE_PREEXEC)
 517              
 518                  /* ProvRegEntry.preexec */
 519                  if (regFile->preexec)
 520                  {
 521                      e->preexec = Batch_Strdup(&self->batch, regFile->preexec);
 522                      if (!e->preexec)
 523                          return -1;
 524                  }
 525              
 526              #endif /* defined(CONFIG_ENABLE_PREEXEC) */
 527 mike     1.1 
 528                  /* ProvRegEntry.hosting*/
 529                  e->hosting = PROV_HOSTING_INPROC;
 530              
 531 krisbash 1.4     e->regType = regClass->regtype;
 532              
 533                  e->instanceLifetimeContext = regFile->instanceLifetimeContext;
 534              
 535 mike     1.1     if (regClass->hosting)
 536                  {
 537                      char hosting[64];
 538                      Strlcpy(hosting, regClass->hosting, sizeof(hosting));
 539              
 540                      /* it either user name or one of two special values: 
 541                       *  @inproc@
 542 krisbash 1.4          *  @requestor@
 543 mike     1.1          */
 544                      if (strcmp(hosting, PROV_REG_HOSTING_INPROC) == 0)
 545                      {
 546                          e->hosting = PROV_HOSTING_INPROC;
 547                      }
 548                      else if (strcmp(hosting, PROV_REG_HOSTING_REQUESTOR) == 0)
 549                      {
 550                          e->hosting = PROV_HOSTING_REQUESTOR;
 551                      }
 552                      else
 553                      {
 554                          e->hosting = PROV_HOSTING_USER;
 555 krisbash 1.4             e->user =  Batch_Strdup(&self->batch, hosting);
 556 mike     1.1             if (!e->user)
 557                              return -1;
 558                      }
 559                  }
 560              
 561                  /* If an association */
 562                  if (regClass->refName1 && regClass->refName2)
 563                  {
 564                      if (_GetSubclasses2(self, e, regClass->refName1) != MI_RESULT_OK)
 565                          return -1;
 566              
 567                      if (_GetSubclasses2(self, e, regClass->refName2) != MI_RESULT_OK)
 568                          return -1;
 569              
 570                      if (_GetSubclasses2(self, e, regClass->name) != MI_RESULT_OK)
 571                          return -1;
 572              
 573                      if (_AddAssociation(self, e->nameSpace, regClass->name,
 574                          regClass->refName1, regClass->refName2) != MI_RESULT_OK)
 575                      {
 576                          return -1;
 577 mike     1.1         }
 578                  }
 579                  else
 580                  {
 581                      if (_GetSubclasses2(self, e, regClass->name) != MI_RESULT_OK)
 582                          return -1;
 583                  }
 584              
 585                  /* Add entry to end of list */
 586                  {
 587                      e->next = NULL;
 588              
 589                      if (self->tail)
 590                      {
 591                          self->tail->next = e;
 592                          self->tail = e;
 593                      }
 594                      else
 595                      {
 596                          self->tail = e;
 597                          self->head = e;
 598 mike     1.1         }
 599                  }
 600              
 601                  return 0;
 602              }
 603              
 604 krisbash 1.4 static int _AddEntryForExtraClass(
 605                  ProvReg* self,
 606                  const char* nameSpace,
 607                  RegFile* regFile,
 608                  RegClass* regClass)
 609              {
 610                  /* get all sub-classes */
 611                  ProvHosting hosting;
 612                  const char*     user = NULL;
 613                  CharPtr p = regClass->name;
 614                  char* baseClass = _GetNextReverse(&p, ':');
 615                  char* derivedClass = _GetNextReverse(&p, ':');
 616                  MI_Result r;
 617                  size_t size = strlen(nameSpace) + 1;
 618              
 619                  hosting = PROV_HOSTING_INPROC;
 620              
 621                  if (regClass->hosting)
 622                  {
 623                      /* it either user name or one of two special values: 
 624                       *  @inproc@
 625 krisbash 1.4          *  @requestor@ 
 626                       */
 627                      if (strcmp(regClass->hosting, PROV_REG_HOSTING_INPROC) == 0)
 628                      {
 629                          hosting = PROV_HOSTING_INPROC;
 630                      }
 631                      else if (strcmp(regClass->hosting, PROV_REG_HOSTING_REQUESTOR) == 0)
 632                      {
 633                          hosting = PROV_HOSTING_REQUESTOR;
 634                      }
 635                      else
 636                      {
 637                          hosting = PROV_HOSTING_USER;
 638                          user =  regClass->hosting;
 639                      }
 640                  }
 641              
 642              #if 0
 643                  RegFile_Print(regFile, stdout);
 644              #endif
 645              
 646 krisbash 1.4     /* expecting to find at least one class */
 647                  if (!baseClass)
 648                      return MI_RESULT_INVALID_CLASS;
 649              
 650                  {
 651                      ZChar s[PAL_MAX_PATH_SIZE];
 652                      size_t i;
 653              
 654                      if(size > PAL_MAX_PATH_SIZE)
 655                          return -1;
 656              
 657                      for(i=0; i < size; i++)
 658                          s[i] = (ZChar) nameSpace[i];
 659              
 660                      while ( derivedClass )
 661                      {
 662                          r = _AddClassInheritanceInfo(self, s, derivedClass, 
 663                              baseClass, regFile->library, hosting, user, MI_TRUE);
 664              
 665                          if ( MI_RESULT_OK != r )
 666                              return r;
 667 krisbash 1.4 
 668                          baseClass = derivedClass;
 669                          derivedClass = _GetNextReverse(&p, ':');
 670                      }
 671              
 672                      /* add base class with no parent */
 673                      r = _AddClassInheritanceInfo(self, s, derivedClass,
 674                          baseClass, regFile->library, hosting, user, MI_TRUE);
 675              
 676                      if (MI_RESULT_OK != r)
 677                          return -1;
 678                  }
 679              
 680                  return 0;
 681              }
 682              
 683              /* Initialize ProvReg strucutre from given directory */
 684              _Use_decl_annotations_
 685              MI_Result ProvReg_Init(ProvReg* self, const char* directory)
 686 mike     1.1 {
 687 krisbash 1.4     RegFile* reg = NULL;
 688 mike     1.1     Dir* dir = NULL;
 689                  Dir* dir2 = NULL;
 690 krisbash 1.4     MI_Result r = MI_RESULT_FAILED;
 691                  
 692 mike     1.1     /* Zero-fill self */
 693                  memset(self, 0, sizeof(*self));
 694              
 695 krisbash 1.4     dir = Dir_Open(directory);
 696                  if (!dir)
 697                  {
 698                      return r;
 699                  }
 700              
 701 mike     1.1     /* Initialize batch allocator */
 702                  Batch_Init(&self->batch, BATCH_MAX_PAGES);
 703              
 704                  /* For each namespace directory in 'omirgister' */
 705                  for (;;)
 706                  {
 707                      DirEnt* ent = Dir_Read(dir);
 708 krisbash 1.4 
 709 mike     1.1         if (!ent)
 710 krisbash 1.4         {
 711 mike     1.1             break;
 712 krisbash 1.4         }
 713 mike     1.1 
 714                      /* Ignore system directories */
 715                      if (strcmp(ent->name, ".") == 0 || strcmp(ent->name, "..") == 0)
 716                          continue;
 717              
 718                      /* Skip 'CVS' directories */
 719                      if (strcmp(ent->name, "CVS") == 0)
 720                          continue;
 721              
 722                      /* Scan .reg files in the current namespace directory */
 723                      {
 724 krisbash 1.4             char path[PAL_MAX_PATH_SIZE];
 725 mike     1.1 
 726 krisbash 1.4             Strlcpy(path, directory, sizeof(path));
 727 mike     1.1             Strlcat(path, "/", sizeof(path));
 728                          Strlcat(path, ent->name, sizeof(path));
 729              
 730 krisbash 1.4             /* Skip if not a dir */
 731                          if(!Isdir(path))
 732                              continue;
 733              
 734 mike     1.1             dir2 = Dir_Open(path);
 735                          if (!dir2)
 736                          {
 737                              goto failed;
 738                          }
 739              
 740                          for (;;)
 741                          {
 742                              DirEnt* ent2 = Dir_Read(dir2);
 743                              if (!ent2)
 744 krisbash 1.4                 {
 745 mike     1.1                     break;
 746 krisbash 1.4                 }
 747 mike     1.1 
 748                              /* Ignore system directories */
 749                              if (strcmp(ent2->name,".") == 0 || strcmp(ent2->name,"..") == 0)
 750 krisbash 1.4                 {
 751 mike     1.1                     continue;
 752 krisbash 1.4                 }
 753              
 754                              /* Skip non-reg file */
 755                              {
 756                                  char* affix = Strrchr(ent2->name, '.');
 757                                  if (!affix || (Strcasecmp(&affix[1], "reg") != 0))
 758                                      continue;
 759                              }
 760 mike     1.1 
 761                              /* Load the reg file */
 762                              {
 763 krisbash 1.4                     char regPath[PAL_MAX_PATH_SIZE];
 764 mike     1.1 
 765                                  /* Form path to .reg file */
 766                                  Strlcpy(regPath, path, sizeof(regPath));
 767                                  Strlcat(regPath, "/", sizeof(regPath));
 768                                  Strlcat(regPath, ent2->name, sizeof(regPath));
 769              
 770                                  /* Create new reg file object */
 771                                  reg = RegFile_New(regPath);
 772                                  if (!reg)
 773                                  {
 774 krisbash 1.4                         trace_ProvReg_SkipRegFile(scs(regPath));
 775                                      continue;
 776 mike     1.1                     }
 777              
 778                                  /* For each class in the reg file */
 779                                  {
 780                                      RegClass* rc;
 781 krisbash 1.4                         char* p = ent->name;
 782                                      
 783                                      /* Transpose NAMESPACE_SEPARATOR characters to '/' 
 784                                       * characters 
 785                                       */
 786                                      while (*p)
 787                                      {
 788                                          if (*p == NAMESPACE_SEPARATOR)
 789                                              *p = '/';
 790                                          p++;
 791                                      }
 792 mike     1.1 
 793                                      for (rc = reg->classesHead; rc; rc = rc->next)
 794                                      {
 795 krisbash 1.4                             if (_AddEntry(self, ent->name, reg, rc) != 0)
 796 mike     1.1                             {
 797 krisbash 1.4                                 goto failed;
 798 mike     1.1                             }
 799 krisbash 1.4                         }
 800                                  }
 801 mike     1.1 
 802 krisbash 1.4                     /* For each extraClass in the reg file */
 803                                  {
 804                                      RegClass* rc;
 805                                      char* p = ent->name;
 806                                      
 807                                      /* Transpose NAMESPACE_SEPARATOR characters to '/' 
 808                                       * characters 
 809                                       */
 810                                      while (*p)
 811                                      {
 812                                          if (*p == NAMESPACE_SEPARATOR)
 813                                              *p = '/';
 814                                          p++;
 815                                      }
 816              
 817                                      for (rc = reg->extraClassesHead; rc; rc = rc->next)
 818                                      {
 819                                          if (_AddEntryForExtraClass(self, ent->name, reg, rc) != 0)
 820 mike     1.1                             {
 821                                              goto failed;
 822                                          }
 823                                      }
 824                                  }
 825              
 826                                  /* Delete the current entry */
 827                                  RegFile_Delete(reg);
 828                                  reg = NULL;
 829                              }
 830                          }
 831              
 832                          /* Close the directory */
 833                          Dir_Close(dir2);
 834                          dir2 = NULL;
 835                      }
 836                  }
 837 krisbash 1.4     r = MI_RESULT_OK;
 838 mike     1.1 
 839              failed:
 840 krisbash 1.4     if (dir2)
 841                  {
 842                      Dir_Close(dir2);
 843                  }
 844 mike     1.1     if (dir)
 845 krisbash 1.4     {
 846 mike     1.1         Dir_Close(dir);
 847 krisbash 1.4     }
 848                  if (r != MI_RESULT_OK)
 849                  {
 850                      ProvReg_Destroy(self);
 851                      memset(self, 0, sizeof(*self));
 852                  }
 853                  if(reg)
 854                  {
 855                      RegFile_Delete(reg);
 856                      reg = NULL;
 857                  }
 858                  return r;
 859              }
 860 mike     1.1 
 861 krisbash 1.4 /* Initialize ProvReg strucutre from omiregister directory */
 862              _Use_decl_annotations_
 863              MI_Result ProvReg_Init2(ProvReg* self)
 864              {
 865                  return ProvReg_Init(self, OMI_GetPath(ID_REGISTERDIR));
 866 mike     1.1 }
 867              
 868              void ProvReg_Destroy(
 869                  ProvReg* self)
 870              {
 871                  Batch_Destroy(&self->batch);
 872              }
 873              
 874              void ProvReg_Dump(
 875                  ProvReg* self,
 876                  FILE* os)
 877              {
 878                  ProvRegEntry* p;
 879              
 880                  for (p = self->head; p; p = p->next)
 881                  {
 882 krisbash 1.4         Ftprintf(os, PAL_T("==== ProvRegEntry\n"));
 883                      Ftprintf(os, PAL_T("provInterface[%u]\n"), p->provInterface);
 884                      Ftprintf(os, PAL_T("nameSpace[%T]\n"), tcs(p->nameSpace));
 885                      Ftprintf(os, PAL_T("className[%T]\n"), tcs(p->className));
 886                      Ftprintf(os, PAL_T("libraryName[%s]\n"), scs(p->libraryName));
 887 mike     1.1     }
 888              }
 889              
 890              const ProvRegEntry* ProvReg_FindProviderForClass(
 891                  ProvReg* self,
 892 krisbash 1.4     const ZChar* nameSpace,
 893                  const ZChar* className,
 894                  MI_Result *findError)
 895 mike     1.1 {
 896 krisbash 1.4     return ProvReg_FindProviderForClassByType(self, nameSpace, className, PROVREG_DEFAULT, findError);
 897              }
 898 mike     1.1 
 899              
 900              /* returns ok or not-found; baseClass will be null if no base class exist */
 901              MI_Result ProvReg_GetDirectBaseClass(
 902                  ProvReg* self,
 903 krisbash 1.4     const ZChar* nameSpace,
 904                  const ZChar* className,
 905                  const ZChar** baseClass,
 906                  MI_Boolean extraClass)
 907 mike     1.1 {
 908                  ProvRegClassInheritanceNode* classNode;
 909                  ProvRegNamespaceNode* namespaceNode;
 910              
 911                  /* clear out param */
 912                  *baseClass = 0;
 913              
 914                  /* check namespace */
 915 krisbash 1.4     namespaceNode = _FindNamespace(self,nameSpace, extraClass);
 916 mike     1.1 
 917                  if (!namespaceNode)
 918                      return MI_RESULT_INVALID_NAMESPACE;
 919              
 920                  /* find class */
 921                  classNode = _FindClassNodeInTree(namespaceNode->tree, className);
 922              
 923                  if (!classNode)
 924                      return MI_RESULT_INVALID_CLASS;
 925              
 926                  if (classNode->parent)
 927                  {
 928                      *baseClass = classNode->parent->cn;
 929                  }
 930              
 931                  return MI_RESULT_OK;
 932              }
 933              
 934              /* enumerates classes derived classes:
 935               - if deep == false and className == null, returns all root classes
 936               - if deep == true and className == null, returns all classes
 937 mike     1.1  - if deep == false and className provided, returns all classes directly derived from given
 938               - if deep == true and className provided, returns all classes derived from given
 939              */
 940              MI_Result ProvReg_BeginClasses(
 941                  ProvReg* self,
 942 krisbash 1.4     const ZChar* nameSpace,
 943                  const ZChar* className,
 944 mike     1.1     MI_Boolean deep,
 945 krisbash 1.4     ProvRegPosition* pos,
 946                  MI_Boolean extraClass)
 947 mike     1.1 {
 948                  ProvRegNamespaceNode* namespaceNode;
 949              
 950                  /* clear pos */
 951                  memset( pos, 0, sizeof(*pos));
 952                  pos->deep = deep;
 953              
 954                  /* check namespace */
 955 krisbash 1.4     namespaceNode = _FindNamespace(self,nameSpace, extraClass);
 956 mike     1.1 
 957                  if (!namespaceNode)
 958                      return MI_RESULT_INVALID_NAMESPACE;
 959              
 960                  /* find class */
 961                  if (className)
 962                  {
 963                      pos->start = _FindClassNodeInTree(namespaceNode->tree, className);
 964              
 965                      if (!pos->start)
 966                          return MI_RESULT_INVALID_CLASS;
 967              
 968                      pos->current = pos->start->firstChild;
 969                  }
 970                  else
 971                  {
 972                      pos->start = 0;
 973                      pos->current = namespaceNode->tree;
 974                  }
 975              
 976                  return MI_RESULT_OK;
 977 mike     1.1 }
 978              
 979              MI_Result ProvReg_NextClass(
 980                  ProvRegPosition* pos,
 981 krisbash 1.4     const ZChar** className,
 982 mike     1.1     MI_Boolean* done)
 983              {
 984                  if (!pos->current)
 985                  {
 986                      *className = 0;
 987              
 988                      if (done)
 989                          *done = MI_TRUE;
 990              
 991                      return MI_RESULT_OK;
 992                  }
 993              
 994                  *className = pos->current->cn;
 995              
 996                  if (pos->deep)
 997                  {
 998                      pos->current = _GetNextTreeNodeLimittedBy(pos->current,pos->start);
 999                  }
1000                  else
1001                  {
1002                      pos->current = pos->current->nextSibling;
1003 mike     1.1     }
1004              
1005                  if (done)
1006                      *done = MI_FALSE;
1007              
1008                  return MI_RESULT_OK;
1009              }
1010              
1011              MI_Result ProvReg_EndClasses(
1012                  ProvRegPosition* pos)
1013              {
1014                  memset( pos, -1, sizeof(*pos));
1015                  return MI_RESULT_OK;
1016              }
1017              
1018              /* returns enumerator to all registered association classes by given instance class
1019                and (optionally) assoc/result classes */
1020              MI_EXPORT MI_Result ProvReg_BeginAssocClasses(
1021                  ProvReg* self,
1022 krisbash 1.4     const ZChar* nameSpace,
1023                  const ZChar* className,
1024                  const ZChar* assocClassName,  /* can be NULL */
1025                  const ZChar* resultClassName, /* can be NULL */
1026 mike     1.1     ProvRegAssocPosition* pos)
1027              {
1028                  ProvRegNamespaceNode* namespaceNode;
1029              
1030                  if (!nameSpace || !className || !pos)
1031                      return MI_RESULT_INVALID_PARAMETER;
1032              
1033                  /* clear pos */
1034                  memset( pos, 0, sizeof(*pos));
1035              
1036                  /* check namespace */
1037 krisbash 1.4     namespaceNode = _FindNamespace(self,nameSpace, MI_FALSE);
1038 mike     1.1 
1039                  if (!namespaceNode)
1040                      return MI_RESULT_INVALID_NAMESPACE;
1041              
1042                  /* find class */
1043                  pos->currentLeft = _FindClassNodeInTree(namespaceNode->tree, className);
1044              
1045                  if (!pos->currentLeft)
1046                      return MI_RESULT_INVALID_CLASS;
1047              
1048                  //pos->currentAssoc = pos->currentLeft->associatorClasses;
1049              
1050                  /* validate optional parameters */
1051                  if (assocClassName)
1052                  {
1053                      ProvRegClassInheritanceNode* assocClassNode = _FindClassNodeInTree(namespaceNode->tree, assocClassName);
1054              
1055                      if (!assocClassNode)
1056                          return MI_RESULT_INVALID_CLASS;
1057              
1058                      /* store node pointer */
1059 mike     1.1         pos->assocClass = assocClassNode;
1060                  }
1061              
1062                  if (resultClassName)
1063                  {
1064                      ProvRegClassInheritanceNode* resultClassNode = _FindClassNodeInTree(namespaceNode->tree, resultClassName);
1065              
1066                      if (!resultClassNode)
1067                          return MI_RESULT_INVALID_CLASS;
1068              
1069                      /* store node pointer */
1070                      pos->resultClass = resultClassNode;
1071                  }
1072              
1073                  return MI_RESULT_OK;
1074              }
1075              
1076              static MI_Boolean _GetNextAssoc(
1077                  ProvRegAssocPosition* pos)
1078              {
1079                  /* check if we are at new node */
1080 mike     1.1     if (!pos->currentAssoc || !pos->currentLeft)
1081                  {
1082                      /* find class with assoc link */
1083                      while (pos->currentLeft && !pos->currentLeft->associatorClasses)
1084                          pos->currentLeft = pos->currentLeft->parent;
1085              
1086                      if (!pos->currentLeft)
1087                          return MI_FALSE;
1088              
1089                      pos->currentAssoc = pos->currentLeft->associatorClasses;
1090                      return MI_TRUE;
1091                  }
1092              
1093                  pos->currentAssoc = pos->currentAssoc->next;
1094              
1095                  if (pos->currentAssoc)
1096                      return MI_TRUE;
1097              
1098                  /* skip to parent */
1099                  pos->currentLeft = pos->currentLeft->parent;
1100                  return _GetNextAssoc(pos);
1101 mike     1.1 }
1102              
1103              static MI_Boolean _IsNodeOrParentOf(
1104                  ProvRegClassInheritanceNode* parent,
1105                  ProvRegClassInheritanceNode* node)
1106              {
1107                  while (node)
1108                  {
1109                      if (node == parent)
1110                          return MI_TRUE;
1111              
1112                      node = node->parent;
1113                  }
1114                  return MI_FALSE;
1115              }
1116              
1117              MI_EXPORT MI_Result ProvReg_NextAssocClass(
1118                  ProvRegAssocPosition* pos,
1119 krisbash 1.4     const ZChar** className,
1120 mike     1.1     MI_Boolean* done)
1121              {
1122                  /* navigate to next */
1123                  if (!pos->currentLeft)
1124                  {
1125                      if (done)
1126                          *done = MI_TRUE;
1127 mike     1.2 
1128 mike     1.1         return MI_RESULT_OK;
1129                  }
1130              
1131                  while (_GetNextAssoc(pos))
1132                  {
1133                      /* check filters */
1134                      if ( (!pos->assocClass || _IsNodeOrParentOf(pos->assocClass, pos->currentAssoc->assocClass)) 
1135                          && (!pos->resultClass || _IsNodeOrParentOf(pos->resultClass, 
1136                              pos->currentAssoc->assocClass->left != pos->currentLeft ? pos->currentAssoc->assocClass->left : pos->currentAssoc->assocClass->right)
1137                              || _IsNodeOrParentOf(
1138                              pos->currentAssoc->assocClass->left != pos->currentLeft ? pos->currentAssoc->assocClass->left : pos->currentAssoc->assocClass->right,
1139                              pos->resultClass)) )
1140                      {
1141                          *className = pos->currentAssoc->assocClass->cn;
1142 mike     1.2 
1143 mike     1.1             if (done)
1144                              *done = MI_FALSE;
1145 mike     1.2 
1146 mike     1.1             return MI_RESULT_OK;
1147                      }
1148                  }
1149              
1150                  if (done)
1151                      *done = MI_TRUE;
1152 mike     1.2 
1153 mike     1.1     return MI_RESULT_OK;
1154              }
1155              
1156              MI_EXPORT MI_Result ProvReg_EndAssocClasses(
1157                  ProvRegAssocPosition* pos)
1158              {
1159                  memset( pos, -1, sizeof(*pos));
1160                  return MI_RESULT_OK;
1161              }
1162              
1163 krisbash 1.4 void MapRegPositionValuesToRegEntry(
1164                  ProvRegEntry* reg,
1165                  ProvRegPosition* pos)
1166              {
1167                  if(reg && pos)
1168                  {
1169                      reg->className = pos->start->cn;
1170                      reg->classNameHash = Hash(pos->start->cn);
1171                      reg->hosting = pos->start->hosting;
1172                      reg->libraryName = pos->start->library;
1173                      //reg->provInterface
1174                      reg->next = NULL;
1175                      reg->user = pos->start->user;
1176                  }
1177              }
1178              
1179              /* Find event steam provider under given namespace */
1180              _Use_decl_annotations_
1181              const ProvRegEntry* ProvReg_FindProviderForClassByType(
1182                  ProvReg* self,
1183                  const ZChar* nameSpace,
1184 krisbash 1.4     const ZChar* className,
1185                  ProvRegType type,
1186                  MI_Result *findError)
1187              {
1188                  ProvRegEntry* p;
1189                  MI_Boolean namespaceFound = 0;
1190                  unsigned int nameSpaceHash = Hash(nameSpace);
1191                  unsigned int classNameHash = 0;
1192                  if (!className)
1193                  {
1194                      if(findError)
1195                          *findError = MI_RESULT_INVALID_PARAMETER;
1196                      return NULL;
1197                  }
1198                  if (className)
1199                      classNameHash = Hash(className);
1200              
1201                  for (p = self->head; p; p = p->next)
1202                  {
1203                      // comparing namespace everytime may slightly affect perf
1204                      // but it enables us to give right error back to the client
1205 krisbash 1.4         if (nameSpaceHash == p->nameSpaceHash &&
1206                          Tcscasecmp(p->nameSpace, nameSpace) == 0)
1207                      {
1208                          if (p->regType == type)
1209                          {
1210                              if (className)
1211                              {
1212                                  /* for normal and indication class */
1213                                  if( classNameHash == p->classNameHash &&
1214                                      Tcscasecmp(p->className, className) == 0)
1215                                  {
1216                                      if(findError)
1217                                      {
1218                                          *findError = MI_RESULT_OK;
1219                                      }
1220                                      return p;
1221                                  }
1222                              }
1223                              else
1224                              {
1225                                  /* for event stream class */
1226 krisbash 1.4                     if(findError)
1227                                  {
1228                                      *findError = MI_RESULT_OK;
1229                                  }
1230                                  return p;
1231                              }
1232                              namespaceFound = MI_TRUE;
1233                          }
1234                      }
1235                  }
1236              
1237                  if(findError)
1238                  {
1239                      *findError = (MI_TRUE == namespaceFound) ? MI_RESULT_INVALID_CLASS : MI_RESULT_INVALID_NAMESPACE;
1240                  }
1241                  /* Not found */
1242                  return NULL;
1243              }

ViewCVS 0.9.2