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:[email protected]";>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:[email protected]";>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:[email protected]";>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:[email protected]";>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:[email protected]";>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:[email protected]";>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:[email protected]";>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_ */

Reply via email to