diff --git a/src/module/usModuleResource.cpp b/src/module/usModuleResource.cpp index 55215a0bda..35cb0eb378 100644 --- a/src/module/usModuleResource.cpp +++ b/src/module/usModuleResource.cpp @@ -1,271 +1,271 @@ /*============================================================================= 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 "usModuleResource.h" #include "usAtomicInt_p.h" #include "usModuleResourceTree_p.h" #include US_BEGIN_NAMESPACE class ModuleResourcePrivate { public: ModuleResourcePrivate() : associatedResourceTree(NULL) , node(-1) , size(0) , data(NULL) , isFile(false) , isCompressed(false) , ref(1) {} std::string fileName; std::string path; std::string filePath; std::vector resourceTrees; const ModuleResourceTree* associatedResourceTree; int node; int32_t size; const unsigned char* data; unsigned char* uncompressedData; mutable std::vector children; bool isFile; bool isCompressed; /** * Reference count for implicitly shared private implementation. */ AtomicInt ref; }; ModuleResource::ModuleResource() : d(new ModuleResourcePrivate) { } ModuleResource::ModuleResource(const ModuleResource &resource) : d(resource.d) { d->ref.Ref(); } ModuleResource::ModuleResource(const std::string& _file, ModuleResourceTree* associatedResourceTree, const std::vector& resourceTrees) : d(new ModuleResourcePrivate) { d->resourceTrees = resourceTrees; d->associatedResourceTree = associatedResourceTree; std::string file = _file; if (file.empty()) file = "/"; if (file[0] != '/') file = std::string("/") + file; std::size_t index = file.find_last_of('/'); if (index < file.size()-1) { d->fileName = file.substr(index+1); } std::string rawPath = file.substr(0,index+1); // remove duplicate / std::string::value_type lastChar = 0; for (std::size_t i = 0; i < rawPath.size(); ++i) { if (rawPath[i] == '/' && lastChar == '/') { continue; } lastChar = rawPath[i]; d->path.push_back(lastChar); } d->filePath = d->path + d->fileName; d->node = d->associatedResourceTree->FindNode(GetResourcePath()); if (d->node != -1) { d->isFile = !d->associatedResourceTree->IsDir(d->node); if (d->isFile) { d->data = d->associatedResourceTree->GetData(d->node, &d->size); d->isCompressed = d->associatedResourceTree->IsCompressed(d->node); } } } ModuleResource::~ModuleResource() { if (!d->ref.Deref()) delete d; } ModuleResource& ModuleResource::operator =(const ModuleResource& resource) { ModuleResourcePrivate* curr_d = d; d = resource.d; d->ref.Ref(); if (!curr_d->ref.Deref()) delete curr_d; return *this; } bool ModuleResource::operator <(const ModuleResource& resource) const { return this->GetResourcePath() < resource.GetResourcePath(); } bool ModuleResource::operator ==(const ModuleResource& resource) const { return d->associatedResourceTree == resource.d->associatedResourceTree && this->GetResourcePath() == resource.GetResourcePath(); } bool ModuleResource::operator !=(const ModuleResource &resource) const { return !(*this == resource); } bool ModuleResource::IsValid() const { return d->associatedResourceTree && d->associatedResourceTree->IsValid() && d->node > -1; } bool ModuleResource::IsCompressed() const { return d->isCompressed; } -ModuleResource::operator bool() const +ModuleResource::operator bool_type() const { - return IsValid(); + return IsValid() ? &ModuleResource::d : NULL; } std::string ModuleResource::GetName() const { return d->fileName; } std::string ModuleResource::GetPath() const { return d->path; } std::string ModuleResource::GetResourcePath() const { return d->filePath; } std::string ModuleResource::GetBaseName() const { return d->fileName.substr(0, d->fileName.find_first_of('.')); } std::string ModuleResource::GetCompleteBaseName() const { return d->fileName.substr(0, d->fileName.find_last_of('.')); } std::string ModuleResource::GetSuffix() const { std::size_t index = d->fileName.find_last_of('.'); return index < d->fileName.size()-1 ? d->fileName.substr(index+1) : std::string(""); } std::string ModuleResource::GetCompleteSuffix() const { std::size_t index = d->fileName.find_first_of('.'); return index < d->fileName.size()-1 ? d->fileName.substr(index+1) : std::string(""); } bool ModuleResource::IsDir() const { return !d->isFile; } bool ModuleResource::IsFile() const { return d->isFile; } std::vector ModuleResource::GetChildren() const { if (d->isFile || !IsValid()) return d->children; if (!d->children.empty()) return d->children; bool indexPastAssociatedResTree = false; for (std::size_t i = 0; i < d->resourceTrees.size(); ++i) { if (d->resourceTrees[i] == d->associatedResourceTree) { indexPastAssociatedResTree = true; d->associatedResourceTree->GetChildren(d->node, d->children); } else if (indexPastAssociatedResTree) { int nodeIndex = d->resourceTrees[i]->FindNode(GetPath()); if (nodeIndex > -1) { d->resourceTrees[i]->GetChildren(d->node, d->children); } } } return d->children; } int ModuleResource::GetSize() const { return d->size; } const unsigned char* ModuleResource::GetData() const { if (!IsValid()) return NULL; return d->data; } std::size_t ModuleResource::Hash() const { using namespace US_HASH_FUNCTION_NAMESPACE; return US_HASH_FUNCTION(std::string, this->GetResourcePath()); } US_END_NAMESPACE US_USE_NAMESPACE std::ostream& operator<<(std::ostream& os, const ModuleResource& resource) { return os << resource.GetResourcePath(); } diff --git a/src/module/usModuleResource.h b/src/module/usModuleResource.h index abfe1370a7..e35cad739f 100644 --- a/src/module/usModuleResource.h +++ b/src/module/usModuleResource.h @@ -1,305 +1,309 @@ /*============================================================================= 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 USMODULERESOURCE_H #define USMODULERESOURCE_H #include #include #include US_MSVC_PUSH_DISABLE_WARNING(4396) US_BEGIN_NAMESPACE class ModuleResourcePrivate; class ModuleResourceTree; /** * \ingroup MicroServices * * Represents a resource (text file, image, etc.) embedded in a CppMicroServices module. * * A \c %ModuleResource object provides information about a resource (external file) which * was embedded into this module's shared library. \c %ModuleResource objects can be obtained * be calling Module#GetResource or Module#FindResources. * * Example code for retreiving a resource object and reading its contents: * \snippet uServices-resources/main.cpp 1 * * %ModuleResource objects have value semantics and copies are very inexpensive. * * \see ModuleResourceStream * \see \ref MicroServices_Resources */ class US_EXPORT ModuleResource { +private: + + typedef ModuleResourcePrivate* ModuleResource::*bool_type; + public: /** * Creates in invalid %ModuleResource object. */ ModuleResource(); /** * Copy constructor. * @param resource The object to be copied. */ ModuleResource(const ModuleResource& resource); ~ModuleResource(); /** * Assignment operator. * * @param resource The %ModuleResource object which is assigned to this instance. * @return A reference to this %ModuleResource instance. */ ModuleResource& operator=(const ModuleResource& resource); /** * A less then operator using the full resource path as returned by * GetResourcePath() to define the ordering. * * @param resource The object to which this %ModuleResource object is compared to. * @return \c true if this %ModuleResource object is less then \c resource, * \c false otherwise. */ bool operator<(const ModuleResource& resource) const; /** * Equality operator for %ModuleResource objects. * * @param resource The object for testing equality. * @return \c true if this %ModuleResource object is equal to \c resource, i.e. * they are coming from the same module (shared or static) and have an equal * resource path, \c false otherwise. */ bool operator==(const ModuleResource& resource) const; /** * Inequality operator for %ModuleResource objects. * * @param resource The object for testing inequality. * @return The result of !(*this == resource). */ bool operator!=(const ModuleResource& resource) const; /** * Tests this %ModuleResource object for validity. * * Invalid %ModuleResource objects are created by the default constructor or * can be returned by the Module class if the resource path is not found. If a * module from which %ModuleResource objects have been obtained is un-loaded, * these objects become invalid. * * @return \c true if this %ModuleReource object is valid and can safely be used, * \c false otherwise. */ bool IsValid() const; /** * Returns \c true if the resource represents a file and the resource data * is in a compressed format, \c false otherwise. * * @return \c true if the resource data is compressed, \c false otherwise. */ bool IsCompressed() const; /** * Boolean conversion operator using IsValid(). */ - operator bool() const; + operator bool_type() const; /** * Returns the name of the resource, excluding the path. * * Example: * \code * ModuleResource resource = module->GetResource("/data/archive.tar.gz"); * std::string name = resource.GetName(); // name = "archive.tar.gz" * \endcode * * @return The resource name. * @see GetPath(), GetResourcePath() */ std::string GetName() const; /** * Returns the resource's path, without the file name. * * Example: * \code * ModuleResource resource = module->GetResource("/data/archive.tar.gz"); * std::string path = resource.GetPath(); // path = "/data" * \endcode * * @return The resource path without the name. * @see GetResourcePath(), GetName() and IsDir() */ std::string GetPath() const; /** * Returns the resource path including the file name. * * @return The resource path including the file name. * @see GetPath(), GetName() and IsDir() */ std::string GetResourcePath() const; /** * Returns the base name of the resource without the path. * * Example: * \code * ModuleResource resource = module->GetResource("/data/archive.tar.gz"); * std::string base = resource.GetBaseName(); // base = "archive" * \endcode * * @return The resource base name. * @see GetName(), GetSuffix(), GetCompleteSuffix() and GetCompleteBaseName() */ std::string GetBaseName() const; /** * Returns the complete base name of the resource without the path. * * Example: * \code * ModuleResource resource = module->GetResource("/data/archive.tar.gz"); * std::string base = resource.GetCompleteBaseName(); // base = "archive.tar" * \endcode * * @return The resource's complete base name. * @see GetName(), GetSuffix(), GetCompleteSuffix(), and GetBaseName() */ std::string GetCompleteBaseName() const; /** * Returns the suffix of the resource. * * The suffix consists of all characters in the resource name after (but not * including) the last '.'. * * Example: * \code * ModuleResource resource = module->GetResource("/data/archive.tar.gz"); * std::string suffix = resource.GetSuffix(); // suffix = "gz" * \endcode * * @return The resource name suffix. * @see GetName(), GetCompleteSuffix(), GetBaseName() and GetCompleteBaseName() */ std::string GetSuffix() const; /** * Returns the complete suffix of the resource. * * The suffix consists of all characters in the resource name after (but not * including) the first '.'. * * Example: * \code * ModuleResource resource = module->GetResource("/data/archive.tar.gz"); * std::string suffix = resource.GetCompleteSuffix(); // suffix = "tar.gz" * \endcode * * @return The resource name suffix. * @see GetName(), GetSuffix(), GetBaseName(), and GetCompleteBaseName() */ std::string GetCompleteSuffix() const; /** * Returns \c true if this %ModuleResource object points to a directory and thus * may have child resources. * * @return \c true if this object points to a directory, \c false otherwise. */ bool IsDir() const; /** * Returns \c true if this %ModuleResource object points to a file resource. * * @return \c true if this object points to an embedded file, \c false otherwise. */ bool IsFile() const; /** * Returns a list of resource names which are children of this object. * * The returned names are relative to the path of this %ModuleResource object and * may contain duplicates in case of modules which are statically linked into the * module from which this object was retreived. * * @return A list of child resource names. */ std::vector GetChildren() const; /** * Returns the size of the raw embedded data for this %ModuleResource object. * * @return The resource data size. */ int GetSize() const; /** * Returns a data pointer pointing to the raw data of this %ModuleResource object. * If the resource is compressed the data returned is compressed and UncompressResourceData() * must be used to access the data. If the resource represents a directory \c 0 is returned. * * @return A raw pointer to the embedded data, or \c 0 if the resource is not a file resource. */ const unsigned char* GetData() const; private: ModuleResource(const std::string& file, ModuleResourceTree* resourceTree, const std::vector& resourceTrees); friend class Module; friend class ModulePrivate; US_HASH_FUNCTION_FRIEND(ModuleResource); std::size_t Hash() const; ModuleResourcePrivate* d; }; US_END_NAMESPACE US_MSVC_POP_WARNING /** * \ingroup MicroServices */ US_EXPORT std::ostream& operator<<(std::ostream& os, const US_PREPEND_NAMESPACE(ModuleResource)& resource); US_HASH_FUNCTION_NAMESPACE_BEGIN US_HASH_FUNCTION_BEGIN(US_PREPEND_NAMESPACE(ModuleResource)) return arg.Hash(); US_HASH_FUNCTION_END US_HASH_FUNCTION_NAMESPACE_END #endif // USMODULERESOURCE_H diff --git a/src/service/usLDAPFilter.cpp b/src/service/usLDAPFilter.cpp index 36d124e656..c9015b15c3 100644 --- a/src/service/usLDAPFilter.cpp +++ b/src/service/usLDAPFilter.cpp @@ -1,121 +1,121 @@ /*============================================================================= 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 "usLDAPFilter.h" #include "usLDAPExpr_p.h" #include "usServicePropertiesImpl_p.h" #include "usServiceReference.h" #include "usServiceReferenceBasePrivate.h" #include US_BEGIN_NAMESPACE class LDAPFilterData : public SharedData { public: LDAPFilterData() : ldapExpr() {} LDAPFilterData(const std::string& filter) : ldapExpr(filter) {} LDAPFilterData(const LDAPFilterData& other) : SharedData(other), ldapExpr(other.ldapExpr) {} LDAPExpr ldapExpr; }; LDAPFilter::LDAPFilter() : d(0) { } LDAPFilter::LDAPFilter(const std::string& filter) : d(0) { try { d = new LDAPFilterData(filter); } catch (const std::exception& e) { throw std::invalid_argument(e.what()); } } LDAPFilter::LDAPFilter(const LDAPFilter& other) : d(other.d) { } LDAPFilter::~LDAPFilter() { } -LDAPFilter::operator bool() const +LDAPFilter::operator bool_type() const { - return d.ConstData() != 0; + return d.ConstData() != 0 ? &LDAPFilter::d : NULL; } bool LDAPFilter::Match(const ServiceReferenceBase& reference) const { return d->ldapExpr.Evaluate(reference.d->GetProperties(), true); } bool LDAPFilter::Match(const ServiceProperties& dictionary) const { return d->ldapExpr.Evaluate(ServicePropertiesImpl(dictionary), false); } bool LDAPFilter::MatchCase(const ServiceProperties& dictionary) const { return d->ldapExpr.Evaluate(ServicePropertiesImpl(dictionary), true); } std::string LDAPFilter::ToString() const { return d->ldapExpr.ToString(); } bool LDAPFilter::operator==(const LDAPFilter& other) const { return d->ldapExpr.ToString() == other.d->ldapExpr.ToString(); } LDAPFilter& LDAPFilter::operator=(const LDAPFilter& filter) { d = filter.d; return *this; } US_END_NAMESPACE US_USE_NAMESPACE std::ostream& operator<<(std::ostream& os, const LDAPFilter& filter) { return os << filter.ToString(); } diff --git a/src/service/usLDAPFilter.h b/src/service/usLDAPFilter.h index 17b886f6de..c90b051703 100644 --- a/src/service/usLDAPFilter.h +++ b/src/service/usLDAPFilter.h @@ -1,176 +1,180 @@ /*============================================================================= 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 { +private: + + typedef SharedDataPointer LDAPFilter::*bool_type; + 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; + operator bool_type() 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/service/usServiceReferenceBase.cpp b/src/service/usServiceReferenceBase.cpp index 6bc722f85e..0c8e60d8f4 100644 --- a/src/service/usServiceReferenceBase.cpp +++ b/src/service/usServiceReferenceBase.cpp @@ -1,218 +1,218 @@ /*============================================================================= 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 "usServiceReferenceBase.h" #include "usServiceReferenceBasePrivate.h" #include "usServiceRegistrationBasePrivate.h" #include "usModule.h" #include "usModulePrivate.h" US_BEGIN_NAMESPACE typedef ServiceRegistrationBasePrivate::MutexType MutexType; typedef MutexLock MutexLocker; ServiceReferenceBase::ServiceReferenceBase() : d(new ServiceReferenceBasePrivate(0)) { } ServiceReferenceBase::ServiceReferenceBase(const ServiceReferenceBase& ref) : d(ref.d) { d->ref.Ref(); } ServiceReferenceBase::ServiceReferenceBase(ServiceRegistrationBasePrivate* reg) : d(new ServiceReferenceBasePrivate(reg)) { } void ServiceReferenceBase::SetInterfaceId(const std::string& interfaceId) { if (d->ref > 1) { // detach d->ref.Deref(); d = new ServiceReferenceBasePrivate(d->registration); } d->interfaceId = interfaceId; } -ServiceReferenceBase::operator bool() const +ServiceReferenceBase::operator bool_type() const { - return GetModule() != 0; + return GetModule() != 0 ? &ServiceReferenceBase::d : NULL; } ServiceReferenceBase& ServiceReferenceBase::operator=(int null) { if (null == 0) { if (!d->ref.Deref()) delete d; d = new ServiceReferenceBasePrivate(0); } return *this; } ServiceReferenceBase::~ServiceReferenceBase() { if (!d->ref.Deref()) delete d; } Any ServiceReferenceBase::GetProperty(const std::string& key) const { MutexLocker lock(d->registration->propsLock); return d->registration->properties.Value(key); } void ServiceReferenceBase::GetPropertyKeys(std::vector& keys) const { MutexLocker lock(d->registration->propsLock); const std::vector& ks = d->registration->properties.Keys(); keys.assign(ks.begin(), ks.end()); } Module* ServiceReferenceBase::GetModule() const { if (d->registration == 0 || d->registration->module == 0) { return 0; } return d->registration->module->q; } void ServiceReferenceBase::GetUsingModules(std::vector& modules) const { MutexLocker lock(d->registration->propsLock); ServiceRegistrationBasePrivate::ModuleToRefsMap::const_iterator end = d->registration->dependents.end(); for (ServiceRegistrationBasePrivate::ModuleToRefsMap::const_iterator iter = d->registration->dependents.begin(); iter != end; ++iter) { modules.push_back(iter->first); } } bool ServiceReferenceBase::operator<(const ServiceReferenceBase& reference) const { int r1 = 0; int r2 = 0; if (!(*this)) { return true; } if (!reference) { return false; } Any anyR1 = GetProperty(ServiceConstants::SERVICE_RANKING()); Any anyR2 = reference.GetProperty(ServiceConstants::SERVICE_RANKING()); if (anyR1.Type() == typeid(int)) r1 = any_cast(anyR1); if (anyR2.Type() == typeid(int)) r2 = any_cast(anyR2); if (r1 != r2) { // use ranking if ranking differs return r1 < r2; } else { long int id1 = any_cast(GetProperty(ServiceConstants::SERVICE_ID())); long int id2 = any_cast(reference.GetProperty(ServiceConstants::SERVICE_ID())); // otherwise compare using IDs, // is less than if it has a higher ID. return id2 < id1; } } bool ServiceReferenceBase::operator==(const ServiceReferenceBase& reference) const { return d->registration == reference.d->registration; } ServiceReferenceBase& ServiceReferenceBase::operator=(const ServiceReferenceBase& reference) { ServiceReferenceBasePrivate* curr_d = d; d = reference.d; d->ref.Ref(); if (!curr_d->ref.Deref()) delete curr_d; return *this; } bool ServiceReferenceBase::IsConvertibleTo(const std::string& interfaceId) const { return d->IsConvertibleTo(interfaceId); } std::string ServiceReferenceBase::GetInterfaceId() const { return d->interfaceId; } std::size_t ServiceReferenceBase::Hash() const { using namespace US_HASH_FUNCTION_NAMESPACE; return US_HASH_FUNCTION(ServiceRegistrationBasePrivate*, this->d->registration); } US_END_NAMESPACE US_USE_NAMESPACE std::ostream& operator<<(std::ostream& os, const ServiceReferenceBase& serviceRef) { if (serviceRef) { os << "Reference for service object registered from " << serviceRef.GetModule()->GetName() << " " << serviceRef.GetModule()->GetVersion() << " ("; std::vector keys; serviceRef.GetPropertyKeys(keys); size_t keySize = keys.size(); for(size_t i = 0; i < keySize; ++i) { os << keys[i] << "=" << serviceRef.GetProperty(keys[i]).ToString(); if (i < keySize-1) os << ","; } os << ")"; } else { os << "Invalid service reference"; } return os; } diff --git a/src/service/usServiceReferenceBase.h b/src/service/usServiceReferenceBase.h index 9b132920d3..b707fc884d 100644 --- a/src/service/usServiceReferenceBase.h +++ b/src/service/usServiceReferenceBase.h @@ -1,228 +1,232 @@ /*============================================================================= 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 USSERVICEREFERENCEBASE_H #define USSERVICEREFERENCEBASE_H #include US_MSVC_PUSH_DISABLE_WARNING(4396) US_BEGIN_NAMESPACE class Module; class ServiceRegistrationBasePrivate; class ServiceReferenceBasePrivate; /** * \ingroup MicroServices * * A reference to a service. * * \note This class is provided as public API for low-level service queries only. * In almost all cases you should use the template ServiceReference instead. */ class US_EXPORT ServiceReferenceBase { +private: + + typedef ServiceReferenceBasePrivate* ServiceReferenceBase::*bool_type; + public: ServiceReferenceBase(const ServiceReferenceBase& ref); /** * Converts this ServiceReferenceBase instance into a boolean * expression. If this instance was default constructed or * the service it references has been unregistered, the conversion * returns false, otherwise it returns true. */ - operator bool() const; + operator bool_type() const; /** * Releases any resources held or locked by this * ServiceReferenceBase and renders it invalid. */ ServiceReferenceBase& operator=(int null); ~ServiceReferenceBase(); /** * Returns the property value to which the specified property key is mapped * in the properties ServiceProperties object of the service * referenced by this ServiceReferenceBase object. * *

* Property keys are case-insensitive. * *

* This method continues to return property values after the service has * been unregistered. This is so references to unregistered services can * still be interrogated. * * @param key The property key. * @return The property value to which the key is mapped; an invalid Any * if there is no property named after the key. */ Any GetProperty(const std::string& key) const; /** * Returns a list of the keys in the ServiceProperties * object of the service referenced by this ServiceReferenceBase * object. * *

* This method will continue to return the keys after the service has been * unregistered. This is so references to unregistered services can * still be interrogated. * * @param keys A vector being filled with the property keys. */ void GetPropertyKeys(std::vector& keys) const; /** * Returns the module that registered the service referenced by this * ServiceReferenceBase object. * *

* This method must return 0 when the service has been * unregistered. This can be used to determine if the service has been * unregistered. * * @return The module that registered the service referenced by this * ServiceReferenceBase object; 0 if that * service has already been unregistered. * @see ModuleContext::RegisterService(const InterfaceMap&, const ServiceProperties&) */ Module* GetModule() const; /** * Returns the modules that are using the service referenced by this * ServiceReferenceBase object. Specifically, this method returns * the modules whose usage count for that service is greater than zero. * * @param modules A list of modules whose usage count for the service referenced * by this ServiceReferenceBase object is greater than * zero. */ void GetUsingModules(std::vector& modules) const; /** * Returns the interface identifier this ServiceReferenceBase object * is bound to. * * A default constructed ServiceReferenceBase object is not bound to * any interface identifier and calling this method will return an * empty string. * * @return The interface identifier for this ServiceReferenceBase object. */ std::string GetInterfaceId() const; /** * Checks wether this ServiceReferenceBase object can be converted to * another ServiceReferenceBase object, which will be bound to the * given interface identifier. * * ServiceReferenceBase objects can be converted if the underlying service * implementation was registered under multiple service interfaces. * * @param interfaceid * @return \c true if this ServiceReferenceBase object can be converted, * \c false otherwise. */ bool IsConvertibleTo(const std::string& interfaceid) const; /** * Compares this ServiceReferenceBase with the specified * ServiceReferenceBase for order. * *

* If this ServiceReferenceBase and the specified * ServiceReferenceBase have the same \link ServiceConstants::SERVICE_ID() * service id\endlink they are equal. This ServiceReferenceBase is less * than the specified ServiceReferenceBase if it has a lower * {@link ServiceConstants::SERVICE_RANKING service ranking} and greater if it has a * higher service ranking. Otherwise, if this ServiceReferenceBase * and the specified ServiceReferenceBase have the same * {@link ServiceConstants::SERVICE_RANKING service ranking}, this * ServiceReferenceBase is less than the specified * ServiceReferenceBase if it has a higher * {@link ServiceConstants::SERVICE_ID service id} and greater if it has a lower * service id. * * @param reference The ServiceReferenceBase to be compared. * @return Returns a false or true if this * ServiceReferenceBase is less than or greater * than the specified ServiceReferenceBase. */ bool operator<(const ServiceReferenceBase& reference) const; bool operator==(const ServiceReferenceBase& reference) const; ServiceReferenceBase& operator=(const ServiceReferenceBase& reference); private: friend class ModulePrivate; friend class ModuleContext; friend class ServiceObjectsBase; friend class ServiceObjectsBasePrivate; friend class ServiceRegistrationBase; friend class ServiceRegistrationBasePrivate; friend class ServiceListeners; friend class ServiceRegistry; friend class LDAPFilter; template friend class ServiceReference; US_HASH_FUNCTION_FRIEND(ServiceReferenceBase); std::size_t Hash() const; /** * Creates an invalid ServiceReferenceBase object. You can use * this object in boolean expressions and it will evaluate to * false. */ ServiceReferenceBase(); ServiceReferenceBase(ServiceRegistrationBasePrivate* reg); void SetInterfaceId(const std::string& interfaceId); ServiceReferenceBasePrivate* d; }; US_END_NAMESPACE US_MSVC_POP_WARNING /** * \ingroup MicroServices */ US_EXPORT std::ostream& operator<<(std::ostream& os, const US_PREPEND_NAMESPACE(ServiceReferenceBase)& serviceRef); US_HASH_FUNCTION_NAMESPACE_BEGIN US_HASH_FUNCTION_BEGIN(US_PREPEND_NAMESPACE(ServiceReferenceBase)) return arg.Hash(); US_HASH_FUNCTION_END US_HASH_FUNCTION_NAMESPACE_END #endif // USSERVICEREFERENCEBASE_H diff --git a/src/service/usServiceRegistrationBase.cpp b/src/service/usServiceRegistrationBase.cpp index b121bb0a60..a84eb3db16 100644 --- a/src/service/usServiceRegistrationBase.cpp +++ b/src/service/usServiceRegistrationBase.cpp @@ -1,272 +1,272 @@ /*============================================================================= 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 "usServiceRegistrationBase.h" #include "usServiceRegistrationBasePrivate.h" #include "usServiceListenerEntry_p.h" #include "usServiceRegistry_p.h" #include "usServiceFactory.h" #include "usModulePrivate.h" #include "usCoreModuleContext_p.h" #include US_BEGIN_NAMESPACE typedef ServiceRegistrationBasePrivate::MutexLocker MutexLocker; ServiceRegistrationBase::ServiceRegistrationBase() : d(0) { } ServiceRegistrationBase::ServiceRegistrationBase(const ServiceRegistrationBase& reg) : d(reg.d) { if (d) d->ref.Ref(); } ServiceRegistrationBase::ServiceRegistrationBase(ServiceRegistrationBasePrivate* registrationPrivate) : d(registrationPrivate) { if (d) d->ref.Ref(); } ServiceRegistrationBase::ServiceRegistrationBase(ModulePrivate* module, const InterfaceMap& service, const ServicePropertiesImpl& props) : d(new ServiceRegistrationBasePrivate(module, service, props)) { } -ServiceRegistrationBase::operator bool() const +ServiceRegistrationBase::operator bool_type() const { - return d != 0; + return d != NULL ? &ServiceRegistrationBase::d : NULL; } ServiceRegistrationBase& ServiceRegistrationBase::operator=(int null) { if (null == 0) { if (d && !d->ref.Deref()) { delete d; } d = 0; } return *this; } ServiceRegistrationBase::~ServiceRegistrationBase() { if (d && !d->ref.Deref()) delete d; } ServiceReferenceBase ServiceRegistrationBase::GetReference(const std::string& interfaceId) const { if (!d) throw std::logic_error("ServiceRegistrationBase object invalid"); if (!d->available) throw std::logic_error("Service is unregistered"); ServiceReferenceBase ref = d->reference; ref.SetInterfaceId(interfaceId); return ref; } void ServiceRegistrationBase::SetProperties(const ServiceProperties& props) { if (!d) throw std::logic_error("ServiceRegistrationBase object invalid"); MutexLocker lock(d->eventLock); ServiceListeners::ServiceListenerEntries before; // TBD, optimize the locking of services { //MutexLocker lock2(d->module->coreCtx->globalFwLock); if (d->available) { // NYI! Optimize the MODIFIED_ENDMATCH code int old_rank = 0; int new_rank = 0; std::vector classes; { MutexLocker lock3(d->propsLock); { const Any& any = d->properties.Value(ServiceConstants::SERVICE_RANKING()); if (any.Type() == typeid(int)) old_rank = any_cast(any); } d->module->coreCtx->listeners.GetMatchingServiceListeners(d->reference, before, false); classes = ref_any_cast >(d->properties.Value(ServiceConstants::OBJECTCLASS())); long int sid = any_cast(d->properties.Value(ServiceConstants::SERVICE_ID())); d->properties = ServiceRegistry::CreateServiceProperties(props, classes, false, false, sid); { const Any& any = d->properties.Value(ServiceConstants::SERVICE_RANKING()); if (any.Type() == typeid(int)) new_rank = any_cast(any); } } if (old_rank != new_rank) { d->module->coreCtx->services.UpdateServiceRegistrationOrder(*this, classes); } } else { throw std::logic_error("Service is unregistered"); } } ServiceListeners::ServiceListenerEntries matchingListeners; d->module->coreCtx->listeners.GetMatchingServiceListeners(d->reference, matchingListeners); d->module->coreCtx->listeners.ServiceChanged(matchingListeners, ServiceEvent(ServiceEvent::MODIFIED, d->reference), before); d->module->coreCtx->listeners.ServiceChanged(before, ServiceEvent(ServiceEvent::MODIFIED_ENDMATCH, d->reference)); } void ServiceRegistrationBase::Unregister() { if (!d) throw std::logic_error("ServiceRegistrationBase object invalid"); if (d->unregistering) return; // Silently ignore redundant unregistration. { MutexLocker lock(d->eventLock); if (d->unregistering) return; d->unregistering = true; if (d->available) { if (d->module) { d->module->coreCtx->services.RemoveServiceRegistration(*this); } } else { throw std::logic_error("Service is unregistered"); } } if (d->module) { ServiceListeners::ServiceListenerEntries listeners; d->module->coreCtx->listeners.GetMatchingServiceListeners(d->reference, listeners); d->module->coreCtx->listeners.ServiceChanged( listeners, ServiceEvent(ServiceEvent::UNREGISTERING, d->reference)); } { MutexLocker lock(d->eventLock); { MutexLocker lock2(d->propsLock); d->available = false; InterfaceMap::const_iterator factoryIter = d->service.find("org.cppmicroservices.factory"); if (d->module && factoryIter != d->service.end()) { ServiceFactory* serviceFactory = reinterpret_cast(factoryIter->second); ServiceRegistrationBasePrivate::ModuleToServicesMap::const_iterator end = d->prototypeServiceInstances.end(); // unget all prototype services for (ServiceRegistrationBasePrivate::ModuleToServicesMap::const_iterator i = d->prototypeServiceInstances.begin(); i != end; ++i) { for (std::list::const_iterator listIter = i->second.begin(); listIter != i->second.end(); ++listIter) { const InterfaceMap& service = *listIter; try { // NYI, don't call inside lock serviceFactory->UngetService(i->first, *this, service); } catch (const std::exception& /*ue*/) { US_WARN << "ServiceFactory UngetService implementation threw an exception"; } } } // unget module scope services ServiceRegistrationBasePrivate::ModuleToServiceMap::const_iterator moduleEnd = d->moduleServiceInstance.end(); for (ServiceRegistrationBasePrivate::ModuleToServiceMap::const_iterator i = d->moduleServiceInstance.begin(); i != moduleEnd; ++i) { try { // NYI, don't call inside lock serviceFactory->UngetService(i->first, *this, i->second); } catch (const std::exception& /*ue*/) { US_WARN << "ServiceFactory UngetService implementation threw an exception"; } } } d->module = 0; d->dependents.clear(); d->service.clear(); d->prototypeServiceInstances.clear(); d->moduleServiceInstance.clear(); // increment the reference count, since "d->reference" was used originally // to keep d alive. d->ref.Ref(); d->reference = 0; d->unregistering = false; } } } bool ServiceRegistrationBase::operator<(const ServiceRegistrationBase& o) const { if ((!d && !o.d) || !o.d) return false; if (!d) return true; return d->reference <(o.d->reference); } bool ServiceRegistrationBase::operator==(const ServiceRegistrationBase& registration) const { return d == registration.d; } ServiceRegistrationBase& ServiceRegistrationBase::operator=(const ServiceRegistrationBase& registration) { ServiceRegistrationBasePrivate* curr_d = d; d = registration.d; if (d) d->ref.Ref(); if (curr_d && !curr_d->ref.Deref()) delete curr_d; return *this; } US_END_NAMESPACE diff --git a/src/service/usServiceRegistrationBase.h b/src/service/usServiceRegistrationBase.h index f4dafda78f..0dacb93622 100644 --- a/src/service/usServiceRegistrationBase.h +++ b/src/service/usServiceRegistrationBase.h @@ -1,223 +1,228 @@ /*============================================================================= 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 USSERVICEREGISTRATIONBASE_H #define USSERVICEREGISTRATIONBASE_H #include "usServiceProperties.h" #include "usServiceReference.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4396) #endif US_BEGIN_NAMESPACE class ModulePrivate; class ServiceRegistrationBasePrivate; class ServicePropertiesImpl; /** * \ingroup MicroServices * * A registered service. * *

