001package com.avaje.ebean.config;
002
003import com.avaje.ebean.EbeanServerFactory;
004import com.avaje.ebean.PersistenceContextScope;
005import com.avaje.ebean.annotation.Encrypted;
006import com.avaje.ebean.cache.ServerCacheFactory;
007import com.avaje.ebean.cache.ServerCacheManager;
008import com.avaje.ebean.config.dbplatform.DatabasePlatform;
009import com.avaje.ebean.config.dbplatform.DbEncrypt;
010import com.avaje.ebean.event.BeanFindController;
011import com.avaje.ebean.event.BeanPersistController;
012import com.avaje.ebean.event.BeanPersistListener;
013import com.avaje.ebean.event.BeanPostLoad;
014import com.avaje.ebean.event.BeanQueryAdapter;
015import com.avaje.ebean.event.BulkTableEventListener;
016import com.avaje.ebean.event.ServerConfigStartup;
017import com.avaje.ebean.event.TransactionEventListener;
018import com.avaje.ebean.event.changelog.ChangeLogListener;
019import com.avaje.ebean.event.changelog.ChangeLogPrepare;
020import com.avaje.ebean.event.changelog.ChangeLogRegister;
021import com.avaje.ebean.event.readaudit.ReadAuditLogger;
022import com.avaje.ebean.event.readaudit.ReadAuditPrepare;
023import com.avaje.ebean.meta.MetaInfoManager;
024import com.fasterxml.jackson.core.JsonFactory;
025
026import javax.sql.DataSource;
027import java.util.ArrayList;
028import java.util.List;
029import java.util.Properties;
030
031/**
032 * The configuration used for creating a EbeanServer.
033 * <p>
034 * Used to programmatically construct an EbeanServer and optionally register it
035 * with the Ebean singleton.
036 * </p>
037 * <p>
038 * If you just use Ebean without this programmatic configuration Ebean will read
039 * the ebean.properties file and take the configuration from there. This usually
040 * includes searching the class path and automatically registering any entity
041 * classes and listeners etc.
042 * </p>
043 * 
044 * <pre>{@code
045 * ServerConfig c = new ServerConfig();
046 * c.setName("ordh2");
047 * 
048 * // read the ebean.properties and load
049 * // those settings into this serverConfig object
050 * c.loadFromProperties();
051 * 
052 * // generate DDL and run it
053 * c.setDdlGenerate(true);
054 * c.setDdlRun(true);
055 * 
056 * // add any classes found in the app.data package
057 * c.addPackage("app.data");
058 * 
059 * // add the names of Jars that contain entities
060 * c.addJar("myJarContainingEntities.jar");
061 * c.addJar("someOtherJarContainingEntities.jar");
062 * 
063 * // register as the 'Default' server
064 * c.setDefaultServer(true);
065 * 
066 * EbeanServer server = EbeanServerFactory.create(c);
067 * 
068 * }</pre>
069 * 
070 * @see EbeanServerFactory
071 * 
072 * @author emcgreal
073 * @author rbygrave
074 */
075public class ServerConfig {
076
077  /**
078   * The EbeanServer name.
079   */
080  private String name;
081
082  private ContainerConfig containerConfig;
083
084  /**
085   * The underlying properties that were used during configuration.
086   */
087  private Properties properties;
088
089  /**
090   * The resource directory.
091   */
092  private String resourceDirectory;
093
094  /**
095   * Set to true to register this EbeanServer with the Ebean singleton.
096   */
097  private boolean register = true;
098
099  /**
100   * Set to true if this is the default/primary server.
101   */
102  private boolean defaultServer;
103
104  /**
105   * Set this to true to disable class path search.
106   */
107  private boolean disableClasspathSearch;
108
109  /**
110   * List of interesting classes such as entities, embedded, ScalarTypes,
111   * Listeners, Finders, Controllers etc.
112   */
113  private List<Class<?>> classes = new ArrayList<Class<?>>();
114
115  /**
116   * The packages that are searched for interesting classes. Only used when
117   * classes is empty/not explicitly specified.
118   */
119  private List<String> packages = new ArrayList<String>();
120
121  /**
122   * The names of Jar files that are searched for entities and other interesting
123   * classes. Only used when classes is empty/not explicitly specified.
124   */
125  private List<String> searchJars = new ArrayList<String>();
126
127  /**
128   * Class name of a classPathReader implementation.
129   */
130  private String classPathReaderClassName;
131
132  /**
133   * This is used to populate @WhoCreated, @WhoModified and
134   * support other audit features (who executed a query etc).
135   */
136  private CurrentUserProvider currentUserProvider;
137
138  /** 
139   * Config controlling the AutoTune behaviour.
140   */
141  private AutoTuneConfig autoTuneConfig = new AutoTuneConfig();
142
143  /**
144   * The JSON format used for DateTime types. Default to millis.
145   */
146  private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.MILLIS;
147
148  /**
149   * For writing JSON specify if null values or empty collections should be exluded.
150   * By default all values are included.
151   */
152  private JsonConfig.Include jsonInclude = JsonConfig.Include.ALL;
153
154  /** 
155   * The database platform name. Used to imply a DatabasePlatform to use.  
156   */
157  private String databasePlatformName;
158
159  /** 
160   * The database platform. 
161   */
162  private DatabasePlatform databasePlatform;
163
164  /**
165   * For DB's using sequences this is the number of sequence values prefetched.
166   */
167  private int databaseSequenceBatchSize = 20;
168
169  /**
170   * Suffix appended to the base table to derive the view that contains the union
171   * of the base table and the history table in order to support asOf queries.
172   */
173  private String asOfViewSuffix = "_with_history";
174
175  /**
176   * Column used to support history and 'As of' queries. This column is a timestamp range
177   * or equivalent.
178   */
179  private String asOfSysPeriod = "sys_period";
180
181  /**
182   * Suffix appended to the base table to derive the view that contains the union
183   * of the base table and the history table in order to support asOf queries.
184   */
185  private String historyTableSuffix = "_history";
186
187  /**
188   * Use for transaction scoped batch mode.
189   */
190  private PersistBatch persistBatch = PersistBatch.NONE;
191
192  /**
193   * Use for per request batch mode.
194   */
195  private PersistBatch persistBatchOnCascade = PersistBatch.NONE;
196
197  private int persistBatchSize = 20;
198
199  /** 
200   * The default batch size for lazy loading 
201   */
202  private int lazyLoadBatchSize = 10;
203
204  /** 
205   * The default batch size for 'query joins'.
206   */
207  private int queryBatchSize = 100;
208
209  private boolean eagerFetchLobs;
210
211  private boolean ddlGenerate;
212
213  private boolean ddlRun;
214
215  private boolean ddlCreateOnly;
216
217  private String ddlInitSql;
218
219  private String ddlSeedSql;
220
221  private boolean useJtaTransactionManager;
222
223  /**
224   * The external transaction manager (like Spring).
225   */
226  private ExternalTransactionManager externalTransactionManager;
227
228  /**
229   * The data source (if programmatically provided). 
230   */
231  private DataSource dataSource;
232
233  /** 
234   * The data source config. 
235   */
236  private DataSourceConfig dataSourceConfig = new DataSourceConfig();
237
238  /**
239   * The db migration config (migration resource path etc).
240   */
241  private DbMigrationConfig migrationConfig = new DbMigrationConfig();
242
243  /**
244   * The ClassLoadConfig used to detect Joda, Java8, Jackson etc and create plugin instances given a className.
245   */
246  private ClassLoadConfig classLoadConfig = new ClassLoadConfig();
247
248  /**
249   * Set to true if the DataSource uses autoCommit.
250   * <p>
251   * Indicates that Ebean should use autoCommit friendly Transactions and TransactionManager.
252   */
253  private boolean autoCommitMode;
254
255  /**
256   * Set to true if transaction begin should be started with explicit statement.
257   */
258  private boolean explicitTransactionBeginMode;
259
260  /** 
261   * The data source JNDI name if using a JNDI DataSource. 
262   */
263  private String dataSourceJndiName;
264
265  /** 
266   * The database boolean true value (typically either 1, T, or Y).
267   */
268  private String databaseBooleanTrue;
269
270  /** 
271   * The database boolean false value (typically either 0, F or N). 
272   */
273  private String databaseBooleanFalse;
274
275  /** 
276   * The naming convention. 
277   */
278  private NamingConvention namingConvention = new UnderscoreNamingConvention();
279
280  /**
281   * Naming convention used in DDL generation for primary keys, foreign keys etc.
282   */
283  private DbConstraintNaming constraintNaming = new DbConstraintNaming();
284
285  /** 
286   * Behaviour of update to include on the change properties. 
287   */
288  private boolean updateChangesOnly = true;
289
290  /**
291   * Behaviour of updates in JDBC batch to by default include all properties.
292   */
293  private boolean updateAllPropertiesInBatch = true;
294
295  /**
296   * Default behaviour for updates when cascade save on a O2M or M2M to delete any missing children.
297   */
298  private boolean updatesDeleteMissingChildren = true;
299  
300  /**
301   * Setting to indicate if UUID should be stored as binary(16) or varchar(40) or native DB type (for H2 and Postgres).
302   */
303  private DbUuid dbUuid = DbUuid.AUTO;
304
305
306  private List<BeanFindController> findControllers = new ArrayList<BeanFindController>();
307  private List<BeanPersistController> persistControllers = new ArrayList<BeanPersistController>();
308  private List<BeanPostLoad> postLoaders = new ArrayList<BeanPostLoad>();
309  private List<BeanPersistListener> persistListeners = new ArrayList<BeanPersistListener>();
310  private List<BeanQueryAdapter> queryAdapters = new ArrayList<BeanQueryAdapter>();
311  private List<BulkTableEventListener> bulkTableEventListeners = new ArrayList<BulkTableEventListener>();
312  private List<ServerConfigStartup> configStartupListeners = new ArrayList<ServerConfigStartup>();
313  private List<TransactionEventListener> transactionEventListeners = new ArrayList<TransactionEventListener>();
314
315  /**
316   * By default inserts are included in the change log.
317   */
318  private boolean changeLogIncludeInserts = true;
319
320  private ChangeLogPrepare changeLogPrepare;
321
322  private ChangeLogListener changeLogListener;
323
324  private ChangeLogRegister changeLogRegister;
325
326  private ReadAuditLogger readAuditLogger;
327
328  private ReadAuditPrepare readAuditPrepare;
329
330  private EncryptKeyManager encryptKeyManager;
331
332  private EncryptDeployManager encryptDeployManager;
333
334  private Encryptor encryptor;
335
336  private DbEncrypt dbEncrypt;
337
338  private ServerCacheFactory serverCacheFactory;
339
340  private ServerCacheManager serverCacheManager;
341
342  private boolean collectQueryStatsByNode = true;
343
344  private boolean collectQueryOrigins = true;
345
346  /**
347   * The default PersistenceContextScope used if one is not explicitly set on a query.
348   */
349  private PersistenceContextScope persistenceContextScope = PersistenceContextScope.TRANSACTION;
350
351  private JsonFactory jsonFactory;
352
353  private boolean localTimeWithNanos;
354
355  private boolean durationWithNanos;
356
357  private int maxCallStack = 5;
358
359  private boolean transactionRollbackOnChecked = true;
360
361  private boolean registerJmxMBeans = true;
362
363  // configuration for the background executor service (thread pool)
364
365  private int backgroundExecutorSchedulePoolSize = 1;
366  private int backgroundExecutorCorePoolSize = 1;
367  private int backgroundExecutorMaxPoolSize = 8;
368  private int backgroundExecutorIdleSecs = 60;
369  private int backgroundExecutorShutdownSecs = 30;
370
371  // defaults for the L2 bean caching
372
373  private int cacheWarmingDelay = 30;
374  private int cacheMaxSize = 10000;
375  private int cacheMaxIdleTime = 600;
376  private int cacheMaxTimeToLive = 60*60*6;
377
378  // defaults for the L2 query caching
379
380  private int queryCacheMaxSize = 1000;
381  private int queryCacheMaxIdleTime = 600;
382  private int queryCacheMaxTimeToLive = 60*60*6;
383  private Object objectMapper;
384
385  /**
386   * Set to true if you want eq("someProperty", null) to generate 1=1 rather than "is null" sql expression.
387   */
388  private boolean expressionEqualsWithNullAsNoop;
389
390  private String jodaLocalTimeMode;
391
392  /**
393   * Construct a Server Configuration for programmatically creating an EbeanServer.
394   */
395  public ServerConfig() {
396
397  }
398  
399  /**
400   * Return the Jackson JsonFactory to use.
401   * <p>
402   * If not set a default implementation will be used.
403   */
404  public JsonFactory getJsonFactory() {
405    return jsonFactory;
406  }
407
408  /**
409   * Set the Jackson JsonFactory to use.
410   * <p>
411   * If not set a default implementation will be used.
412   */
413  public void setJsonFactory(JsonFactory jsonFactory) {
414    this.jsonFactory = jsonFactory;
415  }
416
417  /**
418   * Return the JSON format used for DateTime types.
419   */
420  public JsonConfig.DateTime getJsonDateTime() {
421    return jsonDateTime;
422  }
423
424  /**
425   * Set the JSON format to use for DateTime types.
426   */
427  public void setJsonDateTime(JsonConfig.DateTime jsonDateTime) {
428    this.jsonDateTime = jsonDateTime;
429  }
430
431  /**
432   * Return the JSON include mode used when writing JSON.
433   */
434  public JsonConfig.Include getJsonInclude() {
435    return jsonInclude;
436  }
437
438  /**
439   * Set the JSON include mode used when writing JSON.
440   * <p>
441   * Set to NON_NULL or NON_EMPTY to suppress nulls or null & empty collections respectively.
442   * </p>
443   */
444  public void setJsonInclude(JsonConfig.Include jsonInclude) {
445    this.jsonInclude = jsonInclude;
446  }
447
448  /**
449   * Return the name of the EbeanServer.
450   */
451  public String getName() {
452    return name;
453  }
454
455  /**
456   * Set the name of the EbeanServer.
457   */
458  public void setName(String name) {
459    this.name = name;
460  }
461
462  /**
463   * Return the container / clustering configuration.
464   * <p/>
465   * The container holds all the EbeanServer instances and provides clustering communication
466   * services to all the EbeanServer instances.
467   */
468  public ContainerConfig getContainerConfig() {
469    return containerConfig;
470  }
471
472  /**
473   * Set the container / clustering configuration.
474   * <p/>
475   * The container holds all the EbeanServer instances and provides clustering communication
476   * services to all the EbeanServer instances.
477   */
478  public void setContainerConfig(ContainerConfig containerConfig) {
479    this.containerConfig = containerConfig;
480  }
481
482  /**
483   * Return true if this server should be registered with the Ebean singleton
484   * when it is created.
485   * <p>
486   * By default this is set to true.
487   * </p>
488   */
489  public boolean isRegister() {
490    return register;
491  }
492
493  /**
494   * Set to false if you do not want this server to be registered with the Ebean
495   * singleton when it is created.
496   * <p>
497   * By default this is set to true.
498   * </p>
499   */
500  public void setRegister(boolean register) {
501    this.register = register;
502  }
503
504  /**
505   * Return true if this server should be registered as the "default" server
506   * with the Ebean singleton.
507   * <p>
508   * This is only used when {@link #setRegister(boolean)} is also true.
509   * </p>
510   */
511  public boolean isDefaultServer() {
512    return defaultServer;
513  }
514
515  /**
516   * Set true if this EbeanServer should be registered as the "default" server
517   * with the Ebean singleton.
518   * <p>
519   * This is only used when {@link #setRegister(boolean)} is also true.
520   * </p>
521   */
522  public void setDefaultServer(boolean defaultServer) {
523    this.defaultServer = defaultServer;
524  }
525
526  /**
527   * Return the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
528   * support other audit features (who executed a query etc).
529   */
530  public CurrentUserProvider getCurrentUserProvider() {
531    return currentUserProvider;
532  }
533
534  /**
535   * Set the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
536   * support other audit features (who executed a query etc).
537   */
538  public void setCurrentUserProvider(CurrentUserProvider currentUserProvider) {
539    this.currentUserProvider = currentUserProvider;
540  }
541
542  /**
543   * Return the PersistBatch mode to use by default at the transaction level.
544   * <p>
545   * When INSERT or ALL is used then save(), delete() etc do not execute immediately but instead go into
546   * a JDBC batch execute buffer that is flushed. The buffer is flushed if a query is executed, transaction ends
547   * or the batch size is meet.
548   * </p>
549   */
550  public PersistBatch getPersistBatch() {
551    return persistBatch;
552  }
553
554  /**
555   * Set the JDBC batch mode to use at the transaction level.
556   * <p>
557   * When INSERT or ALL is used then save(), delete() etc do not execute immediately but instead go into
558   * a JDBC batch execute buffer that is flushed. The buffer is flushed if a query is executed, transaction ends
559   * or the batch size is meet.
560   * </p>
561   */
562  public void setPersistBatch(PersistBatch persistBatch) {
563    this.persistBatch = persistBatch;
564  }
565
566  /**
567   * Return the JDBC batch mode to use per save(), delete(), insert() or update() request.
568   * <p>
569   * This makes sense when a save() or delete() cascades and executes multiple child statements. The best case
570   * for this is when saving a master/parent bean this cascade inserts many detail/child beans.
571   * </p>
572   * <p>
573   * This only takes effect when the persistBatch mode at the transaction level does not take effect.
574   * </p>
575   */
576  public PersistBatch getPersistBatchOnCascade() {
577    return persistBatchOnCascade;
578  }
579
580  /**
581   * Set the JDBC batch mode to use per save(), delete(), insert() or update() request.
582   * <p>
583   * This makes sense when a save() or delete() etc cascades and executes multiple child statements. The best caase
584   * for this is when saving a master/parent bean this cascade inserts many detail/child beans.
585   * </p>
586   * <p>
587   * This only takes effect when the persistBatch mode at the transaction level does not take effect.
588   * </p>
589   */
590  public void setPersistBatchOnCascade(PersistBatch persistBatchOnCascade) {
591    this.persistBatchOnCascade = persistBatchOnCascade;
592  }
593
594  /**
595   * Deprecated, please migrate to using setPersistBatch().
596   * <p>
597   * Set to true if you what to use JDBC batching for persisting and deleting
598   * beans.
599   * </p>
600   * <p>
601   * With this Ebean will batch up persist requests and use the JDBC batch api.
602   * This is a performance optimisation designed to reduce the network chatter.
603   * </p>
604   * <p>
605   * When true this is equivalent to {@code setPersistBatch(PersistBatch.ALL)} or
606   * when false to {@code setPersistBatch(PersistBatch.NONE)}
607   * </p>
608   */
609  public void setPersistBatching(boolean persistBatching) {
610    this.persistBatch = (persistBatching) ? PersistBatch.ALL : PersistBatch.NONE;
611  }
612
613  /**
614   * Return the batch size used for JDBC batching. This defaults to 20.
615   */
616  public int getPersistBatchSize() {
617    return persistBatchSize;
618  }
619
620  /**
621   * Set the batch size used for JDBC batching. If unset this defaults to 20.
622   * <p>
623   * You can also set the batch size on the transaction.
624   * </p>
625   * @see com.avaje.ebean.Transaction#setBatchSize(int)
626   */
627  public void setPersistBatchSize(int persistBatchSize) {
628    this.persistBatchSize = persistBatchSize;
629  }
630
631  /**
632   * Gets the query batch size. This defaults to 100.
633   * 
634   * @return the query batch size
635   */
636  public int getQueryBatchSize() {
637    return queryBatchSize;
638  }
639
640  /**
641   * Sets the query batch size. This defaults to 100.
642   * 
643   * @param queryBatchSize
644   *          the new query batch size
645   */
646  public void setQueryBatchSize(int queryBatchSize) {
647    this.queryBatchSize = queryBatchSize;
648  }
649
650  /**
651   * Return the default batch size for lazy loading of beans and collections.
652   */
653  public int getLazyLoadBatchSize() {
654    return lazyLoadBatchSize;
655  }
656
657  /**
658   * Set the default batch size for lazy loading.
659   * <p>
660   * This is the number of beans or collections loaded when lazy loading is
661   * invoked by default.
662   * </p>
663   * <p>
664   * The default value is for this is 10 (load 10 beans or collections).
665   * </p>
666   * <p>
667   * You can explicitly control the lazy loading batch size for a given join on
668   * a query using +lazy(batchSize) or JoinConfig.
669   * </p>
670   */
671  public void setLazyLoadBatchSize(int lazyLoadBatchSize) {
672    this.lazyLoadBatchSize = lazyLoadBatchSize;
673  }
674
675  /**
676   * Set the number of sequences to fetch/preallocate when using DB sequences.
677   * <p>
678   * This is a performance optimisation to reduce the number times Ebean
679   * requests a sequence to be used as an Id for a bean (aka reduce network
680   * chatter).
681   * </p>
682   */
683  public void setDatabaseSequenceBatchSize(int databaseSequenceBatchSize) {
684    this.databaseSequenceBatchSize = databaseSequenceBatchSize;
685  }
686
687  /**
688   * Return the ChangeLogPrepare.
689   * <p>
690   *   This is used to set user context information to the ChangeSet in the
691   *   foreground thread prior to the logging occurring in a background thread.
692   * </p>
693   */
694  public ChangeLogPrepare getChangeLogPrepare() {
695    return changeLogPrepare;
696  }
697
698  /**
699   * Set the ChangeLogPrepare.
700   * <p>
701   *   This is used to set user context information to the ChangeSet in the
702   *   foreground thread prior to the logging occurring in a background thread.
703   * </p>
704   */
705  public void setChangeLogPrepare(ChangeLogPrepare changeLogPrepare) {
706    this.changeLogPrepare = changeLogPrepare;
707  }
708
709  /**
710   * Return the ChangeLogListener which actually performs the logging of change sets
711   * in the background.
712   */
713  public ChangeLogListener getChangeLogListener() {
714    return changeLogListener;
715  }
716
717  /**
718   * Set the ChangeLogListener which actually performs the logging of change sets
719   * in the background.
720   */
721  public void setChangeLogListener(ChangeLogListener changeLogListener) {
722    this.changeLogListener = changeLogListener;
723  }
724
725  /**
726   * Return the ChangeLogRegister which controls which ChangeLogFilter is used for each
727   * bean type and in this way provide fine grained control over which persist requests
728   * are included in the change log.
729   */
730  public ChangeLogRegister getChangeLogRegister() {
731    return changeLogRegister;
732  }
733
734  /**
735   * Set the ChangeLogRegister which controls which ChangeLogFilter is used for each
736   * bean type and in this way provide fine grained control over which persist requests
737   * are included in the change log.
738   */
739  public void setChangeLogRegister(ChangeLogRegister changeLogRegister) {
740    this.changeLogRegister = changeLogRegister;
741  }
742
743  /**
744   * Return true if inserts should be included in the change log by default.
745   */
746  public boolean isChangeLogIncludeInserts() {
747    return changeLogIncludeInserts;
748  }
749
750  /**
751   * Set if inserts should be included in the change log by default.
752   */
753  public void setChangeLogIncludeInserts(boolean changeLogIncludeInserts) {
754    this.changeLogIncludeInserts = changeLogIncludeInserts;
755  }
756
757  /**
758   * Return the ReadAuditLogger to use.
759   */
760  public ReadAuditLogger getReadAuditLogger() {
761    return readAuditLogger;
762  }
763
764  /**
765   * Set the ReadAuditLogger to use. If not set the default implementation is used
766   * which logs the read events in JSON format to a standard named SLF4J logger
767   * (which can be configured in say logback to log to a separate log file).
768   */
769  public void setReadAuditLogger(ReadAuditLogger readAuditLogger) {
770    this.readAuditLogger = readAuditLogger;
771  }
772
773  /**
774   * Return the ReadAuditPrepare to use.
775   */
776  public ReadAuditPrepare getReadAuditPrepare() {
777    return readAuditPrepare;
778  }
779
780  /**
781   * Set the ReadAuditPrepare to use.
782   * <p>
783   * It is expected that an implementation is used that read user context information
784   * (user id, user ip address etc) and sets it on the ReadEvent bean before it is sent
785   * to the ReadAuditLogger.
786   * </p>
787   */
788  public void setReadAuditPrepare(ReadAuditPrepare readAuditPrepare) {
789    this.readAuditPrepare = readAuditPrepare;
790  }
791
792  /**
793   * Return the DB migration configuration.
794   */
795  public DbMigrationConfig getMigrationConfig() {
796    return migrationConfig;
797  }
798
799  /**
800   * Set the DB migration configuration.
801   */
802  public void setMigrationConfig(DbMigrationConfig migrationConfig) {
803    this.migrationConfig = migrationConfig;
804  }
805
806  /**
807   * Return the suffix appended to the base table to derive the view that contains the union
808   * of the base table and the history table in order to support asOf queries.
809   */
810  public String getAsOfViewSuffix() {
811    return asOfViewSuffix;
812  }
813
814  /**
815   * Set the suffix appended to the base table to derive the view that contains the union
816   * of the base table and the history table in order to support asOf queries.
817   */
818  public void setAsOfViewSuffix(String asOfViewSuffix) {
819    this.asOfViewSuffix = asOfViewSuffix;
820  }
821
822  /**
823   * Return the database column used to support history and 'As of' queries. This column is a timestamp range
824   * or equivalent.
825   */
826  public String getAsOfSysPeriod() {
827    return asOfSysPeriod;
828  }
829
830  /**
831   * Set the database column used to support history and 'As of' queries. This column is a timestamp range
832   * or equivalent.
833   */
834  public void setAsOfSysPeriod(String asOfSysPeriod) {
835    this.asOfSysPeriod = asOfSysPeriod;
836  }
837
838  /**
839   * Return the history table suffix (defaults to _history).
840   */
841  public String getHistoryTableSuffix() {
842    return historyTableSuffix;
843  }
844
845  /**
846   * Set the history table suffix.
847   */
848  public void setHistoryTableSuffix(String historyTableSuffix) {
849    this.historyTableSuffix = historyTableSuffix;
850  }
851
852  /**
853   * Return true if we are running in a JTA Transaction manager.
854   */
855  public boolean isUseJtaTransactionManager() {
856    return useJtaTransactionManager;
857  }
858
859  /**
860   * Set to true if we are running in a JTA Transaction manager.
861   */
862  public void setUseJtaTransactionManager(boolean useJtaTransactionManager) {
863    this.useJtaTransactionManager = useJtaTransactionManager;
864  }
865
866  /**
867   * Return the external transaction manager.
868   */
869  public ExternalTransactionManager getExternalTransactionManager() {
870    return externalTransactionManager;
871  }
872
873  /**
874   * Set the external transaction manager.
875   */
876  public void setExternalTransactionManager(ExternalTransactionManager externalTransactionManager) {
877    this.externalTransactionManager = externalTransactionManager;
878  }
879
880  /**
881   * Return the ServerCacheFactory.
882   */
883  public ServerCacheFactory getServerCacheFactory() {
884    return serverCacheFactory;
885  }
886
887  /**
888   * Set the ServerCacheFactory to use.
889   */
890  public void setServerCacheFactory(ServerCacheFactory serverCacheFactory) {
891    this.serverCacheFactory = serverCacheFactory;
892  }
893
894  /**
895   * Return the ServerCacheManager.
896   */
897  public ServerCacheManager getServerCacheManager() {
898    return serverCacheManager;
899  }
900
901  /**
902   * Set the ServerCacheManager to use.
903   */
904  public void setServerCacheManager(ServerCacheManager serverCacheManager) {
905    this.serverCacheManager = serverCacheManager;
906  }
907
908  /**
909   * Return true if LOB's should default to fetch eager.
910   * By default this is set to false and LOB's must be explicitly fetched.
911   */
912  public boolean isEagerFetchLobs() {
913    return eagerFetchLobs;
914  }
915
916  /**
917   * Set to true if you want LOB's to be fetch eager by default.
918   * By default this is set to false and LOB's must be explicitly fetched.
919   */
920  public void setEagerFetchLobs(boolean eagerFetchLobs) {
921    this.eagerFetchLobs = eagerFetchLobs;
922  }
923
924  /**
925   * Return the max call stack to use for origin location.
926   */
927  public int getMaxCallStack() {
928    return maxCallStack;
929  }
930
931  /**
932   * Set the max call stack to use for origin location.
933   */
934  public void setMaxCallStack(int maxCallStack) {
935    this.maxCallStack = maxCallStack;
936  }
937
938  /**
939   * Return true if transactions should rollback on checked exceptions.
940   */
941  public boolean isTransactionRollbackOnChecked() {
942    return transactionRollbackOnChecked;
943  }
944
945  /**
946   * Set to true if transactions should by default rollback on checked exceptions.
947   */
948  public void setTransactionRollbackOnChecked(boolean transactionRollbackOnChecked) {
949    this.transactionRollbackOnChecked = transactionRollbackOnChecked;
950  }
951
952  /**
953   * Return true if the server should register JMX MBeans.
954   */
955  public boolean isRegisterJmxMBeans() {
956    return registerJmxMBeans;
957  }
958
959  /**
960   * Set if the server should register JMX MBeans.
961   */
962  public void setRegisterJmxMBeans(boolean registerJmxMBeans) {
963    this.registerJmxMBeans = registerJmxMBeans;
964  }
965
966  /**
967   * Return the Background executor schedule pool size. Defaults to 1.
968   */
969  public int getBackgroundExecutorSchedulePoolSize() {
970    return backgroundExecutorSchedulePoolSize;
971  }
972
973  /**
974   * Set the Background executor schedule pool size.
975   */
976  public void setBackgroundExecutorSchedulePoolSize(int backgroundExecutorSchedulePoolSize) {
977    this.backgroundExecutorSchedulePoolSize = backgroundExecutorSchedulePoolSize;
978  }
979
980  /**
981   * Return the Background executor core pool size.
982   */
983  public int getBackgroundExecutorCorePoolSize() {
984    return backgroundExecutorCorePoolSize;
985  }
986
987  /**
988   * Set the Background executor core pool size.
989   */
990  public void setBackgroundExecutorCorePoolSize(int backgroundExecutorCorePoolSize) {
991    this.backgroundExecutorCorePoolSize = backgroundExecutorCorePoolSize;
992  }
993
994  /**
995   * Return the Background executor max pool size.
996   */
997  public int getBackgroundExecutorMaxPoolSize() {
998    return backgroundExecutorMaxPoolSize;
999  }
1000
1001  /**
1002   * Set the Background executor max pool size.
1003   */
1004  public void setBackgroundExecutorMaxPoolSize(int backgroundExecutorMaxPoolSize) {
1005    this.backgroundExecutorMaxPoolSize = backgroundExecutorMaxPoolSize;
1006  }
1007
1008  /**
1009   * Return the Background executor idle seconds.
1010   */
1011  public int getBackgroundExecutorIdleSecs() {
1012    return backgroundExecutorIdleSecs;
1013  }
1014
1015  /**
1016   * Set the Background executor idle seconds.
1017   */
1018  public void setBackgroundExecutorIdleSecs(int backgroundExecutorIdleSecs) {
1019    this.backgroundExecutorIdleSecs = backgroundExecutorIdleSecs;
1020  }
1021
1022  /**
1023   * Return the Background executor shutdown seconds. This is the time allowed for the pool to shutdown nicely
1024   * before it is forced shutdown.
1025   */
1026  public int getBackgroundExecutorShutdownSecs() {
1027    return backgroundExecutorShutdownSecs;
1028  }
1029
1030  /**
1031   * Set the Background executor shutdown seconds. This is the time allowed for the pool to shutdown nicely
1032   * before it is forced shutdown.
1033   */
1034  public void setBackgroundExecutorShutdownSecs(int backgroundExecutorShutdownSecs) {
1035    this.backgroundExecutorShutdownSecs = backgroundExecutorShutdownSecs;
1036  }
1037
1038  /**
1039   * Return the cache warming delay in seconds.
1040   */
1041  public int getCacheWarmingDelay() {
1042    return cacheWarmingDelay;
1043  }
1044
1045  /**
1046   * Set the cache warming delay in seconds.
1047   */
1048  public void setCacheWarmingDelay(int cacheWarmingDelay) {
1049    this.cacheWarmingDelay = cacheWarmingDelay;
1050  }
1051
1052  /**
1053   * Return the L2 cache default max size.
1054   */
1055  public int getCacheMaxSize() {
1056    return cacheMaxSize;
1057  }
1058
1059  /**
1060   * Set the L2 cache default max size.
1061   */
1062  public void setCacheMaxSize(int cacheMaxSize) {
1063    this.cacheMaxSize = cacheMaxSize;
1064  }
1065
1066  /**
1067   * Return the L2 cache default max idle time in seconds.
1068   */
1069  public int getCacheMaxIdleTime() {
1070    return cacheMaxIdleTime;
1071  }
1072
1073  /**
1074   * Set the L2 cache default max idle time in seconds.
1075   */
1076  public void setCacheMaxIdleTime(int cacheMaxIdleTime) {
1077    this.cacheMaxIdleTime = cacheMaxIdleTime;
1078  }
1079
1080  /**
1081   * Return the L2 cache default max time to live in seconds.
1082   */
1083  public int getCacheMaxTimeToLive() {
1084    return cacheMaxTimeToLive;
1085  }
1086
1087  /**
1088   * Set the L2 cache default max time to live in seconds.
1089   */
1090  public void setCacheMaxTimeToLive(int cacheMaxTimeToLive) {
1091    this.cacheMaxTimeToLive = cacheMaxTimeToLive;
1092  }
1093
1094  /**
1095   * Return the L2 query cache default max size.
1096   */
1097  public int getQueryCacheMaxSize() {
1098    return queryCacheMaxSize;
1099  }
1100
1101  /**
1102   * Set the L2 query cache default max size.
1103   */
1104  public void setQueryCacheMaxSize(int queryCacheMaxSize) {
1105    this.queryCacheMaxSize = queryCacheMaxSize;
1106  }
1107
1108  /**
1109   * Return the L2 query cache default max idle time in seconds.
1110   */
1111  public int getQueryCacheMaxIdleTime() {
1112    return queryCacheMaxIdleTime;
1113  }
1114
1115  /**
1116   * Set the L2 query cache default max idle time in seconds.
1117   */
1118  public void setQueryCacheMaxIdleTime(int queryCacheMaxIdleTime) {
1119    this.queryCacheMaxIdleTime = queryCacheMaxIdleTime;
1120  }
1121
1122  /**
1123   * Return the L2 query cache default max time to live in seconds.
1124   */
1125  public int getQueryCacheMaxTimeToLive() {
1126    return queryCacheMaxTimeToLive;
1127  }
1128
1129  /**
1130   * Set the L2 query cache default max time to live in seconds.
1131   */
1132  public void setQueryCacheMaxTimeToLive(int queryCacheMaxTimeToLive) {
1133    this.queryCacheMaxTimeToLive = queryCacheMaxTimeToLive;
1134  }
1135
1136  /**
1137   * Return the NamingConvention.
1138   * <p>
1139   * If none has been set the default UnderscoreNamingConvention is used.
1140   * </p>
1141   */
1142  public NamingConvention getNamingConvention() {
1143    return namingConvention;
1144  }
1145
1146  /**
1147   * Set the NamingConvention.
1148   * <p>
1149   * If none is set the default UnderscoreNamingConvention is used.
1150   * </p>
1151   */
1152  public void setNamingConvention(NamingConvention namingConvention) {
1153    this.namingConvention = namingConvention;
1154  }
1155
1156  /**
1157   * Return the constraint naming convention used in DDL generation.
1158   */
1159  public DbConstraintNaming getConstraintNaming() {
1160    return constraintNaming;
1161  }
1162
1163  /**
1164   * Set the constraint naming convention used in DDL generation.
1165   */
1166  public void setConstraintNaming(DbConstraintNaming constraintNaming) {
1167    this.constraintNaming = constraintNaming;
1168  }
1169
1170  /**
1171   * Return the configuration for AutoTune.
1172   */
1173  public AutoTuneConfig getAutoTuneConfig() {
1174    return autoTuneConfig;
1175  }
1176
1177  /**
1178   * Set the configuration for AutoTune.
1179   */
1180  public void setAutoTuneConfig(AutoTuneConfig autoTuneConfig) {
1181    this.autoTuneConfig = autoTuneConfig;
1182  }
1183
1184  /**
1185   * Return the DataSource.
1186   */
1187  public DataSource getDataSource() {
1188    return dataSource;
1189  }
1190
1191  /**
1192   * Set a DataSource.
1193   */
1194  public void setDataSource(DataSource dataSource) {
1195    this.dataSource = dataSource;
1196  }
1197
1198  /**
1199   * Return the configuration to build a DataSource using Ebean's own DataSource
1200   * implementation.
1201   */
1202  public DataSourceConfig getDataSourceConfig() {
1203    return dataSourceConfig;
1204  }
1205
1206  /**
1207   * Set the configuration required to build a DataSource using Ebean's own
1208   * DataSource implementation.
1209   */
1210  public void setDataSourceConfig(DataSourceConfig dataSourceConfig) {
1211    this.dataSourceConfig = dataSourceConfig;
1212  }
1213
1214  /**
1215   * Return the JNDI name of the DataSource to use.
1216   */
1217  public String getDataSourceJndiName() {
1218    return dataSourceJndiName;
1219  }
1220
1221  /**
1222   * Set the JNDI name of the DataSource to use.
1223   * <p>
1224   * By default a prefix of "java:comp/env/jdbc/" is used to lookup the
1225   * DataSource. This prefix is not used if dataSourceJndiName starts with
1226   * "java:".
1227   * </p>
1228   */
1229  public void setDataSourceJndiName(String dataSourceJndiName) {
1230    this.dataSourceJndiName = dataSourceJndiName;
1231  }
1232  
1233  /**
1234   * Return true if autoCommit mode is on. This indicates to Ebean to use autoCommit friendly Transactions and TransactionManager.
1235   */
1236  public boolean isAutoCommitMode() {
1237    return autoCommitMode;
1238  }
1239
1240  /**
1241   * Set to true if autoCommit mode is on and Ebean should use autoCommit friendly Transactions and TransactionManager.
1242   */
1243  public void setAutoCommitMode(boolean autoCommitMode) {
1244    this.autoCommitMode = autoCommitMode;
1245  }
1246
1247  /**
1248   * Return true if transaction begin should be started with explicit statement.
1249   */
1250  public boolean isExplicitTransactionBeginMode() {
1251    return explicitTransactionBeginMode;
1252  }
1253
1254  /**
1255   * Set to true if transaction begin should be started with explicit statement.
1256   * <p>
1257   * This works for H2 and Postgres but not for Oracle - only use this if you first name
1258   * is Daryl or you have explicitly talked to Rob about this feature.
1259   * </p>
1260   * <p>
1261   * This is generally not expected to be turned on but instead allow transactions to start
1262   * implicitly which is generally the standard approach.
1263   * </p>
1264   */
1265  public void setExplicitTransactionBeginMode(boolean explicitTransactionBeginMode) {
1266    this.explicitTransactionBeginMode = explicitTransactionBeginMode;
1267  }
1268
1269  /**
1270   * Return a value used to represent TRUE in the database.
1271   * <p>
1272   * This is used for databases that do not support boolean natively.
1273   * </p>
1274   * <p>
1275   * The value returned is either a Integer or a String (e.g. "1", or "T").
1276   * </p>
1277   */
1278  public String getDatabaseBooleanTrue() {
1279    return databaseBooleanTrue;
1280  }
1281
1282  /**
1283   * Set the value to represent TRUE in the database.
1284   * <p>
1285   * This is used for databases that do not support boolean natively.
1286   * </p>
1287   * <p>
1288   * The value set is either a Integer or a String (e.g. "1", or "T").
1289   * </p>
1290   */
1291  public void setDatabaseBooleanTrue(String databaseTrue) {
1292    this.databaseBooleanTrue = databaseTrue;
1293  }
1294
1295  /**
1296   * Return a value used to represent FALSE in the database.
1297   * <p>
1298   * This is used for databases that do not support boolean natively.
1299   * </p>
1300   * <p>
1301   * The value returned is either a Integer or a String (e.g. "0", or "F").
1302   * </p>
1303   */
1304  public String getDatabaseBooleanFalse() {
1305    return databaseBooleanFalse;
1306  }
1307
1308  /**
1309   * Set the value to represent FALSE in the database.
1310   * <p>
1311   * This is used for databases that do not support boolean natively.
1312   * </p>
1313   * <p>
1314   * The value set is either a Integer or a String (e.g. "0", or "F").
1315   * </p>
1316   */
1317  public void setDatabaseBooleanFalse(String databaseFalse) {
1318    this.databaseBooleanFalse = databaseFalse;
1319  }
1320
1321  /**
1322   * Return the number of DB sequence values that should be preallocated.
1323   */
1324  public int getDatabaseSequenceBatchSize() {
1325    return databaseSequenceBatchSize;
1326  }
1327
1328  /**
1329   * Set the number of DB sequence values that should be preallocated and cached
1330   * by Ebean.
1331   * <p>
1332   * This is only used for DB's that use sequences and is a performance
1333   * optimisation. This reduces the number of times Ebean needs to get a
1334   * sequence value from the Database reducing network chatter.
1335   * </p>
1336   * <p>
1337   * By default this value is 10 so when we need another Id (and don't have one
1338   * in our cache) Ebean will fetch 10 id's from the database. Note that when
1339   * the cache drops to have full (which is 5 by default) Ebean will fetch
1340   * another batch of Id's in a background thread.
1341   * </p>
1342   */
1343  public void setDatabaseSequenceBatch(int databaseSequenceBatchSize) {
1344    this.databaseSequenceBatchSize = databaseSequenceBatchSize;
1345  }
1346
1347  /**
1348   * Return the database platform name (can be null).
1349   * <p>
1350   * If null then the platform is determined automatically via the JDBC driver
1351   * information.
1352   * </p>
1353   */
1354  public String getDatabasePlatformName() {
1355    return databasePlatformName;
1356  }
1357
1358  /**
1359   * Explicitly set the database platform name
1360   * <p>
1361   * If none is set then the platform is determined automatically via the JDBC
1362   * driver information.
1363   * </p>
1364   * <p>
1365   * This can be used when the Database Platform can not be automatically
1366   * detected from the JDBC driver (possibly 3rd party JDBC driver). It is also
1367   * useful when you want to do offline DDL generation for a database platform
1368   * that you don't have access to.
1369   * </p>
1370   * <p>
1371   * Values are oracle, h2, postgres, mysql, mssqlserver2005.
1372   * </p>
1373   * 
1374   * @see DataSourceConfig#setOffline(boolean)
1375   */
1376  public void setDatabasePlatformName(String databasePlatformName) {
1377    this.databasePlatformName = databasePlatformName;
1378  }
1379
1380  /**
1381   * Return the database platform to use for this server.
1382   */
1383  public DatabasePlatform getDatabasePlatform() {
1384    return databasePlatform;
1385  }
1386
1387  /**
1388   * Explicitly set the database platform to use.
1389   * <p>
1390   * If none is set then the platform is determined via the databasePlatformName
1391   * or automatically via the JDBC driver information.
1392   * </p>
1393   */
1394  public void setDatabasePlatform(DatabasePlatform databasePlatform) {
1395    this.databasePlatform = databasePlatform;
1396  }
1397
1398  /**
1399   * Return the EncryptKeyManager.
1400   */
1401  public EncryptKeyManager getEncryptKeyManager() {
1402    return encryptKeyManager;
1403  }
1404
1405  /**
1406   * Set the EncryptKeyManager.
1407   * <p>
1408   * This is required when you want to use encrypted properties.
1409   * </p>
1410   * <p>
1411   * You can also set this in ebean.proprerties:
1412   * </p>
1413   * 
1414   * <pre class="code">
1415   * # set via ebean.properties
1416   * 
1417   * ebean.encryptKeyManager=com.avaje.tests.basic.encrypt.BasicEncyptKeyManager
1418   * </pre>
1419   */
1420  public void setEncryptKeyManager(EncryptKeyManager encryptKeyManager) {
1421    this.encryptKeyManager = encryptKeyManager;
1422  }
1423
1424  /**
1425   * Return the EncryptDeployManager.
1426   * <p>
1427   * This is optionally used to programmatically define which columns are
1428   * encrypted instead of using the {@link Encrypted} Annotation.
1429   * </p>
1430   */
1431  public EncryptDeployManager getEncryptDeployManager() {
1432    return encryptDeployManager;
1433  }
1434
1435  /**
1436   * Set the EncryptDeployManager.
1437   * <p>
1438   * This is optionally used to programmatically define which columns are
1439   * encrypted instead of using the {@link Encrypted} Annotation.
1440   * </p>
1441   */
1442  public void setEncryptDeployManager(EncryptDeployManager encryptDeployManager) {
1443    this.encryptDeployManager = encryptDeployManager;
1444  }
1445
1446  /**
1447   * Return the Encryptor used to encrypt data on the java client side (as
1448   * opposed to DB encryption functions).
1449   */
1450  public Encryptor getEncryptor() {
1451    return encryptor;
1452  }
1453
1454  /**
1455   * Set the Encryptor used to encrypt data on the java client side (as opposed
1456   * to DB encryption functions).
1457   * <p>
1458   * Ebean has a default implementation that it will use if you do not set your
1459   * own Encryptor implementation.
1460   * </p>
1461   */
1462  public void setEncryptor(Encryptor encryptor) {
1463    this.encryptor = encryptor;
1464  }
1465
1466  /**
1467   * Return the DbEncrypt used to encrypt and decrypt properties.
1468   * <p>
1469   * Note that if this is not set then the DbPlatform may already have a
1470   * DbEncrypt set and that will be used.
1471   * </p>
1472   */
1473  public DbEncrypt getDbEncrypt() {
1474    return dbEncrypt;
1475  }
1476
1477  /**
1478   * Set the DbEncrypt used to encrypt and decrypt properties.
1479   * <p>
1480   * Note that if this is not set then the DbPlatform may already have a
1481   * DbEncrypt set (H2, MySql, Postgres and Oracle platforms have a DbEncrypt)
1482   * </p>
1483   */
1484  public void setDbEncrypt(DbEncrypt dbEncrypt) {
1485    this.dbEncrypt = dbEncrypt;
1486  }
1487
1488  /**
1489   * Return the DB type used to store UUID.
1490   */
1491  public DbUuid getDbUuid() {
1492    return dbUuid;
1493  }
1494
1495  /**
1496   * Set the DB type used to store UUID.
1497   */
1498  public void setDbUuid(DbUuid dbUuid) {
1499    this.dbUuid = dbUuid;
1500  }
1501
1502  /**
1503   * Return true if LocalTime should be persisted with nanos precision.
1504   */
1505  public boolean isLocalTimeWithNanos() {
1506    return localTimeWithNanos;
1507  }
1508
1509  /**
1510   * Set to true if LocalTime should be persisted with nanos precision.
1511   * <p>
1512   * Otherwise it is persisted using java.sql.Time which is seconds precision.
1513   * </p>
1514   */
1515  public void setLocalTimeWithNanos(boolean localTimeWithNanos) {
1516    this.localTimeWithNanos = localTimeWithNanos;
1517  }
1518
1519  /**
1520   * Return true if Duration should be persisted with nanos precision (SQL DECIMAL).
1521   * <p>
1522   * Otherwise it is persisted with second precision (SQL INTEGER).
1523   * </p>
1524   */
1525  public boolean isDurationWithNanos() {
1526    return durationWithNanos;
1527  }
1528
1529  /**
1530   * Set to true if Duration should be persisted with nanos precision (SQL DECIMAL).
1531   * <p>
1532   * Otherwise it is persisted with second precision (SQL INTEGER).
1533   * </p>
1534   */
1535  public void setDurationWithNanos(boolean durationWithNanos) {
1536    this.durationWithNanos = durationWithNanos;
1537  }
1538
1539  /**
1540   * Set to true to generate the "create all" DDL on startup.
1541   *
1542   * Typically we want this on when we are running tests locally (and often using H2)
1543   * and we want to create the full DB schema from scratch to run tests.
1544   */
1545  public void setDdlGenerate(boolean ddlGenerate) {
1546    this.ddlGenerate = ddlGenerate;
1547  }
1548
1549  /**
1550   * Set to true to run the generated "create all DDL" on startup.
1551   *
1552   * Typically we want this on when we are running tests locally (and often using H2)
1553   * and we want to create the full DB schema from scratch to run tests.
1554   */
1555  public void setDdlRun(boolean ddlRun) {
1556    this.ddlRun = ddlRun;
1557  }
1558
1559  /**
1560   * Return true if the "drop all ddl" should be skipped.
1561   *
1562   * Typically we want to do this when using H2 (in memory) as our test database and the drop statements
1563   * are not required so skipping the drop table statements etc makes it faster with less noise in the logs.
1564   */
1565  public boolean isDdlCreateOnly() {
1566    return ddlCreateOnly;
1567  }
1568
1569  /**
1570   * Set to true if the "drop all ddl" should be skipped.
1571   *
1572   * Typically we want to do this when using H2 (in memory) as our test database and the drop statements
1573   * are not required so skipping the drop table statements etc makes it faster with less noise in the logs.
1574   */
1575  public void setDdlCreateOnly(boolean ddlCreateOnly) {
1576    this.ddlCreateOnly = ddlCreateOnly;
1577  }
1578
1579  /**
1580   * Return SQL script to execute after the "create all" DDL has been run.
1581   * <p>
1582   *   Typically this is a sql script that inserts test seed data when running tests.
1583   *   Place a sql script in src/test/resources that inserts test seed data.
1584   * </p>
1585   */
1586  public String getDdlSeedSql() {
1587    return ddlSeedSql;
1588  }
1589
1590  /**
1591   * Set a SQL script to execute after the "create all" DDL has been run.
1592   * <p>
1593   *   Typically this is a sql script that inserts test seed data when running tests.
1594   *   Place a sql script in src/test/resources that inserts test seed data.
1595   * </p>
1596   */
1597  public void setDdlSeedSql(String ddlSeedSql) {
1598    this.ddlSeedSql = ddlSeedSql;
1599  }
1600
1601  /**
1602   * Return a SQL script to execute before the "create all" DDL has been run.
1603   */
1604  public String getDdlInitSql() {
1605    return ddlInitSql;
1606  }
1607
1608  /**
1609   * Set a SQL script to execute before the "create all" DDL has been run.
1610   */
1611  public void setDdlInitSql(String ddlInitSql) {
1612    this.ddlInitSql = ddlInitSql;
1613  }
1614
1615  /**
1616   * Return true if the DDL should be generated.
1617   */
1618  public boolean isDdlGenerate() {
1619    return ddlGenerate;
1620  }
1621
1622  /**
1623   * Return true if the DDL should be run.
1624   */
1625  public boolean isDdlRun() {
1626    return ddlRun;
1627  }
1628
1629  /**
1630   * Return true if the class path search should be disabled.
1631   */
1632  public boolean isDisableClasspathSearch() {
1633    return disableClasspathSearch;
1634  }
1635
1636  /**
1637   * Set to true to disable the class path search even for the case where no entity bean classes
1638   * have been registered. This can be used to start an EbeanServer instance just to use the
1639   * SQL functions such as SqlQuery, SqlUpdate etc.
1640   */
1641  public void setDisableClasspathSearch(boolean disableClasspathSearch) {
1642    this.disableClasspathSearch = disableClasspathSearch;
1643  }
1644
1645  /**
1646   * Return the mode to use for Joda LocalTime support 'normal' or 'utc'.
1647   */
1648  public String getJodaLocalTimeMode() {
1649    return jodaLocalTimeMode;
1650  }
1651
1652  /**
1653   * Set the mode to use for Joda LocalTime support 'normal' or 'utc'.
1654   */
1655  public void setJodaLocalTimeMode(String jodaLocalTimeMode) {
1656    this.jodaLocalTimeMode = jodaLocalTimeMode;
1657  }
1658
1659  /**
1660   * Programmatically add classes (typically entities) that this server should
1661   * use.
1662   * <p>
1663   * The class can be an Entity, Embedded type, ScalarType, BeanPersistListener,
1664   * BeanFinder or BeanPersistController.
1665   * </p>
1666   * <p>
1667   * If no classes are specified then the classes are found automatically via
1668   * searching the class path.
1669   * </p>
1670   * <p>
1671   * Alternatively the classes can be added via {@link #setClasses(List)}.
1672   * </p>
1673   * 
1674   * @param cls
1675   *          the entity type (or other type) that should be registered by this
1676   *          server.
1677   */
1678  public void addClass(Class<?> cls) {
1679    if (classes == null) {
1680      classes = new ArrayList<Class<?>>();
1681    }
1682    classes.add(cls);
1683  }
1684
1685  /**
1686   * Add a package to search for entities via class path search.
1687   * <p>
1688   * This is only used if classes have not been explicitly specified.
1689   * </p>
1690   */
1691  public void addPackage(String packageName) {
1692    if (packages == null) {
1693      packages = new ArrayList<String>();
1694    }
1695    packages.add(packageName);
1696  }
1697
1698  /**
1699   * Return packages to search for entities via class path search.
1700   * <p>
1701   * This is only used if classes have not been explicitly specified.
1702   * </p>
1703   */
1704  public List<String> getPackages() {
1705    return packages;
1706  }
1707
1708  /**
1709   * Set packages to search for entities via class path search.
1710   * <p>
1711   * This is only used if classes have not been explicitly specified.
1712   * </p>
1713   */
1714  public void setPackages(List<String> packages) {
1715    this.packages = packages;
1716  }
1717
1718  /**
1719   * Add the name of a Jar to search for entities via class path search.
1720   * <p>
1721   * This is only used if classes have not been explicitly specified.
1722   * </p>
1723   * <p>
1724   * If you are using ebean.properties you can specify jars to search by setting
1725   * a ebean.search.jars property.
1726   * </p>
1727   * 
1728   * <pre class="code">
1729   * # EBean will search through classes for entities, but will not search jar files 
1730   * # unless you tell it to do so, for performance reasons.  Set this value to a 
1731   * # comma-delimited list of jar files you want ebean to search.
1732   * ebean.search.jars=example.jar
1733   * </pre>
1734   */
1735  public void addJar(String jarName) {
1736    if (searchJars == null) {
1737      searchJars = new ArrayList<String>();
1738    }
1739    searchJars.add(jarName);
1740  }
1741
1742  /**
1743   * Return packages to search for entities via class path search.
1744   * <p>
1745   * This is only used if classes have not been explicitly specified.
1746   * </p>
1747   */
1748  public List<String> getJars() {
1749    return searchJars;
1750  }
1751
1752  /**
1753   * Set the names of Jars to search for entities via class path search.
1754   * <p>
1755   * This is only used if classes have not been explicitly specified.
1756   * </p>
1757   */
1758  public void setJars(List<String> searchJars) {
1759    this.searchJars = searchJars;
1760  }
1761
1762  /**
1763   * Return the class name of a classPathReader implementation.
1764   */
1765  public String getClassPathReaderClassName() {
1766    return classPathReaderClassName;
1767  }
1768
1769  /**
1770   * Set the class name of a classPathReader implementation.
1771   *
1772   * Refer to server.util.ClassPathReader, this should really by a plugin but doing this for now
1773   * to be relatively compatible with current implementation.
1774   */
1775  public void setClassPathReaderClassName(String classPathReaderClassName) {
1776    this.classPathReaderClassName = classPathReaderClassName;
1777  }
1778
1779  /**
1780   * Set the list of classes (entities, listeners, scalarTypes etc) that should
1781   * be used for this server.
1782   * <p>
1783   * If no classes are specified then the classes are found automatically via
1784   * searching the class path.
1785   * </p>
1786   * <p>
1787   * Alternatively the classes can contain added via {@link #addClass(Class)}.
1788   * </p>
1789   */
1790  public void setClasses(List<Class<?>> classes) {
1791    this.classes = classes;
1792  }
1793
1794  /**
1795   * Return the classes registered for this server. Typically this includes
1796   * entities and perhaps listeners.
1797   */
1798  public List<Class<?>> getClasses() {
1799    return classes;
1800  }
1801
1802  /**
1803   * Return true to only update changed properties.
1804   */
1805  public boolean isUpdateChangesOnly() {
1806    return updateChangesOnly;
1807  }
1808
1809  /**
1810   * Set to true to only update changed properties.
1811   */
1812  public void setUpdateChangesOnly(boolean updateChangesOnly) {
1813    this.updateChangesOnly = updateChangesOnly;
1814  }
1815
1816  /**
1817   * Returns true if updates in JDBC batch default to include all properties by default.
1818   */
1819  public boolean isUpdateAllPropertiesInBatch() {
1820    return updateAllPropertiesInBatch;
1821  }
1822
1823  /**
1824   * Set to false if by default updates in JDBC batch should not include all properties.
1825   * <p>
1826   *   This mode can be explicitly set per transaction.
1827   * </p>
1828   *
1829   * @see com.avaje.ebean.Transaction#setUpdateAllLoadedProperties(boolean)
1830   */
1831  public void setUpdateAllPropertiesInBatch(boolean updateAllPropertiesInBatch) {
1832    this.updateAllPropertiesInBatch = updateAllPropertiesInBatch;
1833  }
1834
1835  /**
1836   * Return true if updates by default delete missing children when cascading save to a OneToMany or
1837   * ManyToMany. When not set this defaults to true.
1838   */
1839  public boolean isUpdatesDeleteMissingChildren() {
1840    return updatesDeleteMissingChildren;
1841  }
1842
1843  /**
1844   * Set if updates by default delete missing children when cascading save to a OneToMany or
1845   * ManyToMany. When not set this defaults to true.
1846   */
1847  public void setUpdatesDeleteMissingChildren(boolean updatesDeleteMissingChildren) {
1848    this.updatesDeleteMissingChildren = updatesDeleteMissingChildren;
1849  }
1850
1851  /**
1852   * Return true if the ebeanServer should collection query statistics by ObjectGraphNode.
1853   */
1854  public boolean isCollectQueryStatsByNode() {
1855    return collectQueryStatsByNode;
1856  }
1857
1858  /**
1859   * Set to true to collection query execution statistics by ObjectGraphNode.
1860   * <p>
1861   * These statistics can be used to highlight code/query 'origin points' that result in lots of lazy loading.
1862   * </p>
1863   * <p>
1864   * It is considered safe/fine to have this set to true for production.
1865   * </p>
1866   * <p>
1867   * This information can be later retrieved via {@link MetaInfoManager}.
1868   * </p>
1869   * @see MetaInfoManager
1870   */
1871  public void setCollectQueryStatsByNode(boolean collectQueryStatsByNode) {
1872    this.collectQueryStatsByNode = collectQueryStatsByNode;
1873  }
1874
1875  /**
1876   * Return true if query plans should also collect their 'origins'. This means for a given query plan you
1877   * can identify the code/origin points where this query resulted from including lazy loading origins.
1878   */
1879  public boolean isCollectQueryOrigins() {
1880    return collectQueryOrigins;
1881  }
1882
1883  /**
1884   * Set to true if query plans should collect their 'origin' points. This means for a given query plan you
1885   * can identify the code/origin points where this query resulted from including lazy loading origins.
1886   * <p>
1887   * This information can be later retrieved via {@link MetaInfoManager}.
1888   * </p>
1889   * @see MetaInfoManager
1890   */
1891  public void setCollectQueryOrigins(boolean collectQueryOrigins) {
1892    this.collectQueryOrigins = collectQueryOrigins;
1893  }
1894
1895  /**
1896   * Returns the resource directory.
1897   */
1898  public String getResourceDirectory() {
1899    return resourceDirectory;
1900  }
1901
1902  /**
1903   * Sets the resource directory.
1904   */
1905  public void setResourceDirectory(String resourceDirectory) {
1906    this.resourceDirectory = resourceDirectory;
1907  }
1908
1909  /**
1910   * Register a BeanQueryAdapter instance.
1911   * <p>
1912   * Note alternatively you can use {@link #setQueryAdapters(List)} to set all
1913   * the BeanQueryAdapter instances.
1914   * </p>
1915   */
1916  public void add(BeanQueryAdapter beanQueryAdapter) {
1917    queryAdapters.add(beanQueryAdapter);
1918  }
1919
1920  /**
1921   * Return the BeanQueryAdapter instances.
1922   */
1923  public List<BeanQueryAdapter> getQueryAdapters() {
1924    return queryAdapters;
1925  }
1926
1927  /**
1928   * Register all the BeanQueryAdapter instances.
1929   * <p>
1930   * Note alternatively you can use {@link #add(BeanQueryAdapter)} to add
1931   * BeanQueryAdapter instances one at a time.
1932   * </p>
1933   */
1934  public void setQueryAdapters(List<BeanQueryAdapter> queryAdapters) {
1935    this.queryAdapters = queryAdapters;
1936  }
1937
1938  /**
1939   * Register a BeanPersistController instance.
1940   * <p>
1941   * Note alternatively you can use {@link #setPersistControllers(List)} to set
1942   * all the BeanPersistController instances.
1943   * </p>
1944   */
1945  public void add(BeanPersistController beanPersistController) {
1946    persistControllers.add(beanPersistController);
1947  }
1948
1949  /**
1950   * Register a BeanPostLoad instance.
1951   * <p>
1952   * Note alternatively you can use {@link #setPostLoaders(List)} to set
1953   * all the BeanPostLoad instances.
1954   * </p>
1955   */
1956  public void add(BeanPostLoad postLoad) {
1957    postLoaders.add(postLoad);
1958  }
1959
1960  /**
1961   * Return the list of BeanFindController instances.
1962   */
1963  public List<BeanFindController> getFindControllers() {
1964    return findControllers;
1965  }
1966
1967  /**
1968   * Set the list of BeanFindController instances.
1969   */
1970  public void setFindControllers(List<BeanFindController> findControllers) {
1971    this.findControllers = findControllers;
1972  }
1973
1974  /**
1975   * Return the list of BeanPostLoader instances.
1976   */
1977  public List<BeanPostLoad> getPostLoaders() {
1978    return postLoaders;
1979  }
1980
1981  /**
1982   * Set the list of BeanPostLoader instances.
1983   */
1984  public void setPostLoaders(List<BeanPostLoad> postLoaders) {
1985    this.postLoaders = postLoaders;
1986  }
1987
1988  /**
1989   * Return the BeanPersistController instances.
1990   */
1991  public List<BeanPersistController> getPersistControllers() {
1992    return persistControllers;
1993  }
1994
1995  /**
1996   * Register all the BeanPersistController instances.
1997   * <p>
1998   * Note alternatively you can use {@link #add(BeanPersistController)} to add
1999   * BeanPersistController instances one at a time.
2000   * </p>
2001   */
2002  public void setPersistControllers(List<BeanPersistController> persistControllers) {
2003    this.persistControllers = persistControllers;
2004  }
2005
2006  /**
2007   * Register a TransactionEventListener instance
2008   * <p>
2009   * Note alternatively you can use {@link #setTransactionEventListeners(List)}
2010   * to set all the TransactionEventListener instances.
2011   * </p>
2012   */
2013  public void add(TransactionEventListener listener) {
2014    transactionEventListeners.add(listener);
2015  }
2016
2017  /**
2018   * Return the TransactionEventListener instances.
2019   */
2020  public List<TransactionEventListener> getTransactionEventListeners() {
2021    return transactionEventListeners;
2022  }
2023
2024  /**
2025   * Register all the TransactionEventListener instances.
2026   * <p>
2027   * Note alternatively you can use {@link #add(TransactionEventListener)} to
2028   * add TransactionEventListener instances one at a time.
2029   * </p>
2030   */
2031  public void setTransactionEventListeners(List<TransactionEventListener> transactionEventListeners) {
2032    this.transactionEventListeners = transactionEventListeners;
2033  }
2034
2035  /**
2036   * Register a BeanPersistListener instance.
2037   * <p>
2038   * Note alternatively you can use {@link #setPersistListeners(List)} to set
2039   * all the BeanPersistListener instances.
2040   * </p>
2041   */
2042  public void add(BeanPersistListener beanPersistListener) {
2043    persistListeners.add(beanPersistListener);
2044  }
2045
2046  /**
2047   * Return the BeanPersistListener instances.
2048   */
2049  public List<BeanPersistListener> getPersistListeners() {
2050    return persistListeners;
2051  }
2052
2053  /**
2054   * Add a BulkTableEventListener
2055   */
2056  public void add(BulkTableEventListener bulkTableEventListener) {
2057    bulkTableEventListeners.add(bulkTableEventListener);
2058  }
2059
2060  /**
2061   * Return the list of BulkTableEventListener instances.
2062   */
2063  public List<BulkTableEventListener> getBulkTableEventListeners() {
2064    return bulkTableEventListeners;
2065  }
2066
2067  /**
2068   * Add a ServerConfigStartup.
2069   */
2070  public void addServerConfigStartup(ServerConfigStartup configStartupListener) {
2071    configStartupListeners.add(configStartupListener);
2072  }
2073
2074  /**
2075   * Return the list of ServerConfigStartup instances.
2076   */
2077  public List<ServerConfigStartup> getServerConfigStartupListeners() {
2078    return configStartupListeners;
2079  }
2080
2081  /**
2082   * Register all the BeanPersistListener instances.
2083   * <p>
2084   * Note alternatively you can use {@link #add(BeanPersistListener)} to add
2085   * BeanPersistListener instances one at a time.
2086   * </p>
2087   */
2088  public void setPersistListeners(List<BeanPersistListener> persistListeners) {
2089    this.persistListeners = persistListeners;
2090  }
2091
2092  /**
2093   * Return the default PersistenceContextScope to be used if one is not explicitly set on a query.
2094   * <p/>
2095   * The PersistenceContextScope can specified on each query via {@link com.avaje.ebean
2096   * .Query#setPersistenceContextScope(com.avaje.ebean.PersistenceContextScope)}. If it
2097   * is not set on the query this default scope is used.
2098   *
2099   * @see com.avaje.ebean.Query#setPersistenceContextScope(com.avaje.ebean.PersistenceContextScope)
2100   */
2101  public PersistenceContextScope getPersistenceContextScope() {
2102    // if somehow null return TRANSACTION scope
2103    return persistenceContextScope == null ? PersistenceContextScope.TRANSACTION : persistenceContextScope;
2104  }
2105
2106  /**
2107   * Set the PersistenceContext scope to be used if one is not explicitly set on a query.
2108   * <p/>
2109   * This defaults to {@link PersistenceContextScope#TRANSACTION}.
2110   * <p/>
2111   * The PersistenceContextScope can specified on each query via {@link com.avaje.ebean
2112   * .Query#setPersistenceContextScope(com.avaje.ebean.PersistenceContextScope)}. If it
2113   * is not set on the query this scope is used.
2114   *
2115   * @see com.avaje.ebean.Query#setPersistenceContextScope(com.avaje.ebean.PersistenceContextScope)
2116   */
2117  public void setPersistenceContextScope(PersistenceContextScope persistenceContextScope) {
2118    this.persistenceContextScope = persistenceContextScope;
2119  }
2120
2121  /**
2122   * Return the ClassLoadConfig which is used to detect Joda, Java8 types etc and also
2123   * create new instances of plugins given a className.
2124   */
2125  public ClassLoadConfig getClassLoadConfig() {
2126    return classLoadConfig;
2127  }
2128
2129  /**
2130   * Set the ClassLoadConfig which is used to detect Joda, Java8 types etc and also
2131   * create new instances of plugins given a className.
2132   */
2133  public void setClassLoadConfig(ClassLoadConfig classLoadConfig) {
2134    this.classLoadConfig = classLoadConfig;
2135  }
2136
2137  /**
2138   * Load settings from ebean.properties.
2139   */
2140  public void loadFromProperties() {
2141    loadFromProperties(PropertyMap.defaultProperties());
2142  }
2143
2144  /**
2145   * Load the settings from the given properties
2146   */
2147  public void loadFromProperties(Properties properties) {
2148    // keep the properties used for configuration so that these are available for plugins
2149    this.properties = properties;
2150    PropertiesWrapper p = new PropertiesWrapper("ebean", name, properties);
2151    loadSettings(p);
2152  }
2153
2154  /**
2155   * Load settings from test-ebean.properties and do nothing if the properties is not found.
2156   * <p>
2157   * This is typically used when test-ebean.properties is put into the test class path and used
2158   * to configure Ebean for running tests.
2159   * </p>
2160   */
2161  public void loadTestProperties() {
2162    Properties properties = PropertyMap.testProperties();
2163    if (!properties.isEmpty()) {
2164      PropertiesWrapper p = new PropertiesWrapper("ebean", name, properties);
2165      loadSettings(p);
2166    }
2167  }
2168
2169  /**
2170   * Return the properties that we used for configuration and were set via a call to loadFromProperties().
2171   */
2172  public Properties getProperties() {
2173    return properties;
2174  }
2175
2176  /**
2177   * Return the instance to use (can be null) for the given plugin.
2178   *
2179   * @param properties the properties
2180   * @param pluginType the type of plugin
2181   * @param key        properties key
2182   * @param instance   existing instance
2183   */
2184  @SuppressWarnings("unchecked")
2185  protected  <T> T createInstance(PropertiesWrapper properties, Class<T> pluginType, String key, T instance) {
2186
2187    if (instance != null) {
2188      return instance;
2189    }
2190    String classname = properties.get(key, null);
2191    return createInstance(pluginType, classname);
2192  }
2193
2194  /**
2195   * Return the instance to use (can be null) for the given plugin.
2196   * @param pluginType the type of plugin
2197   * @param classname the implementation class as per properties
2198   */
2199  protected <T> T createInstance(Class<T> pluginType, String classname) {
2200    return classname == null ? null : (T) classLoadConfig.newInstance(classname);
2201  }
2202
2203  /**
2204   * loads the data source settings to preserve existing behaviour. IMHO, if someone has set the datasource config already,
2205   * they don't want the settings to be reloaded and reset. This allows a descending class to override this behaviour and prevent it
2206   * from happening.
2207   *
2208   * @param p - The defined property source passed to load settings
2209   */
2210  protected void loadDataSourceSettings(PropertiesWrapper p) {
2211    dataSourceConfig.loadSettings(p.withPrefix("datasource"));
2212  }
2213
2214  /**
2215   * This is broken out for the same reason as above - preserve existing behaviour but let it be overridden.
2216   */
2217  protected void loadAutoTuneSettings(PropertiesWrapper p) {
2218    autoTuneConfig.loadSettings(p);
2219  }
2220
2221  /**
2222   * Load the configuration settings from the properties file.
2223   */
2224  protected void loadSettings(PropertiesWrapper p) {
2225
2226    migrationConfig.loadSettings(p);
2227
2228    namingConvention = createNamingConvention(p, namingConvention);
2229    if (namingConvention != null) {
2230      namingConvention.loadFromProperties(p);
2231    }
2232    if (autoTuneConfig == null) {
2233      autoTuneConfig = new AutoTuneConfig();
2234    }
2235    loadAutoTuneSettings(p);
2236
2237    if (dataSourceConfig == null) {
2238      dataSourceConfig = new DataSourceConfig();
2239    }
2240    loadDataSourceSettings(p);
2241
2242    explicitTransactionBeginMode = p.getBoolean("explicitTransactionBeginMode", explicitTransactionBeginMode);
2243    autoCommitMode = p.getBoolean("autoCommitMode", autoCommitMode);
2244    useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", useJtaTransactionManager);
2245
2246    disableClasspathSearch = p.getBoolean("disableClasspathSearch", disableClasspathSearch);
2247    currentUserProvider = createInstance(p, CurrentUserProvider.class, "currentUserProvider", currentUserProvider);
2248    databasePlatform = createInstance(p, DatabasePlatform.class, "databasePlatform", databasePlatform);
2249    encryptKeyManager = createInstance(p, EncryptKeyManager.class, "encryptKeyManager", encryptKeyManager);
2250    encryptDeployManager = createInstance(p, EncryptDeployManager.class, "encryptDeployManager", encryptDeployManager);
2251    encryptor = createInstance(p, Encryptor.class, "encryptor", encryptor);
2252    dbEncrypt = createInstance(p, DbEncrypt.class, "dbEncrypt", dbEncrypt);
2253    serverCacheFactory = createInstance(p, ServerCacheFactory.class, "serverCacheFactory", serverCacheFactory);
2254    serverCacheManager = createInstance(p, ServerCacheManager.class, "serverCacheManager", serverCacheManager);
2255    cacheWarmingDelay = p.getInt("cacheWarmingDelay", cacheWarmingDelay);
2256    classPathReaderClassName = p.get("classpathreader");
2257    
2258    String jarsProp = p.get("search.jars", p.get("jars", null));
2259    if (jarsProp != null) {
2260      searchJars = getSearchJarsPackages(jarsProp);
2261    }
2262
2263    if (packages != null) {
2264      String packagesProp = p.get("search.packages", p.get("packages", null));
2265      packages = getSearchJarsPackages(packagesProp);
2266    }
2267
2268    collectQueryStatsByNode = p.getBoolean("collectQueryStatsByNode", collectQueryStatsByNode);
2269    collectQueryOrigins = p.getBoolean("collectQueryOrigins", collectQueryOrigins);
2270
2271    updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
2272    updateChangesOnly = p.getBoolean("updateChangesOnly", updateChangesOnly);
2273    
2274    boolean defaultDeleteMissingChildren = p.getBoolean("defaultDeleteMissingChildren", updatesDeleteMissingChildren);
2275    updatesDeleteMissingChildren = p.getBoolean("updatesDeleteMissingChildren", defaultDeleteMissingChildren);
2276
2277    if (p.get("batch.mode") != null || p.get("persistBatching") != null) {
2278      throw new IllegalArgumentException("Property 'batch.mode' or 'persistBatching' is being set but no longer used. Please change to use 'persistBatchMode'");
2279    }
2280
2281    persistBatch = p.getEnum(PersistBatch.class, "persistBatch", persistBatch);
2282    persistBatchOnCascade = p.getEnum(PersistBatch.class, "persistBatchOnCascade", persistBatchOnCascade);
2283
2284    int batchSize = p.getInt("batch.size", persistBatchSize);
2285    persistBatchSize = p.getInt("persistBatchSize", batchSize);
2286
2287    persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope", "TRANSACTION"));
2288
2289    changeLogIncludeInserts = p.getBoolean("changeLogIncludeInserts", changeLogIncludeInserts);
2290    expressionEqualsWithNullAsNoop = p.getBoolean("expressionEqualsWithNullAsNoop", expressionEqualsWithNullAsNoop);
2291
2292    asOfViewSuffix = p.get("asOfViewSuffix", asOfViewSuffix);
2293    asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod);
2294    historyTableSuffix = p.get("historyTableSuffix", historyTableSuffix);
2295    dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName);
2296    databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
2297    databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
2298    databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
2299    databasePlatformName = p.get("databasePlatformName", databasePlatformName);
2300    dbUuid = p.getEnum(DbUuid.class, "dbuuid", dbUuid);
2301    if (p.getBoolean("uuidStoreAsBinary", false)) {
2302      dbUuid = DbUuid.BINARY;
2303    }
2304    localTimeWithNanos = p.getBoolean("localTimeWithNanos", localTimeWithNanos);
2305    jodaLocalTimeMode = p.get("jodaLocalTimeMode", jodaLocalTimeMode);
2306
2307    lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", lazyLoadBatchSize);
2308    queryBatchSize = p.getInt("queryBatchSize", queryBatchSize);
2309
2310    jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude);
2311    String jsonDateTimeFormat = p.get("jsonDateTime", null);
2312    if (jsonDateTimeFormat != null) {
2313      jsonDateTime = JsonConfig.DateTime.valueOf(jsonDateTimeFormat);
2314    } else {
2315      jsonDateTime = JsonConfig.DateTime.MILLIS;
2316    }
2317
2318    ddlGenerate = p.getBoolean("ddl.generate", ddlGenerate);
2319    ddlRun = p.getBoolean("ddl.run", ddlRun);
2320    ddlCreateOnly = p.getBoolean("ddl.createOnly", ddlCreateOnly);
2321    ddlInitSql = p.get("ddl.initSql", ddlInitSql);
2322    ddlSeedSql = p.get("ddl.seedSql", ddlSeedSql);
2323
2324    classes = getClasses(p);
2325  }
2326
2327  private NamingConvention createNamingConvention(PropertiesWrapper properties, NamingConvention namingConvention) {
2328
2329    NamingConvention nc = createInstance(properties, NamingConvention.class, "namingconvention", null);
2330    return (nc != null) ? nc : namingConvention;
2331  }
2332
2333  /**
2334   * Build the list of classes from the comma delimited string.
2335   * 
2336   * @param properties
2337   *          the properties
2338   * 
2339   * @return the classes
2340   */
2341  private List<Class<?>> getClasses(PropertiesWrapper properties) {
2342
2343    String classNames = properties.get("classes", null);
2344    if (classNames == null) {
2345      return classes;
2346    }
2347
2348    List<Class<?>> classes = new ArrayList<Class<?>>();
2349
2350    String[] split = classNames.split("[ ,;]");
2351    for (int i = 0; i < split.length; i++) {
2352      String cn = split[i].trim();
2353      if (cn.length() > 0 && !"class".equalsIgnoreCase(cn)) {
2354        try {
2355          classes.add(Class.forName(cn));
2356        } catch (ClassNotFoundException e) {
2357          String msg = "Error registering class [" + cn + "] from [" + classNames + "]";
2358          throw new RuntimeException(msg, e);
2359        }
2360      }
2361    }
2362    return classes;
2363  }
2364
2365  private List<String> getSearchJarsPackages(String searchPackages) {
2366
2367    List<String> hitList = new ArrayList<String>();
2368
2369    if (searchPackages != null) {
2370
2371      String[] entries = searchPackages.split("[ ,;]");
2372      for (int i = 0; i < entries.length; i++) {
2373        hitList.add(entries[i].trim());
2374      }
2375    }
2376    return hitList;
2377  }
2378
2379  /**
2380   * Return the PersistBatch mode to use for 'batchOnCascade' taking into account if the database
2381   * platform supports getGeneratedKeys in batch mode.
2382   * <p>
2383   * Used to effectively turn off batchOnCascade for SQL Server - still allows explicit batch mode.
2384   * </p>
2385   */
2386  public PersistBatch appliedPersistBatchOnCascade() {
2387
2388    return databasePlatform.isDisallowBatchOnCascade() ? PersistBatch.NONE : persistBatchOnCascade;
2389  }
2390
2391  /**
2392   * Return the Jackson ObjectMapper.
2393   * <p>
2394   * Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
2395   * </p>
2396   */
2397  public Object getObjectMapper() {
2398    return objectMapper;
2399  }
2400
2401  /**
2402   * Set the Jackson ObjectMapper.
2403   * <p>
2404   * Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
2405   * </p>
2406   */
2407  public void setObjectMapper(Object objectMapper) {
2408    this.objectMapper = objectMapper;
2409  }
2410
2411  /**
2412   * Return true if eq("someProperty", null) should to generate "1=1" rather than "is null" sql expression.
2413   */
2414  public boolean isExpressionEqualsWithNullAsNoop() {
2415    return expressionEqualsWithNullAsNoop;
2416  }
2417
2418  /**
2419   * Set to true if you want eq("someProperty", null) to generate "1=1" rather than "is null" sql expression.
2420   * <p>
2421   *   Setting this to true has the effect that eq(propertyName, value), ieq(propertyName, value) and
2422   *   ne(propertyName, value) have no effect when the value is null. The expression factory adds a NoopExpression
2423   *   which will add "1=1" into the SQL rather than "is null".
2424   * </p>
2425   */
2426  public void setExpressionEqualsWithNullAsNoop(boolean expressionEqualsWithNullAsNoop) {
2427    this.expressionEqualsWithNullAsNoop = expressionEqualsWithNullAsNoop;
2428  }
2429
2430  /**
2431   * Specify how UUID is stored.
2432   */
2433  public enum DbUuid {
2434
2435    /**
2436     * Store using native UUID in H2 and Postgres.
2437     */
2438    AUTO,
2439
2440    /**
2441     * Store using DB VARCHAR.
2442     */
2443    VARCHAR,
2444
2445    /**
2446     * Store using DB BINARY.
2447     */
2448    BINARY
2449  }
2450}