/**
* 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.Map;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.n52.sos.config.SettingValue;
import org.n52.sos.ds.ConnectionProviderException;
import org.n52.sos.ds.Datasource;
import org.n52.sos.exception.ConfigurationException;
import org.n52.sos.service.Configurator;
import org.n52.sos.web.ControllerConstants;
import org.n52.sos.web.MetaDataHandler;
import org.n52.sos.web.auth.UserService;
import org.n52.sos.web.install.InstallConstants.Step;
/**
* @since 4.0.0
*
*/
@Controller
@RequestMapping(ControllerConstants.Paths.INSTALL_FINISH)
public class InstallFinishController extends AbstractProcessingInstallationController {
private static final Logger LOG = LoggerFactory.getLogger(InstallFinishController.class);
@Autowired
private UserService userService;
@Override
protected Step getStep() {
return Step.FINISH;
}
@Override
@RequestMapping(method = RequestMethod.POST)
public ModelAndView post(HttpServletRequest req, HttpServletResponse resp) throws InstallationRedirectError,
InstallationSettingsError {
HttpSession session = checkPrevious(req);
process(getParameters(req), getSettings(session));
session.invalidate();
return redirect(ControllerConstants.Paths.GET_INVOLVED + "?install=finished");
}
@Override
protected void process(Map<String, String> param, InstallationConfiguration c) throws InstallationSettingsError {
checkUsername(param, c);
checkPassword(param, c);
clearSettings(c);
Datasource datasource = c.getDatasource();
Properties properties = datasource.getDatasourceProperties(c.getDatabaseSettings());
// save the used datasource class
properties.put(Datasource.class.getCanonicalName(), datasource.getClass().getCanonicalName());
try {
if (c.isDropSchema()) {
String[] dropSchema = datasource.dropSchema(c.getDatabaseSettings());
LOG.debug("Drop database with the following statements!");
datasource.execute(dropSchema, c.getDatabaseSettings());
LOG.debug("Dropping the database finished!");
}
datasource.prepare(c.getDatabaseSettings());
if (c.isCreateSchema()) {
String[] createSchema = datasource.createSchema(c.getDatabaseSettings());
LOG.debug("Create database with the following statements!");
datasource.execute(createSchema, c.getDatabaseSettings());
if (datasource.isPostCreateSchema()) {
datasource.executePostCreateSchema(c.getDatabaseSettings());
}
LOG.debug("Database creation finished!");
}
if (c.isForceUpdateSchema()) {
String[] updateSchema = datasource.updateSchema(c.getDatabaseSettings());
if (LOG.isDebugEnabled()) {
LOG.debug("Update database with the following statements:");
int counter = 1;
for (String string : updateSchema) {
LOG.debug("{}. Statement: {}", counter++, string);
}
}
datasource.execute(updateSchema, c.getDatabaseSettings());
LOG.debug("Updating the database finished!");
}
} catch (Throwable e) {
throw new InstallationSettingsError(c, String.format(ErrorMessages.COULD_NOT_CONNECT_TO_THE_DATABASE,
e.getMessage()), e);
}
saveServiceSettings(c);
createAdministratorUser(c);
datasource.checkPostCreation(properties);
saveDatabaseProperties(properties, c);
saveInstallationDate();
instantiateConfigurator(properties, c);
}
protected void checkUsername(Map<String, String> param, InstallationConfiguration c)
throws InstallationSettingsError {
String username = param.get(ControllerConstants.ADMIN_USERNAME_REQUEST_PARAMETER);
if (username == null || username.trim().isEmpty()) {
throw new InstallationSettingsError(c, ErrorMessages.USERNAME_IS_INVALID);
}
c.setUsername(username);
}
protected void checkPassword(Map<String, String> param, InstallationConfiguration c)
throws InstallationSettingsError {
String password = param.get(ControllerConstants.ADMIN_PASSWORD_REQUEST_PARAMETER);
if (password == null || password.trim().isEmpty()) {
throw new InstallationSettingsError(c, ErrorMessages.PASSWORD_IS_INVALID);
}
c.setPassword(password);
}
protected void instantiateConfigurator(Properties properties, InstallationConfiguration c)
throws InstallationSettingsError {
if (Configurator.getInstance() == null) {
LOG.info("Instantiating Configurator...");
try {
Configurator.createInstance(properties, getBasePath());
} catch (ConfigurationException ex) {
throw new InstallationSettingsError(c, String.format(ErrorMessages.COULD_NOT_INSTANTIATE_CONFIGURATOR,
ex.getMessage()), ex);
}
} else {
LOG.error("Configurator seems to be already instantiated...");
}
}
protected void saveDatabaseProperties(Properties properties, InstallationConfiguration c)
throws InstallationSettingsError {
try {
getDatabaseSettingsHandler().saveAll(properties);
} catch (ConfigurationException e) {
/* TODO desctruct configurator? */
throw new InstallationSettingsError(c, String.format(ErrorMessages.COULD_NOT_WRITE_DATASOURCE_CONFIG,
e.getMessage()), e);
}
}
protected void saveInstallationDate() {
try {
/*
* save the installation date (same format as maven svn buildnumber
* plugin produces)
*/
DateTimeFormatter f = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
getMetaDataHandler().save(MetaDataHandler.Metadata.INSTALL_DATE, f.print(new DateTime()));
} catch (ConfigurationException ex) {
/* don't fail on this one */
LOG.error("Error saveing installation date", ex);
}
}
protected void saveServiceSettings(InstallationConfiguration c) throws InstallationSettingsError {
try {
for (SettingValue<?> e : c.getSettings().values()) {
getSettingsManager().changeSetting(e);
}
} catch (ConfigurationException e) {
throw new InstallationSettingsError(c, String.format(ErrorMessages.COULD_NOT_INSERT_SETTINGS,
e.getMessage()), e);
} catch (ConnectionProviderException e) {
throw new InstallationSettingsError(c, String.format(ErrorMessages.COULD_NOT_INSERT_SETTINGS,
e.getMessage()), e);
}
}
protected void createAdministratorUser(InstallationConfiguration c) throws InstallationSettingsError {
try {
userService.createAdmin(c.getUsername(), c.getPassword());
} catch (Throwable e) {
throw new InstallationSettingsError(c, String.format(ErrorMessages.COULD_NOT_SAVE_ADMIN_CREDENTIALS,
e.getMessage()), e);
}
}
protected void clearSettings(InstallationConfiguration c) throws InstallationSettingsError {
try {
getSettingsManager().deleteAll();
} catch (Throwable e) {
throw new InstallationSettingsError(c, String.format(ErrorMessages.COULD_NOT_DELETE_PREVIOUS_SETTINGS,
e.getMessage()));
}
}
}