text: /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You under the Apache License, Version 2.0
   *  (the "License"); you may not use this file except in compliance with
   *  the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  /***************************************************************************
   * Description: Context handling (Autoconf)                                *
   * Author:      Henri Gomez <hgomez@apache.org>                            *
   ***************************************************************************/
  
  #include "jk_global.h"
  #include "jk_context.h"
  #include "jk_ajp_common.h"
  
  
  /*
   * Set the virtual name of the context
   */
  
  int context_set_virtual(jk_context_t *c, char *virt)
  {
      if (c) {
  
          if (virt) {
              c->virt = jk_pool_strdup(&c->p, virt);
  
              if (!c->virt)
                  return JK_FALSE;
          }
  
          return JK_TRUE;
      }
  
      return JK_FALSE;
  }
  
  /*
   * Init the context info struct
   */
  
  int context_open(jk_context_t *c, char *virt)
  {
      if (c) {
          jk_open_pool(&c->p, c->buf, sizeof(jk_pool_atom_t) * SMALL_POOL_SIZE);
          c->size = 0;
          c->capacity = 0;
          c->contexts = NULL;
  
          return context_set_virtual(c, virt);
      }
  
      return JK_FALSE;
  }
  
  /*
   * Close the context info struct
   */
  
  int context_close(jk_context_t *c)
  {
      if (c) {
  
          jk_close_pool(&c->p);
          return JK_TRUE;
      }
  
      return JK_FALSE;
  }
  
  /*
   * Allocate and open context
   */
  
  int context_alloc(jk_context_t **c, char *virt)
  {
      if (c)
          return context_open(*c =
                              (jk_context_t *)calloc(1, sizeof(jk_context_t)),
                              virt);
  
      return JK_FALSE;
  }
  
  /*
   * Close and destroy context
   */
  
  int context_free(jk_context_t **c)
  {
      if (c && *c) {
          context_close(*c);
          free(*c);
          *c = NULL;
          return JK_TRUE;
      }
  
      return JK_FALSE;
  }
  
  
  /*
   * Ensure there will be memory in context info to store Context Bases
   */
  
  static int context_realloc(jk_context_t *c)
  {
      if (c->size == c->capacity) {
          jk_context_item_t **contexts;
          int capacity = c->capacity + CBASE_INC_SIZE;
  
          contexts =
              (jk_context_item_t **)jk_pool_alloc(&c->p,
                                                  sizeof(jk_context_item_t *) *
                                                  capacity);
  
          if (!contexts)
              return JK_FALSE;
  
          if (c->capacity && c->contexts)
              memcpy(contexts, c->contexts,
                     sizeof(jk_context_item_t *) * c->capacity);
  
          c->contexts = contexts;
          c->capacity = capacity;
      }
  
      return JK_TRUE;
  }
  
  /*
   * Ensure there will be memory in context info to URIS
   */
  
  static int context_item_realloc(jk_context_t *c, jk_context_item_t *ci)
  {
      if (ci->size == ci->capacity) {
          char **uris;
          int capacity = ci->capacity + URI_INC_SIZE;
  
          uris = (char **)jk_pool_alloc(&c->p, sizeof(char *) * capacity);
  
          if (!uris)
              return JK_FALSE;
  
          memcpy(uris, ci->uris, sizeof(char *) * ci->capacity);
  
          ci->uris = uris;
          ci->capacity = capacity;
      }
  
      return JK_TRUE;
  }
  
  
  /*
   * Locate a context base in context list
   */
  
  jk_context_item_t *context_find_base(jk_context_t *c, char *cbase)
  {
      int i;
      jk_context_item_t *ci;
  
      if (!c || !cbase)
          return NULL;
  
      for (i = 0; i < c->size; i++) {
  
          ci = c->contexts[i];
  
          if (!ci)
              continue;
  
          if (!strcmp(ci->cbase, cbase))
              return ci;
      }
  
      return NULL;
  }
  
  /*
   * Locate an URI in a context item
   */
  
  char *context_item_find_uri(jk_context_item_t *ci, char *uri)
  {
      int i;
  
      if (!ci || !uri)
          return NULL;
  
      for (i = 0; i < ci->size; i++) {
          if (!strcmp(ci->uris[i], uri))
              return ci->uris[i];
      }
  
      return NULL;
  }
  
  void context_dump_uris(jk_context_t *c, char *cbase, FILE * f)
  {
      jk_context_item_t *ci;
      int i;
  
      ci = context_find_base(c, cbase);
  
      if (!ci)
          return;
  
      for (i = 0; i < ci->size; i++)
          fprintf(f, "/%s/%s\n", ci->cbase, ci->uris[i]);
  
      fflush(f);
  }
  
  
  /*
   * Add a new context item to context
   */
  
  jk_context_item_t *context_add_base(jk_context_t *c, char *cbase)
  {
      jk_context_item_t *ci;
  
      if (!c || !cbase)
          return NULL;
  
      /* Check if the context base was not allready created */
      ci = context_find_base(c, cbase);
  
      if (ci)
          return ci;
  
      if (context_realloc(c) != JK_TRUE)
          return NULL;
  
      ci = (jk_context_item_t *)jk_pool_alloc(&c->p, sizeof(jk_context_item_t));
  
      if (!ci)
          return NULL;
  
      c->contexts[c->size] = ci;
      c->size++;
      ci->cbase = jk_pool_strdup(&c->p, cbase);
      ci->status = 0;
      ci->size = 0;
      ci->capacity = 0;
      ci->uris = NULL;
  
      return ci;
  }
  
  /*
   * Add a new URI to a context item
   */
  
  int context_add_uri(jk_context_t *c, char *cbase, char *uri)
  {
      jk_context_item_t *ci;
  
      if (!uri)
          return JK_FALSE;
  
      /* Get/Create the context base */
      ci = context_add_base(c, cbase);
  
      if (!ci)
          return JK_FALSE;
  
      if (context_item_find_uri(ci, uri) != NULL)
          return JK_TRUE;
  
      if (context_item_realloc(c, ci) == JK_FALSE)
          return JK_FALSE;
  
      ci->uris[ci->size] = jk_pool_strdup(&c->p, uri);
  
      if (ci->uris[ci->size] == NULL)
          return JK_FALSE;
  
      ci->size++;
      return JK_TRUE;
  }
  