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