diff --git a/components/org.wso2.carbon.identity.tenant.resource.manager/pom.xml b/components/org.wso2.carbon.identity.tenant.resource.manager/pom.xml index d384a3cfbc..660c2f4794 100644 --- a/components/org.wso2.carbon.identity.tenant.resource.manager/pom.xml +++ b/components/org.wso2.carbon.identity.tenant.resource.manager/pom.xml @@ -98,6 +98,7 @@ org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}", org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", org.wso2.carbon.context; version="${carbon.kernel.package.import.version.range}", + org.wso2.carbon.core; version="${carbon.kernel.package.import.version.range}", org.wso2.carbon.core.util; version="${carbon.kernel.package.import.version.range}", org.wso2.carbon.databridge.commons; version="${carbon.analytics.common.version.range}", org.wso2.carbon.event.publisher.core; version="${carbon.analytics.common.version.range}", diff --git a/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/TenantAwareAxis2ConfigurationContextObserver.java b/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/TenantAwareAxis2ConfigurationContextObserver.java index 5010aa717a..a178ebb97b 100644 --- a/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/TenantAwareAxis2ConfigurationContextObserver.java +++ b/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/TenantAwareAxis2ConfigurationContextObserver.java @@ -24,22 +24,14 @@ import org.wso2.carbon.event.publisher.core.config.EventPublisherConfiguration; import org.wso2.carbon.event.stream.core.EventStreamConfiguration; import org.wso2.carbon.event.stream.core.exception.EventStreamConfigurationException; -import org.wso2.carbon.identity.configuration.mgt.core.constant.ConfigurationConstants; -import org.wso2.carbon.identity.configuration.mgt.core.exception.ConfigurationManagementException; -import org.wso2.carbon.identity.configuration.mgt.core.model.Resource; -import org.wso2.carbon.identity.configuration.mgt.core.model.ResourceFile; import org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants; -import org.wso2.carbon.identity.tenant.resource.manager.exception.TenantResourceManagementException; import org.wso2.carbon.identity.tenant.resource.manager.internal.TenantResourceManagerDataHolder; import org.wso2.carbon.identity.tenant.resource.manager.util.ResourceUtils; import org.wso2.carbon.utils.AbstractAxis2ConfigurationContextObserver; import java.util.List; -import static org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants.ErrorMessages.ERROR_CODE_ERROR_WHEN_ADDING_EVENT_PUBLISHER_CONFIGURATION; import static org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants.ErrorMessages.ERROR_CODE_ERROR_WHEN_CREATING_TENANT_EVENT_STREAM_CONFIGURATION; -import static org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants.ErrorMessages.ERROR_CODE_ERROR_WHEN_FETCHING_TENANT_SPECIFIC_PUBLISHER_FILES; -import static org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants.PUBLISHER; import static org.wso2.carbon.identity.tenant.resource.manager.util.ResourceUtils.populateMessageWithData; /** @@ -81,7 +73,7 @@ private void loadEventStreamAndPublisherConfigurations(int tenantId) { try { ResourceUtils.startTenantFlow(tenantId); loadTenantEventStreams(eventStreamConfigurationList); - loadTenantPublisherConfigurationFromConfigStore(); + ResourceUtils.loadTenantPublisherConfigurationFromConfigStore(); if (activeEventPublisherConfigurations != null) { ResourceUtils.loadTenantPublisherConfigurationFromSuperTenantConfig(activeEventPublisherConfigurations); @@ -91,52 +83,6 @@ private void loadEventStreamAndPublisherConfigurations(int tenantId) { } } - /** - * This method loads publisher configurations tenant wise by fetching them from configuration store. - */ - private void loadTenantPublisherConfigurationFromConfigStore() { - - try { - List resourcesByTypePublisher = TenantResourceManagerDataHolder.getInstance() - .getConfigurationManager().getResourcesByType(PUBLISHER).getResources(); - for (Resource resource : resourcesByTypePublisher) { - if (!resource.getFiles().isEmpty()) { - ResourceFile tenantSpecificPublisherFile = resource.getFiles().get(0); - if (tenantSpecificPublisherFile != null) { - if (log.isDebugEnabled()) { - log.debug("File for publisher name: " + tenantSpecificPublisherFile.getName() - + " is available in the configuration store."); - } - TenantResourceManagerDataHolder.getInstance().getResourceManager() - .addEventPublisherConfiguration(tenantSpecificPublisherFile); - } - } - } - } catch (ConfigurationManagementException e) { - if (e.getErrorCode() - .equals(ConfigurationConstants.ErrorMessages.ERROR_CODE_FEATURE_NOT_ENABLED.getCode())) { - log.warn("Configuration store is disabled. Super tenant configuration will be used for the tenant " - + "domain: " + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()); - } else if (e.getErrorCode() - .equals(ConfigurationConstants.ErrorMessages.ERROR_CODE_RESOURCES_DOES_NOT_EXISTS.getCode())) { - log.warn("Configuration store does not contain any resources under resource type publisher. Super " - + "tenant configurations will be used for the tenant domain: " + PrivilegedCarbonContext - .getThreadLocalCarbonContext().getTenantDomain()); - } else if (e.getErrorCode() - .equals(ConfigurationConstants.ErrorMessages.ERROR_CODE_RESOURCE_TYPE_DOES_NOT_EXISTS.getCode())) { - log.warn("Configuration store does not contain publisher resource type. Super " - + "tenant configurations will be used for the tenant domain: " + PrivilegedCarbonContext - .getThreadLocalCarbonContext().getTenantDomain()); - } else { - log.error(populateMessageWithData(ERROR_CODE_ERROR_WHEN_FETCHING_TENANT_SPECIFIC_PUBLISHER_FILES, - PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()), e); - } - } catch (TenantResourceManagementException e) { - log.error(populateMessageWithData(ERROR_CODE_ERROR_WHEN_ADDING_EVENT_PUBLISHER_CONFIGURATION, - PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()), e); - } - } - /** * This method returns super tenant event stream configurations. * diff --git a/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/internal/TenantResourceManagementServerStartupObserver.java b/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/internal/TenantResourceManagementServerStartupObserver.java new file mode 100644 index 0000000000..37eb76d22f --- /dev/null +++ b/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/internal/TenantResourceManagementServerStartupObserver.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. 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. + */ + +package org.wso2.carbon.identity.tenant.resource.manager.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.core.ServerStartupObserver; +import org.wso2.carbon.identity.tenant.resource.manager.util.ResourceUtils; + +/** + * Server startup observer for tenant resource management component. + */ +public class TenantResourceManagementServerStartupObserver implements ServerStartupObserver { + + private static final Log LOG = LogFactory.getLog(TenantResourceManagementServerStartupObserver.class); + + @Override + public void completingServerStartup() { + + // Do nothing. + } + + @Override + public void completedServerStartup() { + + if (LOG.isDebugEnabled()) { + LOG.debug("Attempting to load super tenant event publisher configurations from the configuration store."); + } + + /* + Load the super tenant publisher configuration from the config store. This is required if there are + super tenant event publishers configured in the config store (ex: Custom SMS Provider). + + This way of loading configurations is not optimal as it is called after the server startup + completion. These configurations should be loaded before the server startup completion event. Before we can + add the publishers the event streams need to be loaded to the server, current event streams are file based, + and it's loading is triggered using a server startup observer which runs on completingServerStartup + method (org.wso2.carbon.core.internal.DeploymentServerStartupObserver). There is currently no way to make + sure the calling order, therefore this is the only way to guarantee the publishers are loaded after the + event streams are loaded. + */ + ResourceUtils.loadTenantPublisherConfigurationFromConfigStore(); + } +} diff --git a/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/internal/TenantResourceManagerServiceDS.java b/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/internal/TenantResourceManagerServiceDS.java index 37a1c5c788..a8e9e242b2 100644 --- a/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/internal/TenantResourceManagerServiceDS.java +++ b/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/internal/TenantResourceManagerServiceDS.java @@ -27,6 +27,7 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferencePolicy; +import org.wso2.carbon.core.ServerStartupObserver; import org.wso2.carbon.event.publisher.core.EventPublisherService; import org.wso2.carbon.event.stream.core.EventStreamService; import org.wso2.carbon.identity.configuration.mgt.core.ConfigurationManager; @@ -60,6 +61,8 @@ protected void activate(ComponentContext context) { context.getBundleContext() .registerService(ResourceManager.class.getName(), resourceManager, null); TenantResourceManagerDataHolder.getInstance().setResourceManager(resourceManager); + context.getBundleContext().registerService(ServerStartupObserver.class.getName(), + new TenantResourceManagementServerStartupObserver(), null); if (log.isDebugEnabled()) { log.debug("Successfully deployed the tenant resource manager service."); } diff --git a/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/util/ResourceUtils.java b/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/util/ResourceUtils.java index 1d05020518..c07bd1c88c 100644 --- a/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/util/ResourceUtils.java +++ b/components/org.wso2.carbon.identity.tenant.resource.manager/src/main/java/org/wso2/carbon/identity/tenant/resource/manager/util/ResourceUtils.java @@ -23,17 +23,23 @@ import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.event.publisher.core.config.EventPublisherConfiguration; import org.wso2.carbon.event.publisher.core.exception.EventPublisherConfigurationException; -import org.wso2.carbon.event.stream.core.EventStreamConfiguration; -import org.wso2.carbon.event.stream.core.exception.EventStreamConfigurationException; +import org.wso2.carbon.identity.configuration.mgt.core.constant.ConfigurationConstants; +import org.wso2.carbon.identity.configuration.mgt.core.exception.ConfigurationManagementException; +import org.wso2.carbon.identity.configuration.mgt.core.model.Resource; +import org.wso2.carbon.identity.configuration.mgt.core.model.ResourceFile; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants; +import org.wso2.carbon.identity.tenant.resource.manager.exception.TenantResourceManagementException; import org.wso2.carbon.identity.tenant.resource.manager.exception.TenantResourceManagementServerException; import org.wso2.carbon.identity.tenant.resource.manager.internal.TenantResourceManagerDataHolder; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import java.util.List; +import static org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants.ErrorMessages.ERROR_CODE_ERROR_WHEN_ADDING_EVENT_PUBLISHER_CONFIGURATION; import static org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants.ErrorMessages.ERROR_CODE_ERROR_WHEN_CREATING_TENANT_EVENT_PUBLISHER_CONFIGURATION_USING_SUPER_TENANT_CONFIG; +import static org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants.ErrorMessages.ERROR_CODE_ERROR_WHEN_FETCHING_TENANT_SPECIFIC_PUBLISHER_FILES; +import static org.wso2.carbon.identity.tenant.resource.manager.constants.TenantResourceConstants.PUBLISHER; /** * Utility methods for tenant resource management. @@ -139,4 +145,50 @@ public static void startSuperTenantFlow() { carbonContext.setTenantId(MultitenantConstants.SUPER_TENANT_ID); carbonContext.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); } + + /** + * This method loads publisher configurations tenant wise by fetching them from configuration store. + */ + public static void loadTenantPublisherConfigurationFromConfigStore() { + + try { + List resourcesByTypePublisher = TenantResourceManagerDataHolder.getInstance() + .getConfigurationManager().getResourcesByType(PUBLISHER).getResources(); + for (Resource resource : resourcesByTypePublisher) { + if (!resource.getFiles().isEmpty()) { + ResourceFile tenantSpecificPublisherFile = resource.getFiles().get(0); + if (tenantSpecificPublisherFile != null) { + if (log.isDebugEnabled()) { + log.debug("File for publisher name: " + tenantSpecificPublisherFile.getName() + + " is available in the configuration store."); + } + TenantResourceManagerDataHolder.getInstance().getResourceManager() + .addEventPublisherConfiguration(tenantSpecificPublisherFile); + } + } + } + } catch (ConfigurationManagementException e) { + if (e.getErrorCode() + .equals(ConfigurationConstants.ErrorMessages.ERROR_CODE_FEATURE_NOT_ENABLED.getCode())) { + log.warn("Configuration store is disabled. Super tenant configuration will be used for the tenant " + + "domain: " + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()); + } else if (e.getErrorCode() + .equals(ConfigurationConstants.ErrorMessages.ERROR_CODE_RESOURCES_DOES_NOT_EXISTS.getCode())) { + log.warn("Configuration store does not contain any resources under resource type publisher. Super " + + "tenant configurations will be used for the tenant domain: " + PrivilegedCarbonContext + .getThreadLocalCarbonContext().getTenantDomain()); + } else if (e.getErrorCode() + .equals(ConfigurationConstants.ErrorMessages.ERROR_CODE_RESOURCE_TYPE_DOES_NOT_EXISTS.getCode())) { + log.warn("Configuration store does not contain publisher resource type. Super " + + "tenant configurations will be used for the tenant domain: " + PrivilegedCarbonContext + .getThreadLocalCarbonContext().getTenantDomain()); + } else { + log.error(populateMessageWithData(ERROR_CODE_ERROR_WHEN_FETCHING_TENANT_SPECIFIC_PUBLISHER_FILES, + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()), e); + } + } catch (TenantResourceManagementException e) { + log.error(populateMessageWithData(ERROR_CODE_ERROR_WHEN_ADDING_EVENT_PUBLISHER_CONFIGURATION, + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()), e); + } + } } diff --git a/components/org.wso2.carbon.identity.tenant.resource.manager/src/test/java/org/wso2/carbon/identity/tenant/resource/manager/TenantAwareAxis2ConfigurationContextObserverTest.java b/components/org.wso2.carbon.identity.tenant.resource.manager/src/test/java/org/wso2/carbon/identity/tenant/resource/manager/TenantAwareAxis2ConfigurationContextObserverTest.java index 768bb754ae..eebfc85282 100644 --- a/components/org.wso2.carbon.identity.tenant.resource.manager/src/test/java/org/wso2/carbon/identity/tenant/resource/manager/TenantAwareAxis2ConfigurationContextObserverTest.java +++ b/components/org.wso2.carbon.identity.tenant.resource.manager/src/test/java/org/wso2/carbon/identity/tenant/resource/manager/TenantAwareAxis2ConfigurationContextObserverTest.java @@ -166,6 +166,7 @@ private void prepareConfigs() throws Exception { Mockito.when(tenantResourceManagerDataHolder.getConfigurationManager()).thenReturn(configurationManager); Mockito.when(tenantResourceManagerDataHolder.getCarbonEventPublisherService()) .thenReturn(carbonEventPublisherService); + mockedResourceUtils.when(ResourceUtils::loadTenantPublisherConfigurationFromConfigStore).thenCallRealMethod(); File sampleResourceFile = new File(getSamplesPath()); InputStream fileStream = FileUtils.openInputStream(sampleResourceFile);