/** * Copyright (C) 2012-2017 52°North Initiative for Geospatial Open Source * Software GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * If the program is linked with libraries which are licensed under one of * the following licenses, the combination of the program with the linked * library is not considered a "derivative work" of the program: * * - Apache License, version 2.0 * - Apache Software License, version 1.0 * - GNU Lesser General Public License, version 3 * - Mozilla Public License, versions 1.0, 1.1 and 2.0 * - Common Development and Distribution License (CDDL), version 1.0 * * Therefore the distribution of the program linked with libraries licensed * under the aforementioned licenses, is permitted by the copyright holders * if the distribution is compliant with both the GNU General Public * License version 2 and the aforementioned licenses. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. */ package org.n52.sos.web.install; import java.util.HashMap; import java.util.Map; import java.util.ServiceLoader; import java.util.Set; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.n52.sos.config.SettingDefinition; import org.n52.sos.config.SettingValue; import org.n52.sos.ds.Datasource; import org.n52.sos.exception.ConfigurationException; import org.n52.sos.util.StringHelper; import org.n52.sos.web.ControllerConstants; import org.n52.sos.web.install.InstallConstants.Step; import com.google.common.collect.Maps; /** * @since 4.0.0 * */ @Controller @RequestMapping(ControllerConstants.Paths.INSTALL_DATASOURCE) public class InstallDatasourceController extends AbstractProcessingInstallationController { @Override protected Step getStep() { return Step.DATASOURCE; } @Override protected void process(Map<String, String> parameters, InstallationConfiguration c) throws InstallationSettingsError { boolean overwriteTables; boolean alreadyExistent; boolean createTables; boolean forceUpdateTables; Datasource datasource; try { datasource = checkDatasource(parameters, c); overwriteTables = checkOverwrite(datasource, parameters, c); createTables = checkCreate(datasource, parameters, overwriteTables, c); forceUpdateTables = checkUpdate(datasource, parameters, overwriteTables, c); c.setDatabaseSettings(parseDatasourceSettings(datasource, parameters)); datasource.validateConnection(c.getDatabaseSettings()); datasource.validatePrerequisites(c.getDatabaseSettings()); if (datasource.needsSchema()) { alreadyExistent = datasource.checkIfSchemaExists(c.getDatabaseSettings()); if (createTables) { if (alreadyExistent) { if (!overwriteTables) { throw new InstallationSettingsError(c, ErrorMessages.TABLES_ALREADY_CREATED_BUT_SHOULD_NOT_OVERWRITE); } else { try { datasource.validateSchema(c.getDatabaseSettings()); } catch (ConfigurationException e) { throw new InstallationSettingsError(c, String.format( ErrorMessages.EXISTING_SCHEMA_DIFFERS_DROP_CREATE_SCHEMA, e.getMessage()), e); } } } if (!datasource.checkSchemaCreation(c.getDatabaseSettings())) { throw new InstallationSettingsError(c, String.format( ErrorMessages.COULD_NOT_CREATE_SOS_TABLES, "schema creation test table")); } } else if (!alreadyExistent) { throw new InstallationSettingsError(c, ErrorMessages.NO_TABLES_AND_SHOULD_NOT_CREATE); } else { try { datasource.validateSchema(c.getDatabaseSettings()); } catch (ConfigurationException e) { if (StringHelper.isNotEmpty(e.getMessage()) && (e.getMessage().contains(ErrorMessages.TO_CHECK_ERROR_MESSAGE_FOI_COL_IN_OBS_TAB) || e .getMessage().contains( ErrorMessages.TO_CHECK_ERROR_MESSAGE_SERIES_COL_IN_OBS_TAB))) { throw new InstallationSettingsError(c, String.format( ErrorMessages.EXISTING_SCHEMA_DIFFERS_UPDATE_SCHEMA, e.getMessage()), e); } else if (!forceUpdateTables) { throw new InstallationSettingsError(c, String.format( ErrorMessages.EXISTING_SCHEMA_REQUIRES_UPDATE, e.getMessage()), e); } } } } } catch (ConfigurationException e) { throw new InstallationSettingsError(c, e.getMessage(), e); } } protected boolean checkOverwrite(Datasource datasource, Map<String, String> parameters, InstallationConfiguration settings) { boolean overwriteTables = false; if (datasource.needsSchema()) { Boolean overwriteTablesParameter = parseBoolean(parameters, InstallConstants.OVERWRITE_TABLES_PARAMETER); if (overwriteTablesParameter != null) { overwriteTables = overwriteTablesParameter; } } parameters.remove(InstallConstants.OVERWRITE_TABLES_PARAMETER); settings.setDropSchema(overwriteTables); return overwriteTables; } protected boolean checkCreate(Datasource datasource, Map<String, String> parameters, boolean overwriteTables, InstallationConfiguration settings) { boolean createTables = false; if (datasource.needsSchema()) { Boolean createTablesParameter = parseBoolean(parameters, InstallConstants.CREATE_TABLES_PARAMETER); if (createTablesParameter != null) { createTables = (overwriteTables) ? overwriteTables : createTablesParameter; } } parameters.remove(InstallConstants.CREATE_TABLES_PARAMETER); settings.setCreateSchema(createTables); return createTables; } protected boolean checkUpdate(Datasource datasource, Map<String, String> parameters, boolean createTables, InstallationConfiguration settings) { boolean updateTables = false; if (datasource.needsSchema()) { Boolean updateTablesParameter = parseBoolean(parameters, InstallConstants.UPDATE_TABLES_PARAMETER); if (updateTablesParameter != null) { updateTables = (createTables) ? false : updateTablesParameter.booleanValue(); } } parameters.remove(InstallConstants.UPDATE_TABLES_PARAMETER); settings.setForceUpdateSchema(updateTables); return updateTables; } protected Map<String, Object> parseDatasourceSettings(Datasource datasource, Map<String, String> parameters) { Set<SettingDefinition<?, ?>> defs = datasource.getSettingDefinitions(); Map<String, Object> parsedSettings = new HashMap<String, Object>(parameters.size()); for (SettingDefinition<?, ?> def : defs) { SettingValue<?> newValue = getSettingsManager().getSettingFactory().newSettingValue(def, parameters.get(def.getKey())); parsedSettings.put(def.getKey(), newValue.getValue()); } return parsedSettings; } protected Map<String, Datasource> getDatasources() { ServiceLoader<Datasource> load = ServiceLoader.load(Datasource.class); Map<String, Datasource> dialects = Maps.newHashMap(); for (Datasource dd : load) { dialects.put(dd.getDialectName(), dd); } return dialects; } protected Datasource checkDatasource(Map<String, String> parameters, InstallationConfiguration settings) throws InstallationSettingsError { String datasourceName = parameters.get(InstallConstants.DATASOURCE_PARAMETER); parameters.remove(InstallConstants.DATASOURCE_PARAMETER); Datasource datasource = getDatasources().get(datasourceName); if (datasource == null) { throw new InstallationSettingsError(settings, String.format(ErrorMessages.INVALID_DATASOURCE, datasourceName)); } else { settings.setDatasource(datasource); } return datasource; } }