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

org.eclipse.dirigible.database.h2.H2Database Maven / Gradle / Ivy

/*
 * Copyright (c) 2024 Eclipse Dirigible contributors
 *
 * All rights reserved. This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v20.html
 *
 * SPDX-FileCopyrightText: Eclipse Dirigible contributors SPDX-License-Identifier: EPL-2.0
 */
package org.eclipse.dirigible.database.h2;

import static java.text.MessageFormat.format;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.eclipse.dirigible.commons.config.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

/**
 * H2 Database adapter.
 */
public class H2Database {

    /** The Constant logger. */
    private static final Logger logger = LoggerFactory.getLogger(H2Database.class);

    /** The Constant TYPE. */
    public static final String NAME = "h2";

    /** The Constant TYPE. */
    public static final String TYPE = "local";

    /** The Constant DIRIGIBLE_DATABASE_H2_ROOT_FOLDER. */
    public static final String DIRIGIBLE_DATABASE_H2_ROOT_FOLDER = "DIRIGIBLE_DATABASE_H2_ROOT_FOLDER"; //$NON-NLS-1$

    /** The Constant DIRIGIBLE_DATABASE_H2_ROOT_FOLDER_DEFAULT. */
    public static final String DIRIGIBLE_DATABASE_H2_ROOT_FOLDER_DEFAULT = DIRIGIBLE_DATABASE_H2_ROOT_FOLDER + "_DEFAULT"; //$NON-NLS-1$

    /** The Constant DATASOURCES. */
    private static final Map DATASOURCES = Collections.synchronizedMap(new HashMap<>());

    /**
     * Constructor with default root folder - user.dir
     *
     * @throws SQLException in case the database cannot be created
     */
    public H2Database() throws SQLException {
        this(null);
    }

    /**
     * Constructor with root folder parameter.
     *
     * @param rootFolder the root folder
     * @throws SQLException in case the database cannot be created
     */
    public H2Database(String rootFolder) throws SQLException {
        if (logger.isDebugEnabled()) {
            logger.debug("Initializing the embedded H2 datasource...");
        }

        initialize();

        if (logger.isDebugEnabled()) {
            logger.debug("Embedded H2 datasource initialized.");
        }
    }

    /**
     * Initialize.
     */
    public void initialize() {
        Configuration.loadModuleConfig("/dirigible-database-h2.properties");
        if (logger.isDebugEnabled()) {
            logger.debug(this.getClass()
                             .getCanonicalName()
                    + " module initialized.");
        }
    }

    /**
     * Gets the data source.
     *
     * @param name the name
     * @return the data source
     * @throws SQLException
     */
    public DataSource getDataSource(String name) throws SQLException {
        DataSource dataSource = DATASOURCES.get(name);
        if (dataSource != null) {
            return dataSource;
        }
        dataSource = createDataSource(name);
        return dataSource;
    }

    /**
     * Gets the name.
     *
     * @return the name
     */
    public String getName() {
        return NAME;
    }

    /**
     * Gets the type.
     *
     * @return the type
     */
    public String getType() {
        return TYPE;
    }

    /**
     * Creates the data source.
     *
     * @param name the name
     * @return the data source
     * @throws SQLException
     */
    protected DataSource createDataSource(String name) throws SQLException {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating an embedded H2 datasource...");
        }
        synchronized (H2Database.class) {
            try {
                String h2Root = prepareRootFolder(name);

                String databaseUrl = Configuration.get("DIRIGIBLE_DATABASE_H2_URL");
                String databaseUsername = Configuration.get("DIRIGIBLE_DATABASE_H2_USERNAME");
                String databasePassword = Configuration.get("DIRIGIBLE_DATABASE_H2_PASSWORD");

                int timeout = Configuration.getAsInt("DIRIGIBLE_DATABASE_DEFAULT_WAIT_TIMEOUT", 180000);

                if ((databaseUrl != null) && (databaseUsername != null) && (databasePassword != null)) {
                    HikariConfig config = new HikariConfig();

                    config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
                    config.setPoolName("H2DBHikariPool");
                    config.setConnectionTestQuery("VALUES 1");
                    config.addDataSourceProperty("URL", databaseUrl + "/" + name + ";LOCK_TIMEOUT=10000");
                    config.addDataSourceProperty("user", databaseUsername);
                    config.addDataSourceProperty("password", databasePassword);
                    config.setMinimumIdle(5);
                    config.setMaximumPoolSize(50);
                    config.setConnectionTimeout(timeout);
                    config.setLeakDetectionThreshold(timeout);
                    config.setIdleTimeout(600000);
                    config.setMaxLifetime(1800000);
                    config.setAutoCommit(true);

                    HikariDataSource ds = new HikariDataSource(config);

                    if (logger.isWarnEnabled()) {
                        logger.warn("Embedded H2 at: {}", h2Root);
                    }

                    DATASOURCES.put(name, ds);
                    return ds;
                } else {
                    throw new SQLException("Invalid datasource parameters provided for H2 database");
                }
            } catch (IOException e) {
                throw new SQLException(e);
            }
        }
    }

    /**
     * Prepare root folder.
     *
     * @param name the name
     * @return the string
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private String prepareRootFolder(String name) throws IOException {
        // TODO validate name parameter
        // TODO get by name from Configuration

        String rootFolder =
                ("DefaultDB".equals(name)) ? DIRIGIBLE_DATABASE_H2_ROOT_FOLDER_DEFAULT : DIRIGIBLE_DATABASE_H2_ROOT_FOLDER + name;
        String h2Root = Configuration.get(rootFolder, name);
        File rootFile = new File(h2Root);
        File parentFile = rootFile.getCanonicalFile()
                                  .getParentFile();
        if (!parentFile.exists()) {
            if (!parentFile.mkdirs()) {
                throw new IOException(format("Creation of the root folder [{0}] of the embedded H2 database failed.", h2Root));
            }
        }
        return h2Root;
    }

    /**
     * Gets the data sources.
     *
     * @return the data sources
     */
    public Map getDataSources() {
        Map datasources = new HashMap<>();
        datasources.putAll(DATASOURCES);
        return datasources;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy