This is an automated email from the ASF dual-hosted git repository. pnoltes pushed a commit to branch feature/cxx in repository https://gitbox.apache.org/repos/asf/celix.git
commit 34dac36bbc4462ec3c4bb3adcf656a05c905352a Author: Pepijn Noltes <[email protected]> AuthorDate: Thu Jan 3 22:40:58 2019 +0100 CELIX-438: Adds an initial setup for handling resources in bundles --- .travis.yml | 3 +- CMakeLists.txt | 1 + bundles/shell/cxx_shell/CMakeLists.txt | 21 +- .../shell/cxx_shell/resources/version.properties | 3 + bundles/shell/cxx_shell/src/ShellActivator.cc | 10 +- bundles/shell/cxx_shell/src/VersionCommand.cc | 51 +++++ bundles/shell/cxx_shell/src/commands.h | 1 + bundles/shell/cxx_shell_tui/CMakeLists.txt | 2 - .../shell/cxx_shell_tui/src/ShellTuiActivator.cc | 1 + bundles/shell/cxx_shell_tui/src/shell_test.cc | 1 - cmake/celix_project/AddGLog.cmake | 8 +- cmake/celix_project/AddGTest.cmake | 1 + .../{AddGLog.cmake => AddLibzip.cmake} | 20 +- libs/framework_cxx/CMakeLists.txt | 10 +- libs/framework_cxx/include/celix/Framework.h | 25 ++- libs/framework_cxx/src/Bundle.cc | 24 ++- libs/framework_cxx/src/Bundle.h | 18 +- libs/framework_cxx/src/BundleController.h | 196 ++++++++++++++++++- libs/framework_cxx/src/Framework.cc | 103 ++++++++-- libs/registry/CMakeLists.txt | 3 +- libs/registry/include/celix/IResourceBundle.h | 11 +- libs/registry/include/celix/Properties.h | 8 +- libs/registry/src/Properties.cc | 215 +++++++++++++++++++++ libs/registry/src/ServiceRegistry.cc | 11 +- 24 files changed, 665 insertions(+), 82 deletions(-) diff --git a/.travis.yml b/.travis.yml index e3536d2..a95432b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,9 +35,8 @@ matrix: #services: docker before_install: - - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get update -qq - - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get install -qq uuid-dev libxml2-dev lcov libffi-dev libgoogle-glog-dev libczmq-dev libcpputest-dev libjansson-dev + - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get install -qq uuid-dev libxml2-dev lcov libffi-dev libczmq-dev libcpputest-dev libjansson-dev - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson && brew link --force libffi; fi before_script: diff --git a/CMakeLists.txt b/CMakeLists.txt index c1c4a43..7025630 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ if (ENABLE_TESTING) include(cmake/celix_project/AddGTest.cmake) endif () include(cmake/celix_project/AddGLog.cmake) +include(cmake/celix_project/AddLibzip.cmake) # Default bundle version set(DEFAULT_VERSION 1.0.0) diff --git a/bundles/shell/cxx_shell/CMakeLists.txt b/bundles/shell/cxx_shell/CMakeLists.txt index a4ad2df..d2b2113 100644 --- a/bundles/shell/cxx_shell/CMakeLists.txt +++ b/bundles/shell/cxx_shell/CMakeLists.txt @@ -15,8 +15,6 @@ # specific language governing permissions and limitations # under the License. -find_package(glog REQUIRED) - #TODO rename to celix::shell && celix::shell_api add_library(celix_cxx_shell_api INTERFACE) @@ -25,6 +23,17 @@ target_include_directories(celix_cxx_shell_api INTERFACE $<INSTALL_INTERFACE:include/celix/shell> ) +#TODO should eventually be done by a CMake command (i.e. bundle_add_resources) +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/celix_cxx_shell_resources.zip + COMMAND zip -rq ${CMAKE_CURRENT_BINARY_DIR}/celix_cxx_shell_resources.zip * + COMMENT "Packaging Resources" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/resources +) + +add_custom_target(create_resources ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/celix_cxx_shell_resources.zip +) + add_library(celix_cxx_shell SHARED src/ShellActivator.cc src/LbCommand.cc @@ -32,10 +41,18 @@ add_library(celix_cxx_shell SHARED src/StopAndStartCommand.cc src/InspectCommand.cc src/QueryCommand.cc + src/VersionCommand.cc ) target_include_directories(celix_cxx_shell PRIVATE src) target_link_libraries(celix_cxx_shell PRIVATE celix_cxx_shell_api glog::glog) target_link_libraries(celix_cxx_shell PUBLIC celix_framework_cxx) +add_dependencies(celix_cxx_shell create_resources) +if (UNIX AND NOT APPLE) + target_link_libraries(celix_cxx_shell PRIVATE -Wl,--format=binary -Wl,celix_cxx_shell_resources.zip -Wl,--format=default) +else () + #TODO apple +endif () + #if (ENABLE_TESTING) # add_subdirectory(gtest) diff --git a/bundles/shell/cxx_shell/resources/version.properties b/bundles/shell/cxx_shell/resources/version.properties new file mode 100644 index 0000000..2840a93 --- /dev/null +++ b/bundles/shell/cxx_shell/resources/version.properties @@ -0,0 +1,3 @@ +CELIX_VERSION=3.0.0 +COMMIT_ID=TODO +COMMIT_DATA=TODO \ No newline at end of file diff --git a/bundles/shell/cxx_shell/src/ShellActivator.cc b/bundles/shell/cxx_shell/src/ShellActivator.cc index bfbbb8f..ea54219 100644 --- a/bundles/shell/cxx_shell/src/ShellActivator.cc +++ b/bundles/shell/cxx_shell/src/ShellActivator.cc @@ -17,12 +17,17 @@ *under the License. */ +#include <glog/logging.h> + #include "celix/api.h" #include "celix/IShellCommand.h" #include "celix/IShell.h" #include "commands.h" +extern const uint8_t resources[] asm("_binary_celix_cxx_shell_resources_zip_start"); +extern const uint8_t resources_end[] asm("_binary_celix_cxx_shell_resources_zip_end"); + namespace { class Shell : public celix::IShell { @@ -86,6 +91,7 @@ namespace { registrations.push_back(impl::registerStart(ctx)); registrations.push_back(impl::registerInspect(ctx)); registrations.push_back(impl::registerQuery(ctx)); + registrations.push_back(impl::registerVersion(ctx)); registrations.push_back(ctx->registerService(std::shared_ptr<celix::IShell>{new Shell{ctx}})); } @@ -93,12 +99,14 @@ namespace { std::vector<celix::ServiceRegistration> registrations{}; }; + //NOTE that eventually the (ctor) bundle register will be generated by a CMake command (i.e. add_bundle) + //This also applies for the resources, resources_end asm entries. __attribute__((constructor)) static void registerShellBundle() { celix::Properties manifest{}; manifest[celix::MANIFEST_BUNDLE_NAME] = "Shell"; manifest[celix::MANIFEST_BUNDLE_GROUP] = "Celix"; manifest[celix::MANIFEST_BUNDLE_VERSION] = "1.0.0"; - celix::registerStaticBundle<ShellBundleActivator>("celix::Shell", manifest); + celix::registerStaticBundle<ShellBundleActivator>("celix::Shell", manifest, resources, resources_end - resources); } } diff --git a/bundles/shell/cxx_shell/src/VersionCommand.cc b/bundles/shell/cxx_shell/src/VersionCommand.cc new file mode 100644 index 0000000..d95b7a4 --- /dev/null +++ b/bundles/shell/cxx_shell/src/VersionCommand.cc @@ -0,0 +1,51 @@ +/** + *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. + */ + +#include "commands.h" + +#include <functional> + +#include "celix/api.h" +#include "celix/IShellCommand.h" + +namespace { + + void version(std::shared_ptr<celix::BundleContext> ctx, const std::string &, const std::vector<std::string> &, std::ostream &out, std::ostream &err) { + if (ctx->bundle()->hasCacheEntry("version.properties")) { + auto path = ctx->bundle()->absPathForCacheEntry("version.properties"); + celix::Properties versionInfo = celix::loadProperties(path); + std::string version = celix::getProperty(versionInfo, "CELIX_VERSION", ""); + out << "Celix Version: " << version << std::endl; + } else { + err << "Cannot find version.properties entry in the " << ctx->bundle()->group() << " " << ctx->bundle()->name() << " bundle" << std::endl; + } + } +} + + +celix::ServiceRegistration impl::registerVersion(std::shared_ptr<celix::BundleContext> ctx) { + using namespace std::placeholders; + celix::ShellCommandFunction cmd = std::bind(&version, ctx, _1, _2, _3, _4); + + celix::Properties props{}; + props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "version"; + props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "version"; + props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "Show version information about the framework (TODO and installed bundles)"; + return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(cmd), std::move(props)); +} \ No newline at end of file diff --git a/bundles/shell/cxx_shell/src/commands.h b/bundles/shell/cxx_shell/src/commands.h index b9d9a8f..9f1f18b 100644 --- a/bundles/shell/cxx_shell/src/commands.h +++ b/bundles/shell/cxx_shell/src/commands.h @@ -29,6 +29,7 @@ namespace impl { celix::ServiceRegistration registerStart(std::shared_ptr<celix::BundleContext> ctx); celix::ServiceRegistration registerInspect(std::shared_ptr<celix::BundleContext> ctx); celix::ServiceRegistration registerQuery(std::shared_ptr<celix::BundleContext> ctx); + celix::ServiceRegistration registerVersion(std::shared_ptr<celix::BundleContext> ctx); } diff --git a/bundles/shell/cxx_shell_tui/CMakeLists.txt b/bundles/shell/cxx_shell_tui/CMakeLists.txt index cfbf6cf..e9fa13b 100644 --- a/bundles/shell/cxx_shell_tui/CMakeLists.txt +++ b/bundles/shell/cxx_shell_tui/CMakeLists.txt @@ -15,8 +15,6 @@ # specific language governing permissions and limitations # under the License. -find_package(glog REQUIRED) - #TODO rename to celix::shell_tui #OR static lib, but then with all symbols to force constructor attribute diff --git a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc index a66bea5..ec48f6b 100644 --- a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc +++ b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc @@ -140,6 +140,7 @@ namespace { celix::ServiceTracker trk{}; }; + //NOTE that eventually the (ctor) bundle register will be generated by a CMake command (i.e. add_bundle) __attribute__((constructor)) static void registerShellBundle() { celix::Properties manifest{}; diff --git a/bundles/shell/cxx_shell_tui/src/shell_test.cc b/bundles/shell/cxx_shell_tui/src/shell_test.cc index cd3af3c..8e92107 100644 --- a/bundles/shell/cxx_shell_tui/src/shell_test.cc +++ b/bundles/shell/cxx_shell_tui/src/shell_test.cc @@ -29,7 +29,6 @@ int main(int /*argc*/, char **argv) { google::LogToStderr(); auto fw = celix::Framework{}; - std::cout << "Waiting for Framework shutdown\n"; fw.waitForShutdown(); return 0; } \ No newline at end of file diff --git a/cmake/celix_project/AddGLog.cmake b/cmake/celix_project/AddGLog.cmake index 8cc3414..4897f35 100644 --- a/cmake/celix_project/AddGLog.cmake +++ b/cmake/celix_project/AddGLog.cmake @@ -21,9 +21,15 @@ ExternalProject_Add( googlelog_project GIT_REPOSITORY https://github.com/google/glog.git GIT_TAG v0.3.5 + UPDATE_DISCONNECTED TRUE PREFIX ${CMAKE_CURRENT_BINARY_DIR}/glog CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/glog -DCMAKE_CXX_FLAGS=-w ) -set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/glog ${CMAKE_PREFIX_PATH}") +add_library(glog::glog IMPORTED STATIC GLOBAL) +add_dependencies(glog::glog googlelog_project) +set_target_properties(glog::glog PROPERTIES + IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/glog/lib/libglog.a" + INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/glog/include" +) diff --git a/cmake/celix_project/AddGTest.cmake b/cmake/celix_project/AddGTest.cmake index 93227c1..2da1a47 100644 --- a/cmake/celix_project/AddGTest.cmake +++ b/cmake/celix_project/AddGTest.cmake @@ -20,6 +20,7 @@ ExternalProject_Add( googletest_project GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.8.1 + UPDATE_DISCONNECTED TRUE PREFIX ${CMAKE_CURRENT_BINARY_DIR}/gtest INSTALL_COMMAND "" ) diff --git a/cmake/celix_project/AddGLog.cmake b/cmake/celix_project/AddLibzip.cmake similarity index 54% copy from cmake/celix_project/AddGLog.cmake copy to cmake/celix_project/AddLibzip.cmake index 8cc3414..7d14cb6 100644 --- a/cmake/celix_project/AddGLog.cmake +++ b/cmake/celix_project/AddLibzip.cmake @@ -15,15 +15,19 @@ # specific language governing permissions and limitations # under the License. - include(ExternalProject) ExternalProject_Add( - googlelog_project - GIT_REPOSITORY https://github.com/google/glog.git - GIT_TAG v0.3.5 - PREFIX ${CMAKE_CURRENT_BINARY_DIR}/glog - CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/glog -DCMAKE_CXX_FLAGS=-w + libzip_project + GIT_REPOSITORY https://github.com/nih-at/libzip.git + GIT_TAG rel-1-5-1 + UPDATE_DISCONNECTED TRUE + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libzip + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/libzip -DCMAKE_C_FLAGS=-fPIC -DBUILD_SHARED_LIBS=OFF -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_OPENSSL=OFF -Wno-dev ) -set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/glog ${CMAKE_PREFIX_PATH}") - +add_library(libzip::libzip IMPORTED STATIC GLOBAL) +add_dependencies(libzip::libzip libzip_project) +set_target_properties(libzip::libzip PROPERTIES + IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/libzip/lib64/libzip.a" + INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/libzip/include" +) \ No newline at end of file diff --git a/libs/framework_cxx/CMakeLists.txt b/libs/framework_cxx/CMakeLists.txt index c47ae80..f3c116e 100644 --- a/libs/framework_cxx/CMakeLists.txt +++ b/libs/framework_cxx/CMakeLists.txt @@ -15,17 +15,19 @@ # specific language governing permissions and limitations # under the License. -find_package(glog REQUIRED) +find_package(UUID REQUIRED) #TODO rename to celix::framework add_library(celix_framework_cxx SHARED src/Framework.cc src/BundleContext.cc - src/Bundle.cc) + src/Bundle.cc +) target_include_directories(celix_framework_cxx PRIVATE src) target_include_directories(celix_framework_cxx PUBLIC include) -target_link_libraries(celix_framework_cxx PRIVATE glog::glog) -target_link_libraries(celix_framework_cxx PUBLIC celix::registry) +target_link_libraries(celix_framework_cxx PRIVATE glog::glog libzip::libzip) +#NOTE because of libzil libbz2 and libz is also needed. maybe more to other form of resources (i.e. tar) +target_link_libraries(celix_framework_cxx PUBLIC celix::registry bz2 z ${UUID_LIBRARY}) if (ENABLE_TESTING) add_subdirectory(gtest) diff --git a/libs/framework_cxx/include/celix/Framework.h b/libs/framework_cxx/include/celix/Framework.h index 27718f8..89e9a3b 100644 --- a/libs/framework_cxx/include/celix/Framework.h +++ b/libs/framework_cxx/include/celix/Framework.h @@ -35,16 +35,20 @@ namespace celix { void registerStaticBundle( std::string symbolicName, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> bundleActivatorFactory = {}, - celix::Properties manifest = {}); + celix::Properties manifest = {}, + const uint8_t *resourcesZip = nullptr, + size_t resourcesZipLen = 0); template<typename T> void registerStaticBundle( std::string symbolicName, - celix::Properties manifest = {}) { + celix::Properties manifest = {}, + const uint8_t *resourcesZip = nullptr, + size_t resourcesZipLen = 0) { auto actFactory = [](std::shared_ptr<celix::BundleContext> ctx) { return new T{std::move(ctx)}; }; - celix::registerStaticBundle(std::move(symbolicName), actFactory, std::move(manifest)); + celix::registerStaticBundle(std::move(symbolicName), std::move(actFactory), std::move(manifest), resourcesZip, resourcesZipLen); } class Framework { @@ -58,14 +62,20 @@ namespace celix { Framework& operator=(const Framework &rhs) = delete; template<typename T> - long installBundle(std::string name, celix::Properties manifest = {}, bool autoStart = true) { + long installBundle(std::string name, celix::Properties manifest = {}, bool autoStart = true, const uint8_t *resourcesZip = nullptr, size_t resourcesZipLen = 0) { auto actFactory = [](std::shared_ptr<celix::BundleContext> ctx) { return new T{std::move(ctx)}; }; - return installBundle(name, std::move(actFactory), manifest, autoStart); + return installBundle(name, std::move(actFactory), std::move(manifest), autoStart, resourcesZip, resourcesZipLen); } - long installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, celix::Properties manifest = {}, bool autoStart = true); + long installBundle( + std::string name, + std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, + celix::Properties manifest = {}, + bool autoStart = true, + const uint8_t *resourcesZip = nullptr, + const size_t resourcesZipLen = 0); //long installBundle(const std::string &path); @@ -76,6 +86,9 @@ namespace celix { bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const; int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = false) const; + std::string cacheDir() const; + std::string uuid() const; + //TODO trackBundles //long bundleIdForName(const std::string &bndName) const; diff --git a/libs/framework_cxx/src/Bundle.cc b/libs/framework_cxx/src/Bundle.cc index 6f167f7..aba14a2 100644 --- a/libs/framework_cxx/src/Bundle.cc +++ b/libs/framework_cxx/src/Bundle.cc @@ -18,20 +18,30 @@ */ #include <string> +#include <sys/stat.h> +#include <unistd.h> #include "Bundle.h" -bool celix::Bundle::has(const std::string &) const noexcept { return false; } //TODO +bool celix::Bundle::hasCacheEntry(const std::string &path) const noexcept { + auto abs = absPathForCacheEntry(path); + struct stat st; + bool exists = stat(abs.c_str(), &st) == 0; + return exists; +} -bool celix::Bundle::isDir(const std::string &) const noexcept { return false; } //TODO +bool celix::Bundle::isCacheEntryDir(const std::string &) const noexcept { return false; } //TODO -bool celix::Bundle::isFile(const std::string &) const noexcept { return false; } //TODO +bool celix::Bundle::isCacheEntryFile(const std::string &) const noexcept { return false; } //TODO -std::vector <std::string> celix::Bundle::readDir(const std::string &) const noexcept { //TODO +std::vector <std::string> celix::Bundle::readCacheDir(const std::string &) const noexcept { //TODO return std::vector < std::string > {}; } -const std::string& celix::Bundle::root() const noexcept { //TODO - static std::string empty{}; - return empty; +const std::string& celix::Bundle::cacheRoot() const noexcept { + return bundleCache; +} + +std::string celix::Bundle::absPathForCacheEntry(const std::string &entryPath) const noexcept { + return bundleCache + "/" + entryPath; } \ No newline at end of file diff --git a/libs/framework_cxx/src/Bundle.h b/libs/framework_cxx/src/Bundle.h index 5541013..ce5e456 100644 --- a/libs/framework_cxx/src/Bundle.h +++ b/libs/framework_cxx/src/Bundle.h @@ -30,7 +30,9 @@ namespace celix { class Bundle : public celix::IBundle { public: Bundle(long _bndId, celix::Framework *_fw, celix::Properties _manifest) : - bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)}, bndState{BundleState::INSTALLED} { + bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)}, + bundleCache{framework().cacheDir() + "/bundle" + std::to_string(_bndId)}, + bndState{BundleState::INSTALLED} { bndState.store(BundleState::INSTALLED, std::memory_order_release); } @@ -38,11 +40,12 @@ namespace celix { Bundle& operator=(const Bundle&) = delete; //resource part - bool has(const std::string &) const noexcept override; - bool isDir(const std::string &) const noexcept override; - bool isFile(const std::string &) const noexcept override; - std::vector <std::string> readDir(const std::string &) const noexcept override; - const std::string &root() const noexcept override; + bool hasCacheEntry(const std::string &) const noexcept override; + bool isCacheEntryDir(const std::string &) const noexcept override; + bool isCacheEntryFile(const std::string &) const noexcept override; + std::string absPathForCacheEntry(const std::string &) const noexcept override; + std::vector <std::string> readCacheDir(const std::string &) const noexcept override; + const std::string &cacheRoot() const noexcept override; //bundle part bool isFrameworkBundle() const noexcept override { return false; } @@ -58,7 +61,7 @@ namespace celix { } const std::string &group() const noexcept override { - return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME); + return bndManifest.at(celix::MANIFEST_BUNDLE_GROUP); } const std::string &version() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_VERSION); } @@ -81,6 +84,7 @@ namespace celix { const long bndId; celix::Framework *const fw; const celix::Properties bndManifest; + const std::string bundleCache; std::atomic<BundleState> bndState; }; diff --git a/libs/framework_cxx/src/BundleController.h b/libs/framework_cxx/src/BundleController.h index 3f4e1b7..1228066 100644 --- a/libs/framework_cxx/src/BundleController.h +++ b/libs/framework_cxx/src/BundleController.h @@ -20,7 +20,14 @@ #ifndef CXX_CELIX_BUNDLECONTROLLER_H #define CXX_CELIX_BUNDLECONTROLLER_H +#include <fstream> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + #include <glog/logging.h> +#include <zip.h> +#include <dirent.h> #include "celix/IBundle.h" #include "celix/BundleContext.h" @@ -32,8 +39,13 @@ namespace celix { BundleController( std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> _actFactory, std::shared_ptr<celix::Bundle> _bnd, - std::shared_ptr<celix::BundleContext> _ctx) : - actFactory{std::move(_actFactory)}, bnd{std::move(_bnd)}, ctx{std::move(_ctx)} {} + std::shared_ptr<celix::BundleContext> _ctx, + const uint8_t *rZip, + size_t rZipLen) : + actFactory{std::move(_actFactory)}, bnd{std::move(_bnd)}, ctx{std::move(_ctx)}, resourcesZip{rZip}, resourcesZipLen{rZipLen} {} + + BundleController(const BundleController&) = delete; + BundleController& operator=(const BundleController&) = delete; //specific part bool transitionTo(BundleState desired) { @@ -44,13 +56,15 @@ namespace celix { //nop success = true; } else if (state == BundleState::INSTALLED && desired == BundleState::ACTIVE) { - act = std::unique_ptr<celix::IBundleActivator>{actFactory(ctx)}; - bnd->setState(BundleState::ACTIVE); - success = true; + success = createBundleCache(); + if (success) { + act = std::unique_ptr<celix::IBundleActivator>{actFactory(ctx)}; + bnd->setState(BundleState::ACTIVE); + } } else if (state == BundleState::ACTIVE && desired == BundleState::INSTALLED ) { act = nullptr; - bnd->setState(BundleState::INSTALLED); - success = true; + success = deleteBundleCache(); + bnd->setState(BundleState::INSTALLED); //note still going to installed } else { //LOG(ERROR) << "Unexpected desired state " << desired << " from state " << bndState << std::endl; LOG(ERROR) << "Unexpected desired/form state combination " << std::endl; @@ -61,9 +75,177 @@ namespace celix { std::shared_ptr<celix::Bundle> bundle() const { return bnd; } std::shared_ptr<celix::BundleContext> context() const { return ctx; } private: + bool createBundleCache() { + auto bundleCache = bundle()->cacheRoot(); + bool success = createDir(bundleCache); + if (success) { + //auto manifestPath = bundle()->absPathForCacheEntry("META-INF/manifest.mf"); + //TODO success = celix::storeProperties(bundle()->manifest(), manifestPath); + } + if (success) { + success = extractResources(bundleCache); + } + return success; + } + + bool deleteBundleCache() { + return deleteDir(bundle()->cacheRoot()); + } + + bool deleteDir(const std::string &path) { + bool success = false; + DIR *dir; + dir = opendir(path.c_str()); + if (dir == NULL) { + LOG(WARNING) << "Cannot delete dir " << path << ". " << strerror(errno) << std::endl; + } 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, 512, "%s/%s", path.c_str(), dent->d_name); + + struct stat st; + if (stat(subdir, &st) == 0) { + if (S_ISDIR (st.st_mode)) { + std::string sd{subdir}; + success = deleteDir(sd); + } else { + if (remove(subdir) != 0) { + LOG(WARNING) << "Cannot delete dir " << path << ". " << strerror(errno) << std::endl; + } + } + } + } + errno = 0; + dent = readdir(dir); + } + + if (errno != 0) { + LOG(WARNING) << "Cannot delete dir " << path << ". " << strerror(errno) << std::endl; + } else if (closedir(dir) != 0) { + LOG(WARNING) << "Cannot close dir " << path << ". " << strerror(errno) << std::endl; + } else { + if (rmdir(path.c_str()) != 0) { + LOG(WARNING) << "Cannot delete dir " << path << ". " << strerror(errno) << std::endl; + } else { + success = true; + } + } + } + + return success; + } + + bool createDir(const std::string &path) { + bool success = false; + + struct stat st; + bool exists = stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode); + + if (!exists) { + const char *slashAt = strrchr(path.c_str(), '/'); + if (slashAt == nullptr) { + //no sub dir + if (mkdir(path.c_str(), S_IRWXU) == 0) { + success = true; + } else { + LOG(WARNING) << "Cannot create dir " << path << ". " << strerror(errno) << std::endl; + } + } else { + std::string subdir = path.substr(0, slashAt - path.c_str()); + bool subdirCreated = createDir(subdir); + if (subdirCreated) { + if (mkdir(path.c_str(), S_IRWXU) == 0) { + success = true; + } else { + LOG(WARNING) << "Cannot create dir " << path << ". " << strerror(errno) << std::endl; + } + } else { + //nop, error should be reported in the recursion + } + } + } else { + //exists, so true + success = true; + } + + + return success; + } + + bool extractResources(const std::string &bundleCache) { + bool success = false; + if (resourcesZip != nullptr) { + zip_error_t error; + zip_source_t *source = zip_source_buffer_create(resourcesZip, resourcesZipLen, 1, &error); + if (source != nullptr) { + zip_t *zip = zip_open_from_source(source, ZIP_RDONLY, &error); + if (zip != nullptr) { + extractZipSource(zip, bundleCache); + //zip_close(zip); ? not needed on zip_source ? + zip_source_close(source); + success = true; + } else { + LOG(WARNING) << "Cannot create zip from source: " << zip_error_strerror(&error) << std::endl; + } + } else { + LOG(WARNING) << "Cannot create zip source: " << zip_error_strerror(&error) << std::endl; + } + } else { + //no resources + success = true; + } + return success; + } + + bool extractZipSource(zip_t *zip, const std::string &bundleCache) { + bool succes = true; + char buf[128]; + zip_int64_t nrOfEntries = zip_get_num_entries(zip, 0); + for (int i = 0; i < nrOfEntries; ++i) { + zip_stat_t st; + zip_stat_index(zip, i, 0, &st); + if (st.name[strlen(st.name) - 1] == '/') { + //dir + //TODO + LOG(ERROR) << "TODO extract dirs" << std::endl; + succes = false; + } else { + //file + zip_file_t *f = zip_fopen_index(zip, i, 0); + if (f != nullptr) { + std::ofstream outf; + std::string p = bundleCache + "/" + st.name; + outf.open(p); + if (!outf.fail()) { + zip_int64_t read = zip_fread(f, buf, 128); + while (read != 0) { + outf.write(buf, read); + read = zip_fread(f, buf, 128); + } + outf.close(); + } else { + LOG(WARNING) << "Cannot open file '" << p << "': " << std::endl; + } + zip_fclose(f); + } else { + LOG(WARNING) << "Cannot read file from zip: " << zip_strerror(zip) << std::endl; + succes = false; + break; + } + } + } + return succes; + } + const std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory; const std::shared_ptr<celix::Bundle> bnd; const std::shared_ptr<celix::BundleContext> ctx; + const uint8_t *resourcesZip; + const size_t resourcesZipLen; mutable std::mutex mutex{}; std::unique_ptr<celix::IBundleActivator> act{nullptr}; diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc index a96ce86..0b1d856 100644 --- a/libs/framework_cxx/src/Framework.cc +++ b/libs/framework_cxx/src/Framework.cc @@ -21,6 +21,8 @@ *under the License. */ +#include "celix/Framework.h" + #include <unordered_map> #include <mutex> #include <iostream> @@ -32,15 +34,20 @@ #include <linux/limits.h> #include <glog/logging.h> - -#include "celix/Framework.h" +#include <uuid/uuid.h> #include "BundleController.h" + +extern bool extractBundle(const char *bundleZip, const char *targetPath); //FROM miniunz.c + + struct StaticBundleEntry { const std::string symbolicName; const celix::Properties manifest; const std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> activatorFactory; + const uint8_t *resourcesZip; + const size_t resourcesZipLen; }; static struct { @@ -55,7 +62,9 @@ static void unregisterFramework(celix::Framework *fw); class celix::Framework::Impl : public IBundle { public: - Impl(celix::Framework *_fw, celix::Properties _config) : fw{_fw}, config{std::move(_config)}, bndManifest{createManifest()}, cwd{createCwd()} {} + Impl(celix::Framework *_fw, celix::Properties _config) : fw{_fw}, config{std::move(_config)}, bndManifest{createManifest()}, cwd{cwdString()}, fwUUID{uuidString()}{ + startFramework(); + } Impl(const Impl&) = delete; Impl& operator=(const Impl&) = delete; @@ -78,8 +87,13 @@ public: return result; } - long installBundle(std::string symbolicName, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, celix::Properties manifest, bool autoStart) { - //TODO if activator is nullptr -> use empty activator + long installBundle( + std::string symbolicName, + std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, + celix::Properties manifest, + bool autoStart, + const uint8_t *resourcesZip, + size_t resourcesZipLen) { //TODO on separate thread ?? specific bundle resolve thread ?? long bndId = -1L; if (symbolicName.empty()) { @@ -104,7 +118,7 @@ public: bndId = bundles.nextBundleId++; auto bnd = std::shared_ptr<celix::Bundle>{new celix::Bundle{bndId, this->fw, std::move(manifest)}}; auto ctx = std::shared_ptr<celix::BundleContext>{new celix::BundleContext{bnd}}; - bndController = std::shared_ptr<celix::BundleController>{new celix::BundleController{std::move(actFactory), bnd, ctx}}; + bndController = std::shared_ptr<celix::BundleController>{new celix::BundleController{std::move(actFactory), bnd, ctx, resourcesZip, resourcesZipLen}}; bundles.entries.emplace(std::piecewise_construct, std::forward_as_tuple(bndId), std::forward_as_tuple(bndController)); @@ -243,11 +257,15 @@ public: //resource bundle part long id() const noexcept override { return 1L /*note registry empty bundle is id 0, framework is id 1*/; } - bool has(const std::string&) const noexcept override { return false; } - bool isDir(const std::string&) const noexcept override { return false; } - bool isFile(const std::string&) const noexcept override { return false; } - std::vector<std::string> readDir(const std::string&) const noexcept override { return std::vector<std::string>{};} - const std::string& root() const noexcept override { //TODO + bool hasCacheEntry(const std::string &) const noexcept override { return false; } + bool isCacheEntryDir(const std::string &) const noexcept override { return false; } + bool isCacheEntryFile(const std::string &) const noexcept override { return false; } + + //virtual bool storeResource(const std::string &path, std::ostream content) noexcept = 0; + //virtual std::istream open(const std::string &path) const noexcept = 0; + //virtual std::fstream open(const std::string &path) noexcept = 0; + std::string absPathForCacheEntry(const std::string &) const noexcept override { return {}; } + const std::string& cacheRoot() const noexcept override { //TODO return cwd; } @@ -263,7 +281,25 @@ public: bool isValid() const noexcept override { return true; } celix::Framework& framework() const noexcept override { return *fw; } + std::string cacheDir() const { + return cwd + "/.cache"; //TODO make configurable + } + + std::vector<std::string> readCacheDir(const std::string &) const noexcept override { return {}; } //TODO + + std::string uuid() const { + return fwUUID; + } + + bool startFramework() { + //TODO create cache dir using a process id (and lock file?). + //Maybe also move to /var/cache or /tmp and when framework stop delete all framework caches of not running processes + std::cout << "Celix Framework Started"; + return true; + } + bool stopFramework() { + //TODO create cache dir std::lock_guard<std::mutex> lck{shutdown.mutex}; if (!shutdown.shutdownStarted) { shutdown.future = std::async(std::launch::async, [this]{ @@ -279,6 +315,7 @@ public: shutdown.shutdownStarted = true; shutdown.cv.notify_all(); } + std::cout << "Celix Framework Stopped"; return true; } @@ -299,7 +336,15 @@ private: return m; } - std::string createCwd() { + std::string uuidString() { + char uuidStr[37]; + uuid_t uuid; + uuid_generate_time_safe(uuid); + uuid_unparse(uuid, uuidStr); + return std::string{uuidStr}; + } + + std::string cwdString() { char workdir[PATH_MAX]; if (getcwd(workdir, sizeof(workdir)) != NULL) { return std::string{workdir}; @@ -313,6 +358,7 @@ private: const celix::Properties config; const celix::Properties bndManifest; const std::string cwd; + const std::string fwUUID; struct { @@ -352,8 +398,14 @@ celix::Framework::Framework(Framework &&rhs) = default; celix::Framework& celix::Framework::operator=(Framework&& rhs) = default; -long celix::Framework::installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, celix::Properties manifest, bool autoStart) { - return pimpl->installBundle(std::move(name), actFactory, std::move(manifest), autoStart); +long celix::Framework::installBundle( + std::string name, + std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, + celix::Properties manifest, + bool autoStart, + const uint8_t *resourcesZip, + size_t resourcesZipLen) { + return pimpl->installBundle(std::move(name), std::move(actFactory), std::move(manifest), autoStart, resourcesZip, resourcesZipLen); } @@ -373,6 +425,14 @@ bool celix::Framework::uninstallBundle(long bndId) { return pimpl->uninstallBund celix::ServiceRegistry& celix::Framework::registry(const std::string &lang) { return pimpl->registry(lang); } bool celix::Framework::waitForShutdown() const { return pimpl->waitForShutdown(); } +std::string celix::Framework::cacheDir() const { + return pimpl->cacheDir(); +} + +std::string celix::Framework::uuid() const { + return pimpl->uuid(); +} + /*********************************************************************************************************************** * Celix 'global' functions @@ -381,19 +441,26 @@ bool celix::Framework::waitForShutdown() const { return pimpl->waitForShutdown() void celix::registerStaticBundle( std::string symbolicName, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> bundleActivatorFactory, - celix::Properties manifest) { + celix::Properties manifest, + const uint8_t *resourcesZip, + size_t resourcesZipLen) { std::lock_guard<std::mutex> lck{staticRegistry.mutex}; for (auto fw : staticRegistry.frameworks) { - fw->installBundle(symbolicName, bundleActivatorFactory, manifest); + fw->installBundle(symbolicName, bundleActivatorFactory, manifest, true, resourcesZip, resourcesZipLen); } - staticRegistry.bundles.emplace_back(StaticBundleEntry{.symbolicName = std::move(symbolicName), .manifest = std::move(manifest), .activatorFactory = std::move(bundleActivatorFactory)}); + staticRegistry.bundles.emplace_back(StaticBundleEntry{ + .symbolicName = std::move(symbolicName), + .manifest = std::move(manifest), + .activatorFactory = std::move(bundleActivatorFactory), + .resourcesZip = resourcesZip, + .resourcesZipLen = resourcesZipLen}); } static void registerFramework(celix::Framework *fw) { std::lock_guard<std::mutex> lck{staticRegistry.mutex}; staticRegistry.frameworks.insert(fw); for (auto &entry : staticRegistry.bundles) { - fw->installBundle(entry.symbolicName, entry.activatorFactory, entry.manifest); + fw->installBundle(entry.symbolicName, entry.activatorFactory, entry.manifest, true, entry.resourcesZip, entry.resourcesZipLen); } } diff --git a/libs/registry/CMakeLists.txt b/libs/registry/CMakeLists.txt index 2a279de..5880f52 100644 --- a/libs/registry/CMakeLists.txt +++ b/libs/registry/CMakeLists.txt @@ -15,11 +15,10 @@ # specific language governing permissions and limitations # under the License. -find_package(glog REQUIRED) - add_library(celix_registry STATIC src/ServiceRegistry.cc src/Filter.cc + src/Properties.cc ) target_include_directories(celix_registry PRIVATE src) target_include_directories(celix_registry PUBLIC include) diff --git a/libs/registry/include/celix/IResourceBundle.h b/libs/registry/include/celix/IResourceBundle.h index 38b76b3..2b97c65 100644 --- a/libs/registry/include/celix/IResourceBundle.h +++ b/libs/registry/include/celix/IResourceBundle.h @@ -31,16 +31,17 @@ namespace celix { virtual long id() const noexcept = 0; - virtual const std::string& root() const noexcept = 0; + virtual const std::string& cacheRoot() const noexcept = 0; - virtual bool has(const std::string &path) const noexcept = 0; - virtual bool isDir(const std::string &path) const noexcept = 0; - virtual bool isFile(const std::string &path) const noexcept = 0; + virtual bool hasCacheEntry(const std::string &entryPath) const noexcept = 0; + virtual bool isCacheEntryDir(const std::string &path) const noexcept = 0; + virtual bool isCacheEntryFile(const std::string &path) const noexcept = 0; //virtual bool storeResource(const std::string &path, std::ostream content) noexcept = 0; //virtual std::istream open(const std::string &path) const noexcept = 0; //virtual std::fstream open(const std::string &path) noexcept = 0; - virtual std::vector<std::string> readDir(const std::string &path) const noexcept = 0; + virtual std::string absPathForCacheEntry(const std::string &entry) const noexcept = 0; + virtual std::vector<std::string> readCacheDir(const std::string &path) const noexcept = 0; }; diff --git a/libs/registry/include/celix/Properties.h b/libs/registry/include/celix/Properties.h index 1002bfc..649cf4c 100644 --- a/libs/registry/include/celix/Properties.h +++ b/libs/registry/include/celix/Properties.h @@ -56,11 +56,11 @@ namespace celix { return std::stoul(val, nullptr, 10); } - /*TODO + celix::Properties loadProperties(const std::string &path); - celix::Properties loadProperties(std::istream stream); - bool storeProperties(const celix::Properties &props, const std::string &path); - */ + celix::Properties loadProperties(std::istream &stream); + //bool storeProperties(const celix::Properties &props, const std::string &path); TODO + //bool storeProperties(const celix::Properties &props, std::ofstream &stream); TODO } #endif //CXX_CELIX_PROPERTIES_H diff --git a/libs/registry/src/Properties.cc b/libs/registry/src/Properties.cc new file mode 100644 index 0000000..403dee7 --- /dev/null +++ b/libs/registry/src/Properties.cc @@ -0,0 +1,215 @@ +/** + *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. + */ + +#include <fstream> +#include <string> +#include <cstring> + +#include <glog/logging.h> + +#include "celix/Properties.h" + +#define MALLOC_BLOCK_SIZE 5 + + +static char * utils_stringTrim(char * string) { + char* copy = string; + + char *end; + // Trim leading space + while (isspace(*copy)) { + copy++; + } + + // Trim trailing space + end = copy + strlen(copy) - 1; + while(end > copy && isspace(*end)) { + *(end) = '\0'; + end--; + } + + if (copy != string) { + //beginning whitespaces -> move char in copy to to begin string + //This to ensure free still works on the same pointer. + char* nstring = string; + while(*copy != '\0') { + *(nstring++) = *(copy++); + } + (*nstring) = '\0'; + } + + return string; +} + +static void updateBuffers(char **key, char ** value, char **output, int outputPos, int *key_len, int *value_len) { + if (*output == *key) { + if (outputPos == (*key_len) - 1) { + (*key_len) += MALLOC_BLOCK_SIZE; + *key = (char*)realloc(*key, *key_len); + *output = *key; + } + } + else { + if (outputPos == (*value_len) - 1) { + (*value_len) += MALLOC_BLOCK_SIZE; + *value = (char*)realloc(*value, *value_len); + *output = *value; + } + } +} + +static void parseLine(const char* line, celix::Properties &props) { + int linePos = 0; + bool precedingCharIsBackslash = false; + bool isComment = false; + int outputPos = 0; + char *output = NULL; + int key_len = MALLOC_BLOCK_SIZE; + int value_len = MALLOC_BLOCK_SIZE; + linePos = 0; + precedingCharIsBackslash = false; + isComment = false; + output = NULL; + outputPos = 0; + + //Ignore empty lines + if (line[0] == '\n' && line[1] == '\0') { + return; + } + + char *key = (char*)calloc(1, key_len); + char *value = (char*)calloc(1, value_len); + key[0] = '\0'; + value[0] = '\0'; + + while (line[linePos] != '\0') { + if (line[linePos] == ' ' || line[linePos] == '\t') { + if (output == NULL) { + //ignore + linePos += 1; + continue; + } + } + else { + if (output == NULL) { + output = key; + } + } + if (line[linePos] == '=' || line[linePos] == ':' || line[linePos] == '#' || line[linePos] == '!') { + if (precedingCharIsBackslash) { + //escaped special character + output[outputPos++] = line[linePos]; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + precedingCharIsBackslash = false; + } + else { + if (line[linePos] == '#' || line[linePos] == '!') { + if (outputPos == 0) { + isComment = true; + break; + } + else { + output[outputPos++] = line[linePos]; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + } + } + else { // = or : + if (output == value) { //already have a seperator + output[outputPos++] = line[linePos]; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + } + else { + output[outputPos++] = '\0'; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + output = value; + outputPos = 0; + } + } + } + } + else if (line[linePos] == '\\') { + if (precedingCharIsBackslash) { //double backslash -> backslash + output[outputPos++] = '\\'; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + } + precedingCharIsBackslash = true; + } + else { //normal character + precedingCharIsBackslash = false; + output[outputPos++] = line[linePos]; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + } + linePos += 1; + } + if (output != NULL) { + output[outputPos] = '\0'; + } + + if (!isComment) { + //printf("putting 'key'/'value' '%s'/'%s' in properties\n", utils_stringTrim(key), utils_stringTrim(value)); + props[std::string{utils_stringTrim(key)}] = std::string{utils_stringTrim(value)}; + } + if(key) { + free(key); + } + if(value) { + free(value); + } + +} + +celix::Properties celix::loadProperties(const std::string &path) { + std::ifstream file; + file.open(path); + if (file.fail()) { + LOG(WARNING) << "Cannot open file " << path << ". " << file.failbit << std::endl; + return celix::Properties{}; + } else { + return celix::loadProperties(file); + } +} + +celix::Properties celix::loadProperties(std::istream &stream) { + celix::Properties props{}; + + if (!stream.fail()) { + stream.seekg(0, stream.end); + long size = stream.tellg(); + stream.seekg(0, stream.beg); + + if (size > 0){ + while (!stream.eof()) { + std::string line; + std::getline(stream, line); + parseLine(line.c_str(), props); + } + } + } + + //TODO howto singal an error with parsing ... + return props; +} + +//bool celix::storeProperties(const celix::Properties &props, const std::string &path) { +// return false; //TODO +//} +// +//bool celix::storeProperties(const celix::Properties &props, std::ofstream &stream) { +// return false; //TODO +//} \ No newline at end of file diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc index a7465e2..001b08e 100644 --- a/libs/registry/src/ServiceRegistry.cc +++ b/libs/registry/src/ServiceRegistry.cc @@ -42,18 +42,19 @@ namespace { long id() const noexcept override { return 0; } - const std::string& root() const noexcept override { + const std::string& cacheRoot() const noexcept override { static std::string empty{}; return empty; } - bool has(const std::string&) const noexcept override { return false; } - bool isDir(const std::string&) const noexcept override { return false; } - bool isFile(const std::string&) const noexcept override { return false; } + bool hasCacheEntry(const std::string&) const noexcept override { return false; } + bool isCacheEntryDir(const std::string&) const noexcept override { return false; } + bool isCacheEntryFile(const std::string&) const noexcept override { return false; } //std::istream& open(const std::string &path) override {} //std::fstream& open(const std::string &path) override {} - std::vector<std::string> readDir(const std::string&) const noexcept override { return std::vector<std::string>{};} + std::string absPathForCacheEntry(const std::string &) const noexcept override { return {}; } + std::vector<std::string> readCacheDir(const std::string&) const noexcept override { return std::vector<std::string>{};} }; struct SvcEntry {
