Skip to content

Commit

Permalink
Merge pull request #216 from CppMicroServices/209-add-framework-worki…
Browse files Browse the repository at this point in the history
…ng-dir-property

Added new framework working dir property.
  • Loading branch information
saschazelzer committed Jun 28, 2017
2 parents 54881a4 + 448307f commit 2f9ce37
Show file tree
Hide file tree
Showing 13 changed files with 103 additions and 38 deletions.
6 changes: 3 additions & 3 deletions framework/include/cppmicroservices/Any.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,10 @@ class US_Framework_EXPORT Any
* \returns \c true if this Any contains value \c val, \c false otherwise.
*/
template <typename ValueType>
bool operator==(const ValueType& val)
bool operator==(const ValueType& val) const
{
if (Type() != typeid(ValueType)) return false;
return *any_cast<ValueType>(this) == val;
return *any_cast<const ValueType>(this) == val;
}

/**
Expand All @@ -265,7 +265,7 @@ class US_Framework_EXPORT Any
* \returns \c true if this Any does not contain value \c val, \c false otherwise.
*/
template <typename ValueType>
bool operator!=(const ValueType& val)
bool operator!=(const ValueType& val) const
{
return !operator==(val);
}
Expand Down
7 changes: 7 additions & 0 deletions framework/include/cppmicroservices/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,13 @@ US_Framework_EXPORT extern const std::string FRAMEWORK_LOG; // = "org.cppmicrose
*/
US_Framework_EXPORT extern const std::string FRAMEWORK_UUID; // = "org.cppmicroservices.framework.uuid";

/**
* Framework launching property specifying the working directory used for
* resolving relative path names. If not set, the framework will use the process
* current working directory as set during static initialization of the
* framework library.
*/
US_Framework_EXPORT extern const std::string FRAMEWORK_WORKING_DIR; // = "org.cppmicroservices.framework.working.dir";

/*
* Service properties.
Expand Down
26 changes: 25 additions & 1 deletion framework/include/cppmicroservices/FrameworkFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@

#include "cppmicroservices/FrameworkConfig.h"

#include "cppmicroservices/Any.h"

#include <iostream>
#include <map>
#include <unordered_map>
#include <memory>
#include <string>

Expand All @@ -36,6 +39,8 @@ class Any;

class Framework;

typedef std::unordered_map<std::string, Any> FrameworkConfiguration;

/**
* \ingroup MicroServices
*
Expand All @@ -56,7 +61,26 @@ class US_Framework_EXPORT FrameworkFactory
*
* @return A new, configured Framework instance.
*/
Framework NewFramework(const std::map<std::string, Any>& configuration = std::map<std::string, Any>(), std::ostream* logger = nullptr);
Framework NewFramework(const FrameworkConfiguration& configuration, std::ostream* logger = nullptr);

/**
* Create a new Framework instance.
*
* This is the same as calling \code NewFramework(FrameworkConfiguration()) \endcode.
*
* @return A new, configured Framework instance.
*/
Framework NewFramework();

/**
* Create a new Framework instance.
*
* @deprecated Since 3.1, use NewFramework() or NewFramework(const FramworkConfiguration&, std::ostream*)
* instead.
*
* @return A new, configured Framework instance.
*/
US_DEPRECATED Framework NewFramework(const std::map<std::string, Any>& configuration, std::ostream* logger = nullptr);

};

Expand Down
2 changes: 1 addition & 1 deletion framework/src/bundle/Constants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const std::string FRAMEWORK_THREADING_SINGLE = "single";
const std::string FRAMEWORK_THREADING_MULTI = "multi";
const std::string FRAMEWORK_LOG = "org.cppmicroservices.framework.log";
const std::string FRAMEWORK_UUID = "org.cppmicroservices.framework.uuid";

const std::string FRAMEWORK_WORKING_DIR = "org.cppmicroservices.framework.working.dir";
const std::string OBJECTCLASS = "objectclass";
const std::string SERVICE_ID = "service.id";
const std::string SERVICE_PID = "service.pid";
Expand Down
16 changes: 13 additions & 3 deletions framework/src/bundle/CoreBundleContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ US_MSVC_DISABLE_WARNING(4355)
#include "BundleThread.h"
#include "BundleUtils.h"
#include "FrameworkPrivate.h"
#include "Utils.h" // cppmicroservices::ToString()
#include "Utils.h"

#include <iomanip>

