001package ca.uhn.fhir.jpa.migrate;
002
003/*-
004 * #%L
005 * HAPI FHIR Server - SQL Migration
006 * %%
007 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
025import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
026import org.flywaydb.core.api.MigrationVersion;
027import org.flywaydb.core.api.migration.Context;
028import org.flywaydb.core.api.migration.JavaMigration;
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031
032import java.sql.SQLException;
033
034import static org.apache.commons.lang3.StringUtils.isBlank;
035
036public class FlywayMigrationTask implements JavaMigration {
037        private static final Logger ourLog = LoggerFactory.getLogger(FlywayMigrationTask.class);
038
039        private final BaseTask myTask;
040        private final FlywayMigrator myFlywayMigrator;
041        private DriverTypeEnum.ConnectionProperties myConnectionProperties;
042
043        public FlywayMigrationTask(BaseTask theTask, FlywayMigrator theFlywayMigrator) {
044                myTask = theTask;
045                myFlywayMigrator = theFlywayMigrator;
046        }
047
048        @Override
049        public MigrationVersion getVersion() {
050                return MigrationVersion.fromVersion(myTask.getFlywayVersion());
051        }
052
053        @Override
054        public String getDescription() {
055                return myTask.getDescription();
056        }
057
058        @Override
059        public Integer getChecksum() {
060                return myTask.hashCode();
061        }
062
063        @Override
064        public boolean isUndo() {
065                return false;
066        }
067
068        @Override
069        public boolean isBaselineMigration() {
070                return false;
071        }
072
073        @Override
074        public boolean canExecuteInTransaction() {
075                return false;
076        }
077
078        @Override
079        public void migrate(Context theContext) {
080                myTask.setDriverType(myFlywayMigrator.getDriverType());
081                myTask.setDryRun(myFlywayMigrator.isDryRun());
082                myTask.setNoColumnShrink(myFlywayMigrator.isNoColumnShrink());
083                myTask.setConnectionProperties(myConnectionProperties);
084                try {
085                        executeTask();
086                } catch (SQLException e) {
087                        String description = myTask.getDescription();
088                        if (isBlank(description)) {
089                                description = myTask.getClass().getSimpleName();
090                        }
091                        String prefix = "Failure executing task \"" + description + "\", aborting! Cause: ";
092                        throw new InternalErrorException(Msg.code(47) + prefix + e.toString(), e);
093                }
094        }
095
096        private void executeTask() throws SQLException {
097                if (myFlywayMigrator.isSchemaWasInitialized() && !myTask.isRunDuringSchemaInitialization()) {
098                        // Empty schema was initialized, stub out this non-schema-init task since we're starting with a fully migrated schema
099                        myTask.setDoNothing(true);
100                }
101                myTask.execute();
102                if (myTask.initializedSchema()) {
103                        ourLog.info("Empty schema was Initialized.  Stubbing out all following migration tasks that are not Schema Initializations.");
104                        myFlywayMigrator.setSchemaWasInitialized(true);
105                }
106
107                myFlywayMigrator.addExecutedStatements(myTask.getExecutedStatements());
108        }
109
110        public void setConnectionProperties(DriverTypeEnum.ConnectionProperties theConnectionProperties) {
111                myConnectionProperties = theConnectionProperties;
112        }
113}