<commit_before>package org.ohdsi.olympus.model;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PreDestroy;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.ohdsi.olympus.model.WebApiProperties.DIALECT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;

import com.google.common.collect.Lists;

/**
 * TODO
 */
public class WebApiService implements ApplicationListener<EmbeddedServletContainerInitializedEvent> {
    
    private static final Log log = LogFactory.getLog(WebApiService.class);
    
    private String localAddress;
    
    private final WebAppContext context;
    
    private final WebApiPropertiesRepository repo;
    
    private final WebApiRemoteRepository remotesRepo;
    
    private AppPropertiesRepository appPropertiesRepo;
    
    private final boolean isWebApiLaunchEnabled;
    
    @Autowired
    private ContextHandlerCollection contextHandlerCollection;
    
    @Autowired
    private Environment env;
    
    /**
     * @param isWebApiLaunchEnabled
     * @param localAddress e.g. http://localhost:20000 (no ending slash)
     * @param ctx
     * @param repo
     * @param remotesRepo
     * @param appPropertiesRepository
     */
    public WebApiService(final boolean isWebApiLaunchEnabled, final String localAddress, final WebAppContext ctx,
        final WebApiPropertiesRepository repo, final WebApiRemoteRepository remotesRepo,
        final AppPropertiesRepository appPropertiesRepository) {
        this.localAddress = localAddress;
        this.context = ctx;
        this.repo = repo;
        this.isWebApiLaunchEnabled = isWebApiLaunchEnabled;
        this.remotesRepo = remotesRepo;
        this.appPropertiesRepo = appPropertiesRepository;
    }
    
    public boolean hasRemotes() {
        return Lists.newArrayList(this.remotesRepo.findAll()).size() > 0;
    }
    
    /**
     * <properties>
     * <datasource.driverClassName>oracle.jdbc.OracleDriver</datasource.driverClassName>
     * <datasource.dialect>oracle</datasource.dialect> <datasource.dialect.source>sql
     * server</datasource.dialect.source> <datasource.cdm.schema>omopv5_de</datasource.cdm.schema>
     * <datasource.ohdsi.schema>OHDSI</datasource.ohdsi.schema>
     * <datasource.cohort.schema>OHDSI</datasource.cohort.schema>
     * <datasource.url>jdbc:oracle:thin:@172.31.80.28:1521:i2b2idp</datasource.url>
     * <datasource.username>OHDSI</datasource.username> <datasource.password></datasource.password>
     * <flyway.datasource.driverClassName></flyway.datasource.driverClassName>
     * <flyway.datasource.url>jdbc:oracle:thin:@172.31.80.28:1521:i2b2idp</flyway.datasource.url>
     * <flyway.datasource.username>OHDSI</flyway.datasource.username>
     * <flyway.datasource.password></flyway.datasource.password>
     * <flyway.locations>classpath:db/migration/oracle</flyway.locations> <!-- Note: Schema name is
     * case-sensitive. --> <flyway.schemas>${datasource.ohdsi.schema}</flyway.schemas>.
     * </properties>
     * 
     * @param props
     */
    public static void setSystemProperties(final WebApiProperties props) {
        DIALECT dialect = props.getCdmDialect();
        String flywayLocations;
        String driverClassName;
        String jdbcUrl;
        String flywayJdbcUrl;
        String jdbcPort;
        String flywayJdbcPort;
        
        if (DIALECT.ORACLE.equals(dialect)) {
            driverClassName = "oracle.jdbc.OracleDriver";
            flywayLocations = "classpath:db/migration/oracle";
            jdbcUrl = String.format("jdbc:oracle:thin:@%s:%s:%s", props.getJdbcIpAddress(), props.getJdbcPort(),
                props.getCdmDataSourceSid());
            flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayDataSourceSid()) ? jdbcUrl : String.format(
                "jdbc:oracle:thin:@%s:%s:%s", props.getJdbcIpAddress(), props.getJdbcPort(), props.getFlywayDataSourceSid());
        } else if (DIALECT.POSTGRESQL.equals(dialect)) {
            driverClassName = "org.postgresql.Driver";
            flywayLocations = "classpath:db/migration/postgresql";
            jdbcUrl = String.format("jdbc:postgresql://%s:%s/%s", props.getJdbcIpAddress(), props.getJdbcPort(),
                props.getCdmDataSourceSid());
            flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayDataSourceSid()) ? jdbcUrl : String.format(
                "jdbc:postgresql://%s:%s/%s", props.getJdbcIpAddress(), props.getJdbcPort(), props.getFlywayDataSourceSid());
        } else {
            //sql server
            boolean isIntegratedSecurityOption = false;
            if (DIALECT.SQLSERVERINTSECURITY.equals(dialect)) {
                isIntegratedSecurityOption = true;
            }
            jdbcPort = StringUtils.isEmpty(props.getJdbcPort()) ? "1433" : props.getJdbcPort();
            
            driverClassName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
            flywayLocations = "classpath:db/migration/sqlserver";
            if (isIntegratedSecurityOption) {
                jdbcUrl = String.format("jdbc:sqlserver://%s:%s;databaseName=%s;integratedSecurity=true;",
                    props.getJdbcIpAddress(), jdbcPort, props.getCdmSchema());
                flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayDataSourceSid()) ? jdbcUrl : String.format(
                    "jdbc:sqlserver://%s:%s;databaseName=%s;integratedSecurity=true;", props.getJdbcIpAddress(), jdbcPort,
                    props.getCdmSchema());
            } else {
                jdbcUrl = String.format("jdbc:sqlserver://%s:%s;databaseName=%s", props.getJdbcIpAddress(), jdbcPort,
                    props.getCdmSchema());
                flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayDataSourceSid()) ? jdbcUrl : String.format(
                    "jdbc:sqlserver://%s:%s;databaseName=%s", props.getJdbcIpAddress(), jdbcPort, props.getCdmSchema());
            }
            /* Based on meeting Tuesday, I believe databaseName is used even with integrated security
                        if (isIntegratedSecurityOption) {
                            jdbcUrl = String.format("jdbc:sqlserver://%s", props.getJdbcIpAddress());
                            flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayJdbcUser()) ? jdbcUrl : String.format(
                                "jdbc:sqlserver://%s", props.getJdbcIpAddress());
                        }*/
        }
        String flywayUser = StringUtils.isEmpty(props.getFlywayJdbcUser()) ? props.getJdbcUser() : props.getFlywayJdbcUser();
        String flywayPass = StringUtils.isEmpty(props.getFlywayJdbcPass()) ? props.getJdbcPass() : props.getFlywayJdbcPass();
        String flywaySchemas = StringUtils.isEmpty(props.getFlywaySchemas()) ? props.getOhdsiSchema() : props
                .getFlywaySchemas();
        
        setProperty(WebApiProperties.PROP_DATASOURCE_DRIVERCLASSNAME, driverClassName);
        setProperty(WebApiProperties.PROP_DATASOURCE_URL, jdbcUrl);
        setProperty(WebApiProperties.PROP_DATASOURCE_USERNAME, props.getJdbcUser());
        setProperty(WebApiProperties.PROP_DATASOURCE_PASSWORD, props.getJdbcPass());
        setProperty(WebApiProperties.PROP_FLYWAY_DATASOURCE_DRIVERCLASSNAME, driverClassName);
        setProperty(WebApiProperties.PROP_FLYWAY_DATASOURCE_URL, flywayJdbcUrl);
        setProperty(WebApiProperties.PROP_FLYWAY_DATASOURCE_USERNAME, flywayUser);
        setProperty(WebApiProperties.PROP_FLYWAY_DATASOURCE_PASSWORD, flywayPass);
        setProperty(WebApiProperties.PROP_FLYWAY_SCHEMAS, flywaySchemas);
        setProperty(WebApiProperties.PROP_FLYWAY_LOCATIONS, flywayLocations);
        setProperty(WebApiProperties.PROP_DATASOURCE_DIALECT, props.getCdmDialect().getValue());
        setProperty(WebApiProperties.PROP_DATASOURCE_CDM_SCHEMA, props.getCdmSchema());
        setProperty(WebApiProperties.PROP_DATASOURCE_OHDSI_SCHEMA, props.getOhdsiSchema());<commit_msg>Fixes #15 Configuration of SQL Server with integrated security fails<commit_after>package org.ohdsi.olympus.model;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PreDestroy;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.ohdsi.olympus.model.WebApiProperties.DIALECT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;

import com.google.common.collect.Lists;

/**
 * TODO
 */
public class WebApiService implements ApplicationListener<EmbeddedServletContainerInitializedEvent> {
    
    private static final Log log = LogFactory.getLog(WebApiService.class);
    
    private String localAddress;
    
    private final WebAppContext context;
    
    private final WebApiPropertiesRepository repo;
    
    private final WebApiRemoteRepository remotesRepo;
    
    private AppPropertiesRepository appPropertiesRepo;
    
    private final boolean isWebApiLaunchEnabled;
    
    @Autowired
    private ContextHandlerCollection contextHandlerCollection;
    
    @Autowired
    private Environment env;
    
    /**
     * @param isWebApiLaunchEnabled
     * @param localAddress e.g. http://localhost:20000 (no ending slash)
     * @param ctx
     * @param repo
     * @param remotesRepo
     * @param appPropertiesRepository
     */
    public WebApiService(final boolean isWebApiLaunchEnabled, final String localAddress, final WebAppContext ctx,
        final WebApiPropertiesRepository repo, final WebApiRemoteRepository remotesRepo,
        final AppPropertiesRepository appPropertiesRepository) {
        this.localAddress = localAddress;
        this.context = ctx;
        this.repo = repo;
        this.isWebApiLaunchEnabled = isWebApiLaunchEnabled;
        this.remotesRepo = remotesRepo;
        this.appPropertiesRepo = appPropertiesRepository;
    }
    
    public boolean hasRemotes() {
        return Lists.newArrayList(this.remotesRepo.findAll()).size() > 0;
    }
    
    /**
     * <properties>
     * <datasource.driverClassName>oracle.jdbc.OracleDriver</datasource.driverClassName>
     * <datasource.dialect>oracle</datasource.dialect> <datasource.dialect.source>sql
     * server</datasource.dialect.source> <datasource.cdm.schema>omopv5_de</datasource.cdm.schema>
     * <datasource.ohdsi.schema>OHDSI</datasource.ohdsi.schema>
     * <datasource.cohort.schema>OHDSI</datasource.cohort.schema>
     * <datasource.url>jdbc:oracle:thin:@172.31.80.28:1521:i2b2idp</datasource.url>
     * <datasource.username>OHDSI</datasource.username> <datasource.password></datasource.password>
     * <flyway.datasource.driverClassName></flyway.datasource.driverClassName>
     * <flyway.datasource.url>jdbc:oracle:thin:@172.31.80.28:1521:i2b2idp</flyway.datasource.url>
     * <flyway.datasource.username>OHDSI</flyway.datasource.username>
     * <flyway.datasource.password></flyway.datasource.password>
     * <flyway.locations>classpath:db/migration/oracle</flyway.locations> <!-- Note: Schema name is
     * case-sensitive. --> <flyway.schemas>${datasource.ohdsi.schema}</flyway.schemas>.
     * </properties>
     * 
     * @param props
     */
    public static void setSystemProperties(final WebApiProperties props) {
        DIALECT dialect = props.getCdmDialect();
        String flywayLocations;
        String driverClassName;
        String jdbcUrl;
        String flywayJdbcUrl;
        String jdbcPort;
        String flywayJdbcPort;
        String cdmNameAndSchema;

        cdmNameAndSchema = props.getCdmSchema();

        if (DIALECT.ORACLE.equals(dialect)) {
            driverClassName = "oracle.jdbc.OracleDriver";
            flywayLocations = "classpath:db/migration/oracle";
            jdbcUrl = String.format("jdbc:oracle:thin:@%s:%s:%s", props.getJdbcIpAddress(), props.getJdbcPort(),
                props.getCdmDataSourceSid());
            flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayDataSourceSid()) ? jdbcUrl : String.format(
                "jdbc:oracle:thin:@%s:%s:%s", props.getJdbcIpAddress(), props.getJdbcPort(), props.getFlywayDataSourceSid());
        } else if (DIALECT.POSTGRESQL.equals(dialect)) {
            driverClassName = "org.postgresql.Driver";
            flywayLocations = "classpath:db/migration/postgresql";
            jdbcUrl = String.format("jdbc:postgresql://%s:%s/%s", props.getJdbcIpAddress(), props.getJdbcPort(),
                props.getCdmDataSourceSid());
            flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayDataSourceSid()) ? jdbcUrl : String.format(
                "jdbc:postgresql://%s:%s/%s", props.getJdbcIpAddress(), props.getJdbcPort(), props.getFlywayDataSourceSid());
        } else {
            //sql server
            boolean isIntegratedSecurityOption = false;
            String[] parts = cdmNameAndSchema.split("\\.");
            String cdmDatabaseName = parts[0];
            String cdmSchema = parts.length > 1 ? parts[1] : "dbo";

            if (DIALECT.SQLSERVERINTSECURITY.equals(dialect)) {
                isIntegratedSecurityOption = true;
            }
            jdbcPort = StringUtils.isEmpty(props.getJdbcPort()) ? "1433" : props.getJdbcPort();
            
            driverClassName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
            flywayLocations = "classpath:db/migration/sqlserver";
            if (isIntegratedSecurityOption) {
                jdbcUrl = String.format("jdbc:sqlserver://%s:%s;databaseName=%s;integratedSecurity=true;",
                    props.getJdbcIpAddress(), jdbcPort, cdmDatabaseName);
                flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayDataSourceSid()) ? jdbcUrl : String.format(
                    "jdbc:sqlserver://%s:%s;databaseName=%s;integratedSecurity=true;", props.getJdbcIpAddress(), jdbcPort,
                        cdmDatabaseName);
            } else {
                jdbcUrl = String.format("jdbc:sqlserver://%s:%s;databaseName=%s", props.getJdbcIpAddress(), jdbcPort,
                    cdmDatabaseName);
                flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayDataSourceSid()) ? jdbcUrl : String.format(
                    "jdbc:sqlserver://%s:%s;databaseName=%s", props.getJdbcIpAddress(), jdbcPort, cdmDatabaseName);
            }
            /* Based on meeting Tuesday, I believe databaseName is used even with integrated security
                        if (isIntegratedSecurityOption) {
                            jdbcUrl = String.format("jdbc:sqlserver://%s", props.getJdbcIpAddress());
                            flywayJdbcUrl = StringUtils.isEmpty(props.getFlywayJdbcUser()) ? jdbcUrl : String.format(
                                "jdbc:sqlserver://%s", props.getJdbcIpAddress());
                        }*/
        }
        String flywayUser = StringUtils.isEmpty(props.getFlywayJdbcUser()) ? props.getJdbcUser() : props.getFlywayJdbcUser();
        String flywayPass = StringUtils.isEmpty(props.getFlywayJdbcPass()) ? props.getJdbcPass() : props.getFlywayJdbcPass();
        String flywaySchemas = StringUtils.isEmpty(props.getFlywaySchemas()) ? props.getOhdsiSchema() : props
                .getFlywaySchemas();
        
        setProperty(WebApiProperties.PROP_DATASOURCE_DRIVERCLASSNAME, driverClassName);
        setProperty(WebApiProperties.PROP_DATASOURCE_URL, jdbcUrl);
        setProperty(WebApiProperties.PROP_DATASOURCE_USERNAME, props.getJdbcUser());
        setProperty(WebApiProperties.PROP_DATASOURCE_PASSWORD, props.getJdbcPass());
        setProperty(WebApiProperties.PROP_FLYWAY_DATASOURCE_DRIVERCLASSNAME, driverClassName);
        setProperty(WebApiProperties.PROP_FLYWAY_DATASOURCE_URL, flywayJdbcUrl);
        setProperty(WebApiProperties.PROP_FLYWAY_DATASOURCE_USERNAME, flywayUser);
        setProperty(WebApiProperties.PROP_FLYWAY_DATASOURCE_PASSWORD, flywayPass);
        setProperty(WebApiProperties.PROP_FLYWAY_SCHEMAS, flywaySchemas);
        setProperty(WebApiProperties.PROP_FLYWAY_LOCATIONS, flywayLocations);
        setProperty(WebApiProperties.PROP_DATASOURCE_DIALECT, props.getCdmDialect().getValue());
        setProperty(WebApiProperties.PROP_DATASOURCE_CDM_SCHEMA, props.getCdmSchema());
        setProperty(WebApiProperties.PROP_DATASOURCE_OHDSI_SCHEMA, props.getOhdsiSchema());
{'fraction_non_alphanumeric': 0.10733106921185151, 'fraction_numerical': 0.005094273334114065, 'mean_word_length': 3.3469076100789006, 'pattern_counts': {'":': 0, '<': 71, '<?xml version=': 0, '>': 74, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2557200', 'n_tokens_mistral': 5144, 'n_tokens_neox': 4917, 'n_words': 680}