| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef LIBMINIFI_INCLUDE_CORE_CLASSLOADER_H_ |
| #define LIBMINIFI_INCLUDE_CORE_CLASSLOADER_H_ |
| |
| #include <mutex> |
| #include <vector> |
| #include <map> |
| #include "utils/StringUtils.h" |
| #include <dlfcn.h> |
| #include "core/Core.h" |
| #include "io/DataStream.h" |
| |
| namespace org { |
| namespace apache { |
| namespace nifi { |
| namespace minifi { |
| namespace core { |
| |
| #define RESOURCE_FAILURE -1 |
| |
| #define RESOURCE_SUCCESS 1 |
| |
| /** |
| * Factory that is used as an interface for |
| * creating processors from shared objects. |
| */ |
| class ObjectFactory { |
| |
| public: |
| /** |
| * Virtual destructor. |
| */ |
| virtual ~ObjectFactory() { |
| |
| } |
| |
| /** |
| * Create a shared pointer to a new processor. |
| */ |
| virtual std::shared_ptr<CoreComponent> create(const std::string &name) { |
| return nullptr; |
| } |
| |
| /** |
| * Create a shared pointer to a new processor. |
| */ |
| virtual CoreComponent *createRaw(const std::string &name) { |
| return nullptr; |
| } |
| |
| /** |
| * Create a shared pointer to a new processor. |
| */ |
| virtual std::shared_ptr<CoreComponent> create(const std::string &name, uuid_t uuid) { |
| return nullptr; |
| } |
| |
| /** |
| * Create a shared pointer to a new processor. |
| */ |
| virtual CoreComponent* createRaw(const std::string &name, uuid_t uuid) { |
| return nullptr; |
| } |
| |
| /** |
| * Gets the name of the object. |
| * @return class name of processor |
| */ |
| virtual std::string getName() = 0; |
| |
| virtual std::string getClassName() = 0; |
| /** |
| * Gets the class name for the object |
| * @return class name for the processor. |
| */ |
| virtual std::vector<std::string> getClassNames() = 0; |
| |
| virtual std::unique_ptr<ObjectFactory> assign(const std::string &class_name) = 0; |
| |
| }; |
| |
| /** |
| * Factory that is used as an interface for |
| * creating processors from shared objects. |
| */ |
| template<class T> |
| class DefautObjectFactory : public ObjectFactory { |
| |
| public: |
| |
| DefautObjectFactory() { |
| className = core::getClassName<T>(); |
| } |
| /** |
| * Virtual destructor. |
| */ |
| virtual ~DefautObjectFactory() { |
| |
| } |
| |
| /** |
| * Create a shared pointer to a new processor. |
| */ |
| virtual std::shared_ptr<CoreComponent> create(const std::string &name) { |
| std::shared_ptr<T> ptr = std::make_shared<T>(name); |
| return std::static_pointer_cast<CoreComponent>(ptr); |
| } |
| |
| /** |
| * Create a shared pointer to a new processor. |
| */ |
| virtual std::shared_ptr<CoreComponent> create(const std::string &name, uuid_t uuid) { |
| std::shared_ptr<T> ptr = std::make_shared<T>(name, uuid); |
| return std::static_pointer_cast<CoreComponent>(ptr); |
| } |
| |
| /** |
| * Create a shared pointer to a new processor. |
| */ |
| virtual CoreComponent* createRaw(const std::string &name) { |
| T *ptr = new T(name); |
| return dynamic_cast<CoreComponent*>(ptr); |
| } |
| |
| /** |
| * Create a shared pointer to a new processor. |
| */ |
| virtual CoreComponent* createRaw(const std::string &name, uuid_t uuid) { |
| T *ptr = new T(name, uuid); |
| return dynamic_cast<CoreComponent*>(ptr); |
| } |
| |
| /** |
| * Gets the name of the object. |
| * @return class name of processor |
| */ |
| virtual std::string getName() { |
| return className; |
| } |
| |
| /** |
| * Gets the class name for the object |
| * @return class name for the processor. |
| */ |
| virtual std::string getClassName() { |
| return className; |
| } |
| |
| virtual std::vector<std::string> getClassNames() { |
| std::vector<std::string> container; |
| container.push_back(className); |
| return container; |
| } |
| |
| virtual std::unique_ptr<ObjectFactory> assign(const std::string &class_name) { |
| return nullptr; |
| } |
| |
| protected: |
| std::string className; |
| |
| }; |
| |
| /** |
| * Function that is used to create the |
| * processor factory from the shared object. |
| */ |
| typedef ObjectFactory* createFactory(); |
| |
| /** |
| * Processor class loader that accepts |
| * a variety of mechanisms to load in shared |
| * objects. |
| */ |
| class ClassLoader { |
| |
| public: |
| |
| static ClassLoader &getDefaultClassLoader(); |
| |
| /** |
| * Constructor. |
| */ |
| ClassLoader(); |
| |
| ~ClassLoader() { |
| loaded_factories_.clear(); |
| for (auto ptr : dl_handles_) { |
| dlclose(ptr); |
| } |
| } |
| |
| /** |
| * Register the file system resource. |
| * This will attempt to load objects within this resource. |
| * @return return code: RESOURCE_FAILURE or RESOURCE_SUCCESS |
| */ |
| uint16_t registerResource(const std::string &resource, const std::string &resourceName); |
| |
| /** |
| * Register a class with the give ProcessorFactory |
| */ |
| void registerClass(const std::string &name, std::unique_ptr<ObjectFactory> factory) { |
| if (loaded_factories_.find(name) != loaded_factories_.end()) { |
| return; |
| } |
| |
| std::lock_guard<std::mutex> lock(internal_mutex_); |
| |
| loaded_factories_.insert(std::make_pair(name, std::move(factory))); |
| } |
| |
| std::vector<std::string> getGroups() { |
| std::vector<std::string> groups; |
| std::lock_guard<std::mutex> lock(internal_mutex_); |
| for (auto & resource : loaded_factories_) { |
| groups.push_back(resource.first); |
| } |
| return groups; |
| } |
| |
| std::vector<std::string> getClasses() { |
| std::vector<std::string> groups; |
| std::lock_guard<std::mutex> lock(internal_mutex_); |
| for (auto & resource : loaded_factories_) { |
| if (nullptr != resource.second) { |
| auto classes = resource.second->getClassNames(); |
| groups.insert(groups.end(), classes.begin(), classes.end()); |
| }else{ |
| } |
| } |
| return groups; |
| } |
| |
| /** |
| * Instantiate object based on class_name |
| * @param class_name class to create |
| * @param uuid uuid of object |
| * @return nullptr or object created from class_name definition. |
| */ |
| template<class T = CoreComponent> |
| std::shared_ptr<T> instantiate(const std::string &class_name, const std::string &name); |
| |
| /** |
| * Instantiate object based on class_name |
| * @param class_name class to create |
| * @param uuid uuid of object |
| * @return nullptr or object created from class_name definition. |
| */ |
| template<class T = CoreComponent> |
| std::shared_ptr<T> instantiate(const std::string &class_name, uuid_t uuid); |
| |
| /** |
| * Instantiate object based on class_name |
| * @param class_name class to create |
| * @param uuid uuid of object |
| * @return nullptr or object created from class_name definition. |
| */ |
| template<class T = CoreComponent> |
| T *instantiateRaw(const std::string &class_name, const std::string &name); |
| |
| /** |
| * Instantiate object based on class_name |
| * @param class_name class to create |
| * @param uuid uuid of object |
| * @return nullptr or object created from class_name definition. |
| */ |
| template<class T = CoreComponent> |
| T *instantiateRaw(const std::string &class_name, uuid_t uuid); |
| |
| protected: |
| |
| std::map<std::string, std::unique_ptr<ObjectFactory>> loaded_factories_; |
| |
| std::mutex internal_mutex_; |
| |
| std::vector<void *> dl_handles_; |
| }; |
| |
| template<class T> |
| std::shared_ptr<T> ClassLoader::instantiate(const std::string &class_name, const std::string &name) { |
| std::lock_guard<std::mutex> lock(internal_mutex_); |
| auto factory_entry = loaded_factories_.find(class_name); |
| if (factory_entry != loaded_factories_.end()) { |
| auto obj = factory_entry->second->create(name); |
| return std::dynamic_pointer_cast<T>(obj); |
| } else { |
| return nullptr; |
| } |
| } |
| |
| template<class T> |
| std::shared_ptr<T> ClassLoader::instantiate(const std::string &class_name, uuid_t uuid) { |
| std::lock_guard<std::mutex> lock(internal_mutex_); |
| auto factory_entry = loaded_factories_.find(class_name); |
| if (factory_entry != loaded_factories_.end()) { |
| auto obj = factory_entry->second->create(class_name, uuid); |
| return std::dynamic_pointer_cast<T>(obj); |
| } else { |
| return nullptr; |
| } |
| } |
| |
| template<class T> |
| T *ClassLoader::instantiateRaw(const std::string &class_name, const std::string &name) { |
| std::lock_guard<std::mutex> lock(internal_mutex_); |
| auto factory_entry = loaded_factories_.find(class_name); |
| if (factory_entry != loaded_factories_.end()) { |
| auto obj = factory_entry->second->createRaw(name); |
| return dynamic_cast<T*>(obj); |
| } else { |
| return nullptr; |
| } |
| } |
| |
| template<class T> |
| T *ClassLoader::instantiateRaw(const std::string &class_name, uuid_t uuid) { |
| std::lock_guard<std::mutex> lock(internal_mutex_); |
| auto factory_entry = loaded_factories_.find(class_name); |
| if (factory_entry != loaded_factories_.end()) { |
| auto obj = factory_entry->second->createRaw(class_name, uuid); |
| return dynamic_cast<T*>(obj); |
| } else { |
| return nullptr; |
| } |
| } |
| |
| }/* namespace core */ |
| } /* namespace minifi */ |
| } /* namespace nifi */ |
| } /* namespace apache */ |
| } /* namespace org */ |
| |
| #endif /* LIBMINIFI_INCLUDE_CORE_CLASSLOADER_H_ */ |