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:36 UTC

[39/46] celix git commit: CELIX-417: Initial refactoring for CMake usage

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/deployment_admin.c
----------------------------------------------------------------------
diff --git a/deployment_admin/src/deployment_admin.c b/deployment_admin/src/deployment_admin.c
new file mode 100644
index 0000000..17e78db
--- /dev/null
+++ b/deployment_admin/src/deployment_admin.c
@@ -0,0 +1,809 @@
+/**
+ *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.
+ */
+/*
+ * deployment_admin.c
+ *
+ *  \date       Nov 7, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <curl/curl.h>
+#include <curl/easy.h>
+
+#include <uuid/uuid.h>
+
+#include "celixbool.h"
+#include "deployment_admin.h"
+#include "celix_errno.h"
+#include "bundle_context.h"
+#include "constants.h"
+#include "deployment_package.h"
+#include "bundle.h"
+#include "utils.h"
+
+#include "log.h"
+#include "log_store.h"
+#include "log_sync.h"
+
+#include "resource_processor.h"
+#include "miniunz.h"
+
+#define IDENTIFICATION_ID "deployment_admin_identification"
+#define DEFAULT_IDENTIFICATION_ID "celix"
+
+#define ADMIN_URL "deployment_admin_url"
+#define DEFAULT_ADMIN_URL "localhost:8080"
+
+#define DEPLOYMENT_CACHE_DIR "deployment_cache_dir"
+#define DEPLOYMENT_TAGS "deployment_tags"
+// "http://localhost:8080/deployment/"
+
+#define VERSIONS "/versions"
+
+static void* deploymentAdmin_poll(void *deploymentAdmin);
+celix_status_t deploymentAdmin_download(deployment_admin_pt admin, char * url, char **inputFile);
+size_t deploymentAdmin_writeData(void *ptr, size_t size, size_t nmemb, FILE *stream);
+static celix_status_t deploymentAdmin_deleteTree(char * directory);
+celix_status_t deploymentAdmin_readVersions(deployment_admin_pt admin, array_list_pt versions);
+
+celix_status_t deploymentAdmin_stopDeploymentPackageBundles(deployment_admin_pt admin, deployment_package_pt target);
+celix_status_t deploymentAdmin_updateDeploymentPackageBundles(deployment_admin_pt admin, deployment_package_pt source);
+celix_status_t deploymentAdmin_startDeploymentPackageCustomizerBundles(deployment_admin_pt admin, deployment_package_pt source, deployment_package_pt target);
+celix_status_t deploymentAdmin_processDeploymentPackageResources(deployment_admin_pt admin, deployment_package_pt source);
+celix_status_t deploymentAdmin_dropDeploymentPackageResources(deployment_admin_pt admin, deployment_package_pt source, deployment_package_pt target);
+celix_status_t deploymentAdmin_dropDeploymentPackageBundles(deployment_admin_pt admin, deployment_package_pt source, deployment_package_pt target);
+celix_status_t deploymentAdmin_startDeploymentPackageBundles(deployment_admin_pt admin, deployment_package_pt source);
+
+static celix_status_t deploymentAdmin_performRequest(deployment_admin_pt admin, char* entry);
+static celix_status_t deploymentAdmin_auditEventTargetPropertiesSet(deployment_admin_pt admin);
+static celix_status_t deploymentAdmin_auditEventFrameworkStarted(deployment_admin_pt admin);
+
+celix_status_t deploymentAdmin_create(bundle_context_pt context, deployment_admin_pt *admin) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*admin = calloc(1, sizeof(**admin));
+	if (!*admin) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*admin)->running = true;
+		(*admin)->context = context;
+		(*admin)->current = NULL;
+		(*admin)->packages = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+		(*admin)->targetIdentification = NULL;
+		(*admin)->pollUrl = NULL;
+		(*admin)->auditlogUrl = NULL;
+
+        bundleContext_getProperty(context, IDENTIFICATION_ID, (const char**) &(*admin)->targetIdentification);
+        if ((*admin)->targetIdentification == NULL) {
+        	(*admin)->targetIdentification = DEFAULT_IDENTIFICATION_ID;
+        	fw_log(logger, OSGI_FRAMEWORK_LOG_INFO, "Identification ID not set, using default '%s'. Set id by using '%s'",
+        		DEFAULT_IDENTIFICATION_ID, IDENTIFICATION_ID);
+        }
+
+        struct timeval tv;
+		gettimeofday(&tv,NULL);
+		(*admin)->auditlogId =  tv.tv_sec*(uint64_t)1000000+tv.tv_usec;
+        (*admin)->aditlogSeqNr = 0;
+
+		if ((*admin)->targetIdentification == NULL ) {
+		    fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Target name must be set using \"deployment_admin_identification\"");
+		} else {
+			const char *url = NULL;
+			bundleContext_getProperty(context, ADMIN_URL, &url);
+			if (url == NULL) {
+				url = DEFAULT_ADMIN_URL;
+			    fw_log(logger, OSGI_FRAMEWORK_LOG_INFO, "Server URL is not set, using default '%s'. Set id by using '%s'",
+        			DEFAULT_ADMIN_URL, ADMIN_URL);
+			}
+		
+			int pollUrlLength = strlen(url) + strlen((*admin)->targetIdentification) + strlen(VERSIONS) + 13;
+			int auditlogUrlLength = strlen(url) + 10;
+
+			char pollUrl[pollUrlLength];
+			char auditlogUrl[auditlogUrlLength];
+
+			snprintf(pollUrl, pollUrlLength, "%s/deployment/%s%s", url, (*admin)->targetIdentification, VERSIONS);
+			snprintf(auditlogUrl, auditlogUrlLength, "%s/auditlog", url);
+
+			(*admin)->pollUrl = strdup(pollUrl);
+			(*admin)->auditlogUrl = strdup(auditlogUrl);
+
+//				log_store_pt store = NULL;
+//				log_pt log = NULL;
+//				log_sync_pt sync = NULL;
+//				logStore_create(subpool, &store);
+//				log_create(subpool, store, &log);
+//				logSync_create(subpool, (*admin)->targetIdentification, store, &sync);
+//
+//				log_log(log, 20000, NULL);
+
+
+			celixThread_create(&(*admin)->poller, NULL, deploymentAdmin_poll, *admin);
+		}
+	}
+
+	return status;
+}
+
+
+
+celix_status_t deploymentAdmin_destroy(deployment_admin_pt admin) {
+	celix_status_t status = CELIX_SUCCESS;
+
+    admin->running = false;
+
+    celixThread_join(admin->poller, NULL);
+
+	hash_map_iterator_pt iter = hashMapIterator_create(admin->packages);
+
+	while (hashMapIterator_hasNext(iter)) {
+		deployment_package_pt target = (deployment_package_pt) hashMapIterator_nextValue(iter);
+		deploymentPackage_destroy(target);
+	}
+
+	hashMapIterator_destroy(iter);
+
+	hashMap_destroy(admin->packages, false, false);
+
+	if (admin->current != NULL) {
+		free(admin->current);
+	}
+
+	free(admin->pollUrl);
+	free(admin->auditlogUrl);
+
+	free(admin);
+
+	return status;
+}
+
+
+static celix_status_t deploymentAdmin_performRequest(deployment_admin_pt admin, char* entry) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    CURL *curl;
+    CURLcode res;
+    curl = curl_easy_init();
+
+    if (!curl) {
+        status = CELIX_BUNDLE_EXCEPTION;
+
+        fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error initializing curl.");
+    }
+
+    char url[strlen(admin->auditlogUrl)+6];
+    sprintf(url, "%s/send", admin->auditlogUrl);
+
+    if (status == CELIX_SUCCESS) {
+            curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+            curl_easy_setopt(curl, CURLOPT_URL, url);
+            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, entry);
+            res = curl_easy_perform(curl);
+
+            if (res != CURLE_OK ) {
+                status = CELIX_BUNDLE_EXCEPTION;
+                fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error sending auditlog, got curl error code %d", res);
+            }
+    }
+
+    return status;
+}
+
+static celix_status_t deploymentAdmin_auditEventTargetPropertiesSet(deployment_admin_pt admin) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    const char *tags = NULL;
+
+    bundleContext_getProperty(admin->context, DEPLOYMENT_TAGS, &tags);
+
+    if (tags != NULL) {
+        char entry[512];
+        int entrySize = 0;
+
+        entrySize = snprintf(entry, 512, "%s,%llu,%u,0,%i,%s\n", admin->targetIdentification, admin->auditlogId, admin->aditlogSeqNr++, DEPLOYMENT_ADMIN_AUDIT_EVENT__TARGETPROPERTIES_SET, tags);
+
+        if (entrySize >= 512) {
+            status = CELIX_BUNDLE_EXCEPTION;
+        }
+        else {
+            status = deploymentAdmin_performRequest(admin, entry);
+        }
+    }
+
+    return status;
+}
+
+static celix_status_t deploymentAdmin_auditEventFrameworkStarted(deployment_admin_pt admin) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    char entry[512];
+    int entrySize = 0;
+
+    entrySize = snprintf(entry, 512, "%s,%llu,%u,0,%i\n", admin->targetIdentification, admin->auditlogId, admin->aditlogSeqNr++, DEPLOYMENT_ADMIN_AUDIT_EVENT__FRAMEWORK_STARTED);
+
+    if (entrySize >= 512) {
+        status = CELIX_BUNDLE_EXCEPTION;
+    }
+    else {
+        status = deploymentAdmin_performRequest(admin, entry);
+    }
+
+    return status;
+}
+
+
+static void *deploymentAdmin_poll(void *deploymentAdmin) {
+	deployment_admin_pt admin = deploymentAdmin;
+
+	/*first poll send framework started audit event, note this will register the target in Apache ACE*/
+    deploymentAdmin_auditEventFrameworkStarted(admin);
+    deploymentAdmin_auditEventTargetPropertiesSet(admin);
+
+	while (admin->running) {
+        int i;
+
+		//poll ace
+		array_list_pt versions = NULL;
+	    arrayList_create(&versions);
+
+		deploymentAdmin_readVersions(admin, versions);
+
+		char *last = arrayList_get(versions, arrayList_size(versions) - 1);
+
+		if (last != NULL) {
+			if (admin->current == NULL || strcmp(last, admin->current) != 0) {
+				int length = strlen(admin->pollUrl) + strlen(last) + 2;
+				char request[length];
+
+				// TODO
+                //      We do not yet support fix packages
+                //		Check string lenght!
+                // snprintf(request, length, "%s/%s?current=%s", admin->pollUrl, last, admin->current);
+                snprintf(request, length, "%s/%s", admin->pollUrl, last);
+
+				char *inputFilename = NULL;
+				celix_status_t status = deploymentAdmin_download(admin ,request, &inputFilename);
+				if (status == CELIX_SUCCESS) {
+					bundle_pt bundle = NULL;
+					bundleContext_getBundle(admin->context, &bundle);
+					char *entry = NULL;
+					bundle_getEntry(bundle, "/", &entry);
+
+					// Handle file
+					char tmpDir[256];
+					char uuid[37];
+					uuid_t uid;
+					uuid_generate(uid);
+					uuid_unparse(uid, uuid);
+                    snprintf(tmpDir, 256, "%s%s", entry, uuid);
+                    if( mkdir(tmpDir, S_IRWXU) == -1){
+                        fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Failed creating directory %s",tmpDir);
+                    }
+
+					// TODO: update to use bundle cache DataFile instead of module entries.
+					unzip_extractDeploymentPackage(inputFilename, tmpDir);
+					int length = strlen(tmpDir) + 22;
+					char manifest[length];
+					snprintf(manifest, length, "%s/META-INF/MANIFEST.MF", tmpDir);
+					manifest_pt mf = NULL;
+					manifest_createFromFile(manifest, &mf);
+					deployment_package_pt source = NULL;
+					deploymentPackage_create(admin->context, mf, &source);
+					const char *name = NULL;
+					deploymentPackage_getName(source, &name);
+
+					int repoDirLength = strlen(entry) + 5;
+					char repoDir[repoDirLength];
+					snprintf(repoDir, repoDirLength, "%srepo", entry);
+					if( mkdir(repoDir, S_IRWXU) == -1){
+						fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Failed creating directory %s",repoDir);
+					}
+
+					int repoCacheLength = strlen(entry) + strlen(name) + 6;
+					char repoCache[repoCacheLength];
+					snprintf(repoCache, repoCacheLength, "%srepo/%s", entry, name);
+					deploymentAdmin_deleteTree(repoCache);
+					int stat = rename(tmpDir, repoCache);
+					if (stat != 0) {
+						fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "No success");
+					}
+
+					deployment_package_pt target = hashMap_get(admin->packages, name);
+					if (target == NULL) {
+//						target = empty package
+					}
+
+					deploymentAdmin_stopDeploymentPackageBundles(admin, target);
+					deploymentAdmin_updateDeploymentPackageBundles(admin, source);
+					deploymentAdmin_startDeploymentPackageCustomizerBundles(admin, source, target);
+					deploymentAdmin_processDeploymentPackageResources(admin, source);
+					deploymentAdmin_dropDeploymentPackageResources(admin, source, target);
+					deploymentAdmin_dropDeploymentPackageBundles(admin, source, target);
+					deploymentAdmin_startDeploymentPackageBundles(admin, source);
+
+					deploymentAdmin_deleteTree(repoCache);
+					deploymentAdmin_deleteTree(tmpDir);
+					if( remove(inputFilename) == -1){
+						fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Remove of %s failed",inputFilename);
+					}
+					admin->current = strdup(last);
+					hashMap_put(admin->packages, (char*)name, source);
+
+                    free(entry);
+				}
+				if (inputFilename != NULL) {
+					free(inputFilename);
+				}
+			}
+		}
+
+		sleep(5);
+
+		for (i = arrayList_size(versions); i > 0; --i) {
+		    free(arrayList_remove(versions, 0));
+		}
+
+		arrayList_destroy(versions);
+	}
+
+	return NULL;
+}
+
+struct MemoryStruct {
+	char *memory;
+	size_t size;
+};
+
+size_t deploymentAdmin_parseVersions(void *contents, size_t size, size_t nmemb, void *userp) {
+	size_t realsize = size * nmemb;
+	struct MemoryStruct *mem = (struct MemoryStruct *)userp;
+
+	mem->memory = realloc(mem->memory, mem->size + realsize + 1);
+	if (mem->memory == NULL) {
+		/* out of memory! */
+		fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "not enough memory (realloc returned NULL)");
+		exit(EXIT_FAILURE);
+	}
+
+	memcpy(&(mem->memory[mem->size]), contents, realsize);
+	mem->size += realsize;
+	mem->memory[mem->size] = 0;
+
+	return realsize;
+}
+
+celix_status_t deploymentAdmin_readVersions(deployment_admin_pt admin, array_list_pt versions) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	CURL *curl;
+	CURLcode res;
+	curl = curl_easy_init();
+	struct MemoryStruct chunk;
+	chunk.memory = calloc(1, sizeof(char));
+	chunk.size = 0;
+	if (curl) {
+	    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+		curl_easy_setopt(curl, CURLOPT_URL, admin->pollUrl);
+		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, deploymentAdmin_parseVersions);
+		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk);
+		curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
+		res = curl_easy_perform(curl);
+		if (res != CURLE_OK) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+		/* always cleanup */
+		curl_easy_cleanup(curl);
+
+		char *last;
+		char *token = strtok_r(chunk.memory, "\n", &last);
+		while (token != NULL) {
+			arrayList_add(versions, strdup(token));
+			token = strtok_r(NULL, "\n", &last);
+		}
+	}
+
+    if (chunk.memory) {
+        free(chunk.memory);
+    }
+
+	return status;
+}
+
+
+celix_status_t deploymentAdmin_download(deployment_admin_pt admin, char * url, char **inputFile) {
+	celix_status_t status = CELIX_SUCCESS;
+	CURL *curl = NULL;
+	CURLcode res = 0;
+	curl = curl_easy_init();
+	if (curl) {
+		const char *dir = NULL;
+		bundleContext_getProperty(admin->context, DEPLOYMENT_CACHE_DIR, &dir);
+		if (dir != NULL) {
+			*inputFile = calloc(1024, sizeof (char));
+			snprintf(*inputFile, 1024, "%s/%s", dir, "updateXXXXXX");
+		}
+		else {
+			*inputFile = strdup("updateXXXXXX");
+		}
+		umask(0011);
+        int fd = mkstemp(*inputFile);
+        if (fd != -1) {
+            FILE *fp = fopen(*inputFile, "wb+");
+            if(fp!=NULL){
+            	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+            	curl_easy_setopt(curl, CURLOPT_URL, url);
+            	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, deploymentAdmin_writeData);
+            	curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+            	curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
+            	//curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
+            	//curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, updateCommand_downloadProgress);
+            	res = curl_easy_perform(curl);
+
+            	/* always cleanup */
+            	curl_easy_cleanup(curl);
+            	fclose(fp);
+            }
+            else{
+            	status = CELIX_FILE_IO_EXCEPTION;
+            }
+        }
+        else{
+        	status = CELIX_FILE_IO_EXCEPTION;
+        }
+	}
+	else{
+		res = CURLE_FAILED_INIT;
+	}
+
+	if (res != CURLE_OK) {
+		*inputFile[0] = '\0';
+		status = CELIX_ILLEGAL_STATE;
+	}
+
+	return status;
+}
+
+size_t deploymentAdmin_writeData(void *ptr, size_t size, size_t nmemb, FILE *stream) {
+    size_t written = fwrite(ptr, size, nmemb, stream);
+    return written;
+}
+
+
+static celix_status_t deploymentAdmin_deleteTree(char * directory) {
+	DIR *dir;
+	celix_status_t status = CELIX_SUCCESS;
+	dir = opendir(directory);
+	if (dir == NULL) {
+	    status = CELIX_FILE_IO_EXCEPTION;
+	} else {
+
+		struct dirent* dent = NULL;
+
+		errno = 0;
+		dent = readdir(dir);
+		while (errno == 0 && dent != NULL) {
+			if ((strcmp((dent->d_name), ".") != 0) && (strcmp((dent->d_name), "..") != 0)) {
+				char subdir[512];
+				snprintf(subdir, sizeof(subdir), "%s/%s", directory, dent->d_name);
+
+				if (dent->d_type == DT_DIR) {
+					status = deploymentAdmin_deleteTree(subdir);
+				} else {
+					if (remove(subdir) != 0) {
+						status = CELIX_FILE_IO_EXCEPTION;
+						break;
+					}
+				}
+			}
+
+			errno = 0;
+			dent = readdir(dir);
+		}
+
+		if (errno != 0) {
+			status = CELIX_FILE_IO_EXCEPTION;
+		} else if (closedir(dir) != 0) {
+			status = CELIX_FILE_IO_EXCEPTION;
+		} else if (rmdir(directory) != 0) {
+				status = CELIX_FILE_IO_EXCEPTION;
+		}
+	}
+
+	framework_logIfError(logger, status, NULL, "Failed to delete tree");
+
+	return status;
+}
+
+celix_status_t deploymentAdmin_stopDeploymentPackageBundles(deployment_admin_pt admin, deployment_package_pt target) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (target != NULL) {
+		array_list_pt infos = NULL;
+		deploymentPackage_getBundleInfos(target, &infos);
+		int i;
+		for (i = 0; i < arrayList_size(infos); i++) {
+			bundle_pt bundle = NULL;
+			bundle_info_pt info = arrayList_get(infos, i);
+			deploymentPackage_getBundle(target, info->symbolicName, &bundle);
+			if (bundle != NULL) {
+				bundle_stop(bundle);
+			} else {
+				fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "DEPLOYMENT_ADMIN: Bundle %s not found", info->symbolicName);
+			}
+		}
+		arrayList_destroy(infos);
+	}
+
+	return status;
+}
+
+celix_status_t deploymentAdmin_updateDeploymentPackageBundles(deployment_admin_pt admin, deployment_package_pt source) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	array_list_pt infos = NULL;
+	deploymentPackage_getBundleInfos(source, &infos);
+	int i;
+	for (i = 0; i < arrayList_size(infos); i++) {
+		bundle_pt bundle = NULL;
+		bundle_info_pt info = arrayList_get(infos, i);
+
+		bundleContext_getBundle(admin->context, &bundle);
+		char *entry = NULL;
+		bundle_getEntry(bundle, "/", &entry);
+		const char *name = NULL;
+		deploymentPackage_getName(source, &name);
+
+		int bundlePathLength = strlen(entry) + strlen(name) + strlen(info->path) + 7;
+		int bsnLength = strlen(info->symbolicName) + 9;
+
+		char bundlePath[bundlePathLength];
+		snprintf(bundlePath, bundlePathLength, "%srepo/%s/%s", entry, name, info->path);
+
+		char bsn[bsnLength];
+		snprintf(bsn, bsnLength, "osgi-dp:%s", info->symbolicName);
+
+		bundle_pt updateBundle = NULL;
+		deploymentPackage_getBundle(source, info->symbolicName, &updateBundle);
+		if (updateBundle != NULL) {
+			//printf("Update bundle from: %s\n", bundlePath);
+			bundle_update(updateBundle, bundlePath);
+		} else {
+			//printf("Install bundle from: %s\n", bundlePath);
+			bundleContext_installBundle2(admin->context, bsn, bundlePath, &updateBundle);
+		}
+
+        free(entry);
+	}
+	arrayList_destroy(infos);
+	return status;
+}
+
+celix_status_t deploymentAdmin_startDeploymentPackageCustomizerBundles(deployment_admin_pt admin, deployment_package_pt source, deployment_package_pt target) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	array_list_pt bundles = NULL;
+	array_list_pt sourceInfos = NULL;
+
+	arrayList_create(&bundles);
+
+	deploymentPackage_getBundleInfos(source, &sourceInfos);
+	int i;
+	for (i = 0; i < arrayList_size(sourceInfos); i++) {
+		bundle_info_pt sourceInfo = arrayList_get(sourceInfos, i);
+		if (sourceInfo->customizer) {
+			bundle_pt bundle = NULL;
+			deploymentPackage_getBundle(source, sourceInfo->symbolicName, &bundle);
+			if (bundle != NULL) {
+				arrayList_add(bundles, bundle);
+			}
+		}
+	}
+	arrayList_destroy(sourceInfos);
+
+	if (target != NULL) {
+		array_list_pt targetInfos = NULL;
+		deploymentPackage_getBundleInfos(target, &targetInfos);
+		for (i = 0; i < arrayList_size(targetInfos); i++) {
+			bundle_info_pt targetInfo = arrayList_get(targetInfos, i);
+			if (targetInfo->customizer) {
+				bundle_pt bundle = NULL;
+				deploymentPackage_getBundle(target, targetInfo->symbolicName, &bundle);
+				if (bundle != NULL) {
+					arrayList_add(bundles, bundle);
+				}
+			}
+		}
+		arrayList_destroy(targetInfos);
+	}
+
+	for (i = 0; i < arrayList_size(bundles); i++) {
+		bundle_pt bundle = arrayList_get(bundles, i);
+		bundle_start(bundle);
+	}
+
+    arrayList_destroy(bundles);
+
+	return status;
+}
+
+celix_status_t deploymentAdmin_processDeploymentPackageResources(deployment_admin_pt admin, deployment_package_pt source) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	array_list_pt infos = NULL;
+	deploymentPackage_getResourceInfos(source, &infos);
+	int i;
+	for (i = 0; i < arrayList_size(infos); i++) {
+		resource_info_pt info = arrayList_get(infos, i);
+		array_list_pt services = NULL;
+		int length = strlen(OSGI_FRAMEWORK_SERVICE_PID) + strlen(info->resourceProcessor) + 4;
+		char filter[length];
+
+		snprintf(filter, length, "(%s=%s)", OSGI_FRAMEWORK_SERVICE_PID, info->resourceProcessor);
+
+		status = bundleContext_getServiceReferences(admin->context, DEPLOYMENTADMIN_RESOURCE_PROCESSOR_SERVICE, filter, &services);
+		if (status == CELIX_SUCCESS) {
+			if (services != NULL && arrayList_size(services) > 0) {
+				service_reference_pt ref = arrayList_get(services, 0);
+				// In Felix a check is done to assure the processor belongs to the deployment package
+				// Is this according to spec?
+				void *processorP = NULL;
+				status = bundleContext_getService(admin->context, ref, &processorP);
+				if (status == CELIX_SUCCESS) {
+					bundle_pt bundle = NULL;
+					char *entry = NULL;
+					const char *name = NULL;
+					const char *packageName = NULL;
+					resource_processor_service_pt processor = processorP;
+
+					bundleContext_getBundle(admin->context, &bundle);
+					bundle_getEntry(bundle, "/", &entry);
+					deploymentPackage_getName(source, &name);
+
+					int length = strlen(entry) + strlen(name) + strlen(info->path) + 7;
+					char resourcePath[length];
+					snprintf(resourcePath, length, "%srepo/%s/%s", entry, name, info->path);
+					deploymentPackage_getName(source, &packageName);
+
+					processor->begin(processor->processor, (char*)packageName);
+					processor->process(processor->processor, info->path, resourcePath);
+
+                    free(entry);
+				}
+			}
+		}
+
+		if(services != NULL) {
+			arrayList_destroy(services);
+		}
+	}
+
+    arrayList_destroy(infos);
+
+
+	return status;
+}
+
+celix_status_t deploymentAdmin_dropDeploymentPackageResources(deployment_admin_pt admin, deployment_package_pt source, deployment_package_pt target) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (target != NULL) {
+        array_list_pt infos = NULL;
+        deploymentPackage_getResourceInfos(target, &infos);
+        int i;
+        for (i = 0; i < arrayList_size(infos); i++) {
+            resource_info_pt info = arrayList_get(infos, i);
+            resource_info_pt sourceInfo = NULL;
+            deploymentPackage_getResourceInfoByPath(source, info->path, &sourceInfo);
+            if (sourceInfo == NULL) {
+                array_list_pt services = NULL;
+                int length = strlen(OSGI_FRAMEWORK_SERVICE_PID) + strlen(info->resourceProcessor) + 4;
+                char filter[length];
+
+                snprintf(filter, length, "(%s=%s)", OSGI_FRAMEWORK_SERVICE_PID, info->resourceProcessor);
+                status = bundleContext_getServiceReferences(admin->context, DEPLOYMENTADMIN_RESOURCE_PROCESSOR_SERVICE, filter, &services);
+                if (status == CELIX_SUCCESS) {
+                    if (services != NULL && arrayList_size(services) > 0) {
+                        service_reference_pt ref = arrayList_get(services, 0);
+                        // In Felix a check is done to assure the processor belongs to the deployment package
+                        // Is this according to spec?
+                        void *processorP = NULL;
+                        status = bundleContext_getService(admin->context, ref, &processorP);
+                        if (status == CELIX_SUCCESS) {
+                            const char *packageName = NULL;
+                            resource_processor_service_pt processor = processorP;
+
+                            deploymentPackage_getName(source, &packageName);
+                            processor->begin(processor->processor, (char*)packageName);
+                            processor->dropped(processor->processor, info->path);
+                        }
+                    }
+                }
+
+                if (services != NULL) {
+                    arrayList_destroy(services);
+                }
+
+            }
+        }
+
+        arrayList_destroy(infos);
+    }
+
+    return status;
+}
+
+celix_status_t deploymentAdmin_dropDeploymentPackageBundles(deployment_admin_pt admin, deployment_package_pt source, deployment_package_pt target) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (target != NULL) {
+		array_list_pt targetInfos = NULL;
+		deploymentPackage_getBundleInfos(target, &targetInfos);
+		int i;
+		for (i = 0; i < arrayList_size(targetInfos); i++) {
+			bundle_info_pt targetInfo = arrayList_get(targetInfos, i);
+			if (!targetInfo->customizer) {
+				bundle_info_pt info = NULL;
+				deploymentPackage_getBundleInfoByName(source, targetInfo->symbolicName, &info);
+				if (info == NULL) {
+					bundle_pt bundle = NULL;
+					deploymentPackage_getBundle(target, targetInfo->symbolicName, &bundle);
+					bundle_uninstall(bundle);
+				}
+			}
+		}
+		arrayList_destroy(targetInfos);
+	}
+
+	return status;
+}
+
+celix_status_t deploymentAdmin_startDeploymentPackageBundles(deployment_admin_pt admin, deployment_package_pt source) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	array_list_pt infos = NULL;
+	deploymentPackage_getBundleInfos(source, &infos);
+	int i;
+	for (i = 0; i < arrayList_size(infos); i++) {
+		bundle_pt bundle = NULL;
+		bundle_info_pt info = arrayList_get(infos, i);
+		if (!info->customizer) {
+			deploymentPackage_getBundle(source, info->symbolicName, &bundle);
+			if (bundle != NULL) {
+				bundle_start(bundle);
+			} else {
+				fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "DEPLOYMENT_ADMIN: Could not start bundle %s", info->symbolicName);
+			}
+		}
+	}
+	arrayList_destroy(infos);
+
+	return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/deployment_admin.h
----------------------------------------------------------------------
diff --git a/deployment_admin/src/deployment_admin.h b/deployment_admin/src/deployment_admin.h
new file mode 100644
index 0000000..a7e3a39
--- /dev/null
+++ b/deployment_admin/src/deployment_admin.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.
+ */
+/*
+ * deployment_admin.h
+ *
+ *  \date       Nov 7, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef DEPLOYMENT_ADMIN_H_
+#define DEPLOYMENT_ADMIN_H_
+
+#include "bundle_context.h"
+
+typedef struct deployment_admin *deployment_admin_pt;
+
+struct deployment_admin {
+	celix_thread_t poller;
+	bundle_context_pt context;
+
+	bool running;
+	char *current;
+	hash_map_pt packages;
+	char *targetIdentification;
+	char *pollUrl;
+	char *auditlogUrl;
+	unsigned long long auditlogId;
+	unsigned int aditlogSeqNr;
+};
+
+typedef enum {
+	DEPLOYMENT_ADMIN_AUDIT_EVENT__FRAMEWORK_STARTED = 1005,
+	DEPLOYMENT_ADMIN_AUDIT_EVENT__TARGETPROPERTIES_SET = 4001
+
+} DEPLOYMENT_ADMIN_AUDIT_EVENT;
+
+celix_status_t deploymentAdmin_create(bundle_context_pt context, deployment_admin_pt *admin);
+celix_status_t deploymentAdmin_destroy(deployment_admin_pt admin);
+
+#endif /* DEPLOYMENT_ADMIN_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/deployment_admin_activator.c
----------------------------------------------------------------------
diff --git a/deployment_admin/src/deployment_admin_activator.c b/deployment_admin/src/deployment_admin_activator.c
new file mode 100644
index 0000000..93fd6b5
--- /dev/null
+++ b/deployment_admin/src/deployment_admin_activator.c
@@ -0,0 +1,78 @@
+/**
+ *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.
+ */
+/*
+ * deployment_admin_activator.c
+ *
+ *  \date       Nov 7, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+#include <stdlib.h>
+
+#include "bundle_activator.h"
+#include "deployment_admin.h"
+
+struct bundle_activator {
+	deployment_admin_pt admin;
+};
+
+typedef struct bundle_activator* bundle_activator_pt;
+
+celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	bundle_activator_pt activator = NULL;
+
+	activator = calloc(1, sizeof(*activator));
+	if (!activator) {
+		status = CELIX_ENOMEM;
+	} else {
+		status = deploymentAdmin_create(context, &activator->admin);
+
+		*userData = activator;
+	}
+
+	return status;
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	return status;
+}
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	return status;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
+	celix_status_t status;
+
+	bundle_activator_pt activator = (bundle_activator_pt) userData;
+
+	status = deploymentAdmin_destroy(activator->admin);
+
+	free(activator);
+
+	return status;
+}
+
+

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/deployment_package.c
----------------------------------------------------------------------
diff --git a/deployment_admin/src/deployment_package.c b/deployment_admin/src/deployment_package.c
new file mode 100644
index 0000000..1520db8
--- /dev/null
+++ b/deployment_admin/src/deployment_package.c
@@ -0,0 +1,219 @@
+/**
+ *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.
+ */
+/*
+ * deployment_package.c
+ *
+ *  \date       Nov 8, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "celix_errno.h"
+
+#include "deployment_package.h"
+#include "constants.h"
+#include "utils.h"
+#include "bundle_context.h"
+#include "module.h"
+#include "bundle.h"
+
+static const char * const RESOURCE_PROCESSOR = "Resource-Processor";
+static const char * const DEPLOYMENTPACKAGE_CUSTOMIZER = "DeploymentPackage-Customizer";
+
+celix_status_t deploymentPackage_processEntries(deployment_package_pt package);
+static celix_status_t deploymentPackage_isBundleResource(properties_pt attributes, bool *isBundleResource);
+static celix_status_t deploymentPackage_parseBooleanHeader(const char *value, bool *boolValue);
+
+celix_status_t deploymentPackage_create(bundle_context_pt context, manifest_pt manifest, deployment_package_pt *package) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*package = calloc(1, sizeof(**package));
+	if (!(*package)) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*package)->context = context;
+		(*package)->manifest = manifest;
+		(*package)->bundleInfos = NULL;
+		(*package)->resourceInfos = NULL;
+		(*package)->nameToBundleInfo = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+		(*package)->pathToEntry = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+		status = arrayList_create(&(*package)->bundleInfos);
+		if (status == CELIX_SUCCESS) {
+			status = arrayList_create(&(*package)->resourceInfos);
+			if (status == CELIX_SUCCESS) {
+				status = deploymentPackage_processEntries(*package);
+				if (status == CELIX_SUCCESS) {
+					int i;
+					for (i = 0; i < arrayList_size((*package)->bundleInfos); i++) {
+						bundle_info_pt info = arrayList_get((*package)->bundleInfos, i);
+						hashMap_put((*package)->nameToBundleInfo, info->symbolicName, info);
+					}
+					for (i = 0; i < arrayList_size((*package)->resourceInfos); i++) {
+						resource_info_pt info = arrayList_get((*package)->resourceInfos, i);
+						hashMap_put((*package)->pathToEntry, info->path, info);
+					}
+				}
+			}
+		}
+	}
+
+	return status;
+}
+
+celix_status_t deploymentPackage_destroy(deployment_package_pt package) {
+	celix_status_t status = CELIX_SUCCESS;
+	int i;
+
+
+    manifest_destroy(package->manifest);
+
+	hashMap_destroy(package->nameToBundleInfo, false, false);
+	hashMap_destroy(package->pathToEntry, false, false);
+
+
+    for(i = arrayList_size(package->bundleInfos); i  > 0; --i) {
+        free(arrayList_remove(package->bundleInfos, 0));
+    }
+
+	arrayList_destroy(package->bundleInfos);
+
+    for (i = arrayList_size(package->resourceInfos); i > 0; --i) {
+        free(arrayList_remove(package->resourceInfos, 0));
+    }
+
+
+	arrayList_destroy(package->resourceInfos);
+
+	free(package);
+
+	return status;
+}
+
+celix_status_t deploymentPackage_getName(deployment_package_pt package, const char **name) {
+	*name = manifest_getValue(package->manifest, "DeploymentPackage-SymbolicName");
+	return CELIX_SUCCESS;
+}
+
+celix_status_t deploymentPackage_getBundleInfos(deployment_package_pt package, array_list_pt *infos) {
+	*infos = arrayList_clone(package->bundleInfos);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t deploymentPackage_getBundleInfoByName(deployment_package_pt package, const char *name, bundle_info_pt *info) {
+	*info = hashMap_get(package->nameToBundleInfo, name);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t deploymentPackage_getBundle(deployment_package_pt package, const char *name, bundle_pt *bundle) {
+	if (hashMap_containsKey(package->nameToBundleInfo, name)) {
+		array_list_pt bundles = NULL;
+		bundleContext_getBundles(package->context, &bundles);
+		int i;
+		for (i = 0; i < arrayList_size(bundles); i++) {
+			bundle_pt ibundle = arrayList_get(bundles, i);
+			module_pt module = NULL;
+			bundle_getCurrentModule(ibundle, &module);
+			const char *bsn = NULL;
+			module_getSymbolicName(module, &bsn);
+			if (strcmp(bsn, name) == 0) {
+				*bundle = ibundle;
+				break;
+			}
+		}
+
+		arrayList_destroy(bundles);
+	}
+
+	return CELIX_SUCCESS;
+}
+
+celix_status_t deploymentPackage_getResourceInfos(deployment_package_pt package, array_list_pt *infos) {
+	*infos = arrayList_clone(package->resourceInfos);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t deploymentPackage_getResourceInfoByPath(deployment_package_pt package, const char *path, resource_info_pt *info) {
+	*info = hashMap_get(package->pathToEntry, path);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t deploymentPackage_getVersion(deployment_package_pt package, version_pt *version) {
+	const char *versionStr = manifest_getValue(package->manifest, "DeploymentPackage-Version");
+	return version_createVersionFromString(versionStr, version);
+}
+
+celix_status_t deploymentPackage_processEntries(deployment_package_pt package) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	hash_map_pt entries = NULL;
+	manifest_getEntries(package->manifest, &entries);
+	hash_map_iterator_pt iter = hashMapIterator_create(entries);
+	while (hashMapIterator_hasNext(iter)) {
+		hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+		char *name = hashMapEntry_getKey(entry);
+		properties_pt values = hashMapEntry_getValue(entry);
+
+		bool isBundleResource;
+		deploymentPackage_isBundleResource(values, &isBundleResource);
+		if (isBundleResource) {
+			bundle_info_pt info = calloc(1, sizeof(*info));
+			info->path = name;
+			info->attributes = values;
+			info->symbolicName = (char*)properties_get(values, OSGI_FRAMEWORK_BUNDLE_SYMBOLICNAME);
+			const char *version = properties_get(values, OSGI_FRAMEWORK_BUNDLE_VERSION);
+			info->version = NULL;
+			status = version_createVersionFromString((char*)version, &info->version);
+			const char *customizer = properties_get(values, DEPLOYMENTPACKAGE_CUSTOMIZER);
+			deploymentPackage_parseBooleanHeader((char*)customizer, &info->customizer);
+
+			arrayList_add(package->bundleInfos, info);
+		} else {
+			resource_info_pt info = calloc(1, sizeof(*info));
+			info->path = name;
+			info->attributes = values;
+			info->resourceProcessor = (char*)properties_get(values,RESOURCE_PROCESSOR);
+
+			arrayList_add(package->resourceInfos, info);
+		}
+	}
+	hashMapIterator_destroy(iter);
+
+	return status;
+}
+
+static celix_status_t deploymentPackage_isBundleResource(properties_pt attributes, bool *isBundleResource) {
+	*isBundleResource = properties_get(attributes, (char *) OSGI_FRAMEWORK_BUNDLE_SYMBOLICNAME) != NULL;
+	return CELIX_SUCCESS;
+}
+
+static celix_status_t deploymentPackage_parseBooleanHeader(const char *value, bool *boolValue) {
+	*boolValue = false;
+	if (value != NULL) {
+		if (strcmp(value, "true") == 0) {
+			*boolValue = true;
+		} else {
+			*boolValue = false;
+		}
+	}
+	return CELIX_SUCCESS;
+}
+
+

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/deployment_package.h
----------------------------------------------------------------------
diff --git a/deployment_admin/src/deployment_package.h b/deployment_admin/src/deployment_package.h
new file mode 100644
index 0000000..06c1767
--- /dev/null
+++ b/deployment_admin/src/deployment_package.h
@@ -0,0 +1,76 @@
+/**
+ *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.
+ */
+/*
+ * deployment_package.h
+ *
+ *  \date       Nov 8, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef DEPLOYMENT_PACKAGE_H_
+#define DEPLOYMENT_PACKAGE_H_
+
+#include "version.h"
+#include "bundle_context.h"
+
+#include "array_list.h"
+
+struct bundle_info {
+	char *path;
+	version_pt version;
+	char *symbolicName;
+	bool customizer;
+
+	properties_pt attributes;
+};
+
+typedef struct bundle_info *bundle_info_pt;
+
+struct resource_info {
+	char *path;
+	properties_pt attributes;
+
+	char *resourceProcessor;
+};
+
+typedef struct resource_info *resource_info_pt;
+
+struct deployment_package {
+	bundle_context_pt context;
+	manifest_pt manifest;
+	array_list_pt bundleInfos;
+	array_list_pt resourceInfos;
+	hash_map_pt nameToBundleInfo;
+	hash_map_pt pathToEntry;
+};
+
+typedef struct deployment_package *deployment_package_pt;
+
+celix_status_t deploymentPackage_create(bundle_context_pt context, manifest_pt manifest, deployment_package_pt *package);
+celix_status_t deploymentPackage_destroy(deployment_package_pt package);
+celix_status_t deploymentPackage_getName(deployment_package_pt package, const char** name);
+celix_status_t deploymentPackage_getBundleInfos(deployment_package_pt package, array_list_pt *infos);
+celix_status_t deploymentPackage_getBundleInfoByName(deployment_package_pt package, const char* name, bundle_info_pt *info);
+celix_status_t deploymentPackage_getResourceInfos(deployment_package_pt package, array_list_pt *infos);
+celix_status_t deploymentPackage_getResourceInfoByPath(deployment_package_pt package, const char* path, resource_info_pt *info);
+celix_status_t deploymentPackage_getBundle(deployment_package_pt package, const char* name, bundle_pt *bundle);
+celix_status_t deploymentPackage_getVersion(deployment_package_pt package, version_pt *version);
+
+#endif /* DEPLOYMENT_PACKAGE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/ioapi.c
----------------------------------------------------------------------
diff --git a/deployment_admin/src/ioapi.c b/deployment_admin/src/ioapi.c
new file mode 100644
index 0000000..49958f6
--- /dev/null
+++ b/deployment_admin/src/ioapi.c
@@ -0,0 +1,235 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
+
+*/
+
+#if (defined(_WIN32))
+        #define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "ioapi.h"
+
+voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
+{
+    if (pfilefunc->zfile_func64.zopen64_file != NULL)
+        return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
+    else
+    {
+        return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
+    }
+}
+
+long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
+{
+    if (pfilefunc->zfile_func64.zseek64_file != NULL)
+        return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
+    else
+    {
+        uLong offsetTruncated = (uLong)offset;
+        if (offsetTruncated != offset)
+            return -1;
+        else
+            return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
+    }
+}
+
+ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
+{
+    if (pfilefunc->zfile_func64.zseek64_file != NULL)
+        return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
+    else
+    {
+        uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
+        if ((tell_uLong) == ((uLong)-1))
+            return (ZPOS64_T)-1;
+        else
+            return tell_uLong;
+    }
+}
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
+{
+    p_filefunc64_32->zfile_func64.zopen64_file = NULL;
+    p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
+    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+    p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
+    p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
+    p_filefunc64_32->zfile_func64.ztell64_file = NULL;
+    p_filefunc64_32->zfile_func64.zseek64_file = NULL;
+    p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
+    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+    p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
+    p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
+    p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
+}
+
+
+
+static voidpf  ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
+static uLong   ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+static uLong   ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
+static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
+static long    ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+static int     ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
+static int     ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
+
+static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
+{
+    FILE* file = NULL;
+    const char* mode_fopen = NULL;
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+        mode_fopen = "rb";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+        mode_fopen = "r+b";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+        mode_fopen = "wb";
+
+    if ((filename!=NULL) && (mode_fopen != NULL))
+        file = fopen(filename, mode_fopen);
+    return file;
+}
+
+static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
+{
+    FILE* file = NULL;
+    const char* mode_fopen = NULL;
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+        mode_fopen = "rb";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+        mode_fopen = "r+b";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+        mode_fopen = "wb";
+
+    if ((filename!=NULL) && (mode_fopen != NULL))
+        file = fopen64((const char*)filename, mode_fopen);
+    return file;
+}
+
+
+static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
+{
+    uLong ret;
+    ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+    return ret;
+}
+
+static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
+{
+    uLong ret;
+    ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
+    return ret;
+}
+
+static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
+{
+    long ret;
+    ret = ftell((FILE *)stream);
+    return ret;
+}
+
+
+static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
+{
+    ZPOS64_T ret;
+    ret = ftello64((FILE *)stream);
+    return ret;
+}
+
+static long ZCALLBACK fseek_file_func (voidpf  opaque, voidpf stream, uLong offset, int origin)
+{
+    int fseek_origin=0;
+    long ret;
+    switch (origin)
+    {
+    case ZLIB_FILEFUNC_SEEK_CUR :
+        fseek_origin = SEEK_CUR;
+        break;
+    case ZLIB_FILEFUNC_SEEK_END :
+        fseek_origin = SEEK_END;
+        break;
+    case ZLIB_FILEFUNC_SEEK_SET :
+        fseek_origin = SEEK_SET;
+        break;
+    default: return -1;
+    }
+    ret = 0;
+    if (fseek((FILE *)stream, offset, fseek_origin) != 0)
+        ret = -1;
+    return ret;
+}
+
+static long ZCALLBACK fseek64_file_func (voidpf  opaque, voidpf stream, ZPOS64_T offset, int origin)
+{
+    int fseek_origin=0;
+    long ret;
+    switch (origin)
+    {
+    case ZLIB_FILEFUNC_SEEK_CUR :
+        fseek_origin = SEEK_CUR;
+        break;
+    case ZLIB_FILEFUNC_SEEK_END :
+        fseek_origin = SEEK_END;
+        break;
+    case ZLIB_FILEFUNC_SEEK_SET :
+        fseek_origin = SEEK_SET;
+        break;
+    default: return -1;
+    }
+    ret = 0;
+
+    if(fseeko64((FILE *)stream, offset, fseek_origin) != 0)
+                        ret = -1;
+
+    return ret;
+}
+
+
+static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
+{
+    int ret;
+    ret = fclose((FILE *)stream);
+    return ret;
+}
+
+static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
+{
+    int ret;
+    ret = ferror((FILE *)stream);
+    return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+  zlib_filefunc_def* pzlib_filefunc_def;
+{
+    pzlib_filefunc_def->zopen_file = fopen_file_func;
+    pzlib_filefunc_def->zread_file = fread_file_func;
+    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+    pzlib_filefunc_def->ztell_file = ftell_file_func;
+    pzlib_filefunc_def->zseek_file = fseek_file_func;
+    pzlib_filefunc_def->zclose_file = fclose_file_func;
+    pzlib_filefunc_def->zerror_file = ferror_file_func;
+    pzlib_filefunc_def->opaque = NULL;
+}
+
+void fill_fopen64_filefunc (zlib_filefunc64_def*  pzlib_filefunc_def)
+{
+    pzlib_filefunc_def->zopen64_file = fopen64_file_func;
+    pzlib_filefunc_def->zread_file = fread_file_func;
+    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+    pzlib_filefunc_def->ztell64_file = ftell64_file_func;
+    pzlib_filefunc_def->zseek64_file = fseek64_file_func;
+    pzlib_filefunc_def->zclose_file = fclose_file_func;
+    pzlib_filefunc_def->zerror_file = ferror_file_func;
+    pzlib_filefunc_def->opaque = NULL;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/ioapi.h
----------------------------------------------------------------------
diff --git a/deployment_admin/src/ioapi.h b/deployment_admin/src/ioapi.h
new file mode 100644
index 0000000..8309c4c
--- /dev/null
+++ b/deployment_admin/src/ioapi.h
@@ -0,0 +1,200 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
+
+         Changes
+
+    Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
+    Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
+               More if/def section may be needed to support other platforms
+    Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
+                          (but you should use iowin32.c for windows instead)
+
+*/
+
+#ifndef _ZLIBIOAPI64_H
+#define _ZLIBIOAPI64_H
+
+#if (!defined(_WIN32)) && (!defined(WIN32))
+
+  // Linux needs this to support file operation on files larger then 4+GB
+  // But might need better if/def to select just the platforms that needs them.
+
+        #ifndef __USE_FILE_OFFSET64
+                #define __USE_FILE_OFFSET64
+        #endif
+        #ifndef __USE_LARGEFILE64
+                #define __USE_LARGEFILE64
+        #endif
+        #ifndef _LARGEFILE64_SOURCE
+                #define _LARGEFILE64_SOURCE
+        #endif
+        #ifndef _FILE_OFFSET_BIT
+                #define _FILE_OFFSET_BIT 64
+        #endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zlib.h"
+
+#if defined(USE_FILE32API)
+#define fopen64 fopen
+#define ftello64 ftell
+#define fseeko64 fseek
+#else
+#ifdef _MSC_VER
+ #define fopen64 fopen
+ #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
+  #define ftello64 _ftelli64
+  #define fseeko64 _fseeki64
+ #else // old MSC
+  #define ftello64 ftell
+  #define fseeko64 fseek
+ #endif
+#endif
+#endif
+
+/*
+#ifndef ZPOS64_T
+  #ifdef _WIN32
+                #define ZPOS64_T fpos_t
+  #else
+    #include <stdint.h>
+    #define ZPOS64_T uint64_t
+  #endif
+#endif
+*/
+
+#ifdef HAVE_MINIZIP64_CONF_H
+#include "mz64conf.h"
+#endif
+
+/* a type choosen by DEFINE */
+#ifdef HAVE_64BIT_INT_CUSTOM
+typedef  64BIT_INT_CUSTOM_TYPE ZPOS64_T;
+#else
+#ifdef HAS_STDINT_H
+#include "stdint.h"
+typedef uint64_t ZPOS64_T;
+#else
+
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 ZPOS64_T;
+#else
+typedef unsigned long long int ZPOS64_T;
+#endif
+#endif
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ      (1)
+#define ZLIB_FILEFUNC_MODE_WRITE     (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE   (8)
+
+
+#ifndef ZCALLBACK
+ #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+   #define ZCALLBACK CALLBACK
+ #else
+   #define ZCALLBACK
+ #endif
+#endif
+
+
+
+
+typedef voidpf   (ZCALLBACK *open_file_func)      OF((voidpf opaque, const char* filename, int mode));
+typedef uLong    (ZCALLBACK *read_file_func)      OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong    (ZCALLBACK *write_file_func)     OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef int      (ZCALLBACK *close_file_func)     OF((voidpf opaque, voidpf stream));
+typedef int      (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef long     (ZCALLBACK *tell_file_func)      OF((voidpf opaque, voidpf stream));
+typedef long     (ZCALLBACK *seek_file_func)      OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+
+
+/* here is the "old" 32 bits structure structure */
+typedef struct zlib_filefunc_def_s
+{
+    open_file_func      zopen_file;
+    read_file_func      zread_file;
+    write_file_func     zwrite_file;
+    tell_file_func      ztell_file;
+    seek_file_func      zseek_file;
+    close_file_func     zclose_file;
+    testerror_file_func zerror_file;
+    voidpf              opaque;
+} zlib_filefunc_def;
+
+typedef ZPOS64_T (ZCALLBACK *tell64_file_func)    OF((voidpf opaque, voidpf stream));
+typedef long     (ZCALLBACK *seek64_file_func)    OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+typedef voidpf   (ZCALLBACK *open64_file_func)    OF((voidpf opaque, const void* filename, int mode));
+
+typedef struct zlib_filefunc64_def_s
+{
+    open64_file_func    zopen64_file;
+    read_file_func      zread_file;
+    write_file_func     zwrite_file;
+    tell64_file_func    ztell64_file;
+    seek64_file_func    zseek64_file;
+    close_file_func     zclose_file;
+    testerror_file_func zerror_file;
+    voidpf              opaque;
+} zlib_filefunc64_def;
+
+void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+/* now internal definition, only for zip.c and unzip.h */
+typedef struct zlib_filefunc64_32_def_s
+{
+    zlib_filefunc64_def zfile_func64;
+    open_file_func      zopen32_file;
+    tell_file_func      ztell32_file;
+    seek_file_func      zseek32_file;
+} zlib_filefunc64_32_def;
+
+
+#define ZREAD64(filefunc,filestream,buf,size)     ((*((filefunc).zfile_func64.zread_file))   ((filefunc).zfile_func64.opaque,filestream,buf,size))
+#define ZWRITE64(filefunc,filestream,buf,size)    ((*((filefunc).zfile_func64.zwrite_file))  ((filefunc).zfile_func64.opaque,filestream,buf,size))
+//#define ZTELL64(filefunc,filestream)            ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
+//#define ZSEEK64(filefunc,filestream,pos,mode)   ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE64(filefunc,filestream)             ((*((filefunc).zfile_func64.zclose_file))  ((filefunc).zfile_func64.opaque,filestream))
+#define ZERROR64(filefunc,filestream)             ((*((filefunc).zfile_func64.zerror_file))  ((filefunc).zfile_func64.opaque,filestream))
+
+voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
+long    call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
+ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
+
+void    fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
+
+#define ZOPEN64(filefunc,filename,mode)         (call_zopen64((&(filefunc)),(filename),(mode)))
+#define ZTELL64(filefunc,filestream)            (call_ztell64((&(filefunc)),(filestream)))
+#define ZSEEK64(filefunc,filestream,pos,mode)   (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/log.c
----------------------------------------------------------------------
diff --git a/deployment_admin/src/log.c b/deployment_admin/src/log.c
new file mode 100644
index 0000000..98e757d
--- /dev/null
+++ b/deployment_admin/src/log.c
@@ -0,0 +1,73 @@
+/**
+ *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.
+ */
+/*
+ * log.c
+ *
+ *  \date       Apr 19, 2012
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "celix_errno.h"
+
+#include "log.h"
+#include "log_store.h"
+
+struct log {
+	log_store_pt logStore;
+};
+
+celix_status_t log_create(log_store_pt store, log_pt *log) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*log = calloc(1, sizeof(**log));
+	if (!*log) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*log)->logStore = store;
+	}
+
+	return status;
+}
+
+celix_status_t log_destroy(log_pt *log) {
+	free(*log);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t log_log(log_pt log, unsigned int type, properties_pt properties) {
+	celix_status_t status;
+
+	log_event_pt event = NULL;
+
+	status = logStore_put(log->logStore, type, properties, &event);
+
+	return status;
+}
+
+celix_status_t log_bundleChanged(void * listener, bundle_event_pt event) {
+	return CELIX_SUCCESS;
+}
+
+celix_status_t log_frameworkEvent(void * listener, framework_event_pt event) {
+	return CELIX_SUCCESS;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/log.h
----------------------------------------------------------------------
diff --git a/deployment_admin/src/log.h b/deployment_admin/src/log.h
new file mode 100644
index 0000000..fa77911
--- /dev/null
+++ b/deployment_admin/src/log.h
@@ -0,0 +1,44 @@
+/**
+ *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.
+ */
+/*
+ * log.h
+ *
+ *  \date       Apr 18, 2012
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef LOG_H_
+#define LOG_H_
+
+#include "log_event.h"
+#include "log_store.h"
+
+#include "bundle_event.h"
+#include "framework_event.h"
+
+typedef struct log *log_pt;
+
+celix_status_t log_create(log_store_pt store, log_pt *log);
+celix_status_t log_log(log_pt log, unsigned int type, properties_pt properties);
+
+celix_status_t log_bundleChanged(void * listener, bundle_event_pt event);
+celix_status_t log_frameworkEvent(void * listener, framework_event_pt event);
+
+#endif /* LOG_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/log_event.h
----------------------------------------------------------------------
diff --git a/deployment_admin/src/log_event.h b/deployment_admin/src/log_event.h
new file mode 100644
index 0000000..c1a76a9
--- /dev/null
+++ b/deployment_admin/src/log_event.h
@@ -0,0 +1,43 @@
+/**
+ *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.
+ */
+/*
+ * log_event.h
+ *
+ *  \date       Apr 19, 2012
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef LOG_EVENT_H_
+#define LOG_EVENT_H_
+
+#include "properties.h"
+
+struct log_event {
+	char *targetId;
+	unsigned long logId;
+	unsigned long id;
+	unsigned long time;
+	unsigned int type;
+	properties_pt properties;
+};
+
+typedef struct log_event *log_event_pt;
+
+#endif /* LOG_EVENT_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/log_store.c
----------------------------------------------------------------------
diff --git a/deployment_admin/src/log_store.c b/deployment_admin/src/log_store.c
new file mode 100644
index 0000000..c2bfabc
--- /dev/null
+++ b/deployment_admin/src/log_store.c
@@ -0,0 +1,94 @@
+/**
+ *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.
+ */
+/*
+ * log_store.c
+ *
+ *  \date       Apr 18, 2012
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+#include <stdlib.h>
+
+#include <time.h>
+
+#include "celix_errno.h"
+#include "array_list.h"
+
+#include "log_store.h"
+#include "log.h"
+
+struct log_store {
+	unsigned long storeId;
+
+	array_list_pt logEvents;
+};
+
+static celix_status_t logStore_getNextID(log_store_pt store, unsigned long *id);
+
+celix_status_t logStore_create(log_store_pt *store) {
+	celix_status_t status = CELIX_SUCCESS;
+	*store = calloc(1, sizeof(**store));
+	if (!*store) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*store)->storeId = 1;
+		arrayList_create(&(*store)->logEvents);
+	}
+
+	return status;
+}
+
+celix_status_t logStore_put(log_store_pt store, unsigned int type, properties_pt properties, log_event_pt *event) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*event = calloc(1, sizeof(**event));
+	(*event)->targetId = NULL;
+	(*event)->logId = store->storeId;
+	(*event)->id = 0;
+	(*event)->time = time(NULL);
+	(*event)->type = type;
+	(*event)->properties = properties;
+
+	logStore_getNextID(store, &(*event)->id);
+
+	arrayList_add(store->logEvents, *event);
+
+	return status;
+}
+
+celix_status_t logStore_getLogId(log_store_pt store, unsigned long *id) {
+	*id = store->storeId;
+	return CELIX_SUCCESS;
+}
+
+celix_status_t logStore_getEvents(log_store_pt store, array_list_pt *events) {
+	*events = store->logEvents;
+	return CELIX_SUCCESS;
+}
+
+celix_status_t logStore_getHighestId(log_store_pt store, long *id) {
+	*id = ((long) arrayList_size(store->logEvents)) - 1;
+	return CELIX_SUCCESS;
+}
+
+static celix_status_t logStore_getNextID(log_store_pt store, unsigned long *id) {
+	*id = arrayList_size(store->logEvents);
+	return CELIX_SUCCESS;
+}
+

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/log_store.h
----------------------------------------------------------------------
diff --git a/deployment_admin/src/log_store.h b/deployment_admin/src/log_store.h
new file mode 100644
index 0000000..84299b3
--- /dev/null
+++ b/deployment_admin/src/log_store.h
@@ -0,0 +1,45 @@
+/**
+ *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.
+ */
+/*
+ * log_store.h
+ *
+ *  \date       Apr 18, 2012
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef LOG_STORE_H_
+#define LOG_STORE_H_
+
+#include "log_event.h"
+
+#include "properties.h"
+#include "array_list.h"
+
+typedef struct log_store *log_store_pt;
+
+celix_status_t logStore_create(log_store_pt *store);
+celix_status_t logStore_put(log_store_pt store, unsigned int type, properties_pt properties, log_event_pt *event);
+
+celix_status_t logStore_getLogId(log_store_pt store, unsigned long *id);
+celix_status_t logStore_getEvents(log_store_pt store, array_list_pt *events);
+
+celix_status_t logStore_getHighestId(log_store_pt store, long *id);
+
+#endif /* LOG_STORE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/log_sync.c
----------------------------------------------------------------------
diff --git a/deployment_admin/src/log_sync.c b/deployment_admin/src/log_sync.c
new file mode 100644
index 0000000..242beea
--- /dev/null
+++ b/deployment_admin/src/log_sync.c
@@ -0,0 +1,209 @@
+/**
+ *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.
+ */
+/*
+ * log_sync.c
+ *
+ *  \date       Apr 19, 2012
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <curl/curl.h>
+#include <curl/easy.h>
+
+#include "celix_errno.h"
+#include "celix_log.h"
+#include "celixbool.h"
+
+#include "celix_threads.h"
+
+#include "log_sync.h"
+#include "log_event.h"
+
+struct log_sync {
+	log_store_pt logStore;
+
+	char *targetId;
+	bool running;
+
+	celix_thread_t syncTask;
+};
+
+struct log_descriptor {
+	char *targetId;
+	unsigned long logId;
+	unsigned long low;
+	unsigned long high;
+};
+
+typedef struct log_descriptor *log_descriptor_pt;
+
+celix_status_t logSync_queryLog(log_sync_pt logSync, char *targetId, long logId, char **queryReply);
+static size_t logSync_readQeury(void *contents, size_t size, size_t nmemb, void *userp);
+static void *logSync_synchronize(void *logSyncP);
+
+celix_status_t logSync_create(char *targetId, log_store_pt store, log_sync_pt *logSync) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*logSync = calloc(1, sizeof(**logSync));
+	if (!*logSync) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*logSync)->logStore = store;
+		(*logSync)->targetId = targetId;
+		(*logSync)->syncTask = celix_thread_default;
+		(*logSync)->running = true;
+
+		celixThread_create(&(*logSync)->syncTask, NULL, logSync_synchronize, *logSync);
+	}
+
+	return status;
+}
+
+celix_status_t logSync_parseLogDescriptor(log_sync_pt logSync, char *descriptorString, log_descriptor_pt *descriptor) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	fw_log(logger, OSGI_FRAMEWORK_LOG_DEBUG, "Descriptor: %s", descriptorString);
+	char *last = NULL;
+	char *targetId = strtok_r(descriptorString, ",", &last);
+	char *logIdStr = strtok_r(NULL, ",", &last);
+	long logId = 0;
+	if (logIdStr != NULL) {
+		logId = atol(logIdStr);
+	}
+	char *range = strtok_r(NULL, ",", &last);
+	fw_log(logger, OSGI_FRAMEWORK_LOG_DEBUG, "Range: %s", range);
+
+	long low = 0;
+	long high = 0;
+	if (range != NULL) {
+		char *rangeToken = NULL;
+		low = atol(strtok_r(range, "-", &rangeToken));
+		high = atol(strtok_r(NULL, "-", &rangeToken));
+	}
+
+	*descriptor = calloc(1, sizeof(**descriptor));
+	if (!*descriptor) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*descriptor)->targetId = targetId;
+		(*descriptor)->logId = logId;
+		(*descriptor)->low = low;
+		(*descriptor)->high = high;
+	}
+
+	return status;
+}
+
+static void *logSync_synchronize(void *logSyncP) {
+	log_sync_pt logSync = logSyncP;
+
+	while (logSync->running) {
+
+		//query current log
+		// http://localhost:8080/auditlog/query?tid=targetid&logid=logid
+		char *logDescriptorString = NULL;
+		unsigned long id = 0;
+		logStore_getLogId(logSync->logStore, &id);
+		logSync_queryLog(logSync, logSync->targetId, id, &logDescriptorString);
+		log_descriptor_pt descriptor = NULL;
+		logSync_parseLogDescriptor(logSync, logDescriptorString, &descriptor);
+
+		long highest = 0;
+		logStore_getHighestId(logSync->logStore, &highest);
+
+		if (highest >= 0) {
+			int i;
+			for (i = descriptor->high + 1; i <= highest; i++) {
+				array_list_pt events = NULL;
+				logStore_getEvents(logSync->logStore, &events);
+			}
+		}
+
+		if(descriptor!=NULL){
+			free(descriptor);
+		}
+
+		sleep(10);
+	}
+
+
+	celixThread_exit(NULL);
+	return NULL;
+}
+
+struct MemoryStruct {
+	char *memory;
+	size_t size;
+};
+
+celix_status_t logSync_queryLog(log_sync_pt logSync, char *targetId, long logId, char **queryReply) {
+	// http://localhost:8080/auditlog/query?tid=targetid&logid=logid
+	celix_status_t status = CELIX_SUCCESS;
+	int length = strlen(targetId) + 60;
+	char query[length];
+	snprintf(query, length, "http://localhost:8080/auditlog/query?tid=%s&logid=1", targetId);
+
+	CURL *curl;
+	CURLcode res;
+	curl = curl_easy_init();
+	struct MemoryStruct chunk;
+	chunk.memory = calloc(1, sizeof(char));
+	chunk.size = 0;
+	if (curl) {
+		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+		curl_easy_setopt(curl, CURLOPT_URL, query);
+		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, logSync_readQeury);
+		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk);
+		curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
+		res = curl_easy_perform(curl);
+		if (res != CURLE_OK) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+		fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error: %d", res);
+		/* always cleanup */
+		curl_easy_cleanup(curl);
+
+		*queryReply = strdup(chunk.memory);
+	}
+
+	return status;
+}
+
+static size_t logSync_readQeury(void *contents, size_t size, size_t nmemb, void *userp) {
+	size_t realsize = size * nmemb;
+	struct MemoryStruct *mem = (struct MemoryStruct *)userp;
+
+	mem->memory = realloc(mem->memory, mem->size + realsize + 1);
+	if (mem->memory == NULL) {
+		/* out of memory! */
+		fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "not enough memory (realloc returned NULL)");
+		exit(EXIT_FAILURE);
+	}
+
+	memcpy(&(mem->memory[mem->size]), contents, realsize);
+	mem->size += realsize;
+	mem->memory[mem->size] = 0;
+
+	return realsize;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/log_sync.h
----------------------------------------------------------------------
diff --git a/deployment_admin/src/log_sync.h b/deployment_admin/src/log_sync.h
new file mode 100644
index 0000000..7cd10d9
--- /dev/null
+++ b/deployment_admin/src/log_sync.h
@@ -0,0 +1,36 @@
+/**
+ *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.
+ */
+/*
+ * log_sync.h
+ *
+ *  \date       Apr 19, 2012
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef LOG_SYNC_H_
+#define LOG_SYNC_H_
+
+#include "log_store.h"
+
+typedef struct log_sync *log_sync_pt;
+
+celix_status_t logSync_create(char *targetId, log_store_pt store, log_sync_pt *logSync);
+
+#endif /* LOG_SYNC_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/deployment_admin/src/miniunz.c
----------------------------------------------------------------------
diff --git a/deployment_admin/src/miniunz.c b/deployment_admin/src/miniunz.c
new file mode 100644
index 0000000..e543c3b
--- /dev/null
+++ b/deployment_admin/src/miniunz.c
@@ -0,0 +1,402 @@
+/** License
+ * ----------------------------------------------------------
+ *    Condition of use and distribution are the same than zlib :
+ *
+ *   This software is provided 'as-is', without any express or implied
+ *   warranty.  In no event will the authors be held liable for any damages
+ *   arising from the use of this software.
+ *
+ *   Permission is granted to anyone to use this software for any purpose,
+ *   including commercial applications, and to alter it and redistribute it
+ *   freely, subject to the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *      claim that you wrote the original software. If you use this software
+ *      in a product, an acknowledgment in the product documentation would be
+ *      appreciated but is not required.
+ *   2. Altered source versions must be plainly marked as such, and must not be
+ *      misrepresented as being the original software.
+ *   3. This notice may not be removed or altered from any source distribution.
+ *
+ * ----------------------------------------------------------
+ */
+/*
+   miniunz.c
+   Version 1.1, February 14h, 2010
+   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+    Changes made to the original source specific for Apache Celix:
+    * Updated several parts to use output directory fitting Celix.
+    * Removed several parts not needed (main function etc).
+    * Added some checks for OSX/Apple
+*/
+
+#ifndef _WIN32
+        #ifndef __USE_FILE_OFFSET64
+                #define __USE_FILE_OFFSET64
+        #endif
+        #ifndef __USE_LARGEFILE64
+                #define __USE_LARGEFILE64
+        #endif
+        #ifndef _LARGEFILE64_SOURCE
+                #define _LARGEFILE64_SOURCE
+        #endif
+        #ifndef _FILE_OFFSET_BIT
+                #define _FILE_OFFSET_BIT 64
+        #endif
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <unistd.h>
+#include <utime.h>
+#include <sys/stat.h>
+
+#include "unzip.h"
+#include "archive.h"
+
+#define CASESENSITIVITY (0)
+#define WRITEBUFFERSIZE (8192)
+#define MAXFILENAME (256)
+
+#ifdef _WIN32
+#define USEWIN32IOAPI
+#include "iowin32.h"
+#endif
+/*
+  mini unzip, demo of unzip package
+
+  usage :
+  Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]
+
+  list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT
+    if it exists
+*/
+
+
+/* change_file_date : change the date/time of a file
+    filename : the filename of the file where date/time must be modified
+    dosdate : the new date at the MSDos format (4 bytes)
+    tmu_date : the SAME new date at the tm_unz format */
+void change_file_date(filename,dosdate,tmu_date)
+    const char *filename;
+    uLong dosdate;
+    tm_unz tmu_date;
+{
+#ifdef _WIN32
+  HANDLE hFile;
+  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
+
+  hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
+                      0,NULL,OPEN_EXISTING,0,NULL);
+  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
+  DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
+  LocalFileTimeToFileTime(&ftLocal,&ftm);
+  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
+  CloseHandle(hFile);
+#else
+#if defined(unix) || defined(__APPLE__)
+  struct utimbuf ut;
+  struct tm newdate;
+  newdate.tm_sec = tmu_date.tm_sec;
+  newdate.tm_min=tmu_date.tm_min;
+  newdate.tm_hour=tmu_date.tm_hour;
+  newdate.tm_mday=tmu_date.tm_mday;
+  newdate.tm_mon=tmu_date.tm_mon;
+  if (tmu_date.tm_year > 1900)
+      newdate.tm_year=tmu_date.tm_year - 1900;
+  else
+      newdate.tm_year=tmu_date.tm_year ;
+  newdate.tm_isdst=-1;
+
+  ut.actime=ut.modtime=mktime(&newdate);
+  utime(filename,&ut);
+#endif
+#endif
+}
+
+
+/* mymkdir and change_file_date are not 100 % portable
+   As I don't know well Unix, I wait feedback for the unix portion */
+
+int mymkdir(dirname)
+    const char* dirname;
+{
+    int ret=0;
+#ifdef _WIN32
+    ret = _mkdir(dirname);
+#else
+#if defined unix || defined __APPLE__
+    ret = mkdir(dirname,0775);
+#endif
+#endif
+    return ret;
+}
+
+int makedir (newdir)
+    char *newdir;
+{
+  char *buffer ;
+  char *p;
+  int  len = (int)strlen(newdir);
+
+  if (len <= 0)
+    return 0;
+
+  buffer = (char*)malloc(len+1);
+        if (buffer==NULL)
+        {
+                printf("Error allocating memory\n");
+                return UNZ_INTERNALERROR;
+        }
+  strcpy(buffer,newdir);
+
+  if (buffer[len-1] == '/') {
+    buffer[len-1] = '\0';
+  }
+  if (mymkdir(buffer) == 0)
+    {
+      free(buffer);
+      return 1;
+    }
+
+  p = buffer+1;
+  while (1)
+    {
+      char hold;
+
+      while(*p && *p != '\\' && *p != '/')
+        p++;
+      hold = *p;
+      *p = 0;
+      if ((mymkdir(buffer) == -1) && (errno == ENOENT))
+        {
+          printf("couldn't create directory %s\n",buffer);
+          free(buffer);
+          return 0;
+        }
+      if (hold == 0)
+        break;
+      *p++ = hold;
+    }
+  free(buffer);
+  return 1;
+}
+
+int do_extract_currentfile(unzFile uf, char * revisionRoot) {
+    char filename_inzip[256];
+    char* filename_withoutpath;
+    char* p;
+    int err=UNZ_OK;
+    FILE *fout=NULL;
+    void* buf;
+    uInt size_buf;
+
+    unz_file_info64 file_info;
+    err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+
+    if (err!=UNZ_OK)
+    {
+        printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
+        return err;
+    }
+
+    size_buf = WRITEBUFFERSIZE;
+    buf = (void*)malloc(size_buf);
+    if (buf==NULL)
+    {
+        printf("Error allocating memory\n");
+        return UNZ_INTERNALERROR;
+    }
+
+    p = filename_withoutpath = filename_inzip;
+    while ((*p) != '\0')
+    {
+        if (((*p)=='/') || ((*p)=='\\'))
+            filename_withoutpath = p+1;
+        p++;
+    }
+
+    if ((*filename_withoutpath)=='\0') {
+		char dir[strlen(revisionRoot) + strlen(filename_inzip) + 2];
+		strcpy(dir, revisionRoot);
+		strcat(dir, "/");
+		strcat(dir, filename_inzip);
+		mymkdir(dir);
+    }
+    else
+    {
+        const char* write_filename;
+        int skip=0;
+        write_filename = filename_inzip;
+
+        int length = strlen(write_filename) + strlen(revisionRoot) + 2;
+        char fWFN[length];
+        strcpy(fWFN, revisionRoot);
+        strcat(fWFN, "/");
+        strcat(fWFN, write_filename);
+
+        err = unzOpenCurrentFile(uf);
+        if (err!=UNZ_OK)
+        {
+            printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
+        }
+
+        if ((skip==0) && (err==UNZ_OK))
+        {
+            fout=fopen64(fWFN,"wb");
+
+            /* some zipfile don't contain directory alone before file */
+            if ((fout==NULL) && (filename_withoutpath!=(char*)filename_inzip))
+            {
+                char c=*(filename_withoutpath-1);
+                *(filename_withoutpath-1)='\0';
+                int length = strlen(write_filename) + strlen(revisionRoot) + 2;
+                char dir[length];
+				strcpy(dir, revisionRoot);
+				strcat(dir, "/");
+				strcat(dir, write_filename);
+                makedir(dir);
+                *(filename_withoutpath-1)=c;
+
+                fout=fopen64(fWFN,"wb");
+            }
+
+            if (fout==NULL)
+            {
+                printf("error opening %s\n",write_filename);
+            }
+        }
+
+        if (fout!=NULL)
+        {
+            do
+            {
+                err = unzReadCurrentFile(uf,buf,size_buf);
+                if (err<0)
+                {
+                    printf("error %d with zipfile in unzReadCurrentFile\n",err);
+                    break;
+                }
+                if (err>0)
+                    if (fwrite(buf,err,1,fout)!=1)
+                    {
+                        printf("error in writing extracted file\n");
+                        err=UNZ_ERRNO;
+                        break;
+                    }
+            }
+            while (err>0);
+            if (fout)
+                    fclose(fout);
+
+            if (err==0)
+                change_file_date(fWFN,file_info.dosDate,
+                                 file_info.tmu_date);
+        }
+
+        if (err==UNZ_OK)
+        {
+            err = unzCloseCurrentFile (uf);
+            if (err!=UNZ_OK)
+            {
+                printf("error %d with zipfile in unzCloseCurrentFile\n",err);
+            }
+        }
+        else
+            unzCloseCurrentFile(uf); /* don't lose the error */
+    }
+
+    free(buf);
+    return err;
+}
+
+
+int do_extract(unzFile uf, char * revisionRoot) {
+    uLong i;
+    unz_global_info64 gi;
+    int err;
+
+    err = unzGetGlobalInfo64(uf,&gi);
+    if (err!=UNZ_OK)
+        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
+
+    for (i=0;i<gi.number_entry;i++)
+    {
+        if (do_extract_currentfile(uf, revisionRoot) != UNZ_OK)
+            break;
+
+        if ((i+1)<gi.number_entry)
+        {
+            err = unzGoToNextFile(uf);
+            if (err!=UNZ_OK)
+            {
+                printf("error %d with zipfile in unzGoToNextFile\n",err);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+celix_status_t unzip_extractDeploymentPackage(char * packageName, char * destination) {
+    celix_status_t status = CELIX_SUCCESS;
+    char filename_try[MAXFILENAME+16] = "";
+    unzFile uf=NULL;
+
+    if (packageName!=NULL)
+    {
+
+#        ifdef USEWIN32IOAPI
+        zlib_filefunc64_def ffunc;
+#        endif
+
+        strncpy(filename_try, packageName,MAXFILENAME-1);
+        /* strncpy doesnt append the trailing NULL, of the string is too long. */
+        filename_try[ MAXFILENAME ] = '\0';
+
+#        ifdef USEWIN32IOAPI
+        fill_win32_filefunc64A(&ffunc);
+        uf = unzOpen2_64(bundleName,&ffunc);
+#        else
+        uf = unzOpen64(packageName);
+#        endif
+        if (uf==NULL)
+        {
+            strcat(filename_try,".zip");
+#            ifdef USEWIN32IOAPI
+            uf = unzOpen2_64(filename_try,&ffunc);
+#            else
+            uf = unzOpen64(filename_try);
+#            endif
+        }
+    }
+
+    if (uf==NULL)
+    {
+        printf("Cannot open %s or %s.zip\n",packageName,packageName);
+        status = CELIX_FILE_IO_EXCEPTION;
+    } else {
+        if (do_extract(uf, destination) != 0) {
+            status = CELIX_FILE_IO_EXCEPTION;
+        }
+
+        unzClose(uf);
+    }
+
+    return status;
+}