* The framework returns a ServiceRegistrationBase object when a * ModuleContext#RegisterService() method invocation is successful. * The ServiceRegistrationBase object is for the private use of the * registering module and should not be shared with other modules. *

* The ServiceRegistrationBase object may be used to update the * properties of the service or to unregister the service. * * \note This class is provided as public API for low-level service management only. * In almost all cases you should use the template ServiceRegistration instead. * * @see ModuleContext#RegisterService() * @remarks This class is thread safe. */ -class US_EXPORT ServiceRegistrationBase { +class US_EXPORT ServiceRegistrationBase +{ + +private: + + typedef ServiceRegistrationBasePrivate* ServiceRegistrationBase::*bool_type; public: ServiceRegistrationBase(const ServiceRegistrationBase& reg); /** * A boolean conversion operator converting this ServiceRegistrationBase object * to \c true if it is valid and to \c false otherwise. A SeriveRegistration * object is invalid if it was default-constructed or was invalidated by * assigning 0 to it. * * \see operator=(int) * * \return \c true if this ServiceRegistrationBase object is valid, \c false * otherwise. */ - operator bool() const; + operator bool_type() const; /** * Releases any resources held or locked by this * ServiceRegistrationBase and renders it invalid. * * \return This ServiceRegistrationBase object. */ ServiceRegistrationBase& operator=(int null); ~ServiceRegistrationBase(); /** * Returns a ServiceReference object for a service being * registered. *

* The ServiceReference object may be shared with other * modules. * * @throws std::logic_error If this * ServiceRegistrationBase object has already been * unregistered or if it is invalid. * @return ServiceReference object. */ ServiceReferenceBase GetReference(const std::string& interfaceId = std::string()) const; /** * Updates the properties associated with a service. * *

* The ServiceConstants#OBJECTCLASS and ServiceConstants#SERVICE_ID keys * cannot be modified by this method. These values are set by the framework * when the service is registered in the environment. * *

* The following steps are taken to modify service properties: *

    *
  1. The service's properties are replaced with the provided properties. *
  2. A service event of type ServiceEvent#MODIFIED is fired. *
* * @param properties The properties for this service. See {@link ServiceProperties} * for a list of standard service property keys. Changes should not * be made to this object after calling this method. To update the * service's properties this method should be called again. * * @throws std::logic_error If this ServiceRegistrationBase * object has already been unregistered or if it is invalid. * @throws std::invalid_argument If properties contains * case variants of the same key name. */ void SetProperties(const ServiceProperties& properties); /** * Unregisters a service. Remove a ServiceRegistrationBase object * from the framework service registry. All ServiceRegistrationBase * objects associated with this ServiceRegistrationBase object * can no longer be used to interact with the service once unregistration is * complete. * *

* The following steps are taken to unregister a service: *

    *
  1. The service is removed from the framework service registry so that * it can no longer be obtained. *
  2. A service event of type ServiceEvent#UNREGISTERING is fired * so that modules using this service can release their use of the service. * Once delivery of the service event is complete, the * ServiceRegistrationBase objects for the service may no longer be * used to get a service object for the service. *
  3. For each module whose use count for this service is greater than * zero:
    * The module's use count for this service is set to zero.
    * If the service was registered with a ServiceFactory object, the * ServiceFactory#UngetService method is called to release * the service object for the module. *
* * @throws std::logic_error If this * ServiceRegistrationBase object has already been * unregistered or if it is invalid. * @see ModuleContext#UngetService * @see ServiceFactory#UngetService */ void Unregister(); /** * Compare two ServiceRegistrationBase objects. * * If both ServiceRegistrationBase objects are valid, the comparison is done * using the underlying ServiceReference object. Otherwise, this ServiceRegistrationBase * object is less than the other object if and only if this object is invalid and * the other object is valid. * * @param o The ServiceRegistrationBase object to compare with. * @return \c true if this ServiceRegistrationBase object is less than the other object. */ bool operator<(const ServiceRegistrationBase& o) const; bool operator==(const ServiceRegistrationBase& registration) const; ServiceRegistrationBase& operator=(const ServiceRegistrationBase& registration); private: friend class ServiceRegistry; friend class ServiceReferenceBasePrivate; template friend class ServiceRegistration; US_HASH_FUNCTION_FRIEND(ServiceRegistrationBase); /** * Creates an invalid ServiceRegistrationBase object. You can use * this object in boolean expressions and it will evaluate to * false. */ ServiceRegistrationBase(); ServiceRegistrationBase(ServiceRegistrationBasePrivate* registrationPrivate); ServiceRegistrationBase(ModulePrivate* module, const InterfaceMap& service, const ServicePropertiesImpl& props); ServiceRegistrationBasePrivate* d; }; US_END_NAMESPACE #ifdef _MSC_VER #pragma warning(pop) #endif US_HASH_FUNCTION_NAMESPACE_BEGIN US_HASH_FUNCTION_BEGIN(US_PREPEND_NAMESPACE(ServiceRegistrationBase)) return US_HASH_FUNCTION(US_PREPEND_NAMESPACE(ServiceRegistrationBasePrivate)*, arg.d); US_HASH_FUNCTION_END US_HASH_FUNCTION_NAMESPACE_END inline std::ostream& operator<<(std::ostream& os, const US_PREPEND_NAMESPACE(ServiceRegistrationBase)& /*reg*/) { return os << "US_PREPEND_NAMESPACE(ServiceRegistrationBase) object"; } #endif // USSERVICEREGISTRATIONBASE_H