Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_environment.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Adaptive Framework Environment
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 #include "afw_config.h"
16 #include <apr_hash.h>
17 #include <apr_dso.h>
18 #include <libxml/xmlversion.h>
19 
20 
21 typedef struct {
22  const afw_utf8_t *type;
23  const afw_utf8_t *key;
25 
26 
27 static const afw_utf8_t
28 impl_default_name =
29 AFW_UTF8_LITERAL("afw_application");
30 
31 static const afw_error_t
32 impl_early_error =
33 {
34  NULL,
35  afw_error_code_general,
37  "Early error creating environment",
38  0
39 };
40 
41 
42 static afw_boolean_t
43 impl_check_manifest_cb(
44  const afw_object_t *object,
45  void *context,
46  afw_xctx_t *xctx);
47 
48 
49 
50 /* Create default runtime object that just has key. */
51 static void
52 impl_internal_additional_register_default(
53  const afw_utf8_t *type_id,
54  int type_number,
55  const afw_utf8_t *key,
56  const void *value,
57  const void *register_additional_param,
58  const void **register_additional_use,
59  afw_xctx_t *xctx)
60 {
63 
64  env = (afw_environment_internal_t *)xctx->env;
65 
66  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
67  type = apr_hash_get(env->registry_names_ht, type_id->s, type_id->len);
68  if (!type) {
69  AFW_THROW_ERROR_FZ(general, xctx,
70  "Invalid environment registry type %" AFW_UTF8_FMT,
71  AFW_UTF8_FMT_ARG(type_id));
72  }
73  }
75 
76  /* Create runtime object for the value. */
77  if (value) {
79  type->object_type_id, key,
80  (void *)value, true, xctx);
81  }
82  else {
83  afw_runtime_remove_object(type->object_type_id,
84  key, xctx);
85  }
86 }
87 
88 
89 
90 /* Create runtime object and context type for log type. */
91 static void
92 impl_internal_additional_register_log_type(
93  const afw_utf8_t *type_id,
94  int type_number,
95  const afw_utf8_t *key,
96  const void *value,
97  const void *register_additional_param,
98  const void **register_additional_use,
99  afw_xctx_t *xctx)
100 {
101  impl_internal_additional_register_default(type_id, type_number,
102  key, value,
103  register_additional_param, register_additional_use, xctx);
104 
106 }
107 
108 
109 
110 /* Create default runtime object that just has key. */
111 static void
112 impl_internal_additional_register_key_only(
113  const afw_utf8_t *type_id,
114  int type_number,
115  const afw_utf8_t *key,
116  const void *value,
117  const void *register_additional_param,
118  const void **register_additional_use,
119  afw_xctx_t *xctx)
120 {
121  const afw_utf8_t * *ps;
124 
125  env = (afw_environment_internal_t *)xctx->env;
126 
127  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
128  type = apr_hash_get(env->registry_names_ht, type_id->s, type_id->len);
129  if (!type) {
130  AFW_THROW_ERROR_FZ(general, xctx,
131  "Invalid environment registry type %" AFW_UTF8_FMT,
132  AFW_UTF8_FMT_ARG(type_id));
133  }
134 
135  if (value) {
136  ps = afw_pool_calloc(xctx->env->p, sizeof(afw_utf8_t *), xctx);
137  *ps = key;
139  type->object_type_id, key, (void *)ps, true, xctx);
140  }
141  else {
142  afw_runtime_remove_object(type->object_type_id, key, xctx);
143  }
144  }
145  AFW_LOCK_END;
146 }
147 
148 
149 
150 /* Register /afw/ object as well. */
151 static void
152 impl_internal_additional_register_object(
153  const afw_utf8_t *type_id,
154  int type_number,
155  const afw_utf8_t *key,
156  const void *value,
157  const void *register_additional_param,
158  const void **register_additional_use,
159  afw_xctx_t *xctx)
160 {
163 
164  env = (afw_environment_internal_t *)xctx->env;
165 
166  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
167  type = apr_hash_get(env->registry_names_ht, type_id->s, type_id->len);
168  if (!type) {
169  AFW_THROW_ERROR_FZ(general, xctx,
170  "Invalid environment registry type %" AFW_UTF8_FMT,
171  AFW_UTF8_FMT_ARG(type_id));
172  }
173 
174  if (value) {
175  afw_runtime_env_set_object((const afw_object_t *)value, true, xctx);
176  }
177  else {
178  afw_runtime_remove_object(type->object_type_id, key, xctx);
179  }
180  }
181  AFW_LOCK_END;
182 }
183 
184 
185 
186 typedef struct {
187  const afw_utf8_t registry_type_id;
188  const afw_utf8_t property_name;
189  const afw_utf8_t object_type_id;
190  const afw_utf8_t description;
191  afw_environment_register_additional_cb_t register_additional;
192  afw_boolean_t allow_reregister;
194 
195 
196 /*
197  * Initial registry types. See afw_environemnt_registry_type_t.
198  *
199  * IMPORTANT: This must correspond 1 for 1 with
200  * afw_environment_registry_type_enum_t.
201  */
203 impl_initial_types[] = {
204 #define XX(id, register_additional, allow_reregister, property_name, \
205  object_type_id, description) \
206  { \
207  AFW_UTF8_LITERAL(AFW_STRINGIFY(id)), \
208  AFW_UTF8_LITERAL(AFW_STRINGIFY(id)), \
209  AFW_UTF8_LITERAL(object_type_id), \
210  AFW_UTF8_LITERAL(description), \
211  register_additional, \
212  allow_reregister \
213  },
215 #undef XX
216  { { NULL } }
217 };
218 
219 
220 /* Create the Adaptive Framework core environment and return base xctx. */
223  unsigned int version,
224  int argc, const char * const *argv,
225  const afw_error_t **environment_create_error)
226 {
227  apr_status_t rv;
228  afw_xctx_t *xctx;
229  const afw_pool_t *p;
230  afw_utf8_t *name;
232  int i;
234  const afw_utf8_z_t *s;
235  afw_error_t *error;
236  afw_try_t unhandled_error;
237 
238  /* Check and initialize libxml2 */
239  LIBXML_TEST_VERSION
240 
241  /* Initialize apr. */
242  rv = apr_initialize();
243  if (rv != APR_SUCCESS) {
244  *environment_create_error = &impl_early_error;
245  return NULL;
246  }
247 
248  /* Create base pool. */
249  p = afw_pool_internal_create_base_pool();
250  if (!p) goto early_error;
251 
252  /* Allocate cleared afw_error_t. */
253  error = apr_pcalloc(afw_pool_get_apr_pool(p), sizeof(afw_error_t));
254  if (!error) {
255  *environment_create_error = &impl_early_error;
256  goto early_error;
257  }
258 
259  /* Temporary way to handle errors. */
260  AFW_ERROR_INTERNAL_ON_UNHANDLED(unhandled_error) {
261  *environment_create_error = error;
263  //apr_terminate();
264  return NULL;
265  }
266 
267  /* Check version caller is complied against. */
268  s = afw_version_check(version);
269  if (s) {
270  AFW_THROW_UNHANDLED_ERROR(&unhandled_error, error, general, na, 0, s);
271  }
272 
273  /* Allocate memory for env. */
274  env = apr_pcalloc(afw_pool_get_apr_pool(p),
276  if (!env) {
277  AFW_THROW_UNHANDLED_ERROR(&unhandled_error, error, general, na, 0,
278  "apr_pcalloc() failed");
279  };
280  env->pub.p = p;
281  env->pub.pool_number = 1; /* see afw_pool_internal_create_base_pool() */
286  env->pub.debug_fd = stderr;
287  env->pub.stderr_fd = stderr;
288  env->pub.stdout_fd = stdout;
289 
290  /* Create and initialize base xctx. */
291  xctx = afw_xctx_internal_create_initialize(&unhandled_error,
292  error, env, p);
294  env->base_xctx = xctx;
295 
296  /* >>>>>>>>> Errors can be thrown at this point. <<<<<<<<< */
297 
298  /* Create data type method number hash table. */
299  env->data_type_method_number_ht = apr_hash_make(afw_pool_get_apr_pool(p));
300 
301  /* Create data type array for method arrays. */
302  env->data_type_methods = apr_array_make(afw_pool_get_apr_pool(p),
303  40, sizeof(apr_array_header_t *));
304 
305  /* Set xctx name to program name or default. */
306  if (argc > 0) {
307  name = afw_xctx_calloc_type(afw_utf8_t, xctx);
308  /* Name is after last forward or back slash. */
309  for (s = name->s = argv[0]; *s; s++) {
310  if (*s == '/' || *s == '\\') {
311  name->s = s + 1;
312  }
313  }
314  name->len = strlen(name->s);
315  xctx->name = name;
316  }
317  else {
318  xctx->name = &impl_default_name;
319  }
320  env->pub.program_name.s = xctx->name->s;
321  env->pub.program_name.len = xctx->name->len;
322 
323  /* Application id */
324  env->pub.application_id.s = xctx->name->s;
325  env->pub.application_id.len = xctx->name->len;
326 
327  /* Finish up xctx creation. */
328  afw_xctx_internal_create_finishup(xctx);
329 
331 
332  env->registry_names_ht = apr_hash_make(afw_pool_get_apr_pool(p));
333  if (!env->registry_names_ht) AFW_THROW_MEMORY_ERROR(xctx);
334 
335  env->registry_types =
336  apr_array_make(afw_pool_get_apr_pool(p), 20,
338  if (!env->registry_types) AFW_THROW_MEMORY_ERROR(xctx);
339 
340  /* Create core registry types. */
341  for (i = 0; i < afw_environemnt_registry_type_max_core_type; i++) {
342  type = afw_pool_calloc_type(p,
344  APR_ARRAY_PUSH(env->registry_types,
346  type->registry_type_id = &impl_initial_types[i].registry_type_id;
347  type->property_name = &impl_initial_types[i].property_name;
348  type->object_type_id = &impl_initial_types[i].object_type_id;
349  type->description = &impl_initial_types[i].description;
350  type->number = i;
351  type->register_additional = impl_initial_types[i].register_additional;
352  type->allow_reregister = impl_initial_types[i].allow_reregister;
353  type->auto_register = NULL;
354  type->ht = apr_hash_make(afw_pool_get_apr_pool(p));
355  if (!type->ht) AFW_THROW_MEMORY_ERROR(xctx);
356  apr_hash_set(env->registry_names_ht,
357  type->registry_type_id->s, type->registry_type_id->len, type);
358  }
359 
360  /* Register core with new xctx. */
362 
363  /* Register registry type objects and property names. */
364  for (i = 0; i < env->registry_types->nelts; i++) {
365  type = APR_ARRAY_IDX(env->registry_types, i,
369  type->registry_type_id, type, true, xctx);
371  afw_environemnt_registry_type_registry_type,
372  type->property_name, (void *)type, xctx);
373  }
374 
375  /* Create multithreaded pool lock. */
376  env->pub.multithreaded_pool_lock =
377  afw_lock_create_environment_lock(
378  &afw_s_a_lock_multithreaded_pool, p, xctx);
379 
380  /* Create environment lock. */
381  env->pub.environment_lock =
383  &afw_s_a_lock_environment,
384  &afw_s_a_lock_environment_brief,
385  &afw_s_a_lock_environment_description,
386  true, xctx);
387 
388  /* Create adaptor id anchors lock. */
389  env->pub.adaptor_id_anchor_lock =
391  &afw_s_a_lock_adaptor_id_anchor,
392  &afw_s_a_lock_adaptor_id_anchor_brief,
393  &afw_s_a_lock_adaptor_id_anchor_description,
394  true, xctx);
395 
396  /* Create authorization handler id anchors rw lock. */
399  &afw_s_a_lock_authorization_handler_id_anchor,
400  &afw_s_a_lock_authorization_handler_id_anchor_brief,
401  &afw_s_a_lock_authorization_handler_id_anchor_description,
402  xctx);
403 
404  /* Create active log list lock. */
405  env->pub.active_log_list_lock =
407  &afw_s_a_lock_log_list,
408  &afw_s_a_lock_log_list_brief,
409  &afw_s_a_lock_log_list_description,
410  true, xctx);
411 
412  /* Create flags lock. */
413  env->pub.flags_lock =
415  &afw_s_a_lock_flags,
416  &afw_s_a_lock_flags_brief,
417  &afw_s_a_lock_flags_description,
418  true, xctx);
419 
420  /*
421  * Adaptive Framework app should have a AFW_TRY right after call to create
422  * environment. If it doesn't and error occurs, terminate the environment
423  * will be release and the application will abort.
424  */
425  AFW_ERROR_INTERNAL_ON_UNHANDLED(unhandled_error) {
426  apr_terminate();
427  abort();
428  }
429 
430  /* Set error to NULL and return new xctx. */
431  *environment_create_error = NULL;
432  return xctx;
433 
434 early_error:
435  apr_terminate();
436  return NULL;
437 }
438 
439 
440 /* Release resources associated with Adaptive Framework environment. */
441 AFW_DEFINE(void)
443 {
447 }
448 
449 /* Create a new registry type. */
450 AFW_DEFINE(int)
452  const afw_utf8_t *registry_type_id,
453  const afw_utf8_t *property_name,
454  const afw_utf8_t *object_type_id,
455  const afw_utf8_t *description,
456  afw_boolean_t allow_reregister,
458  afw_environment_register_additional_cb_t register_additional,
459  void * register_additional_param,
460  afw_xctx_t *xctx)
461 {
464 
465  env = (afw_environment_internal_t *)xctx->env;
466 
467  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
468  type = apr_hash_get(env->registry_names_ht, registry_type_id->s,
469  registry_type_id->len);
470  if (type) {
471  AFW_THROW_ERROR_FZ(general, xctx,
472  "registry_type \"%" AFW_UTF8_FMT "\" is already assigned",
473  AFW_UTF8_FMT_ARG(registry_type_id));
474  }
475 
477  /* Create new registry type. */
478  type = afw_pool_calloc_type(xctx->env->p,
480  APR_ARRAY_PUSH(env->registry_types,
482  type->registry_type_id = afw_utf8_clone(registry_type_id,
483  xctx->env->p, xctx);
484  type->property_name = afw_utf8_clone(property_name,
485  xctx->env->p, xctx);
486  type->object_type_id = afw_utf8_clone(object_type_id,
487  xctx->env->p, xctx);
488  type->description = afw_utf8_clone(description, xctx->env->p, xctx);
489  type->number = env->registry_types->nelts - 1;
490  type->ht = apr_hash_make(afw_pool_get_apr_pool(xctx->env->p));
491  type->allow_reregister = allow_reregister;
492  type->auto_register = auto_register;
493  type->auto_register_specified = auto_register != NULL;
494  type->register_additional = register_additional;
495  type->register_additional_param = register_additional_param;
496  apr_hash_set(env->registry_names_ht,
497  type->registry_type_id->s, type->registry_type_id->len, type);
500  type->registry_type_id, type, true, xctx);
502  afw_environemnt_registry_type_registry_type,
503  type->property_name, (void *)type, xctx);
504  }
505  AFW_LOCK_END;
506 
507  return type->number;
508 }
509 
510 
511 /* Get the registry type associated with a registry type id. */
514  const afw_utf8_t *registry_type_id,
515  afw_boolean_t load_extension,
516  afw_xctx_t *xctx)
517 {
521 
522  env = (afw_environment_internal_t *)xctx->env;
523 
524  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
525  type = apr_hash_get(
526  env->registry_names_ht,
527  registry_type_id->s,
528  registry_type_id->len);
529 
530  if (!type && load_extension) {
531  ctx.type = &afw_s_registry_type;
532  ctx.key = registry_type_id;
533  afw_runtime_foreach(&afw_s__AdaptiveManifest_,
534  &ctx, impl_check_manifest_cb, xctx);
535  type = apr_hash_get(
536  env->registry_names_ht,
537  registry_type_id->s,
538  registry_type_id->len);
539  }
540  }
541  AFW_LOCK_END;
542 
543  return type;
544 }
545 
546 
547 /* Get the registry type name associated with a registry type number. */
550  int registry_type_number,
551  afw_xctx_t *xctx)
552 {
555 
556  env = (afw_environment_internal_t *)xctx->env;
557 
558  if (registry_type_number >= env->registry_types->nelts) {
559  return NULL;
560  }
561 
562  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
563  type = ((afw_environment_registry_type_t **)env->registry_types->elts)
564  [registry_type_number];
565  }
566  AFW_LOCK_END;
567 
568  return type;
569 }
570 
571 
572 /* Register a value by key for a registry type. */
573 AFW_DEFINE(void)
575  int type_number,
576  const afw_utf8_t *key,
577  const void *value,
578  afw_xctx_t *xctx)
579 {
581  const void *old_value;
582  afw_utf8_octet_t *new_key;
583  const afw_utf8_octet_t *use_key;
585 
586  env = (afw_environment_internal_t *)xctx->env;
587 
588  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
589 
590  if (type_number >= env->registry_types->nelts) {
591  AFW_THROW_ERROR_FZ(general, xctx, "Invalid type_number %d.",
592  type_number);
593  }
594  type = ((afw_environment_registry_type_t **)env->registry_types->elts)
595  [type_number];
596 
597  use_key = key->s;
598  old_value = apr_hash_get(type->ht, key->s, key->len);
599  if (old_value && !type->allow_reregister) {
600  AFW_THROW_ERROR_FZ(general, xctx,
601  "%" AFW_UTF8_FMT " %" AFW_UTF8_FMT " is already registered",
603  &impl_initial_types[type_number].registry_type_id),
604  AFW_UTF8_FMT_ARG(key));
605  }
607  if (value && !old_value) {
608  new_key = afw_pool_calloc(xctx->env->p, key->len, xctx);
609  memcpy(new_key, key->s, key->len);
610  use_key = new_key;
611  }
612 
613  apr_hash_set(type->ht, use_key, key->len, value);
614 
615  if (type->register_additional) {
616  type->register_additional(
617  type->registry_type_id, type->number, key, value,
618  type->register_additional_param, &type->register_additional_use,
619  xctx);
620  }
621  }
622  AFW_LOCK_END;
623 };
624 
625 
626 
627 static afw_boolean_t
628 impl_check_manifest_cb(
629  const afw_object_t *object,
630  void *context,
631  afw_xctx_t *xctx)
632 {
633  const afw_value_t *registers_value;
634  const afw_utf8_t *extension_id;
635  const afw_utf8_t *module_path;
636  afw_utf8_t registry_type_id;
637  afw_utf8_t registry_key;
638  const afw_utf8_t *entry;
639  const afw_iterator_t *iterator;
640  const afw_list_t *list;
641  impl_check_manifest_cb_context_t *ctx = context;
642 
643  if (!object) {
644  return false;
645  }
646 
647  registers_value = afw_object_get_property(object, &afw_s_registers, xctx);
648  if (!registers_value) {
649  return false;
650  }
651 
652  if (!afw_value_is_list_of_string(registers_value) &&
653  !afw_value_is_list_of_anyURI(registers_value))
654  {
655  return false;
656  }
657 
658  /* Loop through entries. */
659  list = ((const afw_value_list_t *)registers_value)->internal;
660  for (iterator = NULL;;)
661  {
662  afw_list_get_next_internal(list, &iterator, NULL,
663  (const void **)&entry, xctx);
664  if (!entry) {
665  break;
666  }
667 
668  /*
669  * Separate <registry type id>/<registry key> from entry and load
670  * extension if match.
671  */
672  for (
673  registry_type_id.s = entry->s,
674  registry_key.s = entry->s,
675  registry_key.len = entry->len;
676  registry_key.len > 0 && *registry_key.s != '/';
677  registry_key.len--, registry_key.s++);
678 
679  if (registry_key.len > 0)
680  {
681  registry_type_id.len = registry_key.s - registry_type_id.s;
682  registry_key.s++;
683  registry_key.len--;
684  if (afw_utf8_equal(ctx->type, &registry_type_id) &&
685  afw_utf8_equal(ctx->key, &registry_key))
686  {
687  extension_id = afw_object_old_get_property_as_string(object,
688  &afw_s_extensionId, xctx);
689  module_path = afw_object_old_get_property_as_string(object,
690  &afw_s_modulePath, xctx);
691  if (extension_id && module_path) {
692  afw_environment_load_extension(extension_id, module_path,
693  NULL, xctx);
694  /*Return indicating complete. */
695  return true;
696  }
697  }
698  }
699  }
700 
701  /* Return indicating not to short circuit */
702  return false;
703 }
704 
705 
706 
707 /* Check to see if a key exists. */
710  int type_number,
711  const afw_utf8_t *key,
712  afw_xctx_t *xctx)
713 {
715  afw_boolean_t result;
717 
718  env = (afw_environment_internal_t *)xctx->env;
719 
720  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
721  if (type_number < 0 ||
722  type_number >= env->registry_types->nelts)
723  {
724  AFW_THROW_ERROR_FZ(general, xctx, "Invalid type_number.",
725  type_number);
726  }
727 
728  type = ((afw_environment_registry_type_t **)env->registry_types->elts)
729  [type_number];
730 
731  result = (apr_hash_get(type->ht, key->s, key->len) != NULL);
732  }
733  AFW_LOCK_END;
734 
735  return result;
736 }
737 
738 
739 
740 /* Get the value associated with a key for a registry type. */
741 AFW_DEFINE(void *)
743  int type_number,
744  const afw_utf8_t *key,
745  afw_xctx_t *xctx)
746 {
748  void *result;
751 
752  env = (afw_environment_internal_t *)xctx->env;
753 
754  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
755 
756  if (type_number < 0 ||
757  type_number >= env->registry_types->nelts)
758  {
759  AFW_THROW_ERROR_FZ(general, xctx, "Invalid type_number.",
760  type_number);
761  }
762 
763  type = ((afw_environment_registry_type_t **)env->registry_types->elts)
764  [type_number];
765 
766  result = apr_hash_get(type->ht, key->s, key->len);
767 
768  /*
769  * If no result yet, see if there is an extension manifest that provides
770  * it, load the extension.
771  */
772  if (!result) {
773  ctx.type = type->registry_type_id;
774  ctx.key = key;
775  afw_runtime_foreach(&afw_s__AdaptiveManifest_,
776  &ctx, impl_check_manifest_cb, xctx);
777  result = apr_hash_get(type->ht, key->s, key->len);
778  }
779 
780  /* If still no result and auto_register, do auto register. */
781  if (!result && type->auto_register) {
782  result = type->auto_register(type->registry_type_id, key, xctx);
783  afw_environment_registry_register(type_number, key, result, xctx);
784  }
785 
786  }
787  AFW_LOCK_END;
788 
789  return result;
790 };
791 
792 
793 /* Limited get the value associated with a key for a registry type. */
794 AFW_DEFINE(void *)
795 afw_environment_registry_get_xctxless(
796  const afw_environment_t *env,
797  int type_number,
798  const afw_utf8_t *key)
799 {
801  void *result;
803 
804  self = (afw_environment_internal_t *)env;
805 
806  if (type_number < 0 ||
807  type_number >= self->registry_types->nelts)
808  {
809  return NULL;
810  }
811 
812  type = ((afw_environment_registry_type_t **)self->registry_types->elts)
813  [type_number];
814 
815  result = apr_hash_get(type->ht, key->s, key->len);
816 
817  return result;
818 }
819 
820 
821 
822 /* Call a callback function for each entry of a registry type. */
823 AFW_DEFINE(void)
825  int type_number,
827  void *data,
828  const afw_pool_t *p,
829  afw_xctx_t *xctx)
830 {
833  apr_hash_index_t *hi;
834  void *value;
835  afw_utf8_octet_t *key_s;
836  apr_ssize_t key_len;
837 
838  env = (afw_environment_internal_t *)xctx->env;
839 
840  if (type_number >= env->registry_types->nelts) {
841  AFW_THROW_ERROR_FZ(general, xctx, "Invalid type_number.",
842  type_number);
843  }
844 
845  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
846  type = ((afw_environment_registry_type_t **)env->registry_types->elts)
847  [type_number];
848 
849  for (hi = apr_hash_first(afw_pool_get_apr_pool(p), type->ht);
850  hi;
851  hi = apr_hash_next(hi))
852  {
853  apr_hash_this(hi, (const void **)&key_s, &key_len, &value);
854  if (callback(type_number, data, key_s, key_len, value, p, xctx)) {
855  break;
856  }
857  }
858  }
859  AFW_LOCK_END;
860 }
861 
862 
863 
864 
865 /* Create and register a configuration type. */
866 AFW_DEFINE(void)
868  const afw_utf8_t *conf_type_id,
870  const afw_utf8_t *title,
871  const afw_utf8_t *description,
872  const afw_utf8_t *id_property_name,
873  const afw_utf8_t *id_registry_type_id,
874  const afw_utf8_t *id_runtime_object_type_id,
875  const afw_utf8_t *subtype_property_name,
876  const afw_utf8_t *subtype_registry_type_id,
877  const afw_utf8_t *subtype_runtime_object_type_id,
878  afw_boolean_t is_unique,
879  afw_xctx_t *xctx)
880 {
881  afw_environment_conf_type_t *conf_type;
882  const afw_pool_t *p;
883  const afw_utf8_t *s;
884 
885  p = xctx->env->p;
886  conf_type = afw_pool_calloc_type(p,
888 
889  s = afw_utf8_clone(conf_type_id, p, xctx);
890  conf_type->conf_type_id.len = s->len;
891  conf_type->conf_type_id.s = s->s;
892  conf_type->create = create;
893  conf_type->title =
894  afw_utf8_clone(title, p, xctx);
895  conf_type->description =
896  afw_utf8_clone(description, p, xctx);
897  conf_type->id_property_name =
898  afw_utf8_clone(id_property_name, p, xctx);
899  conf_type->id_registry_type_id =
900  afw_utf8_clone(id_registry_type_id, p, xctx);
901  conf_type->id_runtime_object_type_id =
902  afw_utf8_clone(id_runtime_object_type_id, p, xctx);
903  conf_type->subtype_property_name =
904  afw_utf8_clone(subtype_property_name, p, xctx);
905  conf_type->subtype_registry_type_id =
906  afw_utf8_clone(subtype_registry_type_id, p, xctx);
907  conf_type->subtype_runtime_object_type_id =
908  afw_utf8_clone(subtype_runtime_object_type_id, p, xctx);
909 
910  conf_type->is_unique = is_unique;
911 
913  afw_environemnt_registry_type_conf_type,
914  &conf_type->conf_type_id,
915  conf_type,
916  xctx);
917 };
918 
919 
920 /* Load and initialize environment extension. */
923  const afw_utf8_t *extension_id,
924  const afw_utf8_t *module_path,
925  const afw_object_t *properties,
926  afw_xctx_t *xctx)
927 {
928  apr_status_t rv;
929  apr_dso_handle_t *dso_handle;
930  const afw_extension_t *extension;
931  const afw_utf8_z_t *path_z;
932  char dsoError[256];
933  const afw_extension_t **extension_instance;
934  const afw_pool_t *p;
936  const afw_utf8_t *dso_suffix;
937  const afw_object_t *manifest;
938  const afw_utf8_t *extensionId;
939  const afw_utf8_t *modulePath;
940  const afw_utf8_t *extension_id_for_message;
941 
942  env = (afw_environment_internal_t *)xctx->env;
943  p = env->pub.p;
944 
945  extensionId = NULL;
946  modulePath = NULL;
947  if (properties) {
948  extensionId = afw_object_old_get_property_as_string(properties,
949  &afw_s_extensionId, xctx);
950  if (extensionId) {
951  if (extension_id && !afw_utf8_equal(extension_id, extensionId)) {
952  AFW_THROW_ERROR_FZ(general, xctx,
953  "extension_id parameter (%" AFW_UTF8_FMT
954  ") does not match properties.extension_id (%" AFW_UTF8_FMT,
955  AFW_UTF8_FMT_ARG(extension_id),
956  AFW_UTF8_FMT_ARG(extensionId));
957  }
958  }
959 
960  modulePath = afw_object_old_get_property_as_string(properties,
961  &afw_s_modulePath, xctx);
962  if (modulePath) {
963  if (module_path && !afw_utf8_equal(module_path, modulePath)) {
964  AFW_THROW_ERROR_FZ(general, xctx,
965  "module_path parameter (%" AFW_UTF8_FMT
966  ") does not match properties.extension_id (%" AFW_UTF8_FMT,
967  AFW_UTF8_FMT_ARG(module_path),
968  AFW_UTF8_FMT_ARG(modulePath));
969  }
970  }
971  }
972 
973  if (!extension_id && !module_path) {
974  AFW_THROW_ERROR_Z(general,
975  "Either extension_id or module_path must be supplied",
976  xctx);
977  }
978 
979  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
980 
981  /* If extension_id specified, ... */
982  if (extension_id) {
983 
984  extension_id_for_message = extension_id;
985 
986  /* If extension is already loaded, just return. */
987  extension = afw_environment_registry_get(
988  afw_environemnt_registry_type_extension,
989  extension_id, xctx);
990  if (extension) {
991  break;
992  }
993 
994  /* If there is not a properties object, make one. */
995  if (!properties)
996  {
997  extension_id = afw_utf8_clone(extension_id, p, xctx);
998  properties = afw_object_create_managed(p, xctx);
1000  &afw_s_extensionId, extension_id, xctx);
1001  }
1002 
1003  if (!module_path) {
1004  manifest = afw_runtime_get_object(&afw_s__AdaptiveManifest_,
1005  extension_id, xctx);
1006  if (manifest) {
1007  module_path = afw_object_old_get_property_as_string(manifest,
1008  &afw_s_modulePath, xctx);
1009  }
1010  }
1011 
1012  if (!module_path) {
1013  AFW_THROW_ERROR_FZ(general, xctx,
1014  "\"modulePath\" needed for \"extension\" %" AFW_UTF8_FMT ".",
1015  AFW_UTF8_FMT_ARG(extension_id));
1016  }
1017 
1018  /* Insure modulePath property matches what was decided.
1019  afw_object_set_property_as_string(properties,
1020  &afw_s_modulePath, module_path, xctx); */
1021 
1022  /* Prepare properties. Supply type=extension if needed. */
1023  if (!afw_object_has_property(properties, &afw_s_type, xctx)) {
1025  &afw_s_type, &afw_s_extension, xctx);
1026  }
1028  properties, xctx);
1029  }
1030 
1031  /* If just path_z specified. */
1032  else {
1033 
1034  extension_id_for_message = &afw_s_unknown;
1035 
1036  /* If there is not a properties object, make one. */
1037  if (!properties)
1038  {
1039  properties = afw_object_create_managed(p, xctx);
1041  &afw_s_modulePath, module_path, xctx);
1042  }
1043 
1044  }
1045 
1046  /* Load the extension module. */
1047  path_z = afw_utf8_to_utf8_z(module_path, p, xctx);
1048  rv = apr_dso_load(&(dso_handle), (const char *)path_z,
1050  if (rv != APR_SUCCESS) {
1051  dso_suffix = afw_os_get_dso_suffix();
1052  if (!afw_utf8_ends_with(module_path, dso_suffix)) {
1053  path_z = afw_utf8_z_printf(p, xctx,
1054  "%" AFW_UTF8_FMT "%" AFW_UTF8_FMT,
1055  AFW_UTF8_FMT_ARG(module_path),
1056  AFW_UTF8_FMT_ARG(dso_suffix));
1057  rv = apr_dso_load(&(dso_handle), (const char *)path_z,
1059  }
1060  }
1061  if (rv != APR_SUCCESS) {
1062  path_z = afw_utf8_z_printf(p, xctx,
1063  AFW_CONFIG_INSTALL_FULL_LIBDIR "/%" AFW_UTF8_FMT,
1064  AFW_UTF8_FMT_ARG(module_path));
1065  rv = apr_dso_load(&(dso_handle), (const char *)path_z,
1067  if (rv != APR_SUCCESS) {
1068  dso_suffix = afw_os_get_dso_suffix();
1069  if (!afw_utf8_ends_with(module_path, dso_suffix)) {
1070  path_z = afw_utf8_z_printf(p, xctx,
1071  AFW_CONFIG_INSTALL_FULL_LIBDIR "/%" AFW_UTF8_FMT "%" AFW_UTF8_FMT,
1072  AFW_UTF8_FMT_ARG(module_path),
1073  AFW_UTF8_FMT_ARG(dso_suffix));
1074  rv = apr_dso_load(&(dso_handle), (const char *)path_z,
1076  }
1077  }
1078  }
1079 
1080  if (rv != APR_SUCCESS) {
1081  memset(&dsoError, 0, sizeof(dsoError));
1082  apr_dso_error(dso_handle, dsoError, sizeof(dsoError));
1083  afw_pool_release(p, xctx);
1084  AFW_THROW_ERROR_RV_FZ(general, apr, rv, xctx,
1085  "Error loading extension extension_id=%" AFW_UTF8_FMT
1086  " modulePath=%s: %s",
1087  AFW_UTF8_FMT_ARG(extension_id_for_message), path_z, dsoError);
1088  }
1089 
1090  /* Get the function pointer to the initialization function. */
1091  rv = apr_dso_sym((apr_dso_handle_sym_t *)&extension_instance,
1093  if (rv != APR_SUCCESS) {
1094  apr_dso_unload(dso_handle);
1095  afw_pool_release(p, xctx);
1096  AFW_THROW_ERROR_RV_FZ(general, apr, rv, xctx,
1097  "Error finding symbol " AFW_ENVIRONMENT_Q_EXTENSION_INSTANCE
1098  " in extension_id=%" AFW_UTF8_FMT " modulePath=%s",
1099  AFW_UTF8_FMT_ARG(extension_id_for_message), path_z);
1100  }
1101 
1102  /*
1103  * If extension_id was not supplied, get it from extension instance. If
1104  * it's already registered, break.
1105  */
1106  if (extension_id_for_message == &afw_s_unknown) {
1107  extension_id = &(*extension_instance)->extension_id;
1108  extension = afw_environment_registry_get(
1109  afw_environemnt_registry_type_extension,
1110  extension_id, xctx);
1111  if (extension) {
1112  break;
1113  }
1114  }
1115 
1116  /* Insure compiled against appropriate AFW library and dependents. */
1118  &(*extension_instance)->extension_id,
1119  (*extension_instance)->afw_compiled_version_hex,
1120  xctx);
1121 
1122  /* Call the initialization function. */
1123  extension = afw_extension_initialize(
1124  (*extension_instance), properties, p, xctx);
1125  extension_id = &extension->extension_id;
1126 
1127  /* Set extensionId in properties */
1129  &afw_s_extensionId, extension_id, xctx);
1130 
1131  /* Register extension. */
1133  afw_environemnt_registry_type_extension,
1134  extension_id, extension, xctx);
1135  AFW_LOG_FZ(info, xctx,
1136  "Extension %" AFW_UTF8_FMT " loaded.",
1137  AFW_UTF8_FMT_ARG(extension_id));
1138 
1139  }
1140 
1141  AFW_LOCK_END;
1142 
1143  return extension;
1144 }
1145 
1146 
1147 /* Register a data type. */
1148 AFW_DEFINE(void)
1150  const afw_utf8_t *data_type_id,
1151  const afw_data_type_t *data_type,
1152  afw_xctx_t *xctx)
1153 {
1154  afw_data_type_t *dt;
1156  apr_array_header_t **h;
1157 
1158  env = (afw_environment_internal_t *)xctx->env;
1159 
1160  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
1161 
1162  /* Make sure data type is not already registered. */
1163  if (afw_environment_get_data_type(data_type_id, xctx)) {
1164  AFW_THROW_ERROR_FZ(general, xctx,
1165  "Data type %" AFW_UTF8_FMT " is already registered",
1166  AFW_UTF8_FMT_ARG(data_type_id));
1167  }
1168 
1169  /* If data_type number unassigned, make copy and assign it. */
1170  if (data_type->data_type_number == 0) {
1171  dt = afw_xctx_calloc(sizeof(afw_data_type_t), xctx);
1172  memcpy(dt, data_type, sizeof(afw_data_type_t));
1173  dt->data_type_number = env->data_type_methods->nelts;
1174  data_type = dt;
1175  }
1176 
1177  /* Only core data types can have preassigned numbers. */
1178  else if (env->core_data_types_registered) {
1179  AFW_THROW_ERROR_Z(general,
1180  "Only core data types can have preassigned data type number",
1181  xctx);
1182  }
1183 
1184  /* Assign empty array to data type's position. */
1185  while (env->data_type_methods->nelts < data_type->data_type_number) {
1186  APR_ARRAY_PUSH(env->data_type_methods, apr_array_header_t *) = NULL;
1187  }
1188  h = &((apr_array_header_t **)env->data_type_methods->elts)
1189  [data_type->data_type_number - 1];
1190  if (*h) {
1191  AFW_THROW_ERROR_FZ(general, xctx,
1192  "Data type number %d is already registered.",
1193  data_type->data_type_number);
1194  }
1195  *h = apr_array_make(afw_pool_get_apr_pool(xctx->p),
1196  30, sizeof(apr_array_header_t *));
1197 
1198  /* Register data type. */
1200  afw_environemnt_registry_type_data_type,
1201  data_type_id,
1202  data_type,
1203  xctx);
1204 
1205  /* Add data type object to runtime. */
1206  afw_runtime_env_set_object(data_type->object, false, xctx);
1207  }
1208 
1209  AFW_LOCK_END;
1210 }
1211 
1212 static const afw_value_function_parameter_t *
1213 impl_resolve_function_parameter(
1214  const afw_value_function_parameter_t *parameter,
1215  afw_xctx_t *xctx)
1216 {
1217  const afw_pool_t *p = xctx->env->p;
1219 
1220  if (!parameter) {
1221  return NULL;
1222  }
1223 
1224  result = afw_memory_dup(parameter,
1226  p, xctx);
1227 
1228  result->meta.inf = &afw_runtime_inf__AdaptiveFunctionParameter_;
1229 
1230  if (parameter->dataType.s) {
1231  result->data_type = afw_environment_get_data_type(&parameter->dataType,
1232  xctx);
1233 
1234  }
1235 
1236  return result;
1237 }
1238 
1239 
1240 
1241 static const afw_value_function_definition_t *
1242 impl_resolve_function(
1243  const afw_value_function_definition_t *function,
1244  afw_xctx_t *xctx)
1245 {
1246  const afw_pool_t *p = xctx->env->p;
1248  afw_size_t count;
1249  const afw_value_function_parameter_t **parameters;
1251 
1252  result = afw_memory_dup(function, sizeof(afw_value_function_definition_t),
1253  p, xctx);
1254 
1255  result->inf = &afw_value_function_definition_inf;
1256 
1257  object = afw_memory_dup(function->object,
1258  sizeof(afw_runtime_object_indirect_t), p, xctx);
1259  object->pub.inf = &afw_runtime_inf__AdaptiveFunction_;
1260  object->internal = result;
1261  result->object = (const afw_object_t *)object;
1262  if (result->dataType.len > 0) {
1264  xctx);
1265  }
1266 
1267  if (result->data_type) {
1268  AFW_THROW_ERROR_Z(general, "Not implemented", xctx);
1269  }
1270 
1271  result->returns = impl_resolve_function_parameter(function->returns, xctx);
1272 
1273  if (result->parameters) {
1274  for (count = 0; function->parameters[count]; count++);
1275  result->parameters = parameters = afw_pool_malloc(p,
1276  sizeof(afw_value_function_parameter_t *) * (count + 1),
1277  xctx);
1278  parameters[count] = NULL;
1279 
1280  for (count = 0; function->parameters[count]; count++) {
1281  parameters[count] =
1282  impl_resolve_function_parameter(
1283  function->parameters[count],
1284  xctx);
1285  }
1286  }
1287 
1288  return result;
1289 }
1290 
1291 
1292 
1293 /* Register a function. */
1294 AFW_DEFINE(void)
1296  const afw_utf8_t *function_id,
1297  const afw_value_function_definition_t *function,
1298  afw_xctx_t *xctx)
1299 {
1301  int *method_number;
1302  apr_array_header_t *methods;
1304 
1305  if (!function->inf) {
1306  function = impl_resolve_function(function, xctx);
1307  }
1308 
1309  env = (afw_environment_internal_t *)xctx->env;
1310 
1311  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
1312 
1313  /*
1314  * If data type is not resolved in function definition, which is the
1315  * case if this is not core (not src/afw libafw), clone the function
1316  * defintion and polymorphic parameters then resolve their data type
1317  * and data type method number in the clone.
1318  */
1319  if (function->dataType.len > 0 && !function->data_type) {
1321  xctx);
1322  memcpy(f, function, sizeof(afw_value_function_definition_t));
1323  function = f;
1325  &function->dataType, xctx);
1326  if (!function->data_type) {
1327  AFW_THROW_ERROR_FZ(general, xctx,
1328  "dataType %" AFW_UTF8_FMT " doesn't exist",
1329  AFW_UTF8_FMT_ARG(&function->dataType));
1330  }
1331  if (function->dataTypeMethodNumber != 0)
1332  {
1333  AFW_THROW_ERROR_Z(general,
1334  "Only core function can have preassigned "
1335  "dataTypeMethodNumber",
1336  xctx);
1337  }
1338  method_number = apr_hash_get(
1339  env->data_type_method_number_ht,
1340  function->untypedFunctionId.s,
1341  function->untypedFunctionId.len);
1342  if (method_number) {
1343  f->dataTypeMethodNumber = *method_number;
1344  }
1345  else {
1346  f->dataTypeMethodNumber = apr_hash_count(
1347  env->data_type_method_number_ht) + 1;
1348  apr_hash_set(env->data_type_method_number_ht,
1349  function->untypedFunctionId.s,
1350  function->untypedFunctionId.len,
1351  &function->dataTypeMethodNumber);
1352  }
1353 
1355  }
1356 
1358  /* Only core functions can have preassigned numbers. */
1359  if (env->core_functions_registered &&
1360  function->dataTypeMethodNumber != 0)
1361  {
1362  AFW_THROW_ERROR_Z(general,
1363  "Only core function can have preassigned function number",
1364  xctx);
1365  }
1366 
1367  /* Make sure data type method is in hash table. */
1368  if (function->data_type) {
1369 
1370  method_number = apr_hash_get(env->data_type_method_number_ht,
1371  function->untypedFunctionId.s,
1372  function->untypedFunctionId.len);
1373  if (method_number) {
1374  if (function->dataTypeMethodNumber == 0) {
1375  f->dataTypeMethodNumber = *method_number;
1376  }
1377  }
1378  else {
1379  if (function->dataTypeMethodNumber == 0) {
1380  f->dataTypeMethodNumber = apr_hash_count(
1381  env->data_type_method_number_ht) + 1;
1382  }
1383  apr_hash_set(env->data_type_method_number_ht,
1384  function->untypedFunctionId.s,
1385  function->untypedFunctionId.len,
1386  &function->dataTypeMethodNumber);
1387  }
1388  }
1389 
1390  /* Register function. */
1392  afw_environemnt_registry_type_function,
1393  function_id,
1394  function,
1395  xctx);
1396 
1397  /* Register camelCaseFunctionLabel. */
1398  if (function->camelCaseFunctionLabel.len > 0 &&
1399  !afw_utf8_equal(&function->camelCaseFunctionLabel, function_id))
1400  {
1402  afw_environemnt_registry_type_function,
1403  &function->camelCaseFunctionLabel,
1404  function,
1405  xctx);
1406  }
1407 
1408  /* Register afwCamelCaseFunctionLabel. */
1409  if (function->afwCamelCaseFunctionLabel.len > 0 &&
1410  !afw_utf8_equal(&function->afwCamelCaseFunctionLabel, function_id)
1411  &&
1412  !afw_utf8_equal(&function->afwCamelCaseFunctionLabel,
1413  &function->camelCaseFunctionLabel)
1414  )
1415  {
1417  afw_environemnt_registry_type_function,
1418  &function->afwCamelCaseFunctionLabel,
1419  function,
1420  xctx);
1421  }
1422 
1423  /* Register function_label. */
1424  if (function->afwCamelCaseFunctionLabel.len > 0 &&
1425  !afw_utf8_equal(&function->functionLabel, function_id)
1426  &&
1427  !afw_utf8_equal(&function->afwCamelCaseFunctionLabel,
1428  &function->functionLabel)
1429  &&
1430  !afw_utf8_equal(&function->afwCamelCaseFunctionLabel,
1431  &function->camelCaseFunctionLabel)
1432  )
1433  {
1435  afw_environemnt_registry_type_function,
1436  &function->functionLabel,
1437  function,
1438  xctx);
1439  }
1440 
1441  /* If there was a data type id, set method. */
1442  if (function->dataType.len > 0) {
1443  methods = ((apr_array_header_t **)env->data_type_methods->elts)
1444  [function->data_type->data_type_number - 1];
1445  while (methods->nelts < function->dataTypeMethodNumber) {
1446  APR_ARRAY_PUSH(methods, const afw_value_function_definition_t *) =
1447  NULL;
1448  }
1449  ((const afw_value_function_definition_t **)methods->elts)
1450  [function->dataTypeMethodNumber - 1] = function;
1451  }
1452 
1453  /* Add function object to runtime. */
1454  afw_runtime_env_set_object(function->object, false, xctx);
1455  }
1456  AFW_LOCK_END;
1457 }
1458 
1459 
1460 /* Get the qualified function instance. */
1463  const afw_utf8_t *qualifier,
1464  const afw_utf8_t *name,
1465  afw_xctx_t *xctx)
1466 {
1467  const afw_value_function_definition_t *result;
1468  int *method_number;
1470  const afw_data_type_t *data_type;
1471  apr_array_header_t *methods;
1472 
1473  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
1474 
1475  if (qualifier && qualifier->s) {
1476  env = (afw_environment_internal_t *)xctx->env;
1477  result = NULL;
1478  data_type = afw_environment_get_data_type(qualifier, xctx);
1479  if (data_type) {
1480  method_number = apr_hash_get(env->data_type_method_number_ht,
1481  name->s, name->len);
1482  if (method_number) {
1483  methods = ((apr_array_header_t **)
1484  env->data_type_methods->elts)
1485  [data_type->data_type_number - 1];
1486  if (*method_number <= methods->nelts) {
1487  result = ((const afw_value_function_definition_t **)
1488  methods->elts)[(*method_number) - 1];
1489  }
1490  }
1491  }
1492  }
1493 
1494  else {
1495  result = (const afw_value_function_definition_t *)
1497  afw_environemnt_registry_type_function, name, xctx);
1498  }
1499  }
1500  AFW_LOCK_END;
1501 
1502  return result;
1503 }
1504 
1505 
1506 /* Get the function associated with a data type method. */
1509  const afw_data_type_t *data_type,
1510  afw_integer_t dataTypeMethodNumber,
1511  afw_xctx_t *xctx)
1512 {
1513  const afw_value_function_definition_t *result;
1514  apr_array_header_t *d;
1516 
1517  env = (afw_environment_internal_t *)xctx->env;
1518  result = NULL;
1519 
1520  if (!data_type) {
1521  AFW_THROW_ERROR_Z(general, "Data type is NULL", xctx);
1522  }
1523 
1524  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
1525 
1526  if (data_type->data_type_number > env->data_type_methods->nelts) {
1527  AFW_THROW_ERROR_Z(general, "Data type number out of range", xctx);
1528  }
1529 
1530  d = ((apr_array_header_t **)env->data_type_methods->elts)
1531  [data_type->data_type_number - 1];
1532  if (dataTypeMethodNumber <= d->nelts) {
1533  result = ((const afw_value_function_definition_t **)d->elts)
1534  [dataTypeMethodNumber - 1];
1535  }
1536 
1537  }
1538  AFW_LOCK_END;
1539 
1540  return result;
1541 }
1542 
1543 
1544 /* Register a NULL terminated list of data types. */
1545 AFW_DEFINE(void)
1547  const afw_data_type_t * const *data_types,
1548  afw_xctx_t *xctx)
1549 {
1550  const afw_data_type_t * const *e;
1551 
1552  for (e = data_types; *e; e++) {
1554  &(*e)->data_type_id, *e, xctx);
1555  }
1556 
1557 }
1558 
1559 
1560 /* Register a NULL terminated list of functions. */
1561 AFW_DEFINE(void)
1563  const afw_value_function_definition_t **functions,
1564  afw_xctx_t *xctx)
1565 {
1566  const afw_value_function_definition_t **function;
1567 
1568  for (function = functions; *function; function++) {
1569  afw_environment_register_function(&(*function)->functionId, *function,
1570  xctx);
1571  }
1572 }
1573 
1574 
1575 /* Register an adaptor factory. */
1576 AFW_DEFINE(void)
1578  const afw_utf8_t *adaptor_type,
1579  const afw_adaptor_factory_t *adaptor_factory,
1580  afw_xctx_t *xctx)
1581 {
1582  const afw_pool_t *p = xctx->env->p;
1583  const afw_utf8_t *flag_id;
1584  const afw_utf8_t *detail_flag_id;
1585  const afw_utf8_t *brief;
1586  const afw_utf8_t *description;
1587 
1588  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
1589 
1591  afw_environemnt_registry_type_adaptor_type,
1592  adaptor_type,
1593  adaptor_factory,
1594  xctx);
1595 
1596  detail_flag_id = afw_utf8_printf(p, xctx,
1597  "trace:adaptorType:%" AFW_UTF8_FMT ":detail",
1598  AFW_UTF8_FMT_ARG(adaptor_type));
1599 
1600  brief = afw_utf8_printf(p, xctx,
1601  "Debug trace adaptor type %" AFW_UTF8_FMT,
1602  AFW_UTF8_FMT_ARG(adaptor_type));
1603 
1604  description = afw_utf8_printf(p, xctx,
1605  "This produces a basic plus additional detail trace for "
1606  "all adaptors of type %" AFW_UTF8_FMT ".",
1607  AFW_UTF8_FMT_ARG(adaptor_type));
1608 
1609  afw_environment_register_flag(detail_flag_id, brief, description,
1610  &afw_s_a_flag_trace_adaptor_detail, xctx);
1611 
1612  flag_id = afw_utf8_printf(p, xctx,
1613  "trace:adaptorType:%" AFW_UTF8_FMT,
1614  AFW_UTF8_FMT_ARG(adaptor_type));
1615 
1616  brief = afw_utf8_printf(p, xctx,
1617  "Trace adaptor type %" AFW_UTF8_FMT,
1618  AFW_UTF8_FMT_ARG(adaptor_type));
1619 
1620  description = afw_utf8_printf(p, xctx,
1621  "This produces a basic trace of all adaptors of type %" AFW_UTF8_FMT ".",
1622  AFW_UTF8_FMT_ARG(adaptor_type));
1623 
1624  afw_environment_register_flag(flag_id, brief, description,
1625  &afw_s_a_flag_trace_adaptor, xctx);
1626 
1627  afw_flag_add_included_by(flag_id, detail_flag_id, xctx);
1628  }
1629  AFW_LOCK_END;
1630 }
1631 
1632 
1633 
1634 /* Register an authorization handler factory. */
1635 AFW_DEFINE(void)
1637  const afw_utf8_t *authorization_handler_type,
1638  const afw_authorization_handler_factory_t *authorization_handler_factory,
1639  afw_xctx_t *xctx)
1640 {
1641  const afw_pool_t *p = xctx->env->p;
1642  const afw_utf8_t *flag_id;
1643  const afw_utf8_t *detail_flag_id;
1644  const afw_utf8_t *brief;
1645  const afw_utf8_t *description;
1646 
1647  AFW_LOCK_BEGIN(xctx->env->environment_lock) {
1648 
1650  afw_environemnt_registry_type_authorization_handler_type,
1651  authorization_handler_type,
1652  authorization_handler_factory,
1653  xctx);
1654 
1655  detail_flag_id = afw_utf8_printf(p, xctx,
1656  "trace:authorizationHandlerType:%" AFW_UTF8_FMT ":detail",
1657  AFW_UTF8_FMT_ARG(authorization_handler_type));
1658 
1659  brief = afw_utf8_printf(p, xctx,
1660  "Debug trace authorizationHandler type %" AFW_UTF8_FMT,
1661  AFW_UTF8_FMT_ARG(authorization_handler_type));
1662 
1663  description = afw_utf8_printf(p, xctx,
1664  "This produces a basic plus additional detail trace for "
1665  "all authorizationHandlers of type %" AFW_UTF8_FMT ".",
1666  AFW_UTF8_FMT_ARG(authorization_handler_type));
1667 
1668  afw_environment_register_flag(detail_flag_id, brief, description,
1669  &afw_s_a_flag_trace_authorizationHandler_detail, xctx);
1670 
1671  flag_id = afw_utf8_printf(p, xctx,
1672  "trace:authorizationHandlerType:%" AFW_UTF8_FMT,
1673  AFW_UTF8_FMT_ARG(authorization_handler_type));
1674 
1675  brief = afw_utf8_printf(p, xctx,
1676  "Trace authorizationHandler type %" AFW_UTF8_FMT,
1677  AFW_UTF8_FMT_ARG(authorization_handler_type));
1678 
1679  description = afw_utf8_printf(p, xctx,
1680  "This produces a basic trace of all authorizationHandlers "
1681  "of type %" AFW_UTF8_FMT ".",
1682  AFW_UTF8_FMT_ARG(authorization_handler_type));
1683 
1684  afw_environment_register_flag(flag_id, brief, description,
1685  &afw_s_a_flag_trace_authorizationHandler, xctx);
1686 
1687  afw_flag_add_included_by(flag_id, detail_flag_id, xctx);
1688  }
1689  AFW_LOCK_END;
1690 }
1691 
1692 
1693 AFW_DEFINE(void)
1695 {
1697 
1698  env = (afw_environment_internal_t *)xctx->env;
1699  env->pub.debug_fd = fd;
1700 }
1701 
1702 
1703 AFW_DEFINE(void)
1705 {
1707 
1708  env = (afw_environment_internal_t *)xctx->env;
1709  env->pub.stderr_fd = fd;
1710 }
1711 
1712 
1713 AFW_DEFINE(void)
1715 {
1717 
1718  env = (afw_environment_internal_t *)xctx->env;
1719  env->pub.stdout_fd = fd;
1720 }
AFW_DEFINE(const afw_object_t *)
#define AFW_DECLARE(type)
Declare a public afw function.
Adaptive Framework Core Internal.
afw_runtime_inf__AdaptiveFunction_
Runtime object inf for object type AdaptiveFunction
afw_runtime_inf__AdaptiveEnvironmentRegistryType_
Runtime object inf for object type AdaptiveEnvironmentRegistryType
afw_runtime_inf__AdaptiveFunctionParameter_
Runtime object inf for object type AdaptiveFunctionParameter
afw_authorization_mode_id_core_value
AdaptiveAuthorizationMode core.
#define afw_value_is_list_of_anyURI(A_VALUE)
Macro to determine if value is evaluated list of anyURI.
#define afw_object_old_get_property_as_string(object, property_name, xctx)
Get property function for data type string value.
afw_object_set_property_as_string(const afw_object_t *object, const afw_utf8_t *property_name, const afw_utf8_t *internal, afw_xctx_t *xctx)
Set property function for data type string values.
#define afw_value_is_list_of_string(A_VALUE)
Macro to determine if value is evaluated list of string.
#define AFW_UTF8_FMT_ARG(A_STRING)
Convenience Macro for use with AFW_UTF8_FMT to specify arg.
Definition: afw_common.h:605
#define AFW_UTF8_LITERAL(A_STRING)
String literal initializer.
Definition: afw_common.h:582
struct afw_iterator_s afw_iterator_t
#define AFW_ENVIRONMENT_DEFAULT_EVALUATION_STACK_MAXIMUM_COUNT
Default for afw_environment_t evaluation_stack_maximum_count.
Definition: afw_common.h:1380
_Bool afw_boolean_t
Definition: afw_common.h:373
#define AFW_UTF8_FMT
Format string specifier used for afw_utf8_t.
Definition: afw_common.h:588
afw_utf8_octet_t afw_utf8_z_t
NFC normalized UTF-8 null terminated string.
Definition: afw_common.h:523
char afw_utf8_octet_t
8 bits of utf-8 codepoint.
Definition: afw_common.h:236
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
#define AFW_ENVIRONMENT_DEFAULT_EVALUATION_STACK_INITIAL_COUNT
Default for afw_environment_t evaluation_stack_initial_count.
Definition: afw_common.h:1377
#define AFW__FILE_LINE__
file:line
Definition: afw_common.h:148
apr_int64_t afw_integer_t
typedef for big signed int.
Definition: afw_common.h:321
void afw_environment_internal_register_core(afw_xctx_t *xctx)
afw_environment_set_stdout_fd(FILE *fd, afw_xctx_t *xctx)
Override fd used for stdout.
const afw_environment_registry_type_t * afw_environment_get_registry_type_by_id(const afw_utf8_t *registry_type_id, afw_boolean_t load_extension, afw_xctx_t *xctx)
Get the registry type associated with a registry type id.
afw_environment_create_registry_type(const afw_utf8_t *registry_type_id, const afw_utf8_t *property_name, const afw_utf8_t *object_type_id, const afw_utf8_t *description, afw_boolean_t allow_reregister, afw_environment_auto_register_cb_t auto_register, afw_environment_register_additional_cb_t register_additional, void *register_additional_param, afw_xctx_t *xctx)
Create a new registry type.
afw_environment_registry_key_exists(int type_number, const afw_utf8_t *key, afw_xctx_t *xctx)
Check to see if a key exists.
afw_environment_registry_get_data_type_method(const afw_data_type_t *data_type, afw_integer_t dataTypeMethodNumber, afw_xctx_t *xctx)
Get the function associated with a data type method.
afw_environment_register_data_types(const afw_data_type_t *const *data_types, afw_xctx_t *xctx)
Register a NULL terminated list of data types.
afw_environment_get_registry_type_by_number(int registry_type_number, afw_xctx_t *xctx)
Get the registry type associated with a registry type number.
const afw_object_t * afw_environment_prepare_conf_type_properties(const afw_object_t *properties, afw_xctx_t *xctx)
Prepare properties for a conf type.
#define afw_environment_register_flag(flag_id, brief, description, included_by_flag_id, xctx)
Register a flag.
afw_environment_register_adaptor_type(const afw_utf8_t *adaptor_type, const afw_adaptor_factory_t *adaptor_factory, afw_xctx_t *xctx)
Register an adaptor factory.
afw_environment_get_qualified_function(const afw_utf8_t *qualifier, const afw_utf8_t *name, afw_xctx_t *xctx)
Get the qualified function instance.
afw_environment_load_extension(const afw_utf8_t *extension_id, const afw_utf8_t *module_path, const afw_object_t *properties, afw_xctx_t *xctx)
Load and initialize environment extension.
afw_environment_create(unsigned int version, int argc, const char *const *argv, const afw_error_t **environment_create_error)
Create the Adaptive Framework core environment and return base xctx.
afw_environment_create_and_register_conf_type(const afw_utf8_t *conf_type_id, afw_environment_conf_type_create_cede_p_t create, const afw_utf8_t *title, const afw_utf8_t *description, const afw_utf8_t *id_property_name, const afw_utf8_t *id_registry_type_id, const afw_utf8_t *id_runtime_object_type_id, const afw_utf8_t *subtype_property_name, const afw_utf8_t *subtype_registry_type_id, const afw_utf8_t *subtype_runtime_object_type_id, afw_boolean_t is_unique, afw_xctx_t *xctx)
Create and register a configuration (conf) type.
const afw_data_type_t * afw_environment_get_data_type(const afw_utf8_t *type, afw_xctx_t *xctx)
Get the data_type associated with configuration entry type.
afw_environment_registry_register(int type_number, const afw_utf8_t *key, const void *value, afw_xctx_t *xctx)
Register a value by key for a registry type.
#define AFW_ENVIRONMENT_REGISTRY_TYPE_MAP(XX)
Environment Core Registry Type Map.
afw_environment_register_functions(const afw_value_function_definition_t **functions, afw_xctx_t *xctx)
Register a NULL terminated list of functions.
afw_boolean_t(* afw_environment_foreach_cb_t)(int type_number, void *data, const afw_utf8_octet_t *key_s, afw_size_t key_len, void *value, const afw_pool_t *p, afw_xctx_t *xctx)
Callback function typedef for afw_environment_foreach().
void(* afw_environment_conf_type_create_cede_p_t)(const afw_utf8_t *type, const afw_object_t *conf, const afw_utf8_t *source_location, const afw_pool_t *p, afw_xctx_t *xctx)
Typedef for afw conf type create functions.
void(* afw_environment_register_additional_cb_t)(const afw_utf8_t *registry_type_id, int type_number, const afw_utf8_t *key, const void *value, const void *register_additional_param, const void **register_additional_use, afw_xctx_t *xctx)
Additional register callback function.
afw_environment_register_authorization_handler_type(const afw_utf8_t *authorization_handler_type, const afw_authorization_handler_factory_t *authorization_handler_factory, afw_xctx_t *xctx)
Register an authorization handler factory.
afw_environment_foreach(int type_number, afw_environment_foreach_cb_t callback, void *data, const afw_pool_t *p, afw_xctx_t *xctx)
Call a callback function for each entry of a registry type.
afw_environment_register_function(const afw_utf8_t *function_id, const afw_value_function_definition_t *function, afw_xctx_t *xctx)
Register a function.
afw_environment_release(afw_xctx_t *xctx)
Create the Adaptive Framework core environment and return base xctx.
afw_environment_registry_get(int type_number, const afw_utf8_t *key, afw_xctx_t *xctx)
Get the value associated with a key for a registry type.
void *(* afw_environment_auto_register_cb_t)(const afw_utf8_t *registry_type_id, const afw_utf8_t *key, afw_xctx_t *xctx)
Auto register callback function.
afw_environment_set_stderr_fd(FILE *fd, afw_xctx_t *xctx)
Override fd used for stderr.
afw_environment_set_debug_fd(FILE *fd, afw_xctx_t *xctx)
Override fd used for debug.
#define AFW_ENVIRONMENT_Q_EXTENSION_INSTANCE
environment extension instance quoted string.
afw_environment_register_data_type(const afw_utf8_t *data_type_id, const afw_data_type_t *data_type, afw_xctx_t *xctx)
Register a data type.
#define AFW_THROW_MEMORY_ERROR(xctx)
Definition: afw_error.h:499
#define AFW_THROW_UNHANDLED_ERROR(unhandled_error, _ERROR, _CODE, _RV_SOURCE_ID, _RV, _MESSAGE_Z)
Definition: afw_error.h:182
#define AFW_THROW_ERROR_FZ(code, xctx, format_z,...)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:319
#define AFW_THROW_ERROR_RV_FZ(code, rv_source_id, rv, xctx, format_z,...)
Macro used to set error and rv in xctx and throw it.
Definition: afw_error.h:338
#define AFW_THROW_ERROR_Z(code, message_z, xctx)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:283
#define afw_extension_initialize(instance, properties, p, xctx)
Call method initialize of interface afw_extension.
Definition: afw_interface.h:96
void afw_flag_add_included_by(const afw_utf8_t *flag_id, const afw_utf8_t *included_by_flag_id, afw_xctx_t *xctx)
Add another include_by flag to a registered flag.
Definition: afw_flag.c:688
#define afw_list_get_next_internal(instance, iterator, data_type, internal, xctx)
Call method get_next_internal of interface afw_list.
afw_lock_create_rw_and_register(const afw_utf8_t *lock_id, const afw_utf8_t *brief, const afw_utf8_t *description, afw_xctx_t *xctx)
Create a read/write lock and register in environment.
Definition: afw_lock.c:175
#define AFW_LOCK_BEGIN(instance)
Macro to begin a lock section.
Definition: afw_lock.h:191
afw_lock_create_and_register(const afw_utf8_t *lock_id, const afw_utf8_t *brief, const afw_utf8_t *description, afw_boolean_t insure_recursive_lock, afw_xctx_t *xctx)
Create a lock and register in environment.
Definition: afw_lock.c:73
#define AFW_LOCK_END
Macro to end a lock section.
Definition: afw_lock.h:202
const afw_log_t * afw_log_internal_create_environment_log(afw_xctx_t *xctx)
Internal create environment log.
Definition: afw_log.c:224
void afw_log_internal_register_logType_context_type(const afw_utf8_t *log_type_id, afw_xctx_t *xctx)
Register logType context type.
Definition: afw_log.c:161
#define AFW_LOG_FZ(priority, xctx, format_z,...)
Log an message to environment's log using a printf style format and parameters.
Definition: afw_log.h:192
void * afw_memory_dup(const void *from, apr_size_t size, const afw_pool_t *p, afw_xctx_t *xctx)
Duplicate a block of memory into specified pool.
Definition: afw_memory.h:88
#define afw_object_get_property(instance, property_name, xctx)
Call method get_property of interface afw_object.
#define afw_object_has_property(instance, property_name, xctx)
Call method has_property of interface afw_object.
#define afw_object_create_managed(p, xctx)
Create an empty entity object in its own pool.
Definition: afw_object.h:913
const afw_utf8_t * afw_os_get_dso_suffix()
Return the suffix appended to dso file names for this system.
Definition: nix/afw_os.c:643
#define afw_pool_malloc(instance, size, xctx)
Call method malloc of interface afw_pool.
#define afw_pool_calloc(instance, size, xctx)
Call method calloc of interface afw_pool.
#define afw_pool_get_apr_pool(instance)
Call method get_apr_pool of interface afw_pool.
#define afw_pool_release(instance, xctx)
Call method release of interface afw_pool.
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
afw_runtime_env_create_and_set_indirect_object(const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, void *internal, afw_boolean_t overwrite, afw_xctx_t *xctx)
Create and set an indirect runtime object.
Definition: afw_runtime.c:528
afw_runtime_env_set_object(const afw_object_t *object, afw_boolean_t overwrite, afw_xctx_t *xctx)
Set an object pointer in the environment's runtime objects.
Definition: afw_runtime.c:210
afw_runtime_remove_object(const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, afw_xctx_t *xctx)
Remove object by object type id and object id.
Definition: afw_runtime.c:262
afw_runtime_get_object(const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, afw_xctx_t *xctx)
Get a runtime object.
Definition: afw_runtime.c:853
afw_runtime_env_create_and_set_indirect_object_using_inf(const afw_object_inf_t *inf, const afw_utf8_t *object_id, void *internal, afw_boolean_t overwrite, afw_xctx_t *xctx)
Create and set an indirect runtime object.
Definition: afw_runtime.c:507
afw_runtime_foreach(const afw_utf8_t *object_type_id, void *context, afw_object_cb_t callback, afw_xctx_t *xctx)
Call a callback for each runtime object.
Definition: afw_runtime.c:900
afw_utf8_ends_with(const afw_utf8_t *string, const afw_utf8_t *ends_with)
Check to see if a string ends with another string.
Definition: afw_utf8.c:513
afw_boolean_t afw_utf8_equal(const afw_utf8_t *s1, const afw_utf8_t *s2)
Check to see if a string equals another string.
const afw_utf8_z_t * afw_utf8_z_printf(const afw_pool_t *p, afw_xctx_t *xctx, const afw_utf8_z_t *format_z,...)
Definition: afw_utf8.h:854
const afw_utf8_t * afw_utf8_clone(const afw_utf8_t *string, const afw_pool_t *p, afw_xctx_t *xctx)
Clone a utf-8 string into a specific pool.
Definition: afw_utf8.h:347
const afw_utf8_z_t * afw_utf8_to_utf8_z(const afw_utf8_t *string, const afw_pool_t *p, afw_xctx_t *xctx)
Convert utf8 to utf8_z in specified pool.
Definition: afw_utf8.h:529
afw_utf8_printf(const afw_pool_t *p, afw_xctx_t *xctx, const afw_utf8_z_t *format,...)
Create a utf-8 string using a c format string in specified pool.
Definition: afw_utf8.c:459
afw_value_function_definition_inf
Value function inf.
Definition: afw_value.h:261
const afw_utf8_z_t * afw_version_check(unsigned int version)
Version check.
#define AFW_VERSION_THROW_ERROR_SUPPLIED_HEX_VERSION_IF_NOT_COMPATIBLE(info, compiled_version, xctx)
Throw error if AFW core is not compatible with the supplied version.
Definition: afw_version.h:76
afw_xctx_internal_create_initialize(afw_try_t *unhandled_error, afw_error_t *error, afw_environment_internal_t *env, const afw_pool_t *p)
Definition: afw_xctx.c:35
#define afw_xctx_calloc(size, xctx)
Macro to allocate cleared memory in xctx's pool.
Definition: afw_xctx.h:185
#define afw_xctx_calloc_type(type, xctx)
Macro to allocate cleared memory to hold type in xctx's pool.
Definition: afw_xctx.h:199
Interface afw_adaptor_factory public struct.
Interface afw_authorization_handler_factory public struct.
Interface afw_data_type public struct.
Struct for afw environment conf type.
const afw_utf8_t * subtype_property_name
Subtype property name for instances of this conf type.
const afw_utf8_t * subtype_runtime_object_type_id
Subtype runtime object type for instances of this conf type.
const afw_utf8_t * id_property_name
Id property name for instances of this conf type.
afw_boolean_t is_unique
This conf type can only be specified once.
afw_environment_conf_type_create_cede_p_t create
Create function for this type.
afw_utf8_t conf_type_id
Id of type.
const afw_utf8_t * description
Description of this type.
const afw_utf8_t * title
Title of this type.
const afw_utf8_t * id_runtime_object_type_id
Runtime object type for instances of this conf type.
const afw_utf8_t * subtype_registry_type_id
Subtype registry type for instances of this conf type.
const afw_utf8_t * id_registry_type_id
Registry type for instances of this conf type.
Struct for typedef afw_environment_t defined in afw_common.h.
Definition: afw_common.h:1383
AFW_ATOMIC afw_integer_t pool_number
Used to give unique number for pool.
Definition: afw_common.h:1464
FILE * stdout_fd
Open file descriptor used for writing standard output. Default stdout.
Definition: afw_common.h:1428
const afw_lock_t * multithreaded_pool_lock
Lock used internal to afw_pool.c.
Definition: afw_common.h:1476
afw_utf8_t application_id
The id of the application.
Definition: afw_common.h:1404
afw_size_t evaluation_stack_maximum_count
maximum_count used to create xctx's evaluation stack.
Definition: afw_common.h:1458
const afw_lock_t * active_log_list_lock
Lock for protecting changes to active log list.
Definition: afw_common.h:1493
const afw_log_t * log
Director log. This log will direct to other logs.
Definition: afw_common.h:1419
const afw_pool_t * p
Pool used to hold environment.
Definition: afw_common.h:1386
const afw_lock_t * flags_lock
Lock for protecting changes to flags (internal to afw_flag.c).
Definition: afw_common.h:1498
const afw_lock_t * adaptor_id_anchor_lock
Lock for protecting changes to adaptor id anchors.
Definition: afw_common.h:1479
afw_size_t evaluation_stack_initial_count
initial_count used to create xctx's evaluation stack.
Definition: afw_common.h:1455
FILE * debug_fd
Open file descriptor used for debug writes. Default stderr.
Definition: afw_common.h:1422
const afw_lock_rw_t * authorization_handler_id_anchor_rw_lock
Lock for protecting changes to authorization handler id anchors.
Definition: afw_common.h:1488
const afw_lock_t * environment_lock
Lock for whole environment.
Definition: afw_common.h:1473
FILE * stderr_fd
Open file descriptor used for writing error output. Default stderr.
Definition: afw_common.h:1425
Adaptive Framework Error.
Definition: afw_error.h:65
Interface afw_extension public struct.
Definition: afw_interface.h:55
Interface afw_list public struct.
Interface afw_object public struct.
Interface afw_pool public struct.
Struct for runtime objects.
Definition: afw_runtime.h:174
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Struct for function value.
Definition: afw_value.h:102
const afw_value_function_parameter_t *const * parameters
Function parameters.
Definition: afw_value.h:157
const afw_object_t * object
Object representing function.
Definition: afw_value.h:106
const afw_data_type_t * data_type
If this is a data type method, this is the data type.
Definition: afw_value.h:169
afw_integer_t dataTypeMethodNumber
Data type member number.
Definition: afw_value.h:190
const afw_value_function_parameter_t * returns
Function returns.
Definition: afw_value.h:163
afw_utf8_t dataType
If this is a data type method, this is the data type id.
Definition: afw_value.h:172
Struct for adaptive function parameter.
Definition: afw_value.h:68
struct for data type list values.
Interface afw_value public struct.
Interface afw_xctx public struct.