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, &current) == 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_ */