Expand All @@ -44,7 +44,7 @@ namespace cppmicroservices {

std::atomic<int> CoreBundleContext::globalId{0};

std::map<std::string, Any> InitProperties(std::map<std::string, Any> configuration)
std::unordered_map<std::string, Any> InitProperties(std::unordered_map<std::string, Any> configuration)
{
// Framework internal diagnostic logging is off by default
configuration.insert(std::make_pair(Constants::FRAMEWORK_LOG, Any(false)));
Expand All @@ -57,6 +57,15 @@ std::map<std::string, Any> InitProperties(std::map<std::string, Any> configurati
configuration[Constants::FRAMEWORK_THREADING_SUPPORT] = std::string("single");
#endif

if (configuration.find(Constants::FRAMEWORK_WORKING_DIR) == configuration.end())
{
configuration.insert(std::make_pair(
Constants::FRAMEWORK_WORKING_DIR,
fs::GetCurrentWorkingDirectory()
)
);
}

configuration.insert(std::make_pair(Constants::FRAMEWORK_STORAGE, Any(FWDIR_DEFAULT)));

configuration[Constants::FRAMEWORK_VERSION] = std::string(CppMicroServices_VERSION_STR);
Expand All @@ -65,9 +74,10 @@ std::map<std::string, Any> InitProperties(std::map<std::string, Any> configurati
return configuration;
}

CoreBundleContext::CoreBundleContext(const std::map<std::string, Any>& props, std::ostream* logger)
CoreBundleContext::CoreBundleContext(const std::unordered_map<std::string, Any>& props, std::ostream* logger)
: id(globalId++)
, frameworkProperties(InitProperties(props))
, workingDir(ref_any_cast<std::string>(frameworkProperties.at(Constants::FRAMEWORK_WORKING_DIR)))
, listeners(this)
, services(this)
, serviceHooks(this)
Expand Down
6 changes: 4 additions & 2 deletions framework/src/bundle/CoreBundleContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ class CoreBundleContext
* Note: CppMicroServices currently has no concept
* of "system properties".
*/
std::map<std::string, Any> frameworkProperties;
std::unordered_map<std::string, Any> frameworkProperties;

const std::string& workingDir;

/**
* The diagnostic logging sink
Expand Down Expand Up @@ -204,7 +206,7 @@ class CoreBundleContext
* Construct a core context
*
*/
CoreBundleContext(const std::map<std::string, Any>& props, std::ostream* logger);
CoreBundleContext(const std::unordered_map<std::string, Any>& props, std::ostream* logger);

struct : detail::MultiThreaded<> { std::weak_ptr<CoreBundleContext> v; } self;

Expand Down
18 changes: 17 additions & 1 deletion framework/src/util/FrameworkFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct CoreBundleContextHolder
std::unique_ptr<CoreBundleContext> ctx;
};

Framework FrameworkFactory::NewFramework(const std::map<std::string, Any>& configuration, std::ostream* logger)
Framework FrameworkFactory::NewFramework(const FrameworkConfiguration& configuration, std::ostream* logger)
{
std::unique_ptr<CoreBundleContext> ctx(new CoreBundleContext(configuration, logger));
auto fwCtx = ctx.get();
Expand All @@ -70,4 +70,20 @@ Framework FrameworkFactory::NewFramework(const std::map<std::string, Any>& confi
return Framework(holder->systemBundle);
}

Framework FrameworkFactory::NewFramework()
{
return NewFramework(FrameworkConfiguration());
}

Framework FrameworkFactory::NewFramework(const std::map<std::string, Any>& configuration, std::ostream* logger)
{
FrameworkConfiguration fwConfig;
for (auto& c : configuration)
{
fwConfig.insert(c);
}

return NewFramework(fwConfig, logger);
}

}
17 changes: 12 additions & 5 deletions framework/src/util/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ std::vector<std::string> SplitString(const std::string& str, const std::string&
return token;
}

std::string GetCurrentWorkingDirectory()
std::string InitCurrentWorkingDirectory()
{
#ifdef US_PLATFORM_WINDOWS
DWORD bufSize = ::GetCurrentDirectoryA(0, NULL);
Expand All @@ -154,6 +154,13 @@ std::string GetCurrentWorkingDirectory()
return std::string();
}

static const std::string s_CurrWorkingDir = InitCurrentWorkingDirectory();

std::string GetCurrentWorkingDirectory()
{
return s_CurrWorkingDir;
}

bool Exists(const std::string& path)
{
#ifdef US_PLATFORM_POSIX
Expand Down Expand Up @@ -206,9 +213,9 @@ bool IsRelative(const std::string& path)
#endif
}

std::string GetAbsolute(const std::string& path)
std::string GetAbsolute(const std::string& path, const std::string& base)
{
if (IsRelative(path)) return GetCurrentWorkingDirectory() + DIR_SEP + path;
if (IsRelative(path)) return base + DIR_SEP + path;
return path;
}

Expand Down Expand Up @@ -315,7 +322,7 @@ bool IsBundleFile(const std::string& location)
std::vector<uint32_t> indices;

resContainer.GetChildren(dir + "/", true, names, indices);
return std::any_of(names.begin(), names.end(), [](const std::string& resourceName) -> bool {
return std::any_of(names.begin(), names.end(), [](const std::string& resourceName) -> bool {
return resourceName == std::string("manifest.json");
});
});
Expand Down Expand Up @@ -351,7 +358,7 @@ std::string GetFileStorage(CoreBundleContext* ctx, const std::string& name, bool
{
return fwdir;
}
const std::string dir = fs::GetAbsolute(fwdir) + DIR_SEP + name;
const std::string dir = fs::GetAbsolute(fwdir, ctx->workingDir) + DIR_SEP + name;
if (!dir.empty())
{
if (fs::Exists(dir))
Expand Down
6 changes: 1 addition & 5 deletions framework/src/util/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ bool IsDirectory(const std::string& path);
bool IsFile(const std::string& path);
bool IsRelative(const std::string& path);

std::string GetAbsolute(const std::string& path);
std::string GetAbsolute(const std::string& path, const std::string& base);

void MakePath(const std::string& path);

Expand Down Expand Up @@ -106,10 +106,6 @@ template<typename T> std::shared_ptr<T> make_shared_array(std::size_t size)
return std::shared_ptr<T>(new T[size], std::default_delete<T[]>());
}

// Platform agnostic way to get the current working directory.
// Supports Linux, Mac, and Windows.
std::string GetCurrentWorkingDirectory();

void TerminateForDebug(const std::exception_ptr ex);

namespace detail {
Expand Down
12 changes: 6 additions & 6 deletions framework/test/BundleTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ void TestBundleStates()
std::vector<BundleEvent> bundleEvents;
FrameworkFactory factory;

std::map<std::string, Any> frameworkConfig;
FrameworkConfiguration frameworkConfig;
auto framework = factory.NewFramework(frameworkConfig);
framework.Start();

Expand Down Expand Up @@ -602,7 +602,7 @@ void TestAutoInstallEmbeddedBundles()
// There are atleast 2 bundles, maybe more depending on how the executable is created
US_TEST_CONDITION(2 <= frameworkCtx.GetBundles().size(), "Test # of installed bundles")
#endif

auto bundles = frameworkCtx.GetBundles();
auto bundleIter = std::find_if(bundles.begin(), bundles.end(),
[](const Bundle& b)
Expand All @@ -617,7 +617,7 @@ void TestAutoInstallEmbeddedBundles()

auto b = frameworkCtx.GetBundle(0);
US_TEST_FOR_EXCEPTION(std::runtime_error, b.Uninstall());

f.Stop();
}

Expand All @@ -639,8 +639,8 @@ void TestNonStandardBundleExtension()

// Test the non-standard file extension bundle's lifecycle
auto bundles = frameworkCtx.GetBundles();
auto bundleIter = std::find_if(bundles.begin(), bundles.end(),
[](const Bundle& b)
auto bundleIter = std::find_if(bundles.begin(), bundles.end(),
[](const Bundle& b)
{
return (std::string("TestBundleExt") == b.GetSymbolicName());
}
Expand Down Expand Up @@ -689,7 +689,7 @@ int BundleTest(int /*argc*/, char* /*argv*/[])

// test a non-default framework instance using a different persistent storage location.
{
std::map<std::string, Any> frameworkConfig;
FrameworkConfiguration frameworkConfig;
frameworkConfig[Constants::FRAMEWORK_STORAGE] = testing::GetTempDirectory();
auto framework = FrameworkFactory().NewFramework(frameworkConfig);
framework.Start();
Expand Down
6 changes: 3 additions & 3 deletions framework/test/FrameworkFactoryTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int FrameworkFactoryTest(int /*argc*/, char* /*argv*/[])

US_TEST_CONDITION(f != f1, "Test unique Framework instantiation");

std::map < std::string, Any > configuration;
FrameworkConfiguration configuration;
configuration["org.osgi.framework.security"] = std::string("osgi");
configuration["org.osgi.framework.startlevel.beginning"] = 0;
configuration["org.osgi.framework.bsnversion"] = std::string("single");
Expand All @@ -56,9 +56,9 @@ int FrameworkFactoryTest(int /*argc*/, char* /*argv*/[])

US_TEST_CONDITION(f2, "Test Framework instantiation with configuration");

auto f3 = FrameworkFactory().NewFramework(std::map<std::string, cppmicroservices::Any>(), &std::clog);
auto f3 = FrameworkFactory().NewFramework(std::unordered_map<std::string, cppmicroservices::Any>(), &std::clog);

US_TEST_CONDITION(f3, "Test Framework instantiation with default configuration and custom logger");
US_TEST_CONDITION(f3, "Test Framework instantiation with default configuration and custom logger");

US_TEST_END()
}
15 changes: 9 additions & 6 deletions framework/test/FrameworkTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ namespace
void TestDefaultConfig()
{
auto f = FrameworkFactory().NewFramework();
US_TEST_CONDITION(f, "Test Framework instantiation");
US_TEST_CONDITION(f, "Test Framework instantiation");

f.Start();

Expand All @@ -59,18 +59,20 @@ namespace
US_TEST_CONDITION(ctx.GetProperty(Constants::FRAMEWORK_STORAGE) == std::string("fwdir"), "Test for default base storage property")
US_TEST_CONDITION(any_cast<bool>(ctx.GetProperty(Constants::FRAMEWORK_LOG)) == false, "Test default diagnostic logging")

US_TEST_CONDITION(ctx.GetProperty(Constants::FRAMEWORK_WORKING_DIR) == testing::GetCurrentWorkingDirectory(), "Test for default working directory")
}

void TestCustomConfig()
{
std::map < std::string, Any > configuration;
FrameworkConfiguration configuration;
configuration["org.osgi.framework.security"] = std::string("osgi");
configuration["org.osgi.framework.startlevel.beginning"] = 0;
configuration["org.osgi.framework.bsnversion"] = std::string("single");
configuration["org.osgi.framework.custom1"] = std::string("foo");
configuration["org.osgi.framework.custom2"] = std::string("bar");
configuration[Constants::FRAMEWORK_LOG] = true;
configuration[Constants::FRAMEWORK_STORAGE] = testing::GetTempDirectory();
configuration[Constants::FRAMEWORK_WORKING_DIR] = testing::GetTempDirectory();

// the threading model framework property is set at compile time and read-only at runtime. Test that this
// is always the case.
Expand All @@ -81,7 +83,7 @@ namespace
#endif

auto f = FrameworkFactory().NewFramework(configuration);
US_TEST_CONDITION(f, "Test Framework instantiation with custom configuration");
US_TEST_CONDITION(f, "Test Framework instantiation with custom configuration");

try
{
Expand All @@ -104,7 +106,8 @@ namespace
US_TEST_CONDITION("foo" == any_cast<std::string>(ctx.GetProperty("org.osgi.framework.custom1")), "Test Framework custom launch properties");
US_TEST_CONDITION("bar" == any_cast<std::string>(ctx.GetProperty("org.osgi.framework.custom2")), "Test Framework custom launch properties");
US_TEST_CONDITION(any_cast<bool>(ctx.GetProperty(Constants::FRAMEWORK_LOG)) == true, "Test for enabled diagnostic logging");
US_TEST_CONDITION(ctx.GetProperty(Constants::FRAMEWORK_STORAGE).ToString() == testing::GetTempDirectory(), "Test for custom base storage path");
US_TEST_CONDITION(ctx.GetProperty(Constants::FRAMEWORK_STORAGE).ToString() == testing::GetTempDirectory(), "Test for custom base storage path");
US_TEST_CONDITION(ctx.GetProperty(Constants::FRAMEWORK_WORKING_DIR) == testing::GetTempDirectory(), "Test for custom working directory");

#ifdef US_ENABLE_THREADING_SUPPORT
US_TEST_CONDITION(ctx.GetProperty(Constants::FRAMEWORK_THREADING_SUPPORT).ToString() == "multi", "Test for attempt to change threading option")
Expand All @@ -115,7 +118,7 @@ namespace

void TestDefaultLogSink()
{
std::map<std::string, Any> configuration;
FrameworkConfiguration configuration;
// turn on diagnostic logging
configuration[Constants::FRAMEWORK_LOG] = true;

Expand Down Expand Up @@ -143,7 +146,7 @@ namespace

void TestCustomLogSink()
{
std::map<std::string, Any> configuration;
FrameworkConfiguration configuration;
// turn on diagnostic logging
configuration[Constants::FRAMEWORK_LOG] = true;

Expand Down

0 comments on commit 2f9ce37

Please sign in to comment.