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
/**************************************************************************
 * (C) 2019-2022 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