All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cds.feature.mt.RoutingDataSourceFactory Maven / Gradle / Ivy

There is a newer version: 3.6.0
Show newest version
/**************************************************************************
 * (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 **************************************************************************/
package com.sap.cds.feature.mt;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.sql.DataSource;

import com.sap.cds.services.datasource.DataSourceFactory;
import com.sap.cds.services.environment.CdsProperties.MultiTenancy;
import com.sap.cds.services.request.RequestContext;
import com.sap.cds.services.runtime.CdsRuntime;
import com.sap.cds.services.runtime.CdsRuntimeAware;
import com.sap.cds.services.utils.CdsErrorStatuses;
import com.sap.cds.services.utils.ErrorStatusException;
import com.sap.cds.services.utils.datasource.DataSourceUtils;
import com.sap.cds.services.utils.datasource.DataSourceUtils.PoolType;
import com.sap.cloud.mt.runtime.DataPoolSettings;
import com.sap.cloud.mt.runtime.DataPoolSettings.ConnectionPoolType;
import com.sap.cloud.mt.runtime.DataSourceLookup;
import com.sap.cloud.mt.runtime.DataSourceLookupBuilder;
import com.sap.cloud.mt.runtime.EnvironmentAccess;
import com.sap.cloud.mt.runtime.IdentityZoneDeterminer;
import com.sap.cloud.mt.runtime.TenantAwareDataSource;
import com.sap.cloud.mt.runtime.TenantProvider;
import com.sap.cloud.mt.subscription.InstanceLifecycleManager;

/**
 * Provider of a tenant dependent data source.
 */
public class RoutingDataSourceFactory implements DataSourceFactory, CdsRuntimeAware {

	private static final String DATA_SOURCE_SECTION_MT = "cds.multitenancy.datasource.";

	private CdsRuntime runtime;
	private MtUtils mtUtils;

	@Override
	public void setCdsRuntime(CdsRuntime runtime) {
		this.runtime = runtime;
		this.mtUtils = new MtUtils(runtime);
	}

	@Override
	public Map create() {
		Map dataSources = new HashMap<>();
		for (Entry entry : mtUtils.createInstanceLifecycleManagers().entrySet()) {
			dataSources.put(entry.getKey(), createRoutingDataSource(entry.getKey(), entry.getValue()));
		}
		return dataSources;
	}

	private DataSource createRoutingDataSource(String name, InstanceLifecycleManager ilm) {
		Map parameterConfig = createParameterConfig(name);
		MultiTenancy multiTenancy = runtime.getEnvironment().getCdsProperties().getMultiTenancy();
		DataSourceLookup lookup = DataSourceLookupBuilder.create()
			.instanceLifecycleManager(ilm)
			.environmentAccess(new EnvironmentAccess() {
				@Override
				public  T getProperty(String key, Class clazz) {
					return runtime.getEnvironment().getProperty(key, clazz, null);
				}

				@Override
				@SuppressWarnings("unchecked")
				public Map getPropertiesForPrefix(String prefix) {
					return getProperty(prefix, HashMap.class);
				}
			})
			.prefixToPoolType(parameterConfig)
			.poolProvider(multiTenancy.getDataSource().getPool())
			.oneDataSourcePerDb(multiTenancy.getDataSource().getCombinePools().isEnabled())
			.build();
		TenantProvider provider = new TenantProvider(new IdentityZoneDeterminer() {
			@Override
			public String getIdentityZone() throws InternalError {
				String tenant = RequestContext.getCurrent(runtime).getUserInfo().getTenant();
				if (tenant == null) {
					throw new ErrorStatusException(CdsErrorStatuses.TENANT_CONTEXT_MISSING);
				}
				return tenant;
			}
		});
		return new TenantAwareDataSource(provider, lookup);
	}

	private Map createParameterConfig(String name) {
		Map config = new LinkedHashMap<>();
		addConfigParameter(config, ConnectionPoolType.HIKARI, PoolType.HIKARI, name);
		addConfigParameter(config, ConnectionPoolType.TOMCAT, PoolType.TOMCAT, name);
		return config;
	}

	private void addConfigParameter(Map config, DataPoolSettings.ConnectionPoolType type,
			PoolType poolType, String name) {
		config.put(DataSourceUtils.getDataSourceSection(name, poolType), type);
		config.put(DATA_SOURCE_SECTION_MT + poolType, type);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy