You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2017/11/20 20:33:14 UTC
[17/46] celix git commit: CELIX-417: Initial refactoring for CMake
usage
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/capability.c
----------------------------------------------------------------------
diff --git a/framework/src/capability.c b/framework/src/capability.c
new file mode 100644
index 0000000..9e4dc3a
--- /dev/null
+++ b/framework/src/capability.c
@@ -0,0 +1,100 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * capability.c
+ *
+ * \date Jul 12, 2010
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdlib.h>
+
+#include "capability_private.h"
+#include "attribute.h"
+#include "celix_log.h"
+
+celix_status_t capability_create(module_pt module, hash_map_pt directives, hash_map_pt attributes, capability_pt *capability) {
+ celix_status_t status;
+ *capability = (capability_pt) malloc(sizeof(**capability));
+ if (!*capability) {
+ status = CELIX_ENOMEM;
+ } else {
+ (*capability)->module = module;
+ (*capability)->attributes = attributes;
+ (*capability)->directives = directives;
+ (*capability)->version = NULL;
+
+ attribute_pt versionAttribute = NULL;
+ attribute_pt serviceAttribute = (attribute_pt) hashMap_get(attributes, "service");
+ status = attribute_getValue(serviceAttribute, &(*capability)->serviceName);
+ if (status == CELIX_SUCCESS) {
+ versionAttribute = (attribute_pt) hashMap_get(attributes, "version");
+ if (versionAttribute != NULL) {
+ char *versionStr = NULL;
+ attribute_getValue(versionAttribute, &versionStr);
+ status = version_createVersionFromString(versionStr, &(*capability)->version);
+ } else {
+ status = version_createEmptyVersion(&(*capability)->version);
+ }
+ }
+
+ }
+
+ framework_logIfError(logger, status, NULL, "Failed to create capability");
+
+ return status;
+}
+
+celix_status_t capability_destroy(capability_pt capability) {
+ hash_map_iterator_pt attrIter = hashMapIterator_create(capability->attributes);
+ while (hashMapIterator_hasNext(attrIter)) {
+ attribute_pt attr = hashMapIterator_nextValue(attrIter);
+ hashMapIterator_remove(attrIter);
+ attribute_destroy(attr);
+ }
+ hashMapIterator_destroy(attrIter);
+ hashMap_destroy(capability->attributes, false, false);
+ hashMap_destroy(capability->directives, false, false);
+
+ capability->attributes = NULL;
+ capability->directives = NULL;
+ capability->module = NULL;
+
+ version_destroy(capability->version);
+ capability->version = NULL;
+
+ free(capability);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t capability_getServiceName(capability_pt capability, const char **serviceName) {
+ *serviceName = capability->serviceName;
+ return CELIX_SUCCESS;
+}
+
+celix_status_t capability_getVersion(capability_pt capability, version_pt *version) {
+ *version = capability->version;
+ return CELIX_SUCCESS;
+}
+
+celix_status_t capability_getModule(capability_pt capability, module_pt *module) {
+ *module = capability->module;
+ return CELIX_SUCCESS;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/capability_private.h
----------------------------------------------------------------------
diff --git a/framework/src/capability_private.h b/framework/src/capability_private.h
new file mode 100644
index 0000000..5e302a5
--- /dev/null
+++ b/framework/src/capability_private.h
@@ -0,0 +1,41 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * capability_private.h
+ *
+ * \date Feb 11, 2013
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+
+#ifndef CAPABILITY_PRIVATE_H_
+#define CAPABILITY_PRIVATE_H_
+
+#include "capability.h"
+
+struct capability {
+ char * serviceName;
+ module_pt module;
+ version_pt version;
+ hash_map_pt attributes;
+ hash_map_pt directives;
+};
+
+#endif /* CAPABILITY_PRIVATE_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/celix_errorcodes.c
----------------------------------------------------------------------
diff --git a/framework/src/celix_errorcodes.c b/framework/src/celix_errorcodes.c
new file mode 100644
index 0000000..80323e7
--- /dev/null
+++ b/framework/src/celix_errorcodes.c
@@ -0,0 +1,64 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * celix_errorcodes.c
+ *
+ * \date Aug 30, 2011
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include "celix_errno.h"
+
+static char* celix_error_string(celix_status_t statcode) {
+ switch (statcode) {
+ case CELIX_BUNDLE_EXCEPTION:
+ return "Bundle exception";
+ case CELIX_INVALID_BUNDLE_CONTEXT:
+ return "Invalid bundle context";
+ case CELIX_ILLEGAL_ARGUMENT:
+ return "Illegal argument";
+ case CELIX_INVALID_SYNTAX:
+ return "Invalid syntax";
+ case CELIX_FRAMEWORK_SHUTDOWN:
+ return "Framework shutdown";
+ case CELIX_ILLEGAL_STATE:
+ return "Illegal state";
+ case CELIX_FRAMEWORK_EXCEPTION:
+ return "Framework exception";
+ case CELIX_FILE_IO_EXCEPTION:
+ return "File I/O exception";
+ case CELIX_SERVICE_EXCEPTION:
+ return "Service exception";
+ default:
+ return "Unknown code";
+ }
+}
+
+char* celix_strerror(celix_status_t errorcode, char *buffer, size_t bufferSize) {
+ if (errorcode < CELIX_START_ERROR) {
+ return strerror(errorcode);
+ } else {
+ char * str = celix_error_string(errorcode);
+ strncpy(buffer, str, bufferSize);
+ return buffer;
+ }
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/celix_launcher.c
----------------------------------------------------------------------
diff --git a/framework/src/celix_launcher.c b/framework/src/celix_launcher.c
new file mode 100644
index 0000000..ba83f25
--- /dev/null
+++ b/framework/src/celix_launcher.c
@@ -0,0 +1,242 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * celix_launcher.c
+ *
+ * \date Mar 23, 2010
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#include "celix_launcher.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <signal.h>
+
+#ifndef CELIX_NO_CURLINIT
+#include <curl/curl.h>
+#endif
+
+#include <string.h>
+#include <curl/curl.h>
+#include <signal.h>
+#include <libgen.h>
+#include "celix_launcher.h"
+#include "framework.h"
+#include "linked_list_iterator.h"
+
+static void show_usage(char* prog_name);
+static void shutdown_framework(int signal);
+static void ignore(int signal);
+
+#define DEFAULT_CONFIG_FILE "config.properties"
+
+static framework_pt framework = NULL;
+
+int celixLauncher_launchWithArgs(int argc, char *argv[]) {
+ // Perform some minimal command-line option parsing...
+ char *opt = NULL;
+ if (argc > 1) {
+ opt = argv[1];
+ }
+
+ char *config_file = NULL;
+
+ if (opt) {
+ // Check whether the user wants some help...
+ if (strcmp("-h", opt) == 0 || strcmp("-help", opt) == 0) {
+ show_usage(argv[0]);
+ return 0;
+ } else {
+ config_file = opt;
+ }
+ } else {
+ config_file = DEFAULT_CONFIG_FILE;
+ }
+
+ struct sigaction sigact;
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = shutdown_framework;
+ sigaction(SIGINT, &sigact, NULL);
+ sigaction(SIGTERM, &sigact, NULL);
+
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = ignore;
+ sigaction(SIGUSR1, &sigact, NULL);
+ sigaction(SIGUSR2, &sigact, NULL);
+
+ int rc = celixLauncher_launch(config_file, &framework);
+ if (rc == 0) {
+ celixLauncher_waitForShutdown(framework);
+ celixLauncher_destroy(framework);
+ }
+ return rc;
+}
+
+static void show_usage(char* prog_name) {
+ printf("Usage:\n %s [path/to/config.properties]\n\n", basename(prog_name));
+}
+
+static void shutdown_framework(int signal) {
+ if (framework != NULL) {
+ celixLauncher_stop(framework); //NOTE main thread will destroy
+ }
+}
+
+static void ignore(int signal) {
+ //ignoring for signal SIGUSR1, SIGUSR2. Can be used on threads
+}
+
+int celixLauncher_launch(const char *configFile, framework_pt *framework) {
+ int status = 0;
+ FILE *config = fopen(configFile, "r");
+ if (config != NULL) {
+ status = celixLauncher_launchWithStream(config, framework);
+ } else {
+ fprintf(stderr, "Error: invalid or non-existing configuration file: '%s'.", configFile);
+ perror("");
+ status = 1;
+ }
+ return status;
+}
+
+int celixLauncher_launchWithStream(FILE *stream, framework_pt *framework) {
+ int status = 0;
+
+ properties_pt config = properties_loadWithStream(stream);
+ fclose(stream);
+ // Make sure we've read it and that nothing went wrong with the file access...
+ if (config == NULL) {
+ fprintf(stderr, "Error: invalid configuration file");
+ perror(NULL);
+ status = 1;
+ }
+ else {
+ status = celixLauncher_launchWithProperties(config, framework);
+ }
+
+ return status;
+}
+
+
+int celixLauncher_launchWithProperties(properties_pt config, framework_pt *framework) {
+ celix_status_t status;
+#ifndef CELIX_NO_CURLINIT
+ // Before doing anything else, let's setup Curl
+ curl_global_init(CURL_GLOBAL_NOTHING);
+#endif
+
+ const char* autoStartProp = properties_get(config, "cosgi.auto.start.1");
+ char* autoStart = NULL;
+ if (autoStartProp != NULL) {
+ autoStart = strndup(autoStartProp, 1024*10);
+ }
+
+ status = framework_create(framework, config);
+ bundle_pt fwBundle = NULL;
+ if (status == CELIX_SUCCESS) {
+ status = fw_init(*framework);
+ if (status == CELIX_SUCCESS) {
+ // Start the system bundle
+ status = framework_getFrameworkBundle(*framework, &fwBundle);
+
+ if(status == CELIX_SUCCESS){
+ bundle_start(fwBundle);
+
+ char delims[] = " ";
+ char *result = NULL;
+ char *save_ptr = NULL;
+ linked_list_pt bundles;
+ array_list_pt installed = NULL;
+ bundle_context_pt context = NULL;
+ linked_list_iterator_pt iter = NULL;
+ unsigned int i;
+
+ linkedList_create(&bundles);
+ result = strtok_r(autoStart, delims, &save_ptr);
+ while (result != NULL) {
+ char *location = strdup(result);
+ linkedList_addElement(bundles, location);
+ result = strtok_r(NULL, delims, &save_ptr);
+ }
+ // First install all bundles
+ // Afterwards start them
+ arrayList_create(&installed);
+ bundle_getContext(fwBundle, &context);
+ iter = linkedListIterator_create(bundles, 0);
+ while (linkedListIterator_hasNext(iter)) {
+ bundle_pt current = NULL;
+ char *location = (char *) linkedListIterator_next(iter);
+ if (bundleContext_installBundle(context, location, ¤t) == CELIX_SUCCESS) {
+ // Only add bundle if it is installed correctly
+ arrayList_add(installed, current);
+ } else {
+ printf("Could not install bundle from %s\n", location);
+ }
+ linkedListIterator_remove(iter);
+ free(location);
+ }
+ linkedListIterator_destroy(iter);
+ linkedList_destroy(bundles);
+
+ for (i = 0; i < arrayList_size(installed); i++) {
+ bundle_pt installedBundle = (bundle_pt) arrayList_get(installed, i);
+ bundle_startWithOptions(installedBundle, 0);
+ }
+
+ arrayList_destroy(installed);
+ }
+ }
+ }
+
+ if (status != CELIX_SUCCESS) {
+ printf("Problem creating framework\n");
+ }
+
+ printf("Launcher: Framework Started\n");
+
+ free(autoStart);
+
+ return status;
+}
+
+void celixLauncher_waitForShutdown(framework_pt framework) {
+ framework_waitForStop(framework);
+}
+
+void celixLauncher_destroy(framework_pt framework) {
+ framework_destroy(framework);
+
+#ifndef CELIX_NO_CURLINIT
+ // Cleanup Curl
+ curl_global_cleanup();
+#endif
+
+ printf("Launcher: Exit\n");
+}
+
+void celixLauncher_stop(framework_pt framework) {
+ bundle_pt fwBundle = NULL;
+ if( framework_getFrameworkBundle(framework, &fwBundle) == CELIX_SUCCESS){
+ bundle_stop(fwBundle);
+ }
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/celix_log.c
----------------------------------------------------------------------
diff --git a/framework/src/celix_log.c b/framework/src/celix_log.c
new file mode 100644
index 0000000..c4d51e2
--- /dev/null
+++ b/framework/src/celix_log.c
@@ -0,0 +1,83 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * celix_log.c
+ *
+ * \date 6 Oct 2013
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdarg.h>
+
+#include "celix_errno.h"
+#include "celix_log.h"
+
+void framework_log(framework_logger_pt logger, framework_log_level_t level, const char *func, const char *file, int line, const char *fmsg, ...) {
+ char msg[512];
+ va_list listPointer;
+ va_start(listPointer, fmsg);
+ vsprintf(msg, fmsg, listPointer);
+
+ //FIXME logger and/or logger->logFucntion can be null. But this solution is not thread safe!
+ if (logger != NULL && logger->logFunction != NULL) {
+ logger->logFunction(level, func, file, line, msg);
+ }
+
+ va_end(listPointer);
+}
+
+void framework_logCode(framework_logger_pt logger, framework_log_level_t level, const char *func, const char *file, int line, celix_status_t code, const char *fmsg, ...) {
+ char message[256];
+ celix_strerror(code, message, 256);
+ char msg[512];
+ va_list listPointer;
+ va_start(listPointer, fmsg);
+ vsprintf(msg, fmsg, listPointer);
+
+ framework_log(logger, level, func, file, line, "%s [%d]: %s", message, code, msg);
+
+ va_end(listPointer);
+}
+
+celix_status_t frameworkLogger_log(framework_log_level_t level, const char *func, const char *file, int line, const char *msg) {
+ char *levelStr = NULL;
+ switch (level) {
+ case OSGI_FRAMEWORK_LOG_ERROR:
+ levelStr = "ERROR";
+ break;
+ case OSGI_FRAMEWORK_LOG_WARNING:
+ levelStr = "WARNING";
+ break;
+ case OSGI_FRAMEWORK_LOG_INFO:
+ levelStr = "INFO";
+ break;
+ case OSGI_FRAMEWORK_LOG_DEBUG:
+ default:
+ levelStr = "DEBUG";
+ break;
+ }
+
+ if (level == OSGI_FRAMEWORK_LOG_ERROR) {
+ printf("%s: %s\n\tat %s(%s:%d)\n", levelStr, msg, func, file, line);
+ } else {
+ printf("%s: %s\n", levelStr, msg);
+ }
+
+ return CELIX_SUCCESS;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/filter.c
----------------------------------------------------------------------
diff --git a/framework/src/filter.c b/framework/src/filter.c
new file mode 100644
index 0000000..f06d6e8
--- /dev/null
+++ b/framework/src/filter.c
@@ -0,0 +1,687 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * filter.c
+ *
+ * \date Apr 28, 2010
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "celix_log.h"
+#include "filter_private.h"
+
+static void filter_skipWhiteSpace(char* filterString, int* pos);
+static filter_pt filter_parseFilter(char* filterString, int* pos);
+static filter_pt filter_parseFilterComp(char* filterString, int* pos);
+static filter_pt filter_parseAnd(char* filterString, int* pos);
+static filter_pt filter_parseOr(char* filterString, int* pos);
+static filter_pt filter_parseNot(char* filterString, int* pos);
+static filter_pt filter_parseItem(char* filterString, int* pos);
+static char * filter_parseAttr(char* filterString, int* pos);
+static char * filter_parseValue(char* filterString, int* pos);
+static array_list_pt filter_parseSubstring(char* filterString, int* pos);
+
+static celix_status_t filter_compare(OPERAND operand, char * string, void * value2, bool *result);
+static celix_status_t filter_compareString(OPERAND operand, char * string, void * value2, bool *result);
+
+static void filter_skipWhiteSpace(char * filterString, int * pos) {
+ int length;
+ for (length = strlen(filterString); (*pos < length) && isspace(filterString[*pos]);) {
+ (*pos)++;
+ }
+}
+
+filter_pt filter_create(const char* filterString) {
+ filter_pt filter = NULL;
+ char* filterStr = (char*) filterString;
+ int pos = 0;
+ filter = filter_parseFilter(filterStr, &pos);
+ if (pos != strlen(filterStr)) {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error: Extraneous trailing characters.");
+ filter_destroy(filter);
+ return NULL;
+ }
+ if(filter != NULL){
+ filter->filterStr = filterStr;
+ }
+
+ return filter;
+}
+
+void filter_destroy(filter_pt filter) {
+ if (filter != NULL) {
+ if(filter->value!=NULL){
+ if (filter->operand == SUBSTRING) {
+ int size = arrayList_size(filter->value);
+ for (; size > 0; --size) {
+ char* operand = (char*) arrayList_remove(filter->value, 0);
+ free(operand);
+ }
+ arrayList_destroy(filter->value);
+ filter->value = NULL;
+ } else if ( (filter->operand == OR) || (filter->operand == AND) ) {
+ int size = arrayList_size(filter->value);
+ unsigned int i = 0;
+ for (i = 0; i < size; i++) {
+ filter_pt f = arrayList_get(filter->value, i);
+ filter_destroy(f);
+ }
+ arrayList_destroy(filter->value);
+ filter->value = NULL;
+ } else if (filter->operand == NOT) {
+ filter_destroy(filter->value);
+ filter->value = NULL;
+ } else {
+ free(filter->value);
+ filter->value = NULL;
+ }
+ }
+ free(filter->attribute);
+ filter->attribute = NULL;
+ free(filter);
+ filter = NULL;
+ }
+}
+
+static filter_pt filter_parseFilter(char * filterString, int * pos) {
+ filter_pt filter;
+ filter_skipWhiteSpace(filterString, pos);
+ if (filterString[*pos] != '(') {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error: Missing '(' in filter string '%s'.", filterString);
+ return NULL;
+ }
+ (*pos)++;
+
+ filter = filter_parseFilterComp(filterString, pos);
+
+ filter_skipWhiteSpace(filterString, pos);
+
+ if (filterString[*pos] != ')') {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error: Missing ')' in filter string '%s'.", filterString);
+ if(filter!=NULL){
+ filter_destroy(filter);
+ }
+ return NULL;
+ }
+ (*pos)++;
+ filter_skipWhiteSpace(filterString, pos);
+
+ if(filter != NULL){
+ if(filter->value == NULL && filter->operand!=PRESENT){
+ filter_destroy(filter);
+ return NULL;
+ }
+ }
+
+ return filter;
+}
+
+static filter_pt filter_parseFilterComp(char * filterString, int * pos) {
+ char c;
+ filter_skipWhiteSpace(filterString, pos);
+
+ c = filterString[*pos];
+
+ switch (c) {
+ case '&': {
+ (*pos)++;
+ return filter_parseAnd(filterString, pos);
+ }
+ case '|': {
+ (*pos)++;
+ return filter_parseOr(filterString, pos);
+ }
+ case '!': {
+ (*pos)++;
+ return filter_parseNot(filterString, pos);
+ }
+ }
+ return filter_parseItem(filterString, pos);
+}
+
+static filter_pt filter_parseAnd(char * filterString, int * pos) {
+
+ array_list_pt operands = NULL;
+ filter_skipWhiteSpace(filterString, pos);
+ bool failure = false;
+
+ if (filterString[*pos] != '(') {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error: Missing '('.");
+ return NULL;
+ }
+
+ arrayList_create(&operands);
+ while(filterString[*pos] == '(') {
+ filter_pt child = filter_parseFilter(filterString, pos);
+ if(child == NULL){
+ failure = true;
+ break;
+ }
+ arrayList_add(operands, child);
+ }
+
+ if(failure == true){
+ array_list_iterator_pt listIt = arrayListIterator_create(operands);
+ while(arrayListIterator_hasNext(listIt)){
+ filter_pt f = arrayListIterator_next(listIt);
+ filter_destroy(f);
+ }
+ arrayListIterator_destroy(listIt);
+ arrayList_destroy(operands);
+ operands = NULL;
+ }
+
+ filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+ filter->operand = AND;
+ filter->attribute = NULL;
+ filter->value = operands;
+
+ return filter;
+}
+
+static filter_pt filter_parseOr(char * filterString, int * pos) {
+
+ array_list_pt operands = NULL;
+
+ filter_skipWhiteSpace(filterString, pos);
+ bool failure = false;
+
+ if (filterString[*pos] != '(') {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error: Missing '('.");
+ return NULL;
+ }
+
+ arrayList_create(&operands);
+ while(filterString[*pos] == '(') {
+ filter_pt child = filter_parseFilter(filterString, pos);
+ if(child == NULL){
+ failure = true;
+ break;
+ }
+ arrayList_add(operands, child);
+ }
+
+ if(failure == true){
+ array_list_iterator_pt listIt = arrayListIterator_create(operands);
+ while(arrayListIterator_hasNext(listIt)){
+ filter_pt f = arrayListIterator_next(listIt);
+ filter_destroy(f);
+ }
+ arrayListIterator_destroy(listIt);
+ arrayList_destroy(operands);
+ operands = NULL;
+ }
+
+ filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+ filter->operand = OR;
+ filter->attribute = NULL;
+ filter->value = operands;
+
+ return filter;
+}
+
+static filter_pt filter_parseNot(char * filterString, int * pos) {
+ filter_pt child = NULL;
+ filter_skipWhiteSpace(filterString, pos);
+
+ if (filterString[*pos] != '(') {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error: Missing '('.");
+ return NULL;
+ }
+
+ child = filter_parseFilter(filterString, pos);
+
+
+ filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+ filter->operand = NOT;
+ filter->attribute = NULL;
+ filter->value = child;
+
+ return filter;
+}
+
+static filter_pt filter_parseItem(char * filterString, int * pos) {
+ char * attr = filter_parseAttr(filterString, pos);
+ if(attr == NULL){
+ return NULL;
+ }
+
+ filter_skipWhiteSpace(filterString, pos);
+ switch(filterString[*pos]) {
+ case '~': {
+ if (filterString[*pos + 1] == '=') {
+ filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+ *pos += 2;
+ filter->operand = APPROX;
+ filter->attribute = attr;
+ filter->value = filter_parseValue(filterString, pos);
+ return filter;
+ }
+ break;
+ }
+ case '>': {
+ if (filterString[*pos + 1] == '=') {
+ filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+ *pos += 2;
+ filter->operand = GREATEREQUAL;
+ filter->attribute = attr;
+ filter->value = filter_parseValue(filterString, pos);
+ return filter;
+ }
+ else {
+ filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+ *pos += 1;
+ filter->operand = GREATER;
+ filter->attribute = attr;
+ filter->value = filter_parseValue(filterString, pos);
+ return filter;
+ }
+ break;
+ }
+ case '<': {
+ if (filterString[*pos + 1] == '=') {
+ filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+ *pos += 2;
+ filter->operand = LESSEQUAL;
+ filter->attribute = attr;
+ filter->value = filter_parseValue(filterString, pos);
+ return filter;
+ }
+ else {
+ filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+ *pos += 1;
+ filter->operand = LESS;
+ filter->attribute = attr;
+ filter->value = filter_parseValue(filterString, pos);
+ return filter;
+ }
+ break;
+ }
+ case '=': {
+ filter_pt filter = NULL;
+ array_list_pt subs;
+ if (filterString[*pos + 1] == '*') {
+ int oldPos = *pos;
+ *pos += 2;
+ filter_skipWhiteSpace(filterString, pos);
+ if (filterString[*pos] == ')') {
+ filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+ filter->operand = PRESENT;
+ filter->attribute = attr;
+ filter->value = NULL;
+ return filter;
+ }
+ *pos = oldPos;
+ }
+ filter = (filter_pt) malloc(sizeof(*filter));
+ (*pos)++;
+ subs = filter_parseSubstring(filterString, pos);
+ if(subs!=NULL){
+ if (arrayList_size(subs) == 1) {
+ char * string = (char *) arrayList_get(subs, 0);
+ if (string != NULL) {
+ filter->operand = EQUAL;
+ filter->attribute = attr;
+ filter->value = string;
+
+ arrayList_clear(subs);
+ arrayList_destroy(subs);
+
+ return filter;
+ }
+ }
+ }
+ filter->operand = SUBSTRING;
+ filter->attribute = attr;
+ filter->value = subs;
+ return filter;
+ }
+ }
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Invalid operator.");
+ free(attr);
+ return NULL;
+}
+
+static char * filter_parseAttr(char * filterString, int * pos) {
+ char c;
+ int begin = *pos;
+ int end = *pos;
+ int length = 0;
+
+ filter_skipWhiteSpace(filterString, pos);
+ c = filterString[*pos];
+
+ while (c != '~' && c != '<' && c != '>' && c != '=' && c != '(' && c != ')') {
+ (*pos)++;
+
+ if (!isspace(c)) {
+ end = *pos;
+ }
+
+ c = filterString[*pos];
+ }
+
+ length = end - begin;
+
+ if (length == 0) {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Missing attr.");
+ return NULL;
+ } else {
+ char * attr = (char *) malloc(length+1);
+ strncpy(attr, filterString+begin, length);
+ attr[length] = '\0';
+ return attr;
+ }
+}
+
+static char * filter_parseValue(char * filterString, int * pos) {
+ char *value = calloc(strlen(filterString) + 1, sizeof(*value));
+ int keepRunning = 1;
+
+ while (keepRunning) {
+ char c = filterString[*pos];
+
+ switch (c) {
+ case ')': {
+ keepRunning = 0;
+ break;
+ }
+ case '(': {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Invalid value.");
+ free(value);
+ return NULL;
+ }
+ case '\0':{
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Unclosed bracket.");
+ free(value);
+ return NULL;
+ }
+ case '\\': {
+ (*pos)++;
+ c = filterString[*pos];
+ }
+ /* no break */
+ default: {
+ char ch[2];
+ ch[0] = c;
+ ch[1] = '\0';
+ strcat(value, ch);
+ (*pos)++;
+ break;
+ }
+ }
+ }
+
+ if (strlen(value) == 0) {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Missing value.");
+ free(value);
+ return NULL;
+ }
+ return value;
+}
+
+static array_list_pt filter_parseSubstring(char * filterString, int * pos) {
+ char *sub = calloc(strlen(filterString) + 1, sizeof(*sub));
+ array_list_pt operands = NULL;
+ int keepRunning = 1;
+
+ arrayList_create(&operands);
+ while (keepRunning) {
+ char c = filterString[*pos];
+
+
+ switch (c) {
+ case ')': {
+ if (strlen(sub) > 0) {
+ arrayList_add(operands, strdup(sub));
+ }
+ keepRunning = 0;
+ break;
+ }
+ case '\0':{
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Unclosed bracket.");
+ keepRunning = false;
+ break;
+ }
+ case '(': {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Invalid value.");
+ keepRunning = false;
+ break;
+ }
+ case '*': {
+ if (strlen(sub) > 0) {
+ arrayList_add(operands, strdup(sub));
+ }
+ sub[0] = '\0';
+ arrayList_add(operands, NULL);
+ (*pos)++;
+ break;
+ }
+ case '\\': {
+ (*pos)++;
+ c = filterString[*pos];
+ }
+ /* no break */
+ default: {
+ char ch[2];
+ ch[0] = c;
+ ch[1] = '\0';
+ strcat(sub, ch);
+ (*pos)++;
+ break;
+ }
+ }
+ }
+ free(sub);
+
+ if (arrayList_size(operands) == 0) {
+ fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Missing value.");
+ arrayList_destroy(operands);
+ return NULL;
+ }
+
+ return operands;
+}
+
+celix_status_t filter_match(filter_pt filter, properties_pt properties, bool *result) {
+ switch (filter->operand) {
+ case AND: {
+ array_list_pt filters = (array_list_pt) filter->value;
+ unsigned int i;
+ for (i = 0; i < arrayList_size(filters); i++) {
+ filter_pt sfilter = (filter_pt) arrayList_get(filters, i);
+ bool mresult;
+ filter_match(sfilter, properties, &mresult);
+ if (!mresult) {
+ *result = 0;
+ return CELIX_SUCCESS;
+ }
+ }
+ *result = 1;
+ return CELIX_SUCCESS;
+ }
+ case OR: {
+ array_list_pt filters = (array_list_pt) filter->value;
+ unsigned int i;
+ for (i = 0; i < arrayList_size(filters); i++) {
+ filter_pt sfilter = (filter_pt) arrayList_get(filters, i);
+ bool mresult;
+ filter_match(sfilter, properties, &mresult);
+ if (mresult) {
+ *result = 1;
+ return CELIX_SUCCESS;
+ }
+ }
+ *result = 0;
+ return CELIX_SUCCESS;
+ }
+ case NOT: {
+ filter_pt sfilter = (filter_pt) filter->value;
+ bool mresult;
+ filter_match(sfilter, properties, &mresult);
+ *result = !mresult;
+ return CELIX_SUCCESS;
+ }
+ case SUBSTRING :
+ case EQUAL :
+ case GREATER :
+ case GREATEREQUAL :
+ case LESS :
+ case LESSEQUAL :
+ case APPROX : {
+ char * value = (properties == NULL) ? NULL: (char*)properties_get(properties, filter->attribute);
+
+ return filter_compare(filter->operand, value, filter->value, result);
+ }
+ case PRESENT: {
+ char * value = (properties == NULL) ? NULL: (char*)properties_get(properties, filter->attribute);
+ *result = value != NULL;
+ return CELIX_SUCCESS;
+ }
+ }
+ *result = 0;
+ return CELIX_SUCCESS;
+}
+
+static celix_status_t filter_compare(OPERAND operand, char * string, void * value2, bool *result) {
+ if (string == NULL) {
+ *result = 0;
+ return CELIX_SUCCESS;
+ }
+ return filter_compareString(operand, string, value2, result);
+
+}
+
+static celix_status_t filter_compareString(OPERAND operand, char * string, void * value2, bool *result) {
+ switch (operand) {
+ case SUBSTRING: {
+ array_list_pt subs = (array_list_pt) value2;
+ int pos = 0;
+ unsigned int i;
+ int size = arrayList_size(subs);
+ for (i = 0; i < size; i++) {
+ char * substr = (char *) arrayList_get(subs, i);
+
+ if (i + 1 < size) {
+ if (substr == NULL) {
+ unsigned int index;
+ char * substr2 = (char *) arrayList_get(subs, i + 1);
+ if (substr2 == NULL) {
+ continue;
+ }
+ index = strcspn(string+pos, substr2);
+ if (index == strlen(string+pos)) {
+ *result = false;
+ return CELIX_SUCCESS;
+ }
+
+ pos = index + strlen(substr2);
+ if (i + 2 < size) {
+ i++;
+ }
+ } else {
+ unsigned int len = strlen(substr);
+ char * region = (char *)malloc(len+1);
+ strncpy(region, string+pos, len);
+ region[len] = '\0';
+ if (strcmp(region, substr) == 0) {
+ pos += len;
+ } else {
+ free(region);
+ *result = false;
+ return CELIX_SUCCESS;
+ }
+ free(region);
+ }
+ } else {
+ unsigned int len;
+ int begin;
+
+ if (substr == NULL) {
+ *result = true;
+ return CELIX_SUCCESS;
+ }
+ len = strlen(substr);
+ begin = strlen(string)-len;
+ *result = (strcmp(string+begin, substr) == 0);
+ return CELIX_SUCCESS;
+ }
+ }
+ *result = true;
+ return CELIX_SUCCESS;
+ }
+ case APPROX: //TODO: Implement strcmp with ignorecase and ignorespaces
+ case EQUAL: {
+ *result = (strcmp(string, (char *) value2) == 0);
+ return CELIX_SUCCESS;
+ }
+ case GREATER: {
+ *result = (strcmp(string, (char *) value2) > 0);
+ return CELIX_SUCCESS;
+ }
+ case GREATEREQUAL: {
+ *result = (strcmp(string, (char *) value2) >= 0);
+ return CELIX_SUCCESS;
+ }
+ case LESS: {
+ *result = (strcmp(string, (char *) value2) < 0);
+ return CELIX_SUCCESS;
+ }
+ case LESSEQUAL: {
+ *result = (strcmp(string, (char *) value2) <= 0);
+ return CELIX_SUCCESS;
+ }
+ case AND:
+ case NOT:
+ case OR:
+ case PRESENT: {
+ }
+ /* no break */
+ }
+ *result = false;
+ return CELIX_SUCCESS;
+}
+
+celix_status_t filter_getString(filter_pt filter, const char **filterStr) {
+ if (filter != NULL) {
+ *filterStr = filter->filterStr;
+ }
+ return CELIX_SUCCESS;
+}
+
+celix_status_t filter_match_filter(filter_pt src, filter_pt dest, bool *result) {
+ char *srcStr = NULL;
+ char *destStr = NULL;
+ *result = false;
+
+ if (src) srcStr = src->filterStr;
+ if (dest) destStr = dest->filterStr;
+
+ if ((srcStr != NULL) && (destStr != NULL)) {
+ // TODO: should be done smarted, e.g. src="&(a=1)(b=2)" and dest="&(b=2)(a=1)" should result in true
+ *result = (strcmp(srcStr, destStr) == 0);
+ }
+
+ return CELIX_SUCCESS;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/filter_private.h
----------------------------------------------------------------------
diff --git a/framework/src/filter_private.h b/framework/src/filter_private.h
new file mode 100644
index 0000000..d19de2d
--- /dev/null
+++ b/framework/src/filter_private.h
@@ -0,0 +1,57 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * filter_private.h
+ *
+ * \date Feb 13, 2013
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+
+#ifndef FILTER_PRIVATE_H_
+#define FILTER_PRIVATE_H_
+
+#include "filter.h"
+#include "array_list.h"
+
+typedef enum operand
+{
+ EQUAL,
+ APPROX,
+ GREATER,
+ GREATEREQUAL,
+ LESS,
+ LESSEQUAL,
+ PRESENT,
+ SUBSTRING,
+ AND,
+ OR,
+ NOT,
+} OPERAND;
+
+struct filter {
+ OPERAND operand;
+ char * attribute;
+ void * value;
+ char *filterStr;
+};
+
+
+#endif /* FILTER_PRIVATE_H_ */