blob: e4fef475bb0d5fb1ef365d1e5000125462107567 [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.
*/
/*
* shell.c
*
* \date Aug 13, 2010
* \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 <log_helper.h>
#include "celix_errno.h"
#include "shell_private.h"
#include "utils.h"
celix_status_t shell_getCommands(shell_pt shell_ptr, array_list_pt *commands_ptr);
celix_status_t shell_getCommandUsage(shell_pt shell_ptr, char *command_name_str, char **usage_pstr);
celix_status_t shell_getCommandDescription(shell_pt shell_ptr, char *command_name_str, char **command_description_pstr);
celix_status_t shell_create(bundle_context_pt context_ptr, shell_service_pt *shell_service_ptr) {
celix_status_t status = CELIX_SUCCESS;
if (!context_ptr || !shell_service_ptr) {
status = CELIX_ILLEGAL_ARGUMENT;
}
if (status == CELIX_SUCCESS) {
*shell_service_ptr = calloc(1, sizeof(**shell_service_ptr));
if (!*shell_service_ptr) {
status = CELIX_ENOMEM;
}
}
if (status == CELIX_SUCCESS) {
(*shell_service_ptr)->shell = calloc(1, sizeof(*(*shell_service_ptr)->shell));
if (!(*shell_service_ptr)->shell) {
status = CELIX_ENOMEM;
}
}
if (status == CELIX_SUCCESS) {
(*shell_service_ptr)->shell->bundle_context_ptr = context_ptr;
(*shell_service_ptr)->shell->command_name_map_ptr = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
(*shell_service_ptr)->shell->command_reference_map_ptr = hashMap_create(NULL, NULL, NULL, NULL);
(*shell_service_ptr)->getCommands = shell_getCommands;
(*shell_service_ptr)->getCommandDescription = shell_getCommandDescription;
(*shell_service_ptr)->getCommandUsage = shell_getCommandUsage;
(*shell_service_ptr)->getCommandReference = shell_getCommandReference;
(*shell_service_ptr)->executeCommand = shell_executeCommand;
status = logHelper_create(context_ptr, &(*shell_service_ptr)->shell->logHelper);
}
if (status != CELIX_SUCCESS) {
shell_destroy(shell_service_ptr);
}
return status;
}
celix_status_t shell_destroy(shell_service_pt *shell_service_ptr) {
celix_status_t status = CELIX_SUCCESS;
if (!shell_service_ptr || !*shell_service_ptr) {
status = CELIX_ILLEGAL_ARGUMENT;
}
if (status == CELIX_SUCCESS) {
if ((*shell_service_ptr)->shell) {
if ((*shell_service_ptr)->shell->command_name_map_ptr) {
hashMap_destroy((*shell_service_ptr)->shell->command_name_map_ptr, false, false);
}
if ((*shell_service_ptr)->shell->command_reference_map_ptr) {
hashMap_destroy((*shell_service_ptr)->shell->command_reference_map_ptr, false, false);
}
if ((*shell_service_ptr)->shell->logHelper) {
logHelper_destroy(&((*shell_service_ptr)->shell->logHelper));
}
free((*shell_service_ptr)->shell);
(*shell_service_ptr)->shell = NULL;
}
free(*shell_service_ptr);
*shell_service_ptr = NULL;
}
return status;
}
celix_status_t shell_addCommand(shell_pt shell_ptr, service_reference_pt reference_ptr, void *svc) {
celix_status_t status = CELIX_SUCCESS;
command_service_pt command_ptr = NULL;
const char *name_str = NULL;
if (!shell_ptr || !reference_ptr) {
return CELIX_ILLEGAL_ARGUMENT;
}
if (status == CELIX_SUCCESS) {
command_ptr = svc;
}
if (status == CELIX_SUCCESS) {
status = serviceReference_getProperty(reference_ptr, "command.name", &name_str);
if (!name_str) {
logHelper_log(shell_ptr->logHelper, OSGI_LOGSERVICE_ERROR, "Command service must contain a 'command.name' property!");
status = CELIX_BUNDLE_EXCEPTION;
}
}
if (status == CELIX_SUCCESS) {
hashMap_put(shell_ptr->command_name_map_ptr, (char *)name_str, command_ptr);
hashMap_put(shell_ptr->command_reference_map_ptr, reference_ptr, command_ptr);
}
if (status != CELIX_SUCCESS) {
shell_removeCommand(shell_ptr, reference_ptr, svc);
char err[32];
celix_strerror(status, err, 32);
logHelper_log(shell_ptr->logHelper, OSGI_LOGSERVICE_ERROR, "Could not add command, got error %s\n", err);
}
return status;
}
celix_status_t shell_removeCommand(shell_pt shell_ptr, service_reference_pt reference_ptr, void *svc) {
celix_status_t status = CELIX_SUCCESS;
command_service_pt command_ptr = NULL;
const char *name_str = NULL;
if (!shell_ptr || !reference_ptr) {
status = CELIX_ILLEGAL_ARGUMENT;
}
if (status == CELIX_SUCCESS) {
command_ptr = hashMap_remove(shell_ptr->command_reference_map_ptr, reference_ptr);
if (!command_ptr) {
status = CELIX_ILLEGAL_ARGUMENT;
}
}
if (status == CELIX_SUCCESS) {
status = serviceReference_getProperty(reference_ptr, "command.name", &name_str);
if (!name_str) {
status = CELIX_BUNDLE_EXCEPTION;
}
}
if (status == CELIX_SUCCESS) {
hashMap_remove(shell_ptr->command_name_map_ptr, (char *)name_str);
}
return status;
}
celix_status_t shell_getCommands(shell_pt shell_ptr, array_list_pt *commands_ptr) {
celix_status_t status = CELIX_SUCCESS;
hash_map_iterator_pt iter = NULL;
if (!shell_ptr || !commands_ptr) {
status = CELIX_ILLEGAL_ARGUMENT;
}
if (status == CELIX_SUCCESS) {
iter = hashMapIterator_create(shell_ptr->command_name_map_ptr);
if (!iter) {
status = CELIX_BUNDLE_EXCEPTION;
}
}
if (status == CELIX_SUCCESS) {
arrayList_create(commands_ptr);
while (hashMapIterator_hasNext(iter)) {
char *name_str = hashMapIterator_nextKey(iter);
arrayList_add(*commands_ptr, name_str);
}
hashMapIterator_destroy(iter);
}
return status;
}
celix_status_t shell_getCommandUsage(shell_pt shell_ptr, char *command_name_str, char **usage_pstr) {
celix_status_t status = CELIX_SUCCESS;
service_reference_pt reference = NULL;
if (!shell_ptr || !command_name_str || !usage_pstr) {
status = CELIX_ILLEGAL_ARGUMENT;
}
if (status == CELIX_SUCCESS) {
status = shell_getCommandReference(shell_ptr, command_name_str, &reference);
if (!reference) {
status = CELIX_BUNDLE_EXCEPTION;
}
}
if (status == CELIX_SUCCESS) {
status = serviceReference_getProperty(reference, "command.usage", (const char**)usage_pstr);
}
return status;
}
celix_status_t shell_getCommandDescription(shell_pt shell_ptr, char *command_name_str, char **command_description_pstr) {
celix_status_t status = CELIX_SUCCESS;
service_reference_pt reference = NULL;
if (!shell_ptr || !command_name_str || !command_description_pstr) {
status = CELIX_ILLEGAL_ARGUMENT;
}
if (status == CELIX_SUCCESS) {
status = shell_getCommandReference(shell_ptr, command_name_str, &reference);
if (!reference) {
status = CELIX_BUNDLE_EXCEPTION;
}
}
if (status == CELIX_SUCCESS) {
serviceReference_getProperty(reference, "command.description", (const char**)command_description_pstr);
}
return status;
}
celix_status_t shell_getCommandReference(shell_pt shell_ptr, char *command_name_str, service_reference_pt *command_reference_ptr) {
celix_status_t status = CELIX_SUCCESS;
if (!shell_ptr || !command_name_str || !command_reference_ptr) {
status = CELIX_ILLEGAL_ARGUMENT;
}
if (status == CELIX_SUCCESS) {
*command_reference_ptr = NULL;
hash_map_iterator_pt iter = hashMapIterator_create(shell_ptr->command_reference_map_ptr);
while (hashMapIterator_hasNext(iter)) {
hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
service_reference_pt reference = hashMapEntry_getKey(entry);
const char *name_str = NULL;
serviceReference_getProperty(reference, "command.name", &name_str);
if (strcmp(name_str, command_name_str) == 0) {
*command_reference_ptr = (service_reference_pt) hashMapEntry_getKey(entry);
break;
}
}
hashMapIterator_destroy(iter);
}
return status;
}
celix_status_t shell_executeCommand(shell_pt shell_ptr, char *command_line_str, FILE *out, FILE *err) {
celix_status_t status = CELIX_SUCCESS;
command_service_pt command_ptr = NULL;
if (!shell_ptr || !command_line_str || !out || !err) {
status = CELIX_ILLEGAL_ARGUMENT;
}
if (status == CELIX_SUCCESS) {
size_t pos = strcspn(command_line_str, " ");
char *command_name_str = (pos != strlen(command_line_str)) ? strndup(command_line_str, pos) : strdup(command_line_str);
command_ptr = hashMap_get(shell_ptr->command_name_map_ptr, command_name_str);
free(command_name_str);
if (!command_ptr) {
fprintf(err, "No such command\n");
status = CELIX_BUNDLE_EXCEPTION;
}
}
if (status == CELIX_SUCCESS) {
status = command_ptr->executeCommand(command_ptr->handle, command_line_str, out, err);
}
return status;
}