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