From 7f3395ce7e9b6e689913327caf61a597a194a197 Mon Sep 17 00:00:00 2001 From: matzman Date: Wed, 14 Oct 2015 00:47:05 +0200 Subject: [PATCH] Added skeleton for sitemap bundle. --- src/hos_cosgi_sitemap/CMakeLists.txt | 98 ++++++++ .../cosgi/service/sitemap/SitemapService.h | 58 +++++ src/hos_cosgi_sitemap/package.xml | 64 ++++++ src/hos_cosgi_sitemap/src/BundleActivator.cpp | 215 ++++++++++++++++++ .../service/sitemap/SitemapServiceImpl.cpp | 65 ++++++ .../service/sitemap/SitemapServiceImpl.h | 66 ++++++ .../sitemap/webresource/SitemapHandler.cpp | 66 ++++++ .../sitemap/webresource/SitemapHandler.h | 74 ++++++ src/hos_launch/launch/hos_cosgi.launch | 1 + 9 files changed, 707 insertions(+) create mode 100644 src/hos_cosgi_sitemap/CMakeLists.txt create mode 100644 src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/SitemapService.h create mode 100644 src/hos_cosgi_sitemap/package.xml create mode 100644 src/hos_cosgi_sitemap/src/BundleActivator.cpp create mode 100644 src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.cpp create mode 100644 src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.h create mode 100644 src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.cpp create mode 100644 src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.h diff --git a/src/hos_cosgi_sitemap/CMakeLists.txt b/src/hos_cosgi_sitemap/CMakeLists.txt new file mode 100644 index 00000000..8f960b4a --- /dev/null +++ b/src/hos_cosgi_sitemap/CMakeLists.txt @@ -0,0 +1,98 @@ +cmake_minimum_required(VERSION 2.8.3) +project(hos_cosgi_sitemap) + +## Find catkin macros and libraries +find_package(catkin REQUIRED COMPONENTS + hos_celix + hos_cosgi_webserver + hos_cosgi_devicerepository + hos_cosgi_core + hos_cpp_utils + hos_deps + roscpp +) + +## System dependencies are found with CMake's conventions +find_package(APR REQUIRED) +find_package(CELIX REQUIRED) +find_package(Boost REQUIRED) +find_package(libvariant REQUIRED) +find_package(Poco REQUIRED COMPONENTS Net NetSSL) + + +################################### +## catkin specific configuration ## +################################### + +catkin_package( + INCLUDE_DIRS include/${PROJECT_NAME}/ + CATKIN_DEPENDS hos_celix hos_cosgi_core roscpp hos_cpp_utils +) + +########### +## Build ## +########### + +add_definitions( + -std=c++11 +) + +include_directories( + include/${PROJECT_NAME}/ + ${catkin_INCLUDE_DIRS} + ${APR_INCLUDE_DIR} + ${APR_INCLUDE_DIR}/apr-1.0 + ${libvariant_INCLUDE_DIR} + ${Poco_INCLUDE_DIRS} +) + +set(BUNDLE_SYMBOLICNAME "hos.hos_sitemap") +set(BUNDLE_VERSION "1.0.0") +set(BUNDLE_NAME "hos_sitemap") + +bundle(hos_cosgi_sitemap + SOURCES + ${PROJECT_SOURCE_DIR}/src/BundleActivator + ${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/sitemap/SitemapServiceImpl + ${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/sitemap/webresource/SitemapHandler +) + +target_link_libraries(hos_cosgi_sitemap + ${catkin_LIBRARIES} + ${APR_LIBRARIES} + ${libvariant_LIBRARY} + ${Poco_LIBRARIES} +) + + +############# +## Install ## +############# + +## Mark cpp header files for installation +install(DIRECTORY include/${PROJECT_NAME}/ + DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} + FILES_MATCHING PATTERN "*.h" +) + +install(FILES + ${CMAKE_BINARY_DIR}/hos_cosgi_sitemap.zip + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/bundles +) + +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} + OPTIONAL +) + + + +################### +## Documentation ## +################### + +find_package(Doxygen) +if(DOXYGEN_FOUND) + add_custom_target(doc) +endif(DOXYGEN_FOUND) + diff --git a/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/SitemapService.h b/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/SitemapService.h new file mode 100644 index 00000000..f5f46514 --- /dev/null +++ b/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/SitemapService.h @@ -0,0 +1,58 @@ + +#pragma once + +#include +#include +#include +#include +#include + + + +namespace hos { +namespace cosgi { +namespace service { + +// forward declarations +namespace core { class CoreService; } +namespace devicerepository { class DeviceRepositoryService; } + +// service namespace +namespace sitemap { + + +/** + * Public COSGI interface of the sitemap service. + */ +class SitemapService + : public virtual interface::Service { + +public: + + /** + * The service name. + */ + static constexpr const char* SERVICE_NAME = "hos_sitemap_service"; + + /** + * Returns a reference to the core service. + * + * \return core service. + */ + virtual core::CoreService* getCoreService() noexcept = 0; + + /** + * Returns a reference to the device repository service. + * + * \return device respository service. + */ + virtual devicerepository::DeviceRepositoryService* getDeviceRepository() noexcept = 0; + +}; + + + +} // namespace sitemap +} // namespace service +} // namespace cosgi +} // namespace hos diff --git a/src/hos_cosgi_sitemap/package.xml b/src/hos_cosgi_sitemap/package.xml new file mode 100644 index 00000000..c73381ea --- /dev/null +++ b/src/hos_cosgi_sitemap/package.xml @@ -0,0 +1,64 @@ + + + hos_cosgi_sitemap + 0.0.0 + The hos_cosgi_sitemap package + + + + + matzman + + + + + + TODO + + + + + + + + + + + + + + + + + + + + + + + + + + catkin + hos_celix + hos_cosgi_core + hos_cpp_utils + hos_deps + roscpp + hos_cosgi_webserver + hos_cosgi_devicerepository + hos_celix + hos_cosgi_core + hos_cpp_utils + hos_deps + roscpp + hos_cosgi_webserver + hos_cosgi_devicerepository + + + + + + + + \ No newline at end of file diff --git a/src/hos_cosgi_sitemap/src/BundleActivator.cpp b/src/hos_cosgi_sitemap/src/BundleActivator.cpp new file mode 100644 index 00000000..f36ff21a --- /dev/null +++ b/src/hos_cosgi_sitemap/src/BundleActivator.cpp @@ -0,0 +1,215 @@ + +// std +#include +#include +#include +#include +#include +// ROS +#include +// APR +#include +// Celix +#include +// WebServer +#include +// Boost +#include +// CoreService +#include "hos/cosgi/service/sitemap/SitemapServiceImpl.h" +#include "hos/cosgi/service/sitemap/webresource/SitemapHandler.h" +#include +#include + + +using namespace hos::cosgi; +using namespace hos::cosgi::service::webserver; +using namespace hos::cosgi::service::sitemap; +using namespace hos::cosgi::service::devicerepository; +using namespace hos::cosgi::service::core; +namespace siteweb = hos::cosgi::service::sitemap::webresource; + + + +struct UserData { + apr_pool_t* memoryPool = nullptr; + std::unique_ptr serviceImpl; + std::unique_ptr webResourceImpl; + service_registration_pt serviceReg = nullptr; + service_registration_pt webResourceReg = nullptr; + serviceListener myServiceListener; + bundle_context_pt bundleContext; +}; + + + +celix_status_t cb_serviceChanged(void* listener, service_event_pt event) { + UserData* myUserData = (UserData*) ((serviceListener*)listener)->handle; + if (event->type == OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) { + char* serviceName = nullptr; + bool checkReg = false; + serviceReference_getProperty(event->reference, (char*)OSGI_FRAMEWORK_OBJECTCLASS, &serviceName); + + if (serviceName && std::strcmp(serviceName, DeviceRepositoryService::SERVICE_NAME) == 0) { + DeviceRepositoryService *service = nullptr; + bundleContext_getService(myUserData->bundleContext, event->reference, (void**)&service); + myUserData->serviceImpl->setRepoService(service); + checkReg = true; + + } + + // Register rule engine service and webresource + if (checkReg && !myUserData->serviceReg && myUserData->serviceImpl->isInitialized()) { + SitemapService* serviceInterface = dynamic_cast(myUserData->serviceImpl.get()); + bundleContext_registerService(myUserData->bundleContext, (char*)SitemapServiceImpl::SERVICE_NAME, serviceInterface, nullptr, &myUserData->serviceReg); + // web resource + service::webserver::WebResourceHandlerFactory* webInterface = dynamic_cast(myUserData->webResourceImpl.get()); + // ToDo: Properly delete properties + properties_pt webResourceProps = properties_create(); + properties_set(webResourceProps, (char*)"path", (char*)"/sitemap"); + bundleContext_registerService(myUserData->bundleContext, (char*)service::webserver::WebResourceHandlerFactory::SERVICE_NAME, webInterface, webResourceProps, &myUserData->webResourceReg); + } + + } else if (event->type == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) { + } + return CELIX_SUCCESS; +} + + + +celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) { + celix_status_t status = CELIX_START_ERROR; + apr_pool_t* memoryPool = nullptr; + + // Create APR memory pool + apr_status_t astatus = apr_pool_create(&memoryPool, NULL); + if (astatus != APR_SUCCESS) { + ROS_ERROR("SitemapBundle: Could not create APR memory pool (%i).", astatus); + } else { + + // Create user data + UserData* myUserData = (UserData*)apr_palloc(memoryPool, sizeof(UserData)); + if (myUserData != nullptr) { + myUserData->memoryPool = memoryPool; + myUserData->bundleContext = context; + *userData = (void*)myUserData; + status = CELIX_SUCCESS; + ROS_INFO("SitemapBundle: Bundle successfully created"); + + } else { + ROS_ERROR("SitemapBundle: Could not create user data struct"); + apr_pool_destroy(memoryPool); + } + } + return status; +} + + +celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + if (userData != nullptr) { + UserData* myUserData = (UserData*)userData; + + // Create sitemap service + if (myUserData->serviceReg != nullptr) { + serviceRegistration_unregister(myUserData->serviceReg); + myUserData->serviceReg = nullptr; + } + myUserData->serviceImpl.reset(new SitemapServiceImpl()); + + // Create sitemap webresource + if (myUserData->webResourceReg != nullptr) { + serviceRegistration_unregister(myUserData->webResourceReg); + } + myUserData->webResourceImpl.reset(new siteweb::SitemapHandlerFactory(myUserData->serviceImpl.get())); + + // Get core Service + service_reference_pt ref = nullptr; + bundleContext_getServiceReference(context, (char*)CoreService::SERVICE_NAME, &ref); + CoreService* coreService = nullptr; + bundleContext_getService(context, ref, (void**)&coreService); + if (coreService == nullptr) { + ROS_ERROR("SitemapBundle: Could not retrieve HOSCoreService. Are you using hos_cosgi_launcher?"); + } else { + myUserData->serviceImpl->setCoreService(coreService); + } + + // Get device repository service + service_reference_pt ref2 = nullptr; + bundleContext_getServiceReference(context, (char*)DeviceRepositoryService::SERVICE_NAME, &ref2); + DeviceRepositoryService* repoService = nullptr; + bundleContext_getService(context, ref2, (void**)&repoService); + if (repoService) { + myUserData->serviceImpl->setRepoService(repoService); + } + + // Register sitemap service and webresource + if (myUserData->serviceImpl->isInitialized()) { + SitemapService* engineInterface = dynamic_cast(myUserData->serviceImpl.get()); + bundleContext_registerService(context, (char*)SitemapService::SERVICE_NAME, engineInterface, nullptr, &myUserData->serviceReg); + // web resource + service::webserver::WebResourceHandlerFactory* webInterface = dynamic_cast(myUserData->webResourceImpl.get()); + // ToDo: Properly delete properties + properties_pt webResourceProps = properties_create(); + properties_set(webResourceProps, (char*)"path", (char*)"/sitemap"); + bundleContext_registerService(context, (char*)service::webserver::WebResourceHandlerFactory::SERVICE_NAME, webInterface, webResourceProps, &myUserData->webResourceReg); + } + + // Register service listener + myUserData->myServiceListener.handle = myUserData; + myUserData->myServiceListener.serviceChanged = cb_serviceChanged; + bundleContext_addServiceListener(context, &myUserData->myServiceListener, nullptr); + + ROS_INFO("SitemapBundle: Bundle successfully started"); + } else { + ROS_ERROR("SitemapBundle: Could not start bundle, user data struct is null"); + } + return status; +} + + +celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_ILLEGAL_STATE; + if (userData != nullptr) { + UserData* myUserData = (UserData*)userData; + status = bundleContext_removeServiceListener(context, &myUserData->myServiceListener); + if (myUserData->webResourceReg != nullptr) { + serviceRegistration_unregister(myUserData->webResourceReg); + myUserData->webResourceReg = nullptr; + } + if (myUserData->webResourceImpl) { + myUserData->webResourceImpl.reset(); + } + if (myUserData->serviceReg != nullptr) { + serviceRegistration_unregister(myUserData->serviceReg); + myUserData->serviceReg = nullptr; + } + if (myUserData->serviceImpl) { + myUserData->serviceImpl.reset(); + } + ROS_INFO("SitemapBundle: Bundle successfully stopped"); + status = CELIX_SUCCESS; + } else { + ROS_ERROR("SitemapBundle: Could not stop bundle, user data struct is null"); + } + return status; +} + + +celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_ILLEGAL_STATE; + if (userData != nullptr) { + apr_pool_t* memoryPool = ((UserData*)userData)->memoryPool; + if (memoryPool != nullptr) { + apr_pool_destroy(memoryPool); + ROS_INFO("SitemapBundle: Bundle successfully destroyed"); + } else { + ROS_ERROR("SitemapBundle: Could not destroy bundle, there is no APR memory pool"); + } + status = CELIX_SUCCESS; + } else { + ROS_ERROR("SitemapBundle: Could not destroy bundle, user data struct is null"); + } + return status; +} + diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.cpp b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.cpp new file mode 100644 index 00000000..d36406e2 --- /dev/null +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.cpp @@ -0,0 +1,65 @@ + +#include "SitemapServiceImpl.h" +// std +#include +#include +#include +// ROS +#include +// libvariant +#include +// HOS +#include +#include + + +// Service Namespace +namespace hos { +namespace cosgi { +namespace service { +namespace sitemap { + + +// Service information +HOS_SERVICE_IMPL_INFO( SitemapServiceImpl, // Implementation + service::sitemap::SitemapService::SERVICE_NAME, // Service Name + 1, 0 ) // Version + + +void SitemapServiceImpl::setCoreService(service::core::CoreService* coreService) noexcept { + if (coreService && !this->coreService) { + this->coreService = coreService; + this->nodehandle = &coreService->getPrivateNodeHandle(); + int major = 0, minor = 0; + coreService->getServiceVersion(major, minor); + ROS_INFO_STREAM("SitemapService: Found HOSCoreService Version " << major << "." << minor); + if (repoService) { + init(); + } + } +} + + +void SitemapServiceImpl::setRepoService(devicerepository::DeviceRepositoryService* repoService) noexcept { + if (repoService && !this->repoService) { + this->repoService = repoService; + int major = 0, minor = 0; + repoService->getServiceVersion(major, minor); + ROS_INFO_STREAM("RuleEngineService: Found HOSDeviceRepositoryService Version " << major << "." << minor); + if (coreService) { + init(); + } + } +} + + +void SitemapServiceImpl::init() noexcept { + initialized = true; + ROS_INFO_STREAM("RuleEngineService: Initialized and Ready."); +} + + +} /* namespace sitemap */ +} /* namespace service */ +} /* namespace cosgi */ +} /* namespace hos */ diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.h b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.h new file mode 100644 index 00000000..d9072bb6 --- /dev/null +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.h @@ -0,0 +1,66 @@ + +#pragma once + +#include +// hos includes +#include +#include +#include +//#include +// ROS includes +#include +// std includes +#include +#include +#include +#include +#include + +namespace hos { +namespace cosgi { +namespace service { +namespace sitemap { + +class SitemapServiceImpl + : public virtual SitemapService, + public implementation::Service { + +private: + service::core::CoreService* coreService = nullptr; + devicerepository::DeviceRepositoryService* repoService = nullptr; + ros::NodeHandle* nodehandle = nullptr; + + bool initialized = false; + + void init() noexcept; + +public: + + /* Initialization */ + + void setCoreService(service::core::CoreService* coreService) noexcept; + + void setRepoService(devicerepository::DeviceRepositoryService* repoService) noexcept; + + + /* Public Service Implementations */ + + virtual core::CoreService* getCoreService() noexcept override { + return coreService; + } + + virtual devicerepository::DeviceRepositoryService* getDeviceRepository() noexcept override { + return repoService; + } + + + /* Internal */ + + bool isInitialized() noexcept { return initialized; } +}; + +} // namespace sitemap +} // namespace service +} // namespace cosgi +} // namespace hos + diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.cpp b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.cpp new file mode 100644 index 00000000..aa927103 --- /dev/null +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.cpp @@ -0,0 +1,66 @@ + +#include "SitemapHandler.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Poco/Net/NetException.h" +#include + + +namespace hos { +namespace cosgi { +namespace service { +namespace sitemap { +namespace webresource { + +using namespace Poco; +using namespace libvariant; + + + +HOS_SERVICE_IMPL_INFO( SitemapHandlerFactory, // Implementation + service::webserver::WebResourceHandlerFactory::SERVICE_NAME, // Service Name + 1, 0 ) // Version + + +SitemapHandlerFactory::SitemapHandlerFactory(SitemapService* service) + : service(service) {} + + + +Net::HTTPRequestHandler* SitemapHandlerFactory::createRequestHandler( Poco::URI matchUri, const Net::HTTPServerRequest& request, bool ssl ) noexcept { + return new SitemapHandler( this, matchUri, service, ssl); +} + + + +void SitemapHandler::_handleRequest(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Net::HTMLForm& form) { + if(req.find("Upgrade") != req.end() && Poco::icompare(req["Upgrade"], "websocket") == 0) { + //__handleEvent(req, resp, true); + throw webserver::webresource::WebResourceHandlerException("ToDo", + Net::HTTPResponse::HTTP_NOT_IMPLEMENTED); + } else { + if (req.getMethod() == Net::HTTPRequest::HTTP_PUT || req.getMethod() == Net::HTTPRequest::HTTP_GET || req.getMethod() == Net::HTTPRequest::HTTP_POST) { + // Put Command + throw webserver::webresource::WebResourceHandlerException("Still a ToDo.", + Net::HTTPResponse::HTTP_NOT_IMPLEMENTED); + } else { + throw webserver::webresource::WebResourceHandlerException("Could not understood request", + Net::HTTPResponse::HTTP_BAD_REQUEST); + } + } +} + + +} // namespace webresource +} // namespace sitemap +} // namespace service +} // namespace cosgi +} // namespace hos diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.h b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.h new file mode 100644 index 00000000..4952ce1f --- /dev/null +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.h @@ -0,0 +1,74 @@ + +#pragma once + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// Service Namespace +namespace hos { +namespace cosgi { +namespace service { +namespace sitemap { +namespace webresource { + +class SitemapHandlerFactory; +class SitemapHandler; + + +class SitemapHandlerFactory + : public webserver::webresource::WebResourceHandlerFactoryImpl { +private: + SitemapService* service; + +public: + SitemapHandlerFactory(SitemapService* service); + + virtual Poco::Net::HTTPRequestHandler* createRequestHandler(Poco::URI matchUri, const Poco::Net::HTTPServerRequest& request, bool ssl ) noexcept override; +}; + + + +class SitemapHandler + : public webserver::webresource::WebResourceHandlerImpl { +protected: + SitemapHandlerFactory* parent; + Poco::URI matchUri; + SitemapService* service; + bool ssl; + +public: + + SitemapHandler( SitemapHandlerFactory* parent, + Poco::URI matchUri, + SitemapService* service, + bool ssl = false ) + : parent(parent), matchUri(matchUri), service(service), ssl(ssl) {} + + virtual void _handleRequest(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Poco::Net::HTMLForm& form) override; + +}; + + +} // namespace webresource +} // namespace sitemap +} // namespace service +} // namespace cosgi +} // namespace hos + diff --git a/src/hos_launch/launch/hos_cosgi.launch b/src/hos_launch/launch/hos_cosgi.launch index 1855fadd..1400b602 100644 --- a/src/hos_launch/launch/hos_cosgi.launch +++ b/src/hos_launch/launch/hos_cosgi.launch @@ -13,6 +13,7 @@ $(find hos_cosgi_core)/../../build_isolated/hos_cosgi_ruleengine/hos_cosgi_ruleengine.zip $(find hos_cosgi_core)/../../build_isolated/hos_cosgi_devicerepository/hos_cosgi_devicerepository.zip $(find hos_cosgi_core)/../../build_isolated/hos_cosgi_webserver/hos_cosgi_webserver.zip + $(find hos_cosgi_core)/../../build_isolated/hos_cosgi_sitemap/hos_cosgi_sitemap.zip $(find hos_cosgi_core)/../../build_isolated/hos_cosgi_testwebapp/hos_cosgi_testwebapp.zip"/>