diff --git a/extension-framework/cpp-extension-lib/include/api/core/Resource.h b/extension-framework/cpp-extension-lib/include/api/core/Resource.h index 60766741cb..8cde8b52b8 100644 --- a/extension-framework/cpp-extension-lib/include/api/core/Resource.h +++ b/extension-framework/cpp-extension-lib/include/api/core/Resource.h @@ -154,12 +154,22 @@ void useControllerServiceClassDefinition(Fn&& fn) { const auto full_name = minifi::core::className(); std::vector class_properties = utils::toProperties(Class::Properties, string_vector_cache); + std::vector provided_interfaces; + if constexpr (requires { Class::ProvidedInterfaces; }) { + provided_interfaces.reserve(Class::ProvidedInterfaces.size()); + for (const auto& iface : Class::ProvidedInterfaces) { + provided_interfaces.push_back(utils::minifiStringView(iface.name)); + } + } MinifiControllerServiceClassDefinition definition{.full_name = utils::minifiStringView(full_name), .description = utils::minifiStringView(Class::Description), .class_properties_count = gsl::narrow(class_properties.size()), .class_properties_ptr = class_properties.data(), + .provided_interfaces_count = gsl::narrow(provided_interfaces.size()), + .provided_interfaces_ptr = provided_interfaces.data(), + .callbacks = MinifiControllerServiceCallbacks{ .create = [](MinifiControllerServiceMetadata metadata) -> MINIFI_OWNED void* { try { @@ -181,6 +191,20 @@ void useControllerServiceClassDefinition(Fn&& fn) { static_cast(self)->disable(); } catch (...) {} }, + .get_interface = [](void* self, MinifiStringView interface_name) -> void* { + try { + const std::string_view name_view{interface_name.data, interface_name.length}; + + if constexpr (requires { Class::ProvidedInterfaces; }) { + for (const auto& iface : Class::ProvidedInterfaces) { + if (iface.name == name_view) { + return iface.cast(self); + } + } + } + return nullptr; + } catch (...) { return nullptr; } + } }}; fn(definition); diff --git a/extensions/stable-api-sandbox/AnimalControllerServiceApis.h b/extensions/stable-api-sandbox/AnimalControllerServiceApis.h new file mode 100644 index 0000000000..eccf373c2d --- /dev/null +++ b/extensions/stable-api-sandbox/AnimalControllerServiceApis.h @@ -0,0 +1,35 @@ +/** + * 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. + */ + +#pragma once + +#include + +namespace org::apache::nifi::minifi::api_sandbox { +class NumberOfLegsControllerApi { + public: + virtual ~NumberOfLegsControllerApi() = default; + virtual uint8_t numberOfLegs() const = 0; +}; + +class CanFlyControllerApi { + public: + virtual ~CanFlyControllerApi() = default; + virtual bool canFly() const = 0; +}; + +} // namespace org::apache::nifi::minifi::api_sandbox diff --git a/extensions/stable-api-sandbox/AnimalControllerServices.cpp b/extensions/stable-api-sandbox/AnimalControllerServices.cpp new file mode 100644 index 0000000000..a8b1efe9d4 --- /dev/null +++ b/extensions/stable-api-sandbox/AnimalControllerServices.cpp @@ -0,0 +1,30 @@ +/** + * 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. + */ + +#include "AnimalControllerServices.h" + +#include "api/utils/ProcessorConfigUtils.h" +namespace org::apache::nifi::minifi::api_sandbox { + +MinifiStatus DogController::enableImpl(api::core::ControllerServiceContext& ctx) { + this->has_jetpack_ = ctx.getProperty(HasJetpack) | minifi::utils::andThen(parsing::parseBool) | + minifi::utils::orThrow(fmt::format("Expected parsable bool from \"{}\"", HasJetpack.name)); + + return MINIFI_STATUS_SUCCESS; +} + +} // namespace org::apache::nifi::minifi::api_sandbox diff --git a/extensions/stable-api-sandbox/AnimalControllerServices.h b/extensions/stable-api-sandbox/AnimalControllerServices.h new file mode 100644 index 0000000000..1ab2933969 --- /dev/null +++ b/extensions/stable-api-sandbox/AnimalControllerServices.h @@ -0,0 +1,67 @@ +/** + * 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. + */ + +#pragma once + +#include "AnimalControllerServiceApis.h" +#include "api/core/ControllerServiceImpl.h" +#include "api/utils/Export.h" +#include "core/PropertyDefinitionBuilder.h" +#include "minifi-cpp/core/ProvidedControllerServiceInterface.h" + +namespace org::apache::nifi::minifi::api_sandbox { +class DogController : public api::core::ControllerServiceImpl, public CanFlyControllerApi, public NumberOfLegsControllerApi { + public: + EXTENSIONAPI static constexpr const char* Description = "Test DogController"; + EXTENSIONAPI static constexpr auto HasJetpack = core::PropertyDefinitionBuilder<>::createProperty("Has Jetpack") + .withDescription("Whether or not the dog has a jetpack") + .withDefaultValue("false") + .withValidator(core::StandardPropertyValidators::BOOLEAN_VALIDATOR) + .build(); + + EXTENSIONAPI static constexpr auto Properties = std::to_array({ + HasJetpack, + }); + EXTENSIONAPI static constexpr auto ProvidedInterfaces = + std::to_array({core::createProvidedInterface(), + core::createProvidedInterface()}); + + using ControllerServiceImpl::ControllerServiceImpl; + MinifiStatus enableImpl(api::core::ControllerServiceContext& ctx) override; + + uint8_t numberOfLegs() const override { return 4; } + bool canFly() const override { return has_jetpack_; } + + private: + bool has_jetpack_ = false; +}; + +class DuckController : public api::core::ControllerServiceImpl, public CanFlyControllerApi, public NumberOfLegsControllerApi { + public: + EXTENSIONAPI static constexpr const char* Description = "Test DuckController"; + + EXTENSIONAPI static constexpr std::array Properties = {}; + EXTENSIONAPI static constexpr auto ProvidedInterfaces = + std::to_array({core::createProvidedInterface(), + core::createProvidedInterface()}); + using ControllerServiceImpl::ControllerServiceImpl; + MinifiStatus enableImpl(api::core::ControllerServiceContext&) override { return MINIFI_STATUS_SUCCESS; } + + uint8_t numberOfLegs() const override { return 2; } + bool canFly() const override { return true; } +}; +} // namespace org::apache::nifi::minifi::api_sandbox diff --git a/extensions/stable-api-sandbox/CMakeLists.txt b/extensions/stable-api-sandbox/CMakeLists.txt new file mode 100644 index 0000000000..8afab9a32a --- /dev/null +++ b/extensions/stable-api-sandbox/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# 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. +# + +if (NOT ENABLE_TEST_PROCESSORS) + return() +endif () + +include(${CMAKE_SOURCE_DIR}/extensions/ExtensionHeader.txt) +file(GLOB SOURCES "*.cpp") + +add_minifi_library(minifi-stable-api-sandbox SHARED ${SOURCES}) + +target_link_libraries(minifi-stable-api-sandbox minifi-cpp-extension-lib) + +register_c_api_extension(minifi-stable-api-sandbox "Stable API Sandbox" SANDBOX-EXTENSION "Stable API Sandbox" "extensions/stable-api-sandbox/tests") diff --git a/extensions/stable-api-sandbox/ExtensionInitializer.cpp b/extensions/stable-api-sandbox/ExtensionInitializer.cpp new file mode 100644 index 0000000000..52ed521925 --- /dev/null +++ b/extensions/stable-api-sandbox/ExtensionInitializer.cpp @@ -0,0 +1,38 @@ +/** + * 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. + */ + +#include "AnimalControllerServices.h" +#include "ZooProcessor.h" +#include "api/core/Resource.h" +#include "api/utils/minifi-c-utils.h" + +#define MKSOC(x) #x +#define MAKESTRING(x) MKSOC(x) // NOLINT(cppcoreguidelines-macro-usage) + +namespace minifi = org::apache::nifi::minifi; + +CEXTENSIONAPI const uint32_t MinifiApiVersion = MINIFI_API_VERSION; + +CEXTENSIONAPI void MinifiInitExtension(MinifiExtensionContext* extension_context) { + const MinifiExtensionDefinition extension_definition{.name = minifi::api::utils::minifiStringView(MAKESTRING(EXTENSION_NAME)), + .version = minifi::api::utils::minifiStringView(MAKESTRING(EXTENSION_VERSION)), + .deinit = nullptr, + .user_data = nullptr}; + auto* extension = MinifiRegisterExtension(extension_context, &extension_definition); + minifi::api::core::registerProcessors(extension); + minifi::api::core::registerControllerServices(extension); +} diff --git a/extensions/stable-api-sandbox/ZooProcessor.cpp b/extensions/stable-api-sandbox/ZooProcessor.cpp new file mode 100644 index 0000000000..e340a1a508 --- /dev/null +++ b/extensions/stable-api-sandbox/ZooProcessor.cpp @@ -0,0 +1,46 @@ +/** + * 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. + */ + +#include "ZooProcessor.h" + +#include "AnimalControllerServices.h" +#include "api/core/ProcessContext.h" + +namespace org::apache::nifi::minifi::api_sandbox { + +MinifiStatus ZooProcessor::onTriggerImpl(api::core::ProcessContext& process_context, api::core::ProcessSession&) { + if (const auto can_fly_opaque = process_context.getControllerService(CanFlyService)) { + if (*can_fly_opaque) { + const auto can_fly_controller_name = process_context.getProperty(CanFlyService, nullptr) | utils::orThrow("Should be here"); + const CanFlyControllerApi* can_fly = reinterpret_cast(*can_fly_opaque); + logger_->log_critical("Can {} fly? {}", can_fly_controller_name, can_fly->canFly()); + } + } + if (const auto num_of_legs_opaque = process_context.getControllerService(NumberOfLegsService)) { + if (*num_of_legs_opaque) { + const auto num_of_legs_name = process_context.getProperty(NumberOfLegsService, nullptr) | utils::orThrow("Should be here"); + const NumberOfLegsControllerApi* num_legs = reinterpret_cast(*num_of_legs_opaque); + logger_->log_critical("{} has {} legs", num_of_legs_name, num_legs->numberOfLegs()); + } + } + return MINIFI_STATUS_SUCCESS; +} + +MinifiStatus ZooProcessor::onScheduleImpl(api::core::ProcessContext& process_context) { + return ProcessorImpl::onScheduleImpl(process_context); +} +} // namespace org::apache::nifi::minifi::api_sandbox diff --git a/extensions/stable-api-sandbox/ZooProcessor.h b/extensions/stable-api-sandbox/ZooProcessor.h new file mode 100644 index 0000000000..98ac0b8f59 --- /dev/null +++ b/extensions/stable-api-sandbox/ZooProcessor.h @@ -0,0 +1,63 @@ +/** + * 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. + */ + +#pragma once + +#include "AnimalControllerServiceApis.h" +#include "api/core/ProcessorImpl.h" +#include "api/utils/Export.h" +#include "core/PropertyDefinitionBuilder.h" +#include "minifi-cpp/core/Annotation.h" + +namespace org::apache::nifi::minifi::api_sandbox { + +class ZooProcessor : public api::core::ProcessorImpl { + public: + EXTENSIONAPI static constexpr const char* Description = "Test ZooProcessor"; + + EXTENSIONAPI static constexpr auto CanFlyService = core::PropertyDefinitionBuilder<>::createProperty("Can fly service") + .withDescription("Test CanFlyService") + .isRequired(true) + .withAllowedTypes() + .build(); + + EXTENSIONAPI static constexpr auto NumberOfLegsService = core::PropertyDefinitionBuilder<>::createProperty("Number of legs service") + .withDescription("Test NumberOfLegsService") + .isRequired(true) + .withAllowedTypes() + .build(); + + EXTENSIONAPI static constexpr auto Properties = std::to_array({ + CanFlyService, + NumberOfLegsService, + }); + EXTENSIONAPI static constexpr auto Success = core::RelationshipDefinition{"success", "success"}; + EXTENSIONAPI static constexpr auto Failure = core::RelationshipDefinition{"failure", "failure"}; + EXTENSIONAPI static constexpr auto Relationships = std::array{Success, Failure}; + EXTENSIONAPI static constexpr bool SupportsDynamicProperties = false; + EXTENSIONAPI static constexpr bool SupportsDynamicRelationships = false; + EXTENSIONAPI static constexpr core::annotation::Input InputRequirement = core::annotation::Input::INPUT_FORBIDDEN; + EXTENSIONAPI static constexpr bool IsSingleThreaded = true; + + using ProcessorImpl::ProcessorImpl; + + protected: + MinifiStatus onTriggerImpl(api::core::ProcessContext&, api::core::ProcessSession&) override; + MinifiStatus onScheduleImpl(api::core::ProcessContext&) override; +}; + +} // namespace org::apache::nifi::minifi::api_sandbox diff --git a/extensions/stable-api-sandbox/tests/CMakeLists.txt b/extensions/stable-api-sandbox/tests/CMakeLists.txt new file mode 100644 index 0000000000..225e7acb6b --- /dev/null +++ b/extensions/stable-api-sandbox/tests/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# 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. +# + +file(GLOB SOURCES "*.cpp") + +SET(EXTENSIONS_TEST_COUNT 0) +FOREACH (testfile ${SOURCES}) + get_filename_component(testfilename "${testfile}" NAME_WE) + add_minifi_executable(${testfilename} "${testfile}") + target_include_directories(${testfilename} BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/libminifi/include") + target_include_directories(${testfilename} BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/extensions/stable-api-sandbox") + createTests(${testfilename}) + target_link_libraries(${testfilename} Catch2WithMain) + target_link_libraries(${testfilename} minifi-stable-api-sandbox) + target_link_libraries(${testfilename} libminifi-c-unittest) + + MATH(EXPR EXTENSIONS_TEST_COUNT "${EXTENSIONS_TEST_COUNT}+1") + add_test(NAME ${testfilename} COMMAND ${testfilename} WORKING_DIRECTORY ${TEST_DIR}) +ENDFOREACH () diff --git a/extensions/stable-api-sandbox/tests/ZooTests.cpp b/extensions/stable-api-sandbox/tests/ZooTests.cpp new file mode 100644 index 0000000000..13329cde7d --- /dev/null +++ b/extensions/stable-api-sandbox/tests/ZooTests.cpp @@ -0,0 +1,71 @@ +/** + * + * 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. + */ + +#include "AnimalControllerServices.h" +#include "CProcessorTestUtils.h" +#include "ZooProcessor.h" +#include "api/core/Resource.h" +#include "minifi-cpp/core/FlowFile.h" +#include "unit/Catch.h" +#include "unit/SingleProcessorTestController.h" +#include "unit/TestBase.h" +#include "unit/TestUtils.h" +#include "utils/CProcessor.h" + +namespace org::apache::nifi::minifi::api_sandbox::test { +TEST_CASE("ZooTest") { + minifi::test::SingleProcessorTestController controller(minifi::test::utils::make_custom_c_processor( + core::ProcessorMetadata{utils::Identifier{}, "ZooProcessor", logging::LoggerFactory::getLogger()})); + const auto dog_with_jetpack = minifi::test::utils::make_custom_c_controller_service(core::ControllerServiceMetadata{ + utils::Identifier{}, + "DogController", + logging::LoggerFactory::getLogger()}); + auto dog_with_jetpack_node = controller.plan->addController("dog_with_jetpack", dog_with_jetpack); + CHECK(dog_with_jetpack->setProperty(DogController::HasJetpack.name, "true")); + + const auto duck = minifi::test::utils::make_custom_c_controller_service(core::ControllerServiceMetadata{utils::Identifier{}, + "DuckController", + logging::LoggerFactory::getLogger()}); + auto duck_node = controller.plan->addController("duck", duck); + + { + CHECK(controller.getProcessor()->setProperty(ZooProcessor::CanFlyService.name, "dog_with_jetpack")); + CHECK(controller.getProcessor()->setProperty(ZooProcessor::NumberOfLegsService.name, "duck")); + controller.trigger(); + CHECK(LogTestController::getInstance() + .contains("[org::apache::nifi::minifi::api_sandbox::ZooProcessor] [critical] Can dog_with_jetpack fly? true")); + CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::api_sandbox::ZooProcessor] [critical] duck has 2 legs")); + } + { + LogTestController::getInstance().clear(); + CHECK(controller.getProcessor()->setProperty(ZooProcessor::CanFlyService.name, "duck")); + CHECK(controller.getProcessor()->setProperty(ZooProcessor::NumberOfLegsService.name, "dog_with_jetpack")); + controller.trigger(); + CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::api_sandbox::ZooProcessor] [critical] Can duck fly? true")); + CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::api_sandbox::ZooProcessor] [critical] dog_with_jetpack has 4 legs")); + } + { + LogTestController::getInstance().clear(); + CHECK(controller.getProcessor()->setProperty(ZooProcessor::CanFlyService.name, "duck")); + CHECK(controller.getProcessor()->setProperty(ZooProcessor::NumberOfLegsService.name, "invalid")); + controller.trigger(); + CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::api_sandbox::ZooProcessor] [critical] Can duck fly? true")); + } +} + +} // namespace org::apache::nifi::minifi::api_sandbox::test diff --git a/libminifi/src/minifi-c.cpp b/libminifi/src/minifi-c.cpp index ea50f1bf7a..7762313824 100644 --- a/libminifi/src/minifi-c.cpp +++ b/libminifi/src/minifi-c.cpp @@ -277,15 +277,23 @@ void useCControllerServiceClassDescription(const MinifiControllerServiceClassDef auto name_segments = minifi::utils::string::split(toStringView(class_description.full_name), "::"); gsl_Assert(!name_segments.empty()); - minifi::ClassDescription description{ - .type_ = minifi::ResourceType::ControllerService, - .short_name_ = name_segments.back(), - .full_name_ = minifi::utils::string::join(".", name_segments), - .description_ = toString(class_description.description), - .class_properties_ = properties, + std::vector implements_apis; + implements_apis.reserve(class_description.provided_interfaces_count); + for (size_t i = 0; i < class_description.provided_interfaces_count; ++i) { + auto api_segments = string::split(toStringView(class_description.provided_interfaces_ptr[i]), "::"); + implements_apis.push_back(core::ControllerServiceType::minifiSystemControllerServiceType(string::join(".", api_segments))); + } + + ClassDescription description{ + .type_ = ResourceType::ControllerService, + .short_name_ = name_segments.back(), + .full_name_ = string::join(".", name_segments), + .description_ = toString(class_description.description), + .class_properties_ = properties, + .api_implementations = implements_apis, }; - minifi::utils::CControllerServiceClassDescription c_class_description{ + CControllerServiceClassDescription c_class_description{ .full_name = toString(class_description.full_name), .class_properties = properties, .callbacks = class_description.callbacks @@ -613,6 +621,14 @@ MinifiStatus MinifiProcessContextGetControllerServiceFromProperty( *controller_service_out = static_cast(c_controller_service->getImpl()); return MINIFI_STATUS_SUCCESS; } + if (class_description.callbacks.get_interface) { + const auto interface_res = class_description.callbacks.get_interface(c_controller_service->getImpl(), controller_service_type); + if (!interface_res) { + return MINIFI_STATUS_VALIDATION_FAILED; + } + *controller_service_out = static_cast(interface_res); + return MINIFI_STATUS_SUCCESS; + } } return MINIFI_STATUS_VALIDATION_FAILED; } diff --git a/minifi-api/common/include/minifi-cpp/core/ProvidedControllerServiceInterface.h b/minifi-api/common/include/minifi-cpp/core/ProvidedControllerServiceInterface.h new file mode 100644 index 0000000000..0f28ff05a4 --- /dev/null +++ b/minifi-api/common/include/minifi-cpp/core/ProvidedControllerServiceInterface.h @@ -0,0 +1,34 @@ +/** + * 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. + */ +#pragma once + +#include +#include "core/ClassName.h" + +namespace org::apache::nifi::minifi::core { +struct ProvidedInterface { + std::string_view name; + void* (*cast)(void* instance); +}; + +template +constexpr ProvidedInterface createProvidedInterface() { + return ProvidedInterface{className(), [](void* instance) -> void* { + return static_cast(static_cast(instance)); + }}; +} +} // namespace org::apache::nifi::minifi::core diff --git a/minifi-api/include/minifi-c/minifi-c.h b/minifi-api/include/minifi-c/minifi-c.h index b54375670f..54aa5fba00 100644 --- a/minifi-api/include/minifi-c/minifi-c.h +++ b/minifi-api/include/minifi-c/minifi-c.h @@ -186,6 +186,7 @@ typedef struct MinifiControllerServiceCallbacks { void(*destroy)(MINIFI_OWNED void*); MinifiStatus(*enable)(void*, MinifiControllerServiceContext*); void(*disable)(void*); + void* (*get_interface)(void* ctx, MinifiStringView interface_type); } MinifiControllerServiceCallbacks; typedef struct MinifiProcessorClassDefinition { @@ -212,6 +213,8 @@ typedef struct MinifiControllerServiceClassDefinition { MinifiStringView description; size_t class_properties_count; const MinifiPropertyDefinition* class_properties_ptr; + size_t provided_interfaces_count; + const MinifiStringView* provided_interfaces_ptr; MinifiControllerServiceCallbacks callbacks; } MinifiControllerServiceClassDefinition; diff --git a/minifi-api/include/minifi-cpp/core/ControllerServiceType.h b/minifi-api/include/minifi-cpp/core/ControllerServiceType.h index 6d5b39de3d..f45a8e3fb4 100644 --- a/minifi-api/include/minifi-cpp/core/ControllerServiceType.h +++ b/minifi-api/include/minifi-cpp/core/ControllerServiceType.h @@ -1,5 +1,5 @@ /** -* Licensed to the Apache Software Foundation (ASF) under one or more + * 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 @@ -17,6 +17,7 @@ #pragma once #include + #include "minifi-cpp/core/ControllerServiceTypeDefinition.h" namespace org::apache::nifi::minifi::core { @@ -27,9 +28,19 @@ struct ControllerServiceType { std::string type; ControllerServiceType(const ControllerServiceTypeDefinition& definition) // NOLINT(runtime/explicit) - : artifact(definition.artifact), - group(definition.group), - type(definition.type) {} + : artifact(definition.artifact), + group(definition.group), + type(definition.type) {} + + static ControllerServiceType minifiSystemControllerServiceType(std::string type) { + return ControllerServiceType("minifi-system", "org.apache.nifi.minifi", std::move(type)); + } + + private: + ControllerServiceType(std::string artifact, std::string group, std::string type) + : artifact(std::move(artifact)), + group(std::move(group)), + type(std::move(type)) {} }; } // namespace org::apache::nifi::minifi::core