diff --git a/modules/appmodel/CMakeLists.txt b/modules/appmodel/CMakeLists.txt index e49323bb0d..2bb5efe5d1 100644 --- a/modules/appmodel/CMakeLists.txt +++ b/modules/appmodel/CMakeLists.txt @@ -9,6 +9,7 @@ set (APPMODEL_SOURCES appmodel-parser.c appmodel-plugin.c appmodel-context.c + app-object-generator.c app-parser-generator.c application.c ) diff --git a/modules/appmodel/Makefile.am b/modules/appmodel/Makefile.am index d237555ce1..f87ac90a78 100644 --- a/modules/appmodel/Makefile.am +++ b/modules/appmodel/Makefile.am @@ -10,6 +10,8 @@ modules_appmodel_libappmodel_la_SOURCES = \ modules/appmodel/appmodel-plugin.c \ modules/appmodel/appmodel-context.c \ modules/appmodel/appmodel-context.h \ + modules/appmodel/app-object-generator.c \ + modules/appmodel/app-object-generator.h \ modules/appmodel/app-parser-generator.c \ modules/appmodel/app-parser-generator.h \ modules/appmodel/application.c \ diff --git a/modules/appmodel/app-object-generator.c b/modules/appmodel/app-object-generator.c new file mode 100644 index 0000000000..9393e37e7d --- /dev/null +++ b/modules/appmodel/app-object-generator.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017 Balabit + * Copyright (c) 2017 Balazs Scheidler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#include "app-object-generator.h" +#include "appmodel.h" + +#include + +gboolean +app_object_generator_is_application_included(AppObjectGenerator *self, const gchar *app_name) +{ + /* include everything if we don't have the option */ + if (!self->included_apps) + return TRUE; + return strstr(self->included_apps, app_name) != NULL; +} + +gboolean +app_object_generator_is_application_excluded(AppObjectGenerator *self, const gchar *app_name) +{ + if (!self->excluded_apps) + return FALSE; + return strstr(self->excluded_apps, app_name) != NULL; +} + +static gboolean +_parse_auto_parse_arg(AppObjectGenerator *self, CfgArgs *args, const gchar *reference) +{ + const gchar *v = cfg_args_get(args, "auto-parse"); + + if (v) + self->is_parsing_enabled = cfg_process_yesno(v); + else + self->is_parsing_enabled = TRUE; + return TRUE; +} + +static gboolean +_parse_auto_parse_exclude_arg(AppObjectGenerator *self, CfgArgs *args, const gchar *reference) +{ + const gchar *v = cfg_args_get(args, "auto-parse-exclude"); + if (!v) + return TRUE; + self->excluded_apps = g_strdup(v); + return TRUE; +} + +static gboolean +_parse_auto_parse_include_arg(AppObjectGenerator *self, CfgArgs *args, const gchar *reference) +{ + const gchar *v = cfg_args_get(args, "auto-parse-include"); + if (!v) + return TRUE; + self->included_apps = g_strdup(v); + return TRUE; +} + +gboolean +app_object_generator_parse_arguments_method(AppObjectGenerator *self, CfgArgs *args, const gchar *reference) +{ + g_assert(args != NULL); + + if (!_parse_auto_parse_arg(self, args, reference)) + return FALSE; + if (!_parse_auto_parse_exclude_arg(self, args, reference)) + return FALSE; + if (!_parse_auto_parse_include_arg(self, args, reference)) + return FALSE; + return TRUE; +} + +static gboolean +_generate(CfgBlockGenerator *s, GlobalConfig *cfg, gpointer args, GString *result, const gchar *reference) +{ + AppObjectGenerator *self = (AppObjectGenerator *) s; + CfgArgs *cfgargs = (CfgArgs *)args; + + if (!self->parse_arguments(self, cfgargs, reference)) + return FALSE; + + self->generate_config(self, cfg, result); + + return TRUE; +} + +void +app_object_generator_init_instance(AppObjectGenerator *self, gint context, const gchar *name) +{ + cfg_block_generator_init_instance(&self->super, context, name); + self->super.generate = _generate; + self->parse_arguments = app_object_generator_parse_arguments_method; +} diff --git a/modules/appmodel/app-object-generator.h b/modules/appmodel/app-object-generator.h new file mode 100644 index 0000000000..330db1344e --- /dev/null +++ b/modules/appmodel/app-object-generator.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 Balabit + * Copyright (c) 2017 Balazs Scheidler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#ifndef APPMODEL_APP_OBJECT_GENERATOR_H_INCLUDED +#define APPMODEL_APP_OBJECT_GENERATOR_H_INCLUDED + +#include "plugin.h" + +typedef struct _AppObjectGenerator AppObjectGenerator; + +struct _AppObjectGenerator +{ + CfgBlockGenerator super; + gboolean (*parse_arguments)(AppObjectGenerator *self, CfgArgs *args, const gchar *reference); + void (*generate_config)(AppObjectGenerator *self, GlobalConfig *cfg, GString *result); + const gchar *included_apps; + const gchar *excluded_apps; + gboolean is_parsing_enabled; +}; + +gboolean app_object_generator_is_application_included(AppObjectGenerator *self, const gchar *app_name); +gboolean app_object_generator_is_application_excluded(AppObjectGenerator *self, const gchar *app_name); + +gboolean app_object_generator_parse_arguments_method(AppObjectGenerator *self, CfgArgs *args, const gchar *reference); +void app_object_generator_init_instance(AppObjectGenerator *self, gint context, const gchar *name); + + +#endif diff --git a/modules/appmodel/app-parser-generator.c b/modules/appmodel/app-parser-generator.c index ad77db2430..26821d0c21 100644 --- a/modules/appmodel/app-parser-generator.c +++ b/modules/appmodel/app-parser-generator.c @@ -22,41 +22,60 @@ * */ -#include "app-parser-generator.h" +#include "app-object-generator.h" #include "appmodel.h" -#include +/* app-parser() */ typedef struct _AppParserGenerator { - CfgBlockGenerator super; - GString *block; + AppObjectGenerator super; const gchar *topic; - const gchar *included_apps; - const gchar *excluded_apps; - gboolean is_parsing_enabled; + GString *block; gboolean first_app_generated; gboolean allow_overlaps; } AppParserGenerator; -static const gchar * -_get_filter_expr(Application *app, Application *base_app) +static gboolean +_parse_topic_arg(AppParserGenerator *self, CfgArgs *args, const gchar *reference) { - if (app->filter_expr) - return app->filter_expr; - if (base_app) - return base_app->filter_expr; - return NULL; + self->topic = cfg_args_get(args, "topic"); + if (!self->topic) + { + msg_error("app-parser() requires a topic() argument", + evt_tag_str("reference", reference)); + return FALSE; + } + return TRUE; } -static const gchar * -_get_parser_expr(Application *app, Application *base_app) +static gboolean +_parse_allow_overlaps(AppParserGenerator *self, CfgArgs *args, const gchar *reference) { - if (app->parser_expr) - return app->parser_expr; - if (base_app) - return base_app->parser_expr; - return NULL; + const gchar *v = cfg_args_get(args, "allow-overlaps"); + if (v) + self->allow_overlaps = cfg_process_yesno(v); + else + self->allow_overlaps = FALSE; + return TRUE; +} + +static gboolean +app_parser_generator_parse_arguments(AppObjectGenerator *s, CfgArgs *args, const gchar *reference) +{ + AppParserGenerator *self = (AppParserGenerator *) s; + g_assert(args != NULL); + + if (!_parse_topic_arg(self, args, reference)) + return FALSE; + + if (!_parse_allow_overlaps(self, args, reference)) + return FALSE; + + if (!app_object_generator_parse_arguments_method(&self->super, args, reference)) + return FALSE; + + return TRUE; } static void @@ -89,39 +108,22 @@ _generate_action(AppParserGenerator *self, Application *app) " set-tag('.app.%s');\n" " set('%s' value('.app.name'));\n" " };\n", - app->name, app->name); + app->super.name, app->super.name); } } -static gboolean -_is_application_included(AppParserGenerator *self, Application *app) -{ - /* include everything if we don't have the option */ - if (!self->included_apps) - return TRUE; - return strstr(self->included_apps, app->name) != NULL; -} - -static gboolean -_is_application_excluded(AppParserGenerator *self, Application *app) -{ - if (!self->excluded_apps) - return FALSE; - return strstr(self->excluded_apps, app->name) != NULL; -} - static void -_generate_application(Application *app, Application *base_app, gpointer user_data) +_generate_application(Application *app, gpointer user_data) { AppParserGenerator *self = (AppParserGenerator *) user_data; - if (strcmp(self->topic, app->topic) != 0) + if (strcmp(self->topic, app->super.instance) != 0) return; - if (!_is_application_included(self, app)) + if (!app_object_generator_is_application_included(&self->super, app->super.name)) return; - if (_is_application_excluded(self, app)) + if (app_object_generator_is_application_excluded(&self->super, app->super.name)) return; if (self->first_app_generated) @@ -141,25 +143,24 @@ _generate_application(Application *app, Application *base_app, gpointer user_dat " if {\n"); } g_string_append_printf(self->block, - " #Start Application %s\n", app->name); + " #Start Application %s\n", app->super.name); - _generate_filter(self, _get_filter_expr(app, base_app)); - _generate_parser(self, _get_parser_expr(app, base_app)); + _generate_filter(self, app->filter_expr); + _generate_parser(self, app->parser_expr); _generate_action(self, app); g_string_append_printf(self->block, - " #End Application %s\n", app->name); + " #End Application %s\n", app->super.name); g_string_append(self->block, " }\n"); - } static void -_generate_applications(AppParserGenerator *self, AppModelContext *appmodel) +_generate_applications(AppParserGenerator *self, GlobalConfig *cfg) { - appmodel_context_iter_applications(appmodel, _generate_application, self); + appmodel_iter_applications(cfg, _generate_application, self); } static void -_generate_framing(AppParserGenerator *self, AppModelContext *appmodel) +_generate_framing(AppParserGenerator *self, GlobalConfig *cfg) { g_string_append(self->block, "\nchannel {\n"); @@ -167,7 +168,7 @@ _generate_framing(AppParserGenerator *self, AppModelContext *appmodel) self->first_app_generated = FALSE; if (!self->allow_overlaps) { - _generate_applications(self, appmodel); + _generate_applications(self, cfg); if (self->first_app_generated) g_string_append(self->block, " else {\n"); else @@ -179,7 +180,7 @@ _generate_framing(AppParserGenerator *self, AppModelContext *appmodel) } else { - _generate_applications(self, appmodel); + _generate_applications(self, cfg); if (self->first_app_generated) g_string_append(self->block, " ;\n"); } @@ -192,106 +193,27 @@ _generate_empty_frame(AppParserGenerator *self) g_string_append(self->block, "channel { filter { tags('.app.doesnotexist'); }; };"); } -static gboolean -_parse_auto_parse_arg(AppParserGenerator *self, CfgArgs *args, const gchar *reference) -{ - const gchar *v = cfg_args_get(args, "auto-parse"); - - if (v) - self->is_parsing_enabled = cfg_process_yesno(v); - else - self->is_parsing_enabled = TRUE; - return TRUE; -} - -static gboolean -_parse_auto_parse_exclude_arg(AppParserGenerator *self, CfgArgs *args, const gchar *reference) -{ - const gchar *v = cfg_args_get(args, "auto-parse-exclude"); - if (!v) - return TRUE; - self->excluded_apps = g_strdup(v); - return TRUE; -} - -static gboolean -_parse_auto_parse_include_arg(AppParserGenerator *self, CfgArgs *args, const gchar *reference) -{ - const gchar *v = cfg_args_get(args, "auto-parse-include"); - if (!v) - return TRUE; - self->included_apps = g_strdup(v); - return TRUE; -} - -static gboolean -_parse_topic_arg(AppParserGenerator *self, CfgArgs *args, const gchar *reference) -{ - self->topic = cfg_args_get(args, "topic"); - if (!self->topic) - { - msg_error("app-parser() requires a topic() argument", - evt_tag_str("reference", reference)); - return FALSE; - } - return TRUE; -} - -static gboolean -_parse_allow_overlaps(AppParserGenerator *self, CfgArgs *args, const gchar *reference) -{ - const gchar *v = cfg_args_get(args, "allow-overlaps"); - if (v) - self->allow_overlaps = cfg_process_yesno(v); - else - self->allow_overlaps = FALSE; - return TRUE; -} - -static gboolean -_parse_arguments(AppParserGenerator *self, CfgArgs *args, const gchar *reference) -{ - g_assert(args != NULL); - - if (!_parse_topic_arg(self, args, reference)) - return FALSE; - if (!_parse_auto_parse_arg(self, args, reference)) - return FALSE; - if (!_parse_auto_parse_exclude_arg(self, args, reference)) - return FALSE; - if (!_parse_auto_parse_include_arg(self, args, reference)) - return FALSE; - if (!_parse_allow_overlaps(self, args, reference)) - return FALSE; - return TRUE; -} - -static gboolean -_generate(CfgBlockGenerator *s, GlobalConfig *cfg, gpointer args, GString *result, const gchar *reference) +void +app_parser_generate_config(AppObjectGenerator *s, GlobalConfig *cfg, GString *result) { AppParserGenerator *self = (AppParserGenerator *) s; - AppModelContext *appmodel = appmodel_get_context(cfg); - CfgArgs *cfgargs = (CfgArgs *)args; - - if (!_parse_arguments(self, cfgargs, reference)) - return FALSE; self->block = result; - if (self->is_parsing_enabled) - _generate_framing(self, appmodel); + if (self->super.is_parsing_enabled) + _generate_framing(self, cfg); else _generate_empty_frame(self); self->block = NULL; - - return TRUE; } + CfgBlockGenerator * app_parser_generator_new(gint context, const gchar *name) { AppParserGenerator *self = g_new0(AppParserGenerator, 1); - cfg_block_generator_init_instance(&self->super, context, name); - self->super.generate = _generate; - return &self->super; + app_object_generator_init_instance(&self->super, context, name); + self->super.parse_arguments = app_parser_generator_parse_arguments; + self->super.generate_config = app_parser_generate_config; + return &self->super.super; } diff --git a/modules/appmodel/application.c b/modules/appmodel/application.c index 98038a75c9..11b32ea20d 100644 --- a/modules/appmodel/application.c +++ b/modules/appmodel/application.c @@ -37,22 +37,20 @@ application_set_parser(Application *self, const gchar *parser_expr) self->parser_expr = g_strdup(parser_expr); } +static void +application_free(AppModelObject *s) +{ + Application *self = (Application *) s; + g_free(self->filter_expr); + g_free(self->parser_expr); +} + Application * application_new(const gchar *name, const gchar *topic) { Application *self = g_new0(Application, 1); - self->name = g_strdup(name); - self->topic = g_strdup(topic); + appmodel_object_init_instance(&self->super, APPLICATION_TYPE_NAME, name, topic); + self->super.free_fn = application_free; return self; } - -void -application_free(Application *self) -{ - g_free(self->name); - g_free(self->topic); - g_free(self->filter_expr); - g_free(self->parser_expr); - g_free(self); -} diff --git a/modules/appmodel/application.h b/modules/appmodel/application.h index 9ca7109e8e..c8dda0cf5a 100644 --- a/modules/appmodel/application.h +++ b/modules/appmodel/application.h @@ -24,12 +24,13 @@ #ifndef APPMODEL_APPLICATION_H_INCLUDED #define APPMODEL_APPLICATION_H_INCLUDED -#include "syslog-ng.h" +#include "appmodel-context.h" + +#define APPLICATION_TYPE_NAME "application" typedef struct _Application { - gchar *name; - gchar *topic; + AppModelObject super; gchar *filter_expr; gchar *parser_expr; } Application; @@ -38,6 +39,5 @@ void application_set_filter(Application *self, const gchar *filter_expr); void application_set_parser(Application *self, const gchar *parser_expr); Application *application_new(const gchar *name, const gchar *topic); -void application_free(Application *s); #endif diff --git a/modules/appmodel/appmodel-context.c b/modules/appmodel/appmodel-context.c index 816c2f79c4..2e28b07ebb 100644 --- a/modules/appmodel/appmodel-context.c +++ b/modules/appmodel/appmodel-context.c @@ -25,83 +25,105 @@ #include +void +appmodel_object_init_instance(AppModelObject *self, const gchar *type, const gchar *name, const gchar *instance) +{ + self->type = g_strdup(type); + self->name = g_strdup(name); + self->instance = g_strdup(instance); +} + +void +appmodel_object_free(AppModelObject *self) +{ + if (self->free_fn) + self->free_fn(self); + + g_free(self->instance); + g_free(self->type); + g_free(self->name); + + g_free(self); +} + struct _AppModelContext { /* the context structure is registered into GlobalConfig, thus it must be * derived from ModuleConfig */ ModuleConfig super; - GHashTable *applications; - GPtrArray *application_ptrs; + GHashTable *objects; + GPtrArray *object_ptrs; }; static gboolean -_application_equal(gconstpointer v1, gconstpointer v2) +_object_equal(gconstpointer v1, gconstpointer v2) { - Application *r1 = (Application *) v1; - Application *r2 = (Application *) v2; + AppModelObject *r1 = (AppModelObject *) v1; + AppModelObject *r2 = (AppModelObject *) v2; if (strcmp(r1->name, r2->name) != 0) return FALSE; - if (strcmp(r1->topic, r2->topic) != 0) + if (strcmp(r1->instance, r2->instance) != 0) return FALSE; return TRUE; } static guint -_application_hash(gconstpointer v) +_object_hash(gconstpointer v) { - Application *r = (Application *) v; + AppModelObject *r = (AppModelObject *) v; - return g_str_hash(r->name) + g_str_hash(r->topic); + return g_str_hash(r->name) + g_str_hash(r->instance); } void -appmodel_context_register_application(AppModelContext *self, Application *app) +appmodel_context_register_object(AppModelContext *self, AppModelObject *app) { - Application *orig_app; + AppModelObject *orig_app; - orig_app = g_hash_table_lookup(self->applications, app); + orig_app = g_hash_table_lookup(self->objects, app); if (!orig_app) { - g_hash_table_insert(self->applications, app, app); - g_ptr_array_add(self->application_ptrs, app); + g_hash_table_insert(self->objects, app, app); + g_ptr_array_add(self->object_ptrs, app); } else { - g_hash_table_replace(self->applications, app, app); + g_hash_table_replace(self->objects, app, app); - g_ptr_array_remove(self->application_ptrs, orig_app); - g_ptr_array_add(self->application_ptrs, app); + g_ptr_array_remove(self->object_ptrs, orig_app); + g_ptr_array_add(self->object_ptrs, app); } } -Application * -appmodel_context_lookup_application(AppModelContext *self, const gchar *name, const gchar *topic) +AppModelObject * +appmodel_context_lookup_object(AppModelContext *self, const gchar *type, const gchar *name, const gchar *instance) { - Application lookup_app = { 0 }; + AppModelObject lookup_app = { 0 }; + lookup_app.type = (gchar *) type; lookup_app.name = (gchar *) name; - lookup_app.topic = (gchar *) topic; - return (Application *) g_hash_table_lookup(self->applications, &lookup_app); + lookup_app.instance = (gchar *) instance; + return (AppModelObject *) g_hash_table_lookup(self->objects, &lookup_app); } void -appmodel_context_iter_applications(AppModelContext *self, void (*foreach)(Application *app, Application *base_app, - gpointer user_data), gpointer user_data) +appmodel_context_iter_objects(AppModelContext *self, + const gchar *type, + AppModelContextIterFunc foreach, + gpointer user_data) { gint i; - for (i = 0; i < self->application_ptrs->len; i++) + for (i = 0; i < self->object_ptrs->len; i++) { - Application *app = g_ptr_array_index(self->application_ptrs, i); + AppModelObject *app = g_ptr_array_index(self->object_ptrs, i); - if (strcmp(app->topic, "*") == 0) + if (strcmp(app->type, type) != 0) continue; - - Application *base_app = appmodel_context_lookup_application(self, app->name, "*"); - foreach(app, base_app, user_data); + foreach(app, user_data); } } @@ -110,8 +132,8 @@ appmodel_context_free_method(ModuleConfig *s) { AppModelContext *self = (AppModelContext *) s; - g_hash_table_destroy(self->applications); - g_ptr_array_free(self->application_ptrs, TRUE); + g_hash_table_destroy(self->objects); + g_ptr_array_free(self->object_ptrs, TRUE); module_config_free_method(s); } @@ -121,9 +143,9 @@ appmodel_context_new(void) AppModelContext *self = g_new0(AppModelContext, 1); self->super.free_fn = appmodel_context_free_method; - self->applications = g_hash_table_new_full(_application_hash, _application_equal, - NULL, (GDestroyNotify) application_free); - self->application_ptrs = g_ptr_array_new(); + self->objects = g_hash_table_new_full(_object_hash, _object_equal, + NULL, (GDestroyNotify) appmodel_object_free); + self->object_ptrs = g_ptr_array_new(); return self; } diff --git a/modules/appmodel/appmodel-context.h b/modules/appmodel/appmodel-context.h index 92132f7b78..6159a006ae 100644 --- a/modules/appmodel/appmodel-context.h +++ b/modules/appmodel/appmodel-context.h @@ -24,15 +24,32 @@ #define APPMODEL_CONTEXT_H_INCLUDED 1 #include "module-config.h" -#include "application.h" typedef struct _AppModelContext AppModelContext; +typedef struct _AppModelObject AppModelObject; +typedef void(*AppModelContextIterFunc)(AppModelObject *object, gpointer user_data); -void appmodel_context_iter_applications(AppModelContext *self, - void (*foreach)(Application *app, Application *base_app, gpointer user_data), - gpointer user_data); -Application *appmodel_context_lookup_application(AppModelContext *self, const gchar *name, const gchar *topic); -void appmodel_context_register_application(AppModelContext *self, Application *app); +struct _AppModelObject +{ + void (*free_fn)(AppModelObject *s); + gchar *type; + gchar *name; + gchar *instance; +}; + +void appmodel_object_init_instance(AppModelObject *self, + const gchar *type, const gchar *name, + const gchar *instance); +void appmodel_object_free(AppModelObject *self); + +void appmodel_context_iter_objects(AppModelContext *self, + const gchar *type, + AppModelContextIterFunc foreach, + gpointer user_data); +AppModelObject *appmodel_context_lookup_object(AppModelContext *self, + const gchar *type, const gchar *name, + const gchar *instance); +void appmodel_context_register_object(AppModelContext *self, AppModelObject *object); void appmodel_context_free(AppModelContext *self); AppModelContext *appmodel_context_new(void); diff --git a/modules/appmodel/appmodel-grammar.ym b/modules/appmodel/appmodel-grammar.ym index 70a0a54794..90eb1ca045 100644 --- a/modules/appmodel/appmodel-grammar.ym +++ b/modules/appmodel/appmodel-grammar.ym @@ -33,8 +33,6 @@ #include "cfg-grammar-internal.h" #include "messages.h" -Application *last_application; - } %define api.prefix {appmodel_} @@ -58,8 +56,8 @@ Application *last_application; start : LL_CONTEXT_ROOT application_definition { - appmodel_register_application(configuration, last_application); - *instance = last_application; + appmodel_register_application(configuration, $2); + *instance = $2; YYACCEPT; } ; @@ -67,25 +65,25 @@ start application_definition : KW_APPLICATION string '[' string ']' - { - last_application = application_new($2, $4); - } - '{' application_options '}' + { + $$ = application_new($2, $4); + }[app] + '{' { $$ = $app; } application_options '}' { - $$ = last_application; + $$ = $app; free($2); free($4); } ; application_options - : application_option semicolons application_options + : application_option semicolons { $$ = $0; } application_options | ; application_option - : KW_FILTER _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_filter(last_application, $3); free($3); } - | KW_PARSER _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_parser(last_application, $3); free($3); } + : KW_FILTER _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_filter($0, $3); free($3); } + | KW_PARSER _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_parser($0, $3); free($3); } ; /* INCLUDE_RULES */ diff --git a/modules/appmodel/appmodel.c b/modules/appmodel/appmodel.c index 054c80a647..e94aea1368 100644 --- a/modules/appmodel/appmodel.c +++ b/modules/appmodel/appmodel.c @@ -23,6 +23,7 @@ */ #include "appmodel.h" #include "cfg.h" +#include "appmodel-context.h" #define MODULE_CONFIG_KEY "appmodel" @@ -43,5 +44,12 @@ appmodel_register_application(GlobalConfig *cfg, Application *application) { AppModelContext *ac = appmodel_get_context(cfg); - appmodel_context_register_application(ac, application); + appmodel_context_register_object(ac, &application->super); +} + +void +appmodel_iter_applications(GlobalConfig *cfg, void (*foreach)(Application *app, gpointer user_data), gpointer user_data) +{ + AppModelContext *appmodel = appmodel_get_context(cfg); + appmodel_context_iter_objects(appmodel, APPLICATION_TYPE_NAME, (AppModelContextIterFunc) foreach, user_data); } diff --git a/modules/appmodel/appmodel.h b/modules/appmodel/appmodel.h index 2e287f3e46..34b0f3dd7e 100644 --- a/modules/appmodel/appmodel.h +++ b/modules/appmodel/appmodel.h @@ -24,9 +24,12 @@ #define APPMODEL_H_INCLUDED 1 #include "module-config.h" -#include "appmodel-context.h" +#include "application.h" AppModelContext *appmodel_get_context(GlobalConfig *cfg); void appmodel_register_application(GlobalConfig *cfg, Application *application); +void appmodel_iter_applications(GlobalConfig *cfg, + void (*foreach)(Application *app, gpointer user_data), + gpointer user_data); #endif diff --git a/modules/appmodel/tests/test_app_parser_generator.c b/modules/appmodel/tests/test_app_parser_generator.c index cb3cb73b68..1fb7e81c60 100644 --- a/modules/appmodel/tests/test_app_parser_generator.c +++ b/modules/appmodel/tests/test_app_parser_generator.c @@ -217,33 +217,6 @@ Test(app_parser_generator, app_parser_generates_references_to_apps) _assert_config_is_valid("port514", NULL); } -Test(app_parser_generator, app_parser_uses_filter_or_parser_from_base_topics) -{ - _register_application("application foo[port514] {\n" - "};"); - - _register_sample_application("foo", "*"); - - _app_parser_generate("port514"); - _assert_parser_framing_is_present(); - _assert_application_is_present("foo"); - _assert_snippet_is_present("program('foo')"); - _assert_snippet_is_present("kv-parser(prefix('foo.'))"); - _assert_config_is_valid("port514", NULL); -} - -Test(app_parser_generator, app_parser_base_topics_are_skipped) -{ - _register_sample_application("foo", "*"); - _register_sample_application("bar", "*"); - - _app_parser_generate("port514"); - _assert_parser_framing_is_present(); - _assert_snippet_is_not_present("program('foo')"); - _assert_snippet_is_not_present("program('bar')"); - _assert_config_is_valid("port514", NULL); -} - Test(app_parser_generator, app_parser_is_disabled_if_auto_parse_is_set_to_no) { _register_sample_application("foo", "port514"); diff --git a/modules/appmodel/tests/test_application.c b/modules/appmodel/tests/test_application.c index a39e477c31..a7e02c322a 100644 --- a/modules/appmodel/tests/test_application.c +++ b/modules/appmodel/tests/test_application.c @@ -30,7 +30,7 @@ Test(application, empty_application_can_be_created_and_freed) Application *app; app = application_new("foobar", "*"); - application_free(app); + appmodel_object_free(&app->super); } Test(application, filter_can_be_set_and_queried) @@ -45,7 +45,7 @@ Test(application, filter_can_be_set_and_queried) application_set_filter(app, filter_expr2); cr_assert_str_eq(app->filter_expr, filter_expr2); - application_free(app); + appmodel_object_free(&app->super); } Test(application, parser_can_be_set_and_queried) @@ -60,5 +60,5 @@ Test(application, parser_can_be_set_and_queried) application_set_parser(app, parser_expr2); cr_assert_str_eq(app->parser_expr, parser_expr2); - application_free(app); + appmodel_object_free(&app->super); } diff --git a/modules/appmodel/tests/test_appmodel.c b/modules/appmodel/tests/test_appmodel.c index 31079bf31a..19fe31750d 100644 --- a/modules/appmodel/tests/test_appmodel.c +++ b/modules/appmodel/tests/test_appmodel.c @@ -40,7 +40,7 @@ _parse_application(const char *appmodel, const gchar *name, const gchar *topic) cr_assert(parse_config(appmodel, LL_CONTEXT_ROOT, NULL, NULL), "Parsing the given configuration failed: %s", appmodel); ac = appmodel_get_context(configuration); - return appmodel_context_lookup_application(ac, name, topic); + return (Application *) appmodel_context_lookup_object(ac, APPLICATION_TYPE_NAME, name, topic); } Test(appmodel, empty_application_can_be_parsed_properly) @@ -49,8 +49,8 @@ Test(appmodel, empty_application_can_be_parsed_properly) app = _parse_application("application foobar[*] {};", "foobar", "*"); cr_assert(app != NULL); - cr_assert_str_eq(app->name, "foobar"); - cr_assert_str_eq(app->topic, "*"); + cr_assert_str_eq(app->super.name, "foobar"); + cr_assert_str_eq(app->super.instance, "*"); } Test(appmodel, name_is_parsed_into_name_member) @@ -67,7 +67,7 @@ Test(appmodel, topic_in_brackets_is_parsed_into_topic) app = _parse_application("application name[port514] {};", "name", "port514"); cr_assert(app != NULL); - cr_assert_str_eq(app->topic, "port514"); + cr_assert_str_eq(app->super.instance, "port514"); } Test(appmodel, filter_expressions_can_be_specified_with_a_filter_keyword) @@ -81,7 +81,7 @@ Test(appmodel, filter_expressions_can_be_specified_with_a_filter_keyword) "};", "name", "port514"); cr_assert(app != NULL); - cr_assert_str_eq(app->topic, "port514"); + cr_assert_str_eq(app->super.instance, "port514"); cr_assert_str_eq(app->filter_expr, " program(\"kernel\"); "); } @@ -96,7 +96,7 @@ Test(appmodel, parser_expressions_can_be_specified_with_a_parser_keyword) "};", "name", "port514"); cr_assert(app != NULL); - cr_assert_str_eq(app->topic, "port514"); + cr_assert_str_eq(app->super.instance, "port514"); cr_assert_str_eq(app->parser_expr, " kv-parser(); "); } diff --git a/modules/appmodel/tests/test_appmodel_context.c b/modules/appmodel/tests/test_appmodel_context.c index d5b58eea68..c4907944e6 100644 --- a/modules/appmodel/tests/test_appmodel_context.c +++ b/modules/appmodel/tests/test_appmodel_context.c @@ -41,12 +41,12 @@ teardown(void) Test(appmodel_context, register_application_makes_the_app_available) { - appmodel_context_register_application(ac, application_new("foobar", "*")); - appmodel_context_lookup_application(ac, "foobar", "*"); + appmodel_context_register_object(ac, &application_new("foobar", "*")->super); + appmodel_context_lookup_object(ac, APPLICATION_TYPE_NAME, "foobar", "*"); } static void -_foreach_app(Application *app, Application *base_app, gpointer user_data) +_foreach_app(AppModelObject *app, gpointer user_data) { GString *result = (GString *) user_data; @@ -57,13 +57,10 @@ Test(appmodel_context, iter_applications_enumerates_apps_without_asterisk) { GString *result = g_string_sized_new(128); - appmodel_context_register_application(ac, application_new("foo", "*")); - appmodel_context_register_application(ac, application_new("foo", "port514")); - appmodel_context_register_application(ac, application_new("bar", "*")); - appmodel_context_register_application(ac, application_new("bar", "port514")); - appmodel_context_register_application(ac, application_new("baz", "*")); - appmodel_context_register_application(ac, application_new("baz", "port514")); - appmodel_context_iter_applications(ac, _foreach_app, result); + appmodel_context_register_object(ac, &application_new("foo", "port514")->super); + appmodel_context_register_object(ac, &application_new("bar", "port514")->super); + appmodel_context_register_object(ac, &application_new("baz", "port514")->super); + appmodel_context_iter_objects(ac, APPLICATION_TYPE_NAME, _foreach_app, result); cr_assert_str_eq(result->str, "foobarbaz"); g_string_free(result, TRUE); } @@ -72,13 +69,10 @@ Test(appmodel_context, iter_applications_enumerates_apps_in_the_order_of_registr { GString *result = g_string_sized_new(128); - appmodel_context_register_application(ac, application_new("baz", "*")); - appmodel_context_register_application(ac, application_new("baz", "port514")); - appmodel_context_register_application(ac, application_new("bar", "*")); - appmodel_context_register_application(ac, application_new("bar", "port514")); - appmodel_context_register_application(ac, application_new("foo", "*")); - appmodel_context_register_application(ac, application_new("foo", "port514")); - appmodel_context_iter_applications(ac, _foreach_app, result); + appmodel_context_register_object(ac, &application_new("baz", "port514")->super); + appmodel_context_register_object(ac, &application_new("bar", "port514")->super); + appmodel_context_register_object(ac, &application_new("foo", "port514")->super); + appmodel_context_iter_objects(ac, APPLICATION_TYPE_NAME, _foreach_app, result); cr_assert_str_eq(result->str, "bazbarfoo"); g_string_free(result, TRUE); }