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

com.sap.cloud.mt.subscription.InstanceLifecycleManagerSqLite Maven / Gradle / Ivy

There is a newer version: 3.3.1
Show newest version
/*******************************************************************************
 *   © 2019-2024 SAP SE or an SAP affiliate company. All rights reserved.
 ******************************************************************************/
package com.sap.cloud.mt.subscription;

import com.google.common.annotations.VisibleForTesting;
import com.sap.cloud.mt.subscription.DbIdentifiers.DB;
import com.sap.cloud.mt.subscription.exceptions.InternalError;
import com.sap.cloud.mt.subscription.exceptions.UnknownTenant;

import java.net.URI;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * This implementation of {@link InstanceLifecycleManager} intended for multi tenancy based on SQLite database
 * files. It should not be used in production.
 */

public class InstanceLifecycleManagerSqLite implements InstanceLifecycleManager {

	// Open mode READWRITE will not create empty SQLite file
	private static final String SQLITE_CONNECTION_OPTIONS = "open_mode=2";
	private final SqLiteFileResolver sqLiteFileResolver;

	public InstanceLifecycleManagerSqLite(Path root) {
		this(new SqLiteFileResolver(root));
	}

	@VisibleForTesting
	public InstanceLifecycleManagerSqLite(SqLiteFileResolver sqliteFileResolver) {
		this.sqLiteFileResolver = sqliteFileResolver;
	}

	@Override
	public void createNewInstance(String tenant, ProvisioningParameters provisioningParameters, BindingParameters bindingParameters) {
		// MTX sidecar will create the database on subscribe or update
	}

	@Override
	public void deleteInstance(String tenant) {
		// MTX sidecar will delete the database on unsubscribe
	}

	@Override
	public DataSourceInfo getDataSourceInfo(String tenant, boolean forceCacheUpdate) throws UnknownTenant {
		Optional path = findPathForTenant(tenant);
		if (path.isPresent()) {
			return buildWithCredentials(newCredentials(tenant, path.get()));
		} else {
			throw new UnknownTenant(tenant);
		}
	}

	@Override
	public ContainerStatus getContainerStatus(String tenant) {
		if (findPathForTenant(tenant).isPresent()) {
			return ContainerStatus.OK;
		} else {
			return ContainerStatus.DOES_NOT_EXIST;
		}
	}

	@Override
	public boolean hasCredentials(String tenantId, boolean forceCacheUpdate) throws InternalError {
		return getContainerStatus(tenantId).equals(ContainerStatus.OK);
	}

	@Override
	public Map getAllTenantInfos(boolean forceCacheUpdate) {
		return sqLiteFileResolver.get().keySet().stream().map(s -> {
					TenantMetadata tenantInfo = new TenantMetadata(s);
					tenantInfo.putAdditionalProperty(DATABASE_ID, s);
					return tenantInfo;
				}).filter(tenantInfo -> FilterTenants.realTenants().test(tenantInfo.getTenantId()))
				.collect(Collectors.toMap(TenantMetadata::getTenantId, Function.identity()));
	}

	@Override
	public void checkThatTenantExists(String tenant) throws UnknownTenant {
		if (!findPathForTenant(tenant).isPresent()) {
			throw new UnknownTenant(tenant);
		}
	}

	@Override
	public List createAndGetLibContainers(DataSourceInfo dataSourceInfo) {
		return Collections.singletonList(dataSourceInfo);
	}

	@Override
	public List getLibContainers() {
		return new ArrayList<>();
	}

	@Override
	public void insertDbIdentifiers(DbIdentifiers dbIdentifiers) {
		// NOOP
	}

	@Override
	public boolean hasDbIdentifiers() {
		return true;
	}

	@Override
	public DB getDbType() {
		return DB.SQLITE;
	}

	private DbCredentials newCredentials(String tenant, Path file) {
		try {
			return new DbCredentialsSqlite(tenant, file);
		} catch (InternalError e) {
			throw new IllegalStateException("The DbCredentialsSqlite threw unexpected Internal Error", e);

		}
	}

	private Optional findPathForTenant(String tenant) {
		return Optional.ofNullable(sqLiteFileResolver.get().get(tenant));
	}

	private DataSourceInfo buildWithCredentials(DbCredentials credentials) {
		return DataSourceInfoBuilder.createBuilder()
				.driver(credentials.getDriver())
				.url(credentials.getUrl())
				.host(credentials.getHost())
				.dbKey(credentials.getDatabaseId())
				.tenantId(credentials.getDatabaseId())
				.id(credentials.getDatabaseId())
				.databaseId(credentials.getDatabaseId())
				.build();
	}

	private static class DbCredentialsSqlite extends DbCredentials {

		public static final String DRIVER = "org.sqlite.JDBC";
		private final String tenant;
		private final Path file;

		private DbCredentialsSqlite(String tenant, Path file) throws InternalError {
			super("sa",
					"",
					"localhost",
					"0",
					DRIVER,
					"");
			this.tenant = tenant;
			this.file = file;
		}

		@Override
		public String getDatabaseId() {
			return this.tenant;
		}

		@Override
		public DB getDB() {
			return DB.SQLITE;
		}

		@Override
		public DbCredentials createCopy() {
			throw new UnsupportedOperationException("Not implemented");
		}

		@Override
		protected String buildUrl() {
			return "jdbc:sqlite:" + file + "?".concat(SQLITE_CONNECTION_OPTIONS);
		}

		@Override
		protected List getHostsFromUri(URI uri) {
			return Collections.emptyList();
		}

		@Override
		protected UserAndPassword getUserFromUri(URI uri) {
			return new UserAndPassword();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy