diff --git a/CMakeLists.txt b/CMakeLists.txt index f15f788bbe..c14f4e9a62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,375 +1,383 @@ project(CppMicroServices) set(${PROJECT_NAME}_MAJOR_VERSION 1) set(${PROJECT_NAME}_MINOR_VERSION 99) set(${PROJECT_NAME}_PATCH_VERSION 0) set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}.${${PROJECT_NAME}_PATCH_VERSION}) cmake_minimum_required(VERSION 2.8) cmake_policy(VERSION 2.8) cmake_policy(SET CMP0017 NEW) #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(CMakeParseArguments) include(CMakePackageConfigHelpers) include(CheckCXXSourceCompiles) include(usFunctionCheckCompilerFlags) include(usFunctionEmbedResources) include(usFunctionGetGccVersion) include(usFunctionGenerateModuleInit) include(usFunctionGenerateExecutableInit) #----------------------------------------------------------------------------- # Init output directories #----------------------------------------------------------------------------- set(US_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") set(US_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") set(US_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") foreach(_type ARCHIVE LIBRARY RUNTIME) if(NOT CMAKE_${_type}_OUTPUT_DIRECTORY) set(CMAKE_${_type}_OUTPUT_DIRECTORY ${US_${_type}_OUTPUT_DIRECTORY}) endif() endforeach() #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # CMake options #----------------------------------------------------------------------------- function(us_cache_var _var_name _var_default _var_type _var_help) set(_advanced 0) set(_force) foreach(_argn ${ARGN}) if(_argn STREQUAL ADVANCED) set(_advanced 1) elseif(_argn STREQUAL FORCE) set(_force FORCE) endif() endforeach() if(US_IS_EMBEDDED) if(NOT DEFINED ${_var_name} OR _force) set(${_var_name} ${_var_default} PARENT_SCOPE) endif() else() set(${_var_name} ${_var_default} CACHE ${_var_type} "${_var_help}" ${_force}) if(_advanced) mark_as_advanced(${_var_name}) endif() endif() endfunction() # Determine if we are being build inside a larger project if(NOT DEFINED US_IS_EMBEDDED) if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(US_IS_EMBEDDED 0) else() set(US_IS_EMBEDDED 1) set(CppMicroServices_EXPORTS 1) endif() endif() +# Determine the name of the install component for "SDK" artifacts. +# The default is "sdk" +if(NOT DEFINED US_SDK_INSTALL_COMPONENT) + set(US_SDK_INSTALL_COMPONENT COMPONENT sdk) +elseif(US_SDK_INSTALL_COMPONENT) + set(US_SDK_INSTALL_COMPONENT COMPONENT ${US_SDK_INSTALL_COMPONENT}) +endif() + us_cache_var(US_ENABLE_AUTOLOADING_SUPPORT OFF BOOL "Enable module auto-loading support") us_cache_var(US_ENABLE_THREADING_SUPPORT OFF BOOL "Enable threading support") us_cache_var(US_ENABLE_DEBUG_OUTPUT OFF BOOL "Enable debug messages" ADVANCED) us_cache_var(US_ENABLE_RESOURCE_COMPRESSION ON BOOL "Enable resource compression" ADVANCED) us_cache_var(US_BUILD_SHARED_LIBS ON BOOL "Build shared libraries") us_cache_var(US_BUILD_TESTING OFF BOOL "Build tests") if(WIN32 AND NOT CYGWIN) set(default_runtime_install_dir bin/) set(default_library_install_dir bin/) set(default_archive_install_dir lib/) set(default_header_install_dir include/) set(default_auxiliary_install_dir share/) else() set(default_runtime_install_dir bin/) set(default_library_install_dir lib/${PROJECT_NAME}) set(default_archive_install_dir lib/${PROJECT_NAME}) set(default_header_install_dir include/${PROJECT_NAME}) set(default_auxiliary_install_dir share/${PROJECT_NAME}) endif() us_cache_var(RUNTIME_INSTALL_DIR ${default_runtime_install_dir} STRING "Relative install location for binaries" ADVANCED) us_cache_var(LIBRARY_INSTALL_DIR ${default_library_install_dir} STRING "Relative install location for libraries" ADVANCED) us_cache_var(ARCHIVE_INSTALL_DIR ${default_archive_install_dir} STRING "Relative install location for archives" ADVANCED) us_cache_var(HEADER_INSTALL_DIR ${default_header_install_dir} STRING "Relative install location for headers" ADVANCED) us_cache_var(AUXILIARY_INSTALL_DIR ${default_auxiliary_install_dir} STRING "Relative install location for auxiliary files" ADVANCED) if(MSVC10 OR MSVC11 OR MSVC12) # Visual Studio 2010 and newer have support for C++11 enabled by default set(US_USE_C++11 1) else() us_cache_var(US_USE_C++11 OFF BOOL "Enable the use of C++11 features" ADVANCED) endif() us_cache_var(US_NAMESPACE "us" STRING "The namespace for the C++ micro services entities") us_cache_var(US_HEADER_PREFIX "" STRING "The file name prefix for the public C++ micro services header files") set(BUILD_SHARED_LIBS ${US_BUILD_SHARED_LIBS}) set(${PROJECT_NAME}_MODULE_INIT_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/CMake/usModuleInit.cpp") set(${PROJECT_NAME}_EXECUTABLE_INIT_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/CMake/usExecutableInit.cpp") #----------------------------------------------------------------------------- # US C/CXX Flags #----------------------------------------------------------------------------- set(US_C_FLAGS) set(US_C_FLAGS_RELEASE) set(US_CXX_FLAGS) set(US_CXX_FLAGS_RELEASE) # This is used as a preprocessor define set(US_USE_CXX11 ${US_USE_C++11}) # Set C++ compiler flags if(NOT MSVC) foreach(_cxxflag -Werror -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast -Wstrict-null-sentinel -Wsign-promo -fdiagnostics-show-option) usFunctionCheckCompilerFlags(${_cxxflag} US_CXX_FLAGS) endforeach() if(US_USE_C++11) usFunctionCheckCompilerFlags("-std=c++0x" US_CXX_FLAGS) endif() endif() if(CMAKE_COMPILER_IS_GNUCXX) usFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) if(${GCC_VERSION} VERSION_LESS "4.0.0") message(FATAL_ERROR "gcc version ${GCC_VERSION} not supported. Please use gcc >= 4.") endif() # With older versions of gcc the flag -fstack-protector-all requires an extra dependency to libssp.so. # If the gcc version is lower than 4.4.0 and the build type is Release let's not include the flag. if(${GCC_VERSION} VERSION_GREATER "4.4.0" OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ${GCC_VERSION} VERSION_LESS "4.4.0")) usFunctionCheckCompilerFlags("-fstack-protector-all" US_CXX_FLAGS) endif() if(MINGW) # suppress warnings about auto imported symbols set(US_CXX_FLAGS "-Wl,--enable-auto-import ${US_CXX_FLAGS}") # we need to define a Windows version set(US_CXX_FLAGS "-D_WIN32_WINNT=0x0500 ${US_CXX_FLAGS}") else() # Enable visibility support if(NOT ${GCC_VERSION} VERSION_LESS "4.5") usFunctionCheckCompilerFlags("-fvisibility=hidden -fvisibility-inlines-hidden" US_CXX_FLAGS) else() set(US_GCC_RTTI_WORKAROUND_NEEDED 1) endif() endif() usFunctionCheckCompilerFlags("-O1 -D_FORTIFY_SOURCE=2" _fortify_source_flag) if(_fortify_source_flag) set(US_CXX_FLAGS_RELEASE "${US_CXX_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") endif() elseif(MSVC) set(US_CXX_FLAGS "/MP /wd4996 ${US_CXX_FLAGS}") endif() if(NOT US_IS_EMBEDDED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${US_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${US_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${US_C_FLAGS}") set(CMAKE_C_FLAGS_REALEASE "${CMAKE_C_FLAGS_RELEASE} ${US_C_FLAGS_RELEASE}") endif() #----------------------------------------------------------------------------- # US Link Flags #----------------------------------------------------------------------------- set(US_LINK_FLAGS ) if(NOT MSVC) foreach(_linkflag -Wl,--no-undefined) set(_add_flag) usFunctionCheckCompilerFlags("${_linkflag}" _add_flag) if(_add_flag) set(US_LINK_FLAGS "${US_LINK_FLAGS} ${_linkflag}") endif() endforeach() endif() #----------------------------------------------------------------------------- # US Header Checks #----------------------------------------------------------------------------- include(CheckIncludeFile) CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT) #----------------------------------------------------------------------------- # US include dirs and libraries #----------------------------------------------------------------------------- set(US_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/include ) set(US_INTERNAL_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src/util ${CMAKE_CURRENT_SOURCE_DIR}/src/service ${CMAKE_CURRENT_SOURCE_DIR}/src/module ) # link library for third party libs if(US_IS_EMBEDDED) set(US_LIBRARY_TARGET ${US_EMBEDDING_LIBRARY}) else() set(US_LIBRARY_TARGET ${PROJECT_NAME}) endif() # link libraries for the CppMicroServices lib set(US_LINK_LIBRARIES ) if(UNIX) list(APPEND US_LINK_LIBRARIES dl) endif() #----------------------------------------------------------------------------- # Source directory #----------------------------------------------------------------------------- set(us_config_h_file "${PROJECT_BINARY_DIR}/include/usConfig.h") configure_file(usConfig.h.in ${us_config_h_file}) set(US_RCC_EXECUTABLE_NAME usResourceCompiler) set(CppMicroServices_RCC_EXECUTABLE_NAME ${US_RCC_EXECUTABLE_NAME}) add_subdirectory(tools) add_subdirectory(src) #----------------------------------------------------------------------------- # US testing #----------------------------------------------------------------------------- if(US_BUILD_TESTING) enable_testing() add_subdirectory(test) endif() #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- add_subdirectory(documentation) #----------------------------------------------------------------------------- # Last configuration and install steps #----------------------------------------------------------------------------- if(NOT US_IS_EMBEDDED) export(TARGETS ${PROJECT_NAME} ${US_RCC_EXECUTABLE_NAME} FILE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake) install(EXPORT ${PROJECT_NAME}Targets FILE ${PROJECT_NAME}Targets.cmake DESTINATION ${AUXILIARY_INSTALL_DIR}/CMake/) endif() set(_install_cmake_scripts ${${PROJECT_NAME}_MODULE_INIT_TEMPLATE} ${${PROJECT_NAME}_EXECUTABLE_INIT_TEMPLATE} ${CMAKE_CURRENT_SOURCE_DIR}/CMake/CMakeParseArguments.cmake ${CMAKE_CURRENT_SOURCE_DIR}/CMake/usFunctionGenerateModuleInit.cmake ${CMAKE_CURRENT_SOURCE_DIR}/CMake/usFunctionGenerateExecutableInit.cmake ${CMAKE_CURRENT_SOURCE_DIR}/CMake/usFunctionEmbedResources.cmake ) install(FILES ${_install_cmake_scripts} DESTINATION ${AUXILIARY_INSTALL_DIR}/CMake/ ) # Configure CppMicroServicesConfig.cmake for the build tree set(PACKAGE_CONFIG_INCLUDE_DIR ${US_INCLUDE_DIRS}) set(PACKAGE_CONFIG_RUNTIME_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) set(PACKAGE_CONFIG_CMAKE_DIR ${PROJECT_SOURCE_DIR}/CMake) if(US_IS_EMBEDDED) set(PACKAGE_EMBEDDED "if(@PROJECT_NAME@_IS_EMBEDDED) set(@PROJECT_NAME@_INTERNAL_INCLUDE_DIRS @US_INTERNAL_INCLUDE_DIRS@) set(@PROJECT_NAME@_SOURCES @US_SOURCES@) set(@PROJECT_NAME@_PUBLIC_HEADERS @US_PUBLIC_HEADERS@) set(@PROJECT_NAME@_PRIVATE_HEADERS @US_PRIVATE_HEADERS@) endif()") else() set(PACKAGE_EMBEDDED ) endif() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake @ONLY ) # Configure CppMicroServicesConfig.cmake for the install tree set(CONFIG_INCLUDE_DIR ${HEADER_INSTALL_DIR}) set(CONFIG_RUNTIME_DIR ${RUNTIME_INSTALL_DIR}) set(CONFIG_CMAKE_DIR ${AUXILIARY_INSTALL_DIR}/CMake) configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake INSTALL_DESTINATION ${AUXILIARY_INSTALL_DIR}/CMake/ PATH_VARS CONFIG_INCLUDE_DIR CONFIG_RUNTIME_DIR CONFIG_CMAKE_DIR NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO ) # Version information configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}ConfigVersion.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake @ONLY ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake DESTINATION ${AUXILIARY_INSTALL_DIR}/CMake/ - COMPONENT sdk + ${US_SDK_INSTALL_COMPONENT} ) #----------------------------------------------------------------------------- # Build the examples #----------------------------------------------------------------------------- option(US_BUILD_EXAMPLES "Build example projects" OFF) if(US_BUILD_EXAMPLES) if(NOT US_BUILD_SHARED_LIBS) message(WARNING "Examples are not available if US_BUILD_SHARED_LIBS is OFF") else() set(CppMicroServices_DIR ${PROJECT_BINARY_DIR}) add_subdirectory(examples) endif() endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5244cbb638..3ec45cab71 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,190 +1,192 @@ #----------------------------------------------------------------------------- # US source files #----------------------------------------------------------------------------- set(_srcs util/usAny.cpp util/jsoncpp.cpp + util/usLDAPProp.cpp util/usSharedLibrary.cpp util/usThreads.cpp util/usUncompressResourceData.c util/usUncompressResourceData.cpp util/usUtils.cpp service/usLDAPExpr.cpp service/usLDAPFilter.cpp service/usServiceException.cpp service/usServiceEvent.cpp service/usServiceListenerEntry.cpp service/usServiceListenerEntry_p.h service/usServiceListeners.cpp service/usServiceListeners_p.h service/usServiceObjects.cpp service/usServiceProperties.cpp service/usServicePropertiesImpl.cpp service/usServiceReferenceBase.cpp service/usServiceReferenceBasePrivate.cpp service/usServiceRegistrationBase.cpp service/usServiceRegistrationBasePrivate.cpp service/usServiceRegistry.cpp service/usServiceRegistry_p.h module/usCoreModuleContext_p.h module/usCoreModuleContext.cpp module/usModuleContext.cpp module/usModule.cpp module/usModuleEvent.cpp module/usModuleInfo.cpp module/usModuleManifest.cpp module/usModulePrivate.cpp module/usModuleRegistry.cpp module/usModuleResource.cpp module/usModuleResourceBuffer.cpp module/usModuleResourceStream.cpp module/usModuleResourceTree.cpp module/usModuleSettings.cpp module/usModuleUtils.cpp module/usModuleVersion.cpp ) set(_private_headers util/usAtomicInt_p.h util/usFunctor_p.h util/usStaticInit_p.h util/usThreads_p.h util/usUtils_p.h util/dirent_win32_p.h util/stdint_p.h util/stdint_vc_p.h service/usServicePropertiesImpl_p.h service/usServiceTracker.tpp service/usServiceTrackerPrivate.h service/usServiceTrackerPrivate.tpp service/usTrackedService_p.h service/usTrackedServiceListener_p.h service/usTrackedService.tpp module/usModuleAbstractTracked_p.h module/usModuleAbstractTracked.tpp module/usModuleResourceBuffer_p.h module/usModuleResourceTree_p.h module/usModuleUtils_p.h ) set(_public_headers util/usAny.h + util/usLDAPProp.h util/usSharedData.h util/usSharedLibrary.h util/usUncompressResourceData.h service/usLDAPFilter.h service/usPrototypeServiceFactory.h service/usServiceEvent.h service/usServiceException.h service/usServiceFactory.h service/usServiceInterface.h service/usServiceObjects.h service/usServiceProperties.h service/usServiceReference.h service/usServiceReferenceBase.h service/usServiceRegistration.h service/usServiceRegistrationBase.h service/usServiceTracker.h service/usServiceTrackerCustomizer.h module/usGetModuleContext.h module/usModule.h module/usModuleActivator.h module/usModuleContext.h module/usModuleEvent.h module/usModuleImport.h module/usModuleInfo.h module/usModuleInitialization.h module/usModuleRegistry.h module/usModuleResource.h module/usModuleResourceStream.h module/usModuleSettings.h module/usModuleVersion.h ) if(US_IS_EMBEDDED) set(US_SOURCES ) get_filename_component(_path_prefix "${PROJECT_SOURCE_DIR}" NAME) set(_path_prefix "${_path_prefix}/src") foreach(_src ${_srcs} ${_public_headers} ${_private_headers}) list(APPEND US_SOURCES ${_path_prefix}/${_src}) endforeach() set(US_SOURCES ${US_SOURCES} PARENT_SCOPE) endif() #----------------------------------------------------------------------------- # Create library (only if not in embedded mode) #----------------------------------------------------------------------------- if(NOT US_IS_EMBEDDED) include_directories(${US_INTERNAL_INCLUDE_DIRS}) usFunctionGenerateModuleInit(_srcs NAME ${PROJECT_NAME}) usFunctionEmbedResources(_srcs LIBRARY_NAME ${PROJECT_NAME} ROOT_DIR resources FILES manifest.json) add_library(${PROJECT_NAME} ${_srcs} ${_public_headers} ${_private_headers} ${us_config_h_file}) if(US_LINK_FLAGS) set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "${US_LINK_FLAGS}") endif() set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY COMPILE_DEFINITIONS US_FORCE_MODULE_INIT) set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${${PROJECT_NAME}_VERSION} ) if(US_LINK_LIBRARIES) target_link_libraries(${PROJECT_NAME} ${US_LINK_LIBRARIES}) endif() endif() #----------------------------------------------------------------------------- # Configure public header wrappers #----------------------------------------------------------------------------- set(US_PUBLIC_HEADERS ${_public_headers}) if(US_HEADER_PREFIX) set(US_PUBLIC_HEADERS ) foreach(_public_header ${_public_headers}) get_filename_component(_public_header_basename ${_public_header} NAME_WE) set(_us_public_header ${_public_header_basename}.h) string(SUBSTRING "${_public_header_basename}" 2 -1 _public_header_basename) set(_header_wrapper "${PROJECT_BINARY_DIR}/include/${US_HEADER_PREFIX}${_public_header_basename}.h") configure_file(${PROJECT_SOURCE_DIR}/CMake/usPublicHeaderWrapper.h.in ${_header_wrapper} @ONLY) list(APPEND US_PUBLIC_HEADERS ${_header_wrapper}) endforeach() endif() foreach(_header ${_public_headers} ${_private_headers}) get_filename_component(_header_name "${_header}" NAME) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${_header} "${PROJECT_BINARY_DIR}/include/${_header_name}") endforeach() if(NOT US_IS_EMBEDDED) set_property(TARGET ${PROJECT_NAME} PROPERTY PUBLIC_HEADER ${US_PUBLIC_HEADERS}) set_property(TARGET ${PROJECT_NAME} PROPERTY PRIVATE_HEADER ${_private_headers} ${us_config_h_file}) else() set(US_PUBLIC_HEADERS ${US_PUBLIC_HEADERS} PARENT_SCOPE) set(US_PRIVATE_HEADERS ${US_PRIVATE_HEADERS} PARENT_SCOPE) endif() #----------------------------------------------------------------------------- # Install support (only if not in embedded mode) #----------------------------------------------------------------------------- if(NOT US_IS_EMBEDDED) install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} COMPONENT sdk - LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR} COMPONENT sdk - ARCHIVE DESTINATION ${ARCHIVE_INSTALL_DIR} COMPONENT sdk - PUBLIC_HEADER DESTINATION ${HEADER_INSTALL_DIR} COMPONENT sdk - PRIVATE_HEADER DESTINATION ${HEADER_INSTALL_DIR} COMPONENT sdk) + RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} ${US_SDK_INSTALL_COMPONENT} + LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR} ${US_SDK_INSTALL_COMPONENT} + ARCHIVE DESTINATION ${ARCHIVE_INSTALL_DIR} ${US_SDK_INSTALL_COMPONENT} + PUBLIC_HEADER DESTINATION ${HEADER_INSTALL_DIR} ${US_SDK_INSTALL_COMPONENT} + PRIVATE_HEADER DESTINATION ${HEADER_INSTALL_DIR} ${US_SDK_INSTALL_COMPONENT}) endif() diff --git a/src/service/usLDAPFilter.h b/src/service/usLDAPFilter.h index d8df499a70..17b886f6de 100644 --- a/src/service/usLDAPFilter.h +++ b/src/service/usLDAPFilter.h @@ -1,174 +1,176 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed 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. =============================================================================*/ #ifndef USLDAPFILTER_H #define USLDAPFILTER_H #include "usServiceProperties.h" #include "usSharedData.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4251) #endif US_BEGIN_NAMESPACE class LDAPFilterData; class ServiceReferenceBase; /** * \ingroup MicroServices * * An RFC 1960-based Filter. * *

* A LDAPFilter can be used numerous times to determine if the match * argument matches the filter string that was used to create the LDAPFilter. *

* Some examples of LDAP filters are: * * - "(cn=Babs Jensen)" * - "(!(cn=Tim Howes))" * - "(&(" + ServiceConstants::OBJECTCLASS() + "=Person)(|(sn=Jensen)(cn=Babs J*)))" * - "(o=univ*of*mich*)" * * \remarks This class is thread safe. + * + * \sa LDAPProp for a fluent API generating LDAP filter strings */ class US_EXPORT LDAPFilter { public: /** * Creates in invalid LDAPFilter object. * Test the validity by using the boolean conversion operator. * *

* Calling methods on an invalid LDAPFilter * will result in undefined behavior. */ LDAPFilter(); /** * Creates a LDAPFilter object. This LDAPFilter * object may be used to match a ServiceReference object or a * ServiceProperties object. * *

* If the filter cannot be parsed, an std::invalid_argument will be * thrown with a human readable message where the filter became unparsable. * * @param filter The filter string. * @return A LDAPFilter object encapsulating the filter string. * @throws std::invalid_argument If filter contains an invalid * filter string that cannot be parsed. * @see "Framework specification for a description of the filter string syntax." TODO! */ LDAPFilter(const std::string& filter); LDAPFilter(const LDAPFilter& other); ~LDAPFilter(); operator bool() const; /** * Filter using a service's properties. *

* This LDAPFilter is executed using the keys and values of the * referenced service's properties. The keys are looked up in a case * insensitive manner. * * @param reference The reference to the service whose properties are used * in the match. * @return true if the service's properties match this * LDAPFilter false otherwise. */ bool Match(const ServiceReferenceBase& reference) const; /** * Filter using a ServiceProperties object with case insensitive key lookup. This * LDAPFilter is executed using the specified ServiceProperties's keys * and values. The keys are looked up in a case insensitive manner. * * @param dictionary The ServiceProperties whose key/value pairs are used * in the match. * @return true if the ServiceProperties's values match this * filter; false otherwise. */ bool Match(const ServiceProperties& dictionary) const; /** * Filter using a ServiceProperties. This LDAPFilter is executed using * the specified ServiceProperties's keys and values. The keys are looked * up in a normal manner respecting case. * * @param dictionary The ServiceProperties whose key/value pairs are used * in the match. * @return true if the ServiceProperties's values match this * filter; false otherwise. */ bool MatchCase(const ServiceProperties& dictionary) const; /** * Returns this LDAPFilter's filter string. *

* The filter string is normalized by removing whitespace which does not * affect the meaning of the filter. * * @return This LDAPFilter's filter string. */ std::string ToString() const; /** * Compares this LDAPFilter to another LDAPFilter. * *

* This implementation returns the result of calling * this->ToString() == other.ToString(). * * @param other The object to compare against this LDAPFilter. * @return Returns the result of calling * this->ToString() == other.ToString(). */ bool operator==(const LDAPFilter& other) const; LDAPFilter& operator=(const LDAPFilter& filter); protected: SharedDataPointer d; }; US_END_NAMESPACE #ifdef _MSC_VER #pragma warning(pop) #endif /** * \ingroup MicroServices */ US_EXPORT std::ostream& operator<<(std::ostream& os, const US_PREPEND_NAMESPACE(LDAPFilter)& filter); #endif // USLDAPFILTER_H diff --git a/src/util/usLDAPProp.cpp b/src/util/usLDAPProp.cpp new file mode 100644 index 0000000000..ff2c835961 --- /dev/null +++ b/src/util/usLDAPProp.cpp @@ -0,0 +1,117 @@ +/*============================================================================= + + Library: CppMicroServices + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics + + Licensed 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 "usLDAPProp.h" + +US_BEGIN_NAMESPACE + +LDAPPropExpr::LDAPPropExpr(const std::string& expr) + : m_ldapExpr(expr) +{} + +LDAPPropExpr& LDAPPropExpr::operator!() +{ + m_ldapExpr = "(!" + m_ldapExpr + ")"; + return *this; +} + +LDAPPropExpr::operator std::string() const +{ + return m_ldapExpr; +} + + +LDAPProp::LDAPProp(const std::string& property) + : m_property(property) +{} + +LDAPPropExpr LDAPProp::operator==(const std::string& s) const +{ + return LDAPPropExpr("(" + m_property + "=" + s + ")"); +} + +LDAPPropExpr LDAPProp::operator==(const us::Any& any) const +{ + return operator==(any.ToString()); +} + +LDAPProp::operator LDAPPropExpr () const +{ + return LDAPPropExpr("(" + m_property + "=*)"); +} + +LDAPPropExpr LDAPProp::operator!() const +{ + return LDAPPropExpr("(!(" + m_property + "=*))"); +} + +LDAPPropExpr LDAPProp::operator!=(const std::string& s) const +{ + return LDAPPropExpr("(!(" + m_property + "=" + s + "))"); +} + +LDAPPropExpr LDAPProp::operator!=(const us::Any& any) const +{ + return operator!=(any.ToString()); +} + +LDAPPropExpr LDAPProp::operator>=(const std::string& s) const +{ + return LDAPPropExpr("(" + m_property + ">=" + s + ")"); +} + +LDAPPropExpr LDAPProp::operator>=(const us::Any& any) const +{ + return operator>=(any.ToString()); +} + +LDAPPropExpr LDAPProp::operator<=(const std::string& s) const +{ + return LDAPPropExpr("(" + m_property + "<=" + s + ")"); +} + +LDAPPropExpr LDAPProp::operator<=(const us::Any& any) const +{ + return operator<=(any.ToString()); +} + +LDAPPropExpr LDAPProp::Approx(const std::string& s) const +{ + return LDAPPropExpr("(" + m_property + "~=" + s + ")"); +} + +LDAPPropExpr LDAPProp::Approx(const us::Any& any) const +{ + return Approx(any.ToString()); +} + + +US_END_NAMESPACE + +us::LDAPPropExpr operator&&(const us::LDAPPropExpr& left, const us::LDAPPropExpr& right) +{ + return us::LDAPPropExpr("(&" + static_cast(left) + static_cast(right) + ")"); +} + +us::LDAPPropExpr operator||(const us::LDAPPropExpr& left, const us::LDAPPropExpr& right) +{ + return us::LDAPPropExpr("(|" + static_cast(left) + static_cast(right) + ")"); +} diff --git a/src/util/usLDAPProp.h b/src/util/usLDAPProp.h new file mode 100644 index 0000000000..e63d27a9ff --- /dev/null +++ b/src/util/usLDAPProp.h @@ -0,0 +1,233 @@ +/*============================================================================= + + Library: CppMicroServices + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics + + Licensed 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. + +=============================================================================*/ + +#ifndef USLDAPPROP_H +#define USLDAPPROP_H + +#include +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4251) +#endif + +US_BEGIN_NAMESPACE + +/// \cond +class US_EXPORT LDAPPropExpr +{ +public: + + explicit LDAPPropExpr(const std::string& expr); + + LDAPPropExpr& operator!(); + + operator std::string() const; + +private: + + LDAPPropExpr& operator=(const LDAPPropExpr&); + + std::string m_ldapExpr; +}; +/// \endcond + +/** + * \ingroup MicroServicesUtils + * + * A fluent API for creating LDAP filter strings. + * + * Examples for creating LDAPFilter objects: + * \code + * // This creates the filter "(&(name=Ben)(!(count=1)))" + * LDAPFilter filter(LDAPProp("name") == "Ben" && !(LDAPProp("count") == 1)); + * + * // This creates the filter "(|(presence=*)(!(absence=*)))" + * LDAPFilter filter(LDAPProp("presence") || !LDAPProp("absence")); + * + * // This creates the filter "(&(ge>=-3)(approx~=hi))" + * LDAPFilter filter(LDAPProp("ge") >= -3 && LDAPProp("approx").Approx("hi")); + * \endcode + * + * \sa LDAPFilter + */ +class US_EXPORT LDAPProp +{ +public: + + /** + * Create a LDAPProp instance for the named LDAP property. + * + * @param property The name of the LDAP property. + */ + LDAPProp(const std::string& property); + + /** + * LDAP equality '=' + * + * @param s A type convertible to std::string. + * @return A LDAP expression object. + * + * @{ + */ + LDAPPropExpr operator==(const std::string& s) const; + LDAPPropExpr operator==(const us::Any& s) const; + template + LDAPPropExpr operator==(const T& s) const + { + std::stringstream ss; + ss << s; + return LDAPPropExpr("(" + m_property + "=" + ss.str() + ")"); + } + /// @} + + operator LDAPPropExpr () const; + + /** + * States the absence of the LDAP property. + * + * @return A LDAP expression object. + */ + LDAPPropExpr operator!() const; + + /** + * Convenience operator for LDAP inequality. + * + * Writing either + * \code + * LDAPProp("attr") != "val" + * \endcode + * or + * \code + * !(LDAPProp("attr") == "val") + * \endcode + * leads to the same string "(!(attr=val))". + * + * @param s A type convertible to std::string. + * @return A LDAP expression object. + * + * @{ + */ + LDAPPropExpr operator!=(const std::string& s) const; + LDAPPropExpr operator!=(const us::Any& s) const; + template + LDAPPropExpr operator!=(const T& s) const + { + std::stringstream ss; + ss << s; + return operator!=(ss.str()); + } + /// @} + + /** + * LDAP greater or equal '>=' + * + * @param s A type convertible to std::string. + * @return A LDAP expression object. + * + * @{ + */ + LDAPPropExpr operator>=(const std::string& s) const; + LDAPPropExpr operator>=(const us::Any& s) const; + template + LDAPPropExpr operator>=(const T& s) const + { + std::stringstream ss; + ss << s; + return operator>=(ss.str()); + } + /// @} + + /** + * LDAP less or equal '<=' + * + * @param s A type convertible to std::string. + * @return A LDAP expression object. + * + * @{ + */ + LDAPPropExpr operator<=(const std::string& s) const; + LDAPPropExpr operator<=(const us::Any& s) const; + template + LDAPPropExpr operator<=(const T& s) const + { + std::stringstream ss; + ss << s; + return operator<=(ss.str()); + } + /// @} + + /** + * LDAP approximation '~=' + * + * @param s A type convertible to std::string. + * @return A LDAP expression object. + * + * @{ + */ + LDAPPropExpr Approx(const std::string& s) const; + LDAPPropExpr Approx(const us::Any& s) const; + template + LDAPPropExpr Approx(const T& s) const + { + std::stringstream ss; + ss << s; + return Approx(ss.str()); + } + /// @} + +private: + + LDAPProp& operator=(const LDAPProp&); + + std::string m_property; +}; + +US_END_NAMESPACE + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +/** + * \ingroup MicroServicesUtils + * + * LDAP logical and '&' + * + * @param left A LDAP expression. + * @param right A LDAP expression. + * @return A LDAP expression + */ +US_EXPORT us::LDAPPropExpr operator&&(const us::LDAPPropExpr& left, const us::LDAPPropExpr& right); + +/** + * \ingroup MicroServicesUtils + * + * LDAP logical or '|' + * + * @param left A LDAP expression. + * @param right A LDAP expression. + * @return A LDAP expression + */ +US_EXPORT us::LDAPPropExpr operator||(const us::LDAPPropExpr& left, const us::LDAPPropExpr& right); + +#endif // USLDAPPROP_H diff --git a/test/usLDAPFilterTest.cpp b/test/usLDAPFilterTest.cpp index f81a4f3bc7..5bdce68814 100644 --- a/test/usLDAPFilterTest.cpp +++ b/test/usLDAPFilterTest.cpp @@ -1,149 +1,163 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed 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 +#include #include "usTestingMacros.h" #include US_USE_NAMESPACE int TestParsing() { // WELL FORMED Expr try { US_TEST_OUTPUT(<< "Parsing (cn=Babs Jensen)") LDAPFilter ldap( "(cn=Babs Jensen)" ); US_TEST_OUTPUT(<< "Parsing (!(cn=Tim Howes))") ldap = LDAPFilter( "(!(cn=Tim Howes))" ); US_TEST_OUTPUT(<< "Parsing " << std::string("(&(") + ServiceConstants::OBJECTCLASS() + "=Person)(|(sn=Jensen)(cn=Babs J*)))") ldap = LDAPFilter( std::string("(&(") + ServiceConstants::OBJECTCLASS() + "=Person)(|(sn=Jensen)(cn=Babs J*)))" ); US_TEST_OUTPUT(<< "Parsing (o=univ*of*mich*)") ldap = LDAPFilter( "(o=univ*of*mich*)" ); } catch (const std::invalid_argument& e) { US_TEST_OUTPUT(<< e.what()); return EXIT_FAILURE; } // MALFORMED Expr try { US_TEST_OUTPUT( << "Parsing malformed expr: cn=Babs Jensen)") LDAPFilter ldap( "cn=Babs Jensen)" ); return EXIT_FAILURE; } catch (const std::invalid_argument&) { } return EXIT_SUCCESS; } int TestEvaluate() { // EVALUATE try { LDAPFilter ldap( "(Cn=Babs Jensen)" ); ServiceProperties props; bool eval = false; // Several values props["cn"] = std::string("Babs Jensen"); props["unused"] = std::string("Jansen"); US_TEST_OUTPUT(<< "Evaluating expr: " << ldap.ToString()) eval = ldap.Match(props); if (!eval) { return EXIT_FAILURE; } // WILDCARD ldap = LDAPFilter( "(cn=Babs *)" ); props.clear(); props["cn"] = std::string("Babs Jensen"); US_TEST_OUTPUT(<< "Evaluating wildcard expr: " << ldap.ToString()) eval = ldap.Match(props); if ( !eval ) { return EXIT_FAILURE; } // NOT FOUND ldap = LDAPFilter( "(cn=Babs *)" ); props.clear(); props["unused"] = std::string("New"); US_TEST_OUTPUT(<< "Expr not found test: " << ldap.ToString()) eval = ldap.Match(props); if ( eval ) { return EXIT_FAILURE; } // std::vector with integer values ldap = LDAPFilter( " ( |(cn=Babs *)(sn=1) )" ); props.clear(); std::vector list; list.push_back(std::string("Babs Jensen")); list.push_back(std::string("1")); props["sn"] = list; US_TEST_OUTPUT(<< "Evaluating vector expr: " << ldap.ToString()) eval = ldap.Match(props); if (!eval) { return EXIT_FAILURE; } // wrong case ldap = LDAPFilter( "(cN=Babs *)" ); props.clear(); props["cn"] = std::string("Babs Jensen"); US_TEST_OUTPUT(<< "Evaluating case sensitive expr: " << ldap.ToString()) eval = ldap.MatchCase(props); if (eval) { return EXIT_FAILURE; } } catch (const std::invalid_argument& e) { US_TEST_OUTPUT( << e.what() ) return EXIT_FAILURE; } return EXIT_SUCCESS; } +void TestLDAPExpressions() +{ + LDAPFilter filter( + LDAPProp("bla") == "jo" && !(LDAPProp("ha") == 1) && + (LDAPProp("presence") || !LDAPProp("absence")) && + LDAPProp("le") <= 4.1 && LDAPProp("ge") >= -3 && + LDAPProp("approx").Approx("Approx") + ); + const std::string filterStr = "(&(&(&(&(&(bla=jo)(!(ha=1)))(|(presence=*)(!(absence=*))))(le<=4.1))(ge>=-3))(approx~=Approx))"; + US_TEST_CONDITION(filter.ToString() == filterStr, "test generated filter string") +} + int usLDAPFilterTest(int /*argc*/, char* /*argv*/[]) { US_TEST_BEGIN("LDAPFilterTest"); + TestLDAPExpressions(); US_TEST_CONDITION(TestParsing() == EXIT_SUCCESS, "Parsing LDAP expressions: ") US_TEST_CONDITION(TestEvaluate() == EXIT_SUCCESS, "Evaluating LDAP expressions: ") US_TEST_END() } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 336f1d20ee..997b65c296 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,19 +1,19 @@ include_directories(${US_INCLUDE_DIRS}) add_definitions(-DUS_RCC_EXECUTABLE_NAME=\"${US_RCC_EXECUTABLE_NAME}\") set(srcs usResourceCompiler.cpp) if(US_ENABLE_RESOURCE_COMPRESSION) list(APPEND srcs usResourceCompressor.c) endif() add_executable(${US_RCC_EXECUTABLE_NAME} ${srcs}) if(WIN32) target_link_libraries(${US_RCC_EXECUTABLE_NAME} Shlwapi) endif() install(TARGETS ${US_RCC_EXECUTABLE_NAME} EXPORT ${PROJECT_NAME}Targets - FRAMEWORK DESTINATION . COMPONENT sdk - RUNTIME DESTINATION bin COMPONENT sdk) + FRAMEWORK DESTINATION . ${US_SDK_INSTALL_COMPONENT} + RUNTIME DESTINATION bin ${US_SDK_INSTALL_COMPONENT})