All Downloads are FREE. Search and download functionalities are using the official Maven repository.

play.db.ebean.orm.EbeanDynamicEvolutions Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2009-2014 Typesafe Inc. 
 */
package play.db.ebean.orm;

import com.typesafe.config.Config;
import io.ebean.EbeanServer;
import io.ebean.EbeanServerFactory;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.dbmigration.model.CurrentModel;
import play.Environment;
import play.api.db.evolutions.DynamicEvolutions;
import play.inject.ApplicationLifecycle;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * A Play module that automatically manages Ebean configuration.
 *
 * @since 14.11.27
 */
@Singleton
public class EbeanDynamicEvolutions extends DynamicEvolutions {

    /**
     * @since 14.11.27
     */
    private final EbeanConfig ebeanConfig;

    /**
     * @since 16.12.16
     */
    private final Config configuration;

    /**
     * @since 14.11.27
     */
    private final Environment environment;

    /**
     * @since 16.02.17
     */
    private final Map servers = new HashMap<>();

    /**
     * Build a default instance.
     *
     * @param ebeanConfig   The current Ebean servers configuration
     * @param configuration The current Play configuration
     * @param environment   The current Play environment
     * @param lifecycle     The current Play lifecycle instance
     * @since 14.11.27
     */
    @Inject
    public EbeanDynamicEvolutions(final EbeanConfig ebeanConfig, final Environment environment,
                                  final Config configuration, final ApplicationLifecycle lifecycle) {
        this.ebeanConfig = ebeanConfig;
        this.configuration = configuration;
        this.environment = environment;
        this.start();
        lifecycle.addStopHook(() -> {
            servers.forEach((database, server) ->
                server.shutdown(
                    false,
                    false
                )
            );
            return CompletableFuture.completedFuture(null);
        });
    }

    /**
     * Helper method that generates the required evolution
     * to properly run Ebean.
     *
     * @param server The EbeanServer
     * @return The complete migration script generated by Ebean
     * @since 14.11.27
     */
    public static String generateEvolutionScript(final EbeanServer server) {
        try {
            final SpiEbeanServer spiServer = (SpiEbeanServer) server;
            final CurrentModel ddl = new CurrentModel(spiServer);
            final String ups = ddl.getCreateDdl();
            final String downs = ddl.getDropAllDdl();
            if (ups == null || ups.trim().isEmpty()) {
                return null;
            }

            return (
                "# --- Created by Ebean DDL\r\n" +
                    "# To stop Ebean DDL generation, remove this comment and start using Evolutions\r\n" +
                    "\r\n" +
                    "# --- !Ups\r\n" +
                    "\r\n" +
                    ups +
                    "\r\n" +
                    "# --- !Downs\r\n" +
                    "\r\n" +
                    downs
            );
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * Initialise the Ebean servers.
     *
     * @since 14.11.27
     */
    public void start() {
        this.ebeanConfig
            .serverConfigs()
            .forEach((key, serverConfig) ->
                this.servers
                    .put(
                        key,
                        EbeanServerFactory.create(serverConfig)
                    )
            );
    }

    /**
     * Generate evolutions.
     *
     * @since 14.11.27
     */
    @Override
    public void create() {
        if (!this.environment.isProd()) {
            this.ebeanConfig
                .serverConfigs()
                .forEach((key, serverConfig) -> {
                    final String evolutionScript;
                    if (!this.configuration.hasPath("play.evolutions.db." + key + ".enabled")
                        ||this.configuration.getBoolean("play.evolutions.db." + key + ".enabled")) {
                        evolutionScript = EbeanDynamicEvolutions.generateEvolutionScript(this.servers.get(key));
                    } else {
                        evolutionScript = null;
                    }
                    if (evolutionScript != null) {
                        final File evolutions = this.environment.getFile("conf/evolutions/" + key + "/1.sql");
                        try {
                            String content = "";
                            if (evolutions.exists()) {
                                content = new String(
                                    Files.readAllBytes(evolutions.toPath()),
                                    StandardCharsets.UTF_8
                                );
                            }

                            if (content.isEmpty() || content.startsWith("# --- Created by Ebean DDL")) {
                                final File dirToCreate = this.environment.getFile("conf/evolutions/" + key);
                                if (!dirToCreate.exists()) {
                                    if (!this.environment.getFile("conf/evolutions/" + key).mkdirs()) {
                                        throw new RuntimeException("Can't create 'Evolution' directory");
                                    }
                                }
                                if (!content.equals(evolutionScript)) {
                                    Files.write(
                                        evolutions.toPath(),
                                        evolutionScript.getBytes(StandardCharsets.UTF_8)
                                    );
                                }
                            }
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy