11package io .ebeaninternal .dbmigration ;
22
33import io .avaje .applog .AppLog ;
4+ import io .avaje .classpath .scanner .core .Location ;
45import io .ebean .DB ;
56import io .ebean .Database ;
67import io .ebean .annotation .Platform ;
7- import io .ebean .config .DatabaseConfig ;
8- import io .ebean .config .DbConstraintNaming ;
9- import io .ebean .config .PlatformConfig ;
10- import io .ebean .config .PropertiesWrapper ;
8+ import io .ebean .config .*;
119import io .ebean .config .dbplatform .DatabasePlatform ;
1210import io .ebean .config .dbplatform .DatabasePlatformProvider ;
1311import io .ebean .dbmigration .DbMigration ;
1412import io .ebean .util .IOUtils ;
13+ import io .ebean .util .StringHelper ;
1514import io .ebeaninternal .api .DbOffline ;
1615import io .ebeaninternal .api .SpiEbeanServer ;
1716import io .ebeaninternal .dbmigration .ddlgeneration .DdlOptions ;
2625import java .io .File ;
2726import java .io .IOException ;
2827import java .io .Writer ;
29- import java .util .ArrayList ;
30- import java .util .List ;
31- import java .util .Properties ;
32- import java .util .ServiceLoader ;
28+ import java .util .*;
3329
3430import static io .ebeaninternal .api .PlatformMatch .matchPlatform ;
3531import static java .lang .System .Logger .Level .*;
@@ -61,8 +57,8 @@ public class DefaultDbMigration implements DbMigration {
6157 private static final String initialVersion = "1.0" ;
6258 private static final String GENERATED_COMMENT = "THIS IS A GENERATED FILE - DO NOT MODIFY" ;
6359
64- private final List <DatabasePlatformProvider > platformProviders = new ArrayList <>();
65- protected final boolean online ;
60+ private List <DatabasePlatformProvider > platformProviders = new ArrayList <>();
61+ protected boolean online ;
6662 private boolean logToSystemOut = true ;
6763 protected SpiEbeanServer server ;
6864 protected String pathToResources = "src/main/resources" ;
@@ -77,8 +73,10 @@ public class DefaultDbMigration implements DbMigration {
7773 protected List <Pair > platforms = new ArrayList <>();
7874 protected DatabaseConfig databaseConfig ;
7975 protected DbConstraintNaming constraintNaming ;
76+ @ Deprecated
8077 protected Boolean strictMode ;
81- protected Boolean includeGeneratedFileComment ;
78+ protected boolean includeGeneratedFileComment ;
79+ @ Deprecated
8280 protected String header ;
8381 protected String applyPrefix = "" ;
8482 protected String version ;
@@ -88,6 +86,9 @@ public class DefaultDbMigration implements DbMigration {
8886 private int lockTimeoutSeconds ;
8987 protected boolean includeBuiltInPartitioning = true ;
9088 protected boolean includeIndex ;
89+ protected boolean generate = false ;
90+ protected boolean generateInit = false ;
91+ private boolean keepLastInit = true ;
9192
9293 /**
9394 * Create for offline migration generation.
@@ -123,12 +124,66 @@ public void setServerConfig(DatabaseConfig config) {
123124 if (constraintNaming == null ) {
124125 this .constraintNaming = databaseConfig .getConstraintNaming ();
125126 }
127+ if (databasePlatform == null ) {
128+ this .databasePlatform = databaseConfig .getDatabasePlatform ();
129+ }
126130 Properties properties = config .getProperties ();
127131 if (properties != null ) {
128- PropertiesWrapper props = new PropertiesWrapper ("ebean" , config .getName (), properties , null );
132+ PropertiesWrapper props = new PropertiesWrapper ("ebean" , config .getName (), properties , config . getClassLoadConfig () );
129133 migrationPath = props .get ("migration.migrationPath" , migrationPath );
130134 migrationInitPath = props .get ("migration.migrationInitPath" , migrationInitPath );
131135 pathToResources = props .get ("migration.pathToResources" , pathToResources );
136+ addForeignKeySkipCheck = props .getBoolean ("migration.addForeignKeySkipCheck" , addForeignKeySkipCheck );
137+ applyPrefix = props .get ("migration.applyPrefix" , applyPrefix );
138+ databasePlatform = props .createInstance (DatabasePlatform .class , "migration.databasePlatform" , databasePlatform );
139+ generatePendingDrop = props .get ("migration.generatePendingDrop" , generatePendingDrop );
140+ includeBuiltInPartitioning = props .getBoolean ("migration.includeBuiltInPartitioning" , includeBuiltInPartitioning );
141+ includeGeneratedFileComment = props .getBoolean ("migration.includeGeneratedFileComment" , includeGeneratedFileComment );
142+ includeIndex = props .getBoolean ("migration.includeIndex" , includeIndex );
143+ lockTimeoutSeconds = props .getInt ("migration.lockTimeoutSeconds" , lockTimeoutSeconds );
144+ logToSystemOut = props .getBoolean ("migration.logToSystemOut" , logToSystemOut );
145+ modelPath = props .get ("migration.modelPath" , modelPath );
146+ modelSuffix = props .get ("migration.modelSuffix" , modelSuffix );
147+ name = props .get ("migration.name" , name );
148+ online = props .getBoolean ("migration.online" , online );
149+ vanillaPlatform = props .getBoolean ("migration.vanillaPlatform" , vanillaPlatform );
150+ version = props .get ("migration.version" , version );
151+ generate = props .getBoolean ("migration.generate" , generate );
152+ generateInit = props .getBoolean ("migration.generateInit" , generateInit );
153+ // header & strictMode must be configured at DatabaseConfig level
154+ parsePlatforms (props , config );
155+ }
156+ }
157+
158+ protected void parsePlatforms (PropertiesWrapper props , DatabaseConfig config ) {
159+ String platforms = props .get ("migration.platforms" );
160+ if (platforms == null || platforms .isEmpty ()) {
161+ return ;
162+ }
163+ String [] tmp = StringHelper .splitNames (platforms );
164+ for (String plat : tmp ) {
165+ DatabasePlatform dbPlatform ;
166+ String platformName = plat ;
167+ String platformPrefix = null ;
168+ int pos = plat .indexOf ('=' );
169+ if (pos != -1 ) {
170+ platformName = plat .substring (0 , pos );
171+ platformPrefix = plat .substring (pos + 1 );
172+ }
173+
174+ if (platformName .indexOf ('.' ) == -1 ) {
175+ // parse platform as enum value
176+ Platform platform = Enum .valueOf (Platform .class , platformName .toUpperCase ());
177+ dbPlatform = platform (platform );
178+ } else {
179+ // parse platform as class
180+ dbPlatform = (DatabasePlatform ) config .getClassLoadConfig ().newInstance (platformName );
181+ }
182+ if (platformPrefix == null ) {
183+ platformPrefix = dbPlatform .platform ().name ().toLowerCase ();
184+ }
185+
186+ addDatabasePlatform (dbPlatform , platformPrefix );
132187 }
133188 }
134189
@@ -319,7 +374,18 @@ private String generateMigrationFor(boolean initMigration) throws IOException {
319374 }
320375
321376 String pendingVersion = generatePendingDrop ();
322- if (pendingVersion != null ) {
377+ if ("auto" .equals (pendingVersion )) {
378+ StringJoiner sj = new StringJoiner ("," );
379+ String diff = generateDiff (request );
380+ if (diff != null ) {
381+ sj .add (diff );
382+ request = createRequest (initMigration );
383+ }
384+ for (String pendingDrop : request .getPendingDrops ()) {
385+ sj .add (generatePendingDrop (request , pendingDrop ));
386+ }
387+ return sj .length () == 0 ? null : sj .toString ();
388+ } else if (pendingVersion != null ) {
323389 return generatePendingDrop (request , pendingVersion );
324390 } else {
325391 return generateDiff (request );
@@ -554,7 +620,7 @@ private String generateMigration(Request request, Migration dbMigration, String
554620 return null ;
555621 } else {
556622 if (!platforms .isEmpty ()) {
557- writeExtraPlatformDdl (fullVersion , request .currentModel , dbMigration , request .migrationDir );
623+ writeExtraPlatformDdl (fullVersion , request .currentModel , dbMigration , request .migrationDir , request . initMigration && keepLastInit );
558624
559625 } else if (databasePlatform != null ) {
560626 // writer needs the current model to provide table/column details for
@@ -634,12 +700,17 @@ private String toUnderScore(String name) {
634700 /**
635701 * Write any extra platform ddl.
636702 */
637- private void writeExtraPlatformDdl (String fullVersion , CurrentModel currentModel , Migration dbMigration , File writePath ) throws IOException {
703+ private void writeExtraPlatformDdl (String fullVersion , CurrentModel currentModel , Migration dbMigration , File writePath , boolean clear ) throws IOException {
638704 DdlOptions options = new DdlOptions (addForeignKeySkipCheck );
639705 for (Pair pair : platforms ) {
640706 DdlWrite writer = new DdlWrite (new MConfiguration (), currentModel .read (), options );
641707 PlatformDdlWriter platformWriter = createDdlWriter (pair .platform );
642708 File subPath = platformWriter .subPath (writePath , pair .prefix );
709+ if (clear ) {
710+ for (File existing : subPath .listFiles ()) {
711+ existing .delete ();
712+ }
713+ }
643714 platformWriter .processMigration (dbMigration , writer , subPath , fullVersion );
644715 }
645716 }
@@ -657,7 +728,7 @@ private boolean writeMigrationXml(Migration dbMigration, File resourcePath, Stri
657728 if (file .exists ()) {
658729 return false ;
659730 }
660- String comment = Boolean . TRUE . equals ( includeGeneratedFileComment ) ? GENERATED_COMMENT : null ;
731+ String comment = includeGeneratedFileComment ? GENERATED_COMMENT : null ;
661732 MigrationXmlWriter xmlWriter = new MigrationXmlWriter (comment );
662733 xmlWriter .write (dbMigration , file );
663734 return true ;
@@ -675,6 +746,9 @@ private void setDefaults() {
675746 databasePlatform = server .databasePlatform ();
676747 }
677748 if (databaseConfig != null ) {
749+ // FIXME: StrictMode and header may be defined HERE and in DatabaseConfig.
750+ // We shoild change either DefaultDbMigration or databaseConfig, so that it is only
751+ // defined on one place
678752 if (strictMode != null ) {
679753 databaseConfig .setDdlStrictMode (strictMode );
680754 }
@@ -749,15 +823,20 @@ public File migrationDirectory() {
749823 * Return the file path to write the xml and sql to.
750824 */
751825 File migrationDirectory (boolean initMigration ) {
752- // path to src/main/resources in typical maven project
753- File resourceRootDir = new File (pathToResources );
754- if (!resourceRootDir .exists ()) {
755- String msg = String .format ("Error - path to resources %s does not exist. Absolute path is %s" , pathToResources , resourceRootDir .getAbsolutePath ());
756- throw new UnknownResourcePathException (msg );
757- }
758- String resourcePath = migrationPath (initMigration );
826+ Location resourcePath = migrationPath (initMigration );
759827 // expect to be a path to something like - src/main/resources/dbmigration
760- File path = new File (resourceRootDir , resourcePath );
828+ File path ;
829+ if (resourcePath .isClassPath ()) {
830+ // path to src/main/resources in typical maven project
831+ File resourceRootDir = new File (pathToResources );
832+ if (!resourceRootDir .exists ()) {
833+ String msg = String .format ("Error - path to resources %s does not exist. Absolute path is %s" , pathToResources , resourceRootDir .getAbsolutePath ());
834+ throw new UnknownResourcePathException (msg );
835+ }
836+ path = new File (resourceRootDir , resourcePath .path ());
837+ } else {
838+ path = new File (resourcePath .path ());
839+ }
761840 if (!path .exists ()) {
762841 if (!path .mkdirs ()) {
763842 logInfo ("Warning - Unable to ensure migration directory exists at %s" , path .getAbsolutePath ());
@@ -766,8 +845,9 @@ File migrationDirectory(boolean initMigration) {
766845 return path ;
767846 }
768847
769- private String migrationPath (boolean initMigration ) {
770- return initMigration ? migrationInitPath : migrationPath ;
848+ private Location migrationPath (boolean initMigration ) {
849+ // remove classpath: or filesystem: prefix
850+ return new Location (initMigration ? migrationInitPath : migrationPath );
771851 }
772852
773853 /**
0 commit comments