JavaMigrationLoader.java
- /*
- * Copyright 2010-2023 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.ibatis.migration;
- import java.io.Reader;
- import java.io.StringReader;
- import java.lang.reflect.Modifier;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Set;
- import org.apache.ibatis.migration.io.ResolverUtil;
- public class JavaMigrationLoader implements MigrationLoader {
- private String[] packageNames;
- private ClassLoader classLoader;
- public JavaMigrationLoader(String... packageNames) {
- this(null, packageNames);
- }
- public JavaMigrationLoader(ClassLoader classLoader, String... packageNames) {
- this.classLoader = classLoader;
- this.packageNames = packageNames;
- }
- @Override
- public List<Change> getMigrations() {
- List<Change> migrations = new ArrayList<>();
- ResolverUtil<MigrationScript> resolver = getResolver();
- resolver.findImplementations(MigrationScript.class, packageNames);
- Set<Class<? extends MigrationScript>> classes = resolver.getClasses();
- for (Class<? extends MigrationScript> clazz : classes) {
- try {
- if (!Modifier.isAbstract(clazz.getModifiers())) {
- MigrationScript script = clazz.getDeclaredConstructor().newInstance();
- Change change = parseChangeFromMigrationScript(script);
- migrations.add(change);
- }
- } catch (Exception e) {
- throw new MigrationException("Could not instanciate MigrationScript: " + clazz.getName(), e);
- }
- }
- return migrations;
- }
- private Change parseChangeFromMigrationScript(MigrationScript script) {
- Change change = new Change();
- change.setId(script.getId());
- change.setDescription(script.getDescription());
- change.setFilename(script.getClass().getName());
- return change;
- }
- @Override
- public Reader getScriptReader(Change change, boolean undo) {
- ResolverUtil<MigrationScript> resolver = getResolver();
- final String className = change.getFilename();
- for (String pkg : packageNames) {
- resolver.find(
- type -> type != null && MigrationScript.class.isAssignableFrom(type) && type.getName().equals(className),
- pkg);
- }
- Set<Class<? extends MigrationScript>> classes = resolver.getClasses();
- // There should be only one script.
- for (Class<? extends MigrationScript> clazz : classes) {
- try {
- MigrationScript script = clazz.getDeclaredConstructor().newInstance();
- return new StringReader(undo ? script.getDownScript() : script.getUpScript());
- } catch (Exception e) {
- throw new MigrationException("Could not instanciate MigrationScript: " + clazz.getName(), e);
- }
- }
- return null;
- }
- @Override
- public Reader getBootstrapReader() {
- return getSoleScriptReader(BootstrapScript.class);
- }
- @Override
- public Reader getOnAbortReader() {
- return getSoleScriptReader(OnAbortScript.class);
- }
- public <T extends SimpleScript> Reader getSoleScriptReader(Class<T> scriptClass) {
- ResolverUtil<T> resolver = getResolver();
- resolver.findImplementations(scriptClass, packageNames);
- Set<Class<? extends T>> classes = resolver.getClasses();
- if (classes == null || classes.isEmpty()) {
- return null;
- }
- if (classes.size() > 1) {
- throw new MigrationException("There can be only one implementation of " + scriptClass.getName());
- }
- Class<? extends T> clazz = classes.iterator().next();
- try {
- T script = clazz.getDeclaredConstructor().newInstance();
- return new StringReader(script.getScript());
- } catch (Exception e) {
- throw new MigrationException("Could not instanciate script class: " + clazz.getName(), e);
- }
- }
- private <T> ResolverUtil<T> getResolver() {
- ResolverUtil<T> resolver = new ResolverUtil<>();
- if (classLoader != null) {
- resolver.setClassLoader(classLoader);
- }
- return resolver;
- }
- }