blob: 6c8c505e7e9070cb28daa32b57adb8ae4f9f2795 [file] [log] [blame]
/**
*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 dp;
struct dirent *result = NULL;
int rc = readdir_r(dir, &dp, &result);
while (rc == 0 && result != NULL) {
if ((strcmp((dp.d_name), ".") != 0) && (strcmp((dp.d_name), "..") != 0)) {
char subdir[512];
snprintf(subdir, sizeof(subdir), "%s/%s", directory, dp.d_name);
if (dp.d_type == DT_DIR) {
status = deploymentAdmin_deleteTree(subdir);
} else {
if (remove(subdir) != 0) {
status = CELIX_FILE_IO_EXCEPTION;
break;
}
}
}
rc = readdir_r(dir, &dp, &result);
}
if (rc != 0) {
status = CELIX_FILE_IO_EXCEPTION;
}
if (closedir(dir) != 0) {
status = CELIX_FILE_IO_EXCEPTION;
}
if (status == CELIX_SUCCESS) {
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;
}