001/* 002 * Copyright 2020 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.migration.action.impl; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.sql.Connection; 021import java.sql.SQLException; 022import java.util.Map; 023import java.util.Map.Entry; 024 025import org.apache.avalon.framework.configuration.Configuration; 026import org.apache.avalon.framework.configuration.ConfigurationException; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.avalon.framework.service.Serviceable; 030import org.apache.commons.io.IOUtils; 031import org.apache.excalibur.source.Source; 032import org.apache.excalibur.source.SourceResolver; 033 034import org.ametys.core.datasource.ConnectionHelper; 035import org.ametys.core.migration.MigrationException; 036import org.ametys.core.migration.action.Action; 037import org.ametys.core.migration.action.data.ActionData; 038import org.ametys.core.migration.action.data.impl.SqlUpgradeActionData; 039import org.ametys.core.migration.version.Version; 040import org.ametys.core.migration.version.impl.SqlVersion; 041import org.ametys.core.script.SQLScriptHelper; 042import org.ametys.runtime.plugin.component.AbstractLogEnabled; 043 044/** 045 * SQL action: A script will be executed 046 */ 047public class SqlUpgradeAction extends AbstractLogEnabled implements Action, Serviceable 048{ 049 /** Source resolver */ 050 protected SourceResolver _sourceResolver; 051 052 @Override 053 public void service(ServiceManager manager) throws ServiceException 054 { 055 _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); 056 } 057 058 @Override 059 public void doAction(ActionData actionData) throws MigrationException 060 { 061 getLogger().debug("Start ugprade for: {}", actionData.toString()); 062 if (!(actionData instanceof SqlUpgradeActionData)) 063 { 064 throw new MigrationException("SQL Upgrade can only be created for an SQL upgrade, this is not the case for upgrade: " + actionData.toString()); 065 } 066 067 SqlUpgradeActionData sqlActionData = (SqlUpgradeActionData) actionData; 068 Version version = sqlActionData.getVersion(); 069 070 if (!(version instanceof SqlVersion)) 071 { 072 throw new MigrationException("SQL Upgrade can only be created with a SQL Version, this is not the case for upgrade: " + sqlActionData.toString()); 073 } 074 075 SqlVersion sqlVersion = (SqlVersion) version; 076 _upgrade(sqlActionData, sqlVersion); 077 078 getLogger().debug("End upgrade for: {}", actionData.toString()); 079 } 080 081 /** 082 * Do the upgrade with the right objects 083 * @param sqlUpgradeData upgrade data 084 * @param sqlVersion version 085 * @throws MigrationException Something went wrong 086 */ 087 protected void _upgrade(SqlUpgradeActionData sqlUpgradeData, SqlVersion sqlVersion) throws MigrationException 088 { 089 Connection connection = null; 090 Source source = null; 091 try 092 { 093 String file = sqlUpgradeData.getFile(); 094 095 String datasourceId = sqlVersion.getDatasourceId(); 096 connection = ConnectionHelper.getConnection(datasourceId); 097 098 file = "plugin:" + sqlUpgradeData.getPlugin() + "://" + file.replaceAll("%DATABASE_TYPE%", sqlVersion.getDatabaseType()); 099 source = _sourceResolver.resolveURI(file); 100 101 try (InputStream is = source.getInputStream()) 102 { 103 String script = IOUtils.toString(is, "UTF-8"); 104 105 Map<String, Object> additionalScriptValue = sqlVersion.getAdditionalValues(); 106 for (Entry<String, Object> keyValue : additionalScriptValue.entrySet()) 107 { 108 Object value = keyValue.getValue(); 109 if (value instanceof String) 110 { 111 script = script.replaceAll("%" + keyValue.getKey() + "%", (String) value); 112 } 113 } 114 115 SQLScriptHelper.runScript(connection, script); 116 } 117 } 118 catch (SQLException | IOException e) 119 { 120 throw new MigrationException("Impossible to run the upgrade: " + sqlUpgradeData.toString(), e); 121 } 122 finally 123 { 124 ConnectionHelper.cleanup(connection); 125 _sourceResolver.release(source); 126 } 127 } 128 129 @Override 130 public ActionData generateActionData(String versionNumber, Version version, String comment, String from, String type, String pluginName, Configuration configuration, boolean restartRequired) throws MigrationException, ConfigurationException 131 { 132 return new SqlUpgradeActionData(versionNumber, version, comment, from, type, pluginName, configuration, restartRequired); 133 } 134 135}