blob: 6c17493ad1710a737ed284e0c16a326616963fa4 [file] [log] [blame]
/**
* 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_ */