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