/* * Copyright 2015-Present Entando S.r.l. (http://www.entando.com) All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. */ package org.entando.entando.aps.system.init; import com.agiletec.aps.system.exception.ApsSystemException; import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import javax.sql.DataSource; import org.entando.entando.aps.system.init.model.Component; import org.entando.entando.aps.system.init.util.TableDataUtils; import org.entando.entando.aps.system.init.util.TableFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author E.Santoboni */ public class DatabaseRestorer extends AbstractDatabaseUtils { private static final Logger _logger = LoggerFactory.getLogger(DatabaseRestorer.class); protected void initOracleSchema(DataSource dataSource) throws Throwable { IDatabaseManager.DatabaseType type = this.getType(dataSource); try { if (!type.equals(IDatabaseManager.DatabaseType.ORACLE)) { return; } String[] queryTimestampFormat = new String[]{"ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'"}; TableDataUtils.executeQueries(dataSource, queryTimestampFormat, false); } catch (Throwable t) { _logger.error("Error initializing oracle schema ", t); throw new ApsSystemException("Error initializing oracle schema", t); } } protected void initDerbySchema(DataSource dataSource) throws Throwable { String username = this.invokeGetMethod("getUsername", dataSource); try { String[] queryCreateSchema = new String[]{"CREATE SCHEMA " + username.toUpperCase()}; TableDataUtils.executeQueries(dataSource, queryCreateSchema, false); } catch (Throwable t) { _logger.info("Error creating derby schema" + t); throw new ApsSystemException("Error creating derby schema", t); } try { String[] initSchemaQuery = new String[]{"SET SCHEMA \"" + username.toUpperCase() + "\""}; TableDataUtils.executeQueries(dataSource, initSchemaQuery, true); } catch (Throwable t) { _logger.error("Error initializating Derby Schema", t); throw new ApsSystemException("Error initializating Derby Schema", t); } } protected void dropAndRestoreBackup(String backupSubFolder) throws ApsSystemException { try { List<Component> components = this.getComponents(); int size = components.size(); for (int i = 0; i < components.size(); i++) { Component componentConfiguration = components.get(size - i - 1); this.dropTables(componentConfiguration.getTableMapping()); } this.dropTables(this.getEntandoTableMapping()); this.restoreBackup(backupSubFolder); } catch (Throwable t) { _logger.error("Error while restoring backup: {}", backupSubFolder, t); throw new ApsSystemException("Error while restoring backup", t); } } private void dropTables(Map<String, List<String>> tableMapping) throws ApsSystemException { if (null == tableMapping) { return; } try { String[] dataSourceNames = this.extractBeanNames(DataSource.class); for (int i = 0; i < dataSourceNames.length; i++) { String dataSourceName = dataSourceNames[i]; List<String> tableClasses = tableMapping.get(dataSourceName); if (null == tableClasses || tableClasses.isEmpty()) continue; DataSource dataSource = (DataSource) this.getBeanFactory().getBean(dataSourceName); int size = tableClasses.size(); for (int j = 0; j < tableClasses.size(); j++) { String tableClassName = tableClasses.get(size - j - 1); Class tableClass = Class.forName(tableClassName); String tableName = TableFactory.getTableName(tableClass); String[] queries = {"DELETE FROM " + tableName}; TableDataUtils.executeQueries(dataSource, queries, true); } } } catch (Throwable t) { _logger.error("Error while dropping tables", t); throw new RuntimeException("Error while dropping tables", t); } } protected void restoreBackup(String backupSubFolder) throws ApsSystemException { try { this.restoreLocalDump(this.getEntandoTableMapping(), backupSubFolder); List<Component> components = this.getComponents(); for (int i = 0; i < components.size(); i++) { Component componentConfiguration = components.get(i); this.restoreLocalDump(componentConfiguration.getTableMapping(), backupSubFolder); } } catch (Throwable t) { _logger.error("Error while restoring local backup", t); throw new ApsSystemException("Error while restoring local backup", t); } } private void restoreLocalDump(Map<String, List<String>> tableMapping, String backupSubFolder) throws ApsSystemException { if (null == tableMapping) { return; } try { StringBuilder folder = new StringBuilder(this.getLocalBackupsFolder()) .append(backupSubFolder).append(File.separator); String[] dataSourceNames = this.extractBeanNames(DataSource.class); for (int i = 0; i < dataSourceNames.length; i++) { String dataSourceName = dataSourceNames[i]; List<String> tableClasses = tableMapping.get(dataSourceName); if (null == tableClasses || tableClasses.isEmpty()) { continue; } DataSource dataSource = (DataSource) this.getBeanFactory().getBean(dataSourceName); this.initOracleSchema(dataSource); for (int j = 0; j < tableClasses.size(); j++) { String tableClassName = tableClasses.get(j); Class tableClass = Class.forName(tableClassName); String tableName = TableFactory.getTableName(tableClass); String fileName = folder.toString() + dataSourceName + File.separator + tableName + ".sql"; InputStream is = this.getStorageManager().getStream(fileName, true); if (null != is) { BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); this.executeQuery(br, dataSource); } } } } catch (Throwable t) { _logger.error("Error while restoring local dump", t); throw new RuntimeException("Error while restoring local dump", t); } } private void executeQuery(BufferedReader br, DataSource dataSource) throws ApsSystemException { try { String startsWith = "insert into"; String endsWith = ");"; String lineSep = System.getProperty("line.separator"); String nextLine = ""; StringBuilder sb = new StringBuilder(); while ((nextLine = br.readLine()) != null) { sb.append(nextLine); if ((sb.toString().toLowerCase().trim().startsWith(startsWith) && (sb.toString().toLowerCase().trim().endsWith(endsWith)))) { String[] queries = {sb.toString()}; try { TableDataUtils.executeQueries(dataSource, queries, true); } catch (Exception e) { _logger.error("Error executing query", e); } sb = new StringBuilder(); } else { sb.append(lineSep); } } } catch (Throwable t) { throw new ApsSystemException("Error reading text", t); } } }