io.ebeaninternal.server.core.InternalConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ebean Show documentation
Show all versions of ebean Show documentation
composite of common runtime dependencies for all platforms
package io.ebeaninternal.server.core;
import com.fasterxml.jackson.core.JsonFactory;
import io.ebean.ExpressionFactory;
import io.ebean.annotation.Platform;
import io.ebean.cache.ServerCacheFactory;
import io.ebean.cache.ServerCacheManager;
import io.ebean.cache.ServerCacheNotify;
import io.ebean.cache.ServerCacheNotifyPlugin;
import io.ebean.cache.ServerCacheOptions;
import io.ebean.cache.ServerCachePlugin;
import io.ebean.config.ExternalTransactionManager;
import io.ebean.config.ProfilingConfig;
import io.ebean.config.ServerConfig;
import io.ebean.config.SlowQueryListener;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbHistorySupport;
import io.ebean.event.changelog.ChangeLogListener;
import io.ebean.event.changelog.ChangeLogPrepare;
import io.ebean.event.changelog.ChangeLogRegister;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.plugin.Plugin;
import io.ebean.plugin.SpiServer;
import io.ebeaninternal.api.ExtraMetrics;
import io.ebeaninternal.api.QueryPlanManager;
import io.ebeaninternal.api.SpiBackgroundExecutor;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiJsonContext;
import io.ebeaninternal.api.SpiLogManager;
import io.ebeaninternal.api.SpiLogger;
import io.ebeaninternal.api.SpiLoggerFactory;
import io.ebeaninternal.api.SpiProfileHandler;
import io.ebeaninternal.dbmigration.DbOffline;
import io.ebeaninternal.server.autotune.AutoTuneService;
import io.ebeaninternal.server.autotune.service.AutoTuneServiceFactory;
import io.ebeaninternal.server.cache.CacheManagerOptions;
import io.ebeaninternal.server.cache.DefaultCacheAdapter;
import io.ebeaninternal.server.cache.DefaultServerCacheManager;
import io.ebeaninternal.server.cache.DefaultServerCachePlugin;
import io.ebeaninternal.server.cache.SpiCacheManager;
import io.ebeaninternal.server.changelog.DefaultChangeLogListener;
import io.ebeaninternal.server.changelog.DefaultChangeLogPrepare;
import io.ebeaninternal.server.changelog.DefaultChangeLogRegister;
import io.ebeaninternal.server.cluster.ClusterManager;
import io.ebeaninternal.server.core.bootup.BootupClasses;
import io.ebeaninternal.server.core.timezone.DataTimeZone;
import io.ebeaninternal.server.core.timezone.MySqlDataTimeZone;
import io.ebeaninternal.server.core.timezone.NoDataTimeZone;
import io.ebeaninternal.server.core.timezone.OracleDataTimeZone;
import io.ebeaninternal.server.core.timezone.SimpleDataTimeZone;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
import io.ebeaninternal.server.deploy.parse.DeployCreateProperties;
import io.ebeaninternal.server.deploy.parse.DeployInherit;
import io.ebeaninternal.server.deploy.parse.DeployUtil;
import io.ebeaninternal.server.dto.DtoBeanManager;
import io.ebeaninternal.server.expression.DefaultExpressionFactory;
import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
import io.ebeaninternal.server.expression.platform.DbExpressionHandlerFactory;
import io.ebeaninternal.server.logger.DLogManager;
import io.ebeaninternal.server.logger.DLoggerFactory;
import io.ebeaninternal.server.persist.Binder;
import io.ebeaninternal.server.persist.DefaultPersister;
import io.ebeaninternal.server.persist.platform.MultiValueBind;
import io.ebeaninternal.server.persist.platform.PostgresMultiValueBind;
import io.ebeaninternal.server.query.CQueryEngine;
import io.ebeaninternal.server.query.CQueryPlanManager;
import io.ebeaninternal.server.query.DefaultOrmQueryEngine;
import io.ebeaninternal.server.query.DefaultRelationalQueryEngine;
import io.ebeaninternal.server.query.DtoQueryEngine;
import io.ebeaninternal.server.query.QueryPlanLogger;
import io.ebeaninternal.server.query.QueryPlanLoggerExplain;
import io.ebeaninternal.server.query.QueryPlanLoggerOracle;
import io.ebeaninternal.server.query.QueryPlanLoggerPostgres;
import io.ebeaninternal.server.query.QueryPlanLoggerSqlServer;
import io.ebeaninternal.server.readaudit.DefaultReadAuditLogger;
import io.ebeaninternal.server.readaudit.DefaultReadAuditPrepare;
import io.ebeaninternal.server.text.json.DJsonContext;
import io.ebeaninternal.server.transaction.DataSourceSupplier;
import io.ebeaninternal.server.transaction.DefaultProfileHandler;
import io.ebeaninternal.server.transaction.DefaultTransactionScopeManager;
import io.ebeaninternal.server.transaction.DocStoreTransactionManager;
import io.ebeaninternal.server.transaction.ExternalTransactionScopeManager;
import io.ebeaninternal.server.transaction.JtaTransactionManager;
import io.ebeaninternal.server.transaction.NoopProfileHandler;
import io.ebeaninternal.server.transaction.TableModState;
import io.ebeaninternal.server.transaction.TransactionManager;
import io.ebeaninternal.server.transaction.TransactionManagerOptions;
import io.ebeaninternal.server.transaction.TransactionScopeManager;
import io.ebeaninternal.server.type.DefaultTypeManager;
import io.ebeaninternal.server.type.TypeManager;
import io.ebeanservice.docstore.api.DocStoreFactory;
import io.ebeanservice.docstore.api.DocStoreIntegration;
import io.ebeanservice.docstore.api.DocStoreUpdateProcessor;
import io.ebeanservice.docstore.none.NoneDocStoreFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
/**
* Used to extend the ServerConfig with additional objects used to configure and
* construct an EbeanServer.
*/
public class InternalConfiguration {
private static final Logger logger = LoggerFactory.getLogger(InternalConfiguration.class);
private final TableModState tableModState;
private final boolean online;
private final ServerConfig serverConfig;
private final BootupClasses bootupClasses;
private final DatabasePlatform databasePlatform;
private final DeployInherit deployInherit;
private final TypeManager typeManager;
private final DtoBeanManager dtoBeanManager;
private final ClockService clockService;
private final DataTimeZone dataTimeZone;
private final Binder binder;
private final DeployCreateProperties deployCreateProperties;
private final DeployUtil deployUtil;
private final BeanDescriptorManager beanDescriptorManager;
private final CQueryEngine cQueryEngine;
private final ClusterManager clusterManager;
private final SpiCacheManager cacheManager;
private final ServerCachePlugin serverCachePlugin;
private ServerCacheNotify cacheNotify;
private boolean localL2Caching;
private final ExpressionFactory expressionFactory;
private final SpiBackgroundExecutor backgroundExecutor;
private final JsonFactory jsonFactory;
private final DocStoreFactory docStoreFactory;
/**
* List of plugins (that ultimately the DefaultServer configures late in construction).
*/
private final List plugins = new ArrayList<>();
private final MultiValueBind multiValueBind;
private final SpiLogManager logManager;
private final ExtraMetrics extraMetrics = new ExtraMetrics();
InternalConfiguration(boolean online, ClusterManager clusterManager, SpiBackgroundExecutor backgroundExecutor,
ServerConfig serverConfig, BootupClasses bootupClasses) {
this.online = online;
this.serverConfig = serverConfig;
this.clockService = new ClockService(serverConfig.getClock());
this.tableModState = new TableModState();
this.logManager = initLogManager();
this.docStoreFactory = initDocStoreFactory(serverConfig.service(DocStoreFactory.class));
this.jsonFactory = serverConfig.getJsonFactory();
this.clusterManager = clusterManager;
this.backgroundExecutor = backgroundExecutor;
this.bootupClasses = bootupClasses;
this.databasePlatform = serverConfig.getDatabasePlatform();
this.expressionFactory = initExpressionFactory(serverConfig);
this.typeManager = new DefaultTypeManager(serverConfig, bootupClasses);
this.multiValueBind = createMultiValueBind(databasePlatform.getPlatform());
this.deployInherit = new DeployInherit(bootupClasses);
this.deployCreateProperties = new DeployCreateProperties(typeManager);
this.deployUtil = new DeployUtil(typeManager, serverConfig);
this.serverCachePlugin = initServerCachePlugin();
this.cacheManager = initCacheManager();
InternalConfigXmlRead xmlRead = new InternalConfigXmlRead(serverConfig);
this.dtoBeanManager = new DtoBeanManager(typeManager, xmlRead.readDtoMapping());
this.beanDescriptorManager = new BeanDescriptorManager(this);
Map asOfTableMapping = beanDescriptorManager.deploy(xmlRead.xmlDeployment());
Map draftTableMap = beanDescriptorManager.getDraftTableMap();
beanDescriptorManager.scheduleBackgroundTrim();
this.dataTimeZone = initDataTimeZone();
this.binder = getBinder(typeManager, databasePlatform, dataTimeZone);
this.cQueryEngine = new CQueryEngine(serverConfig, databasePlatform, binder, asOfTableMapping, draftTableMap);
}
private SpiLogManager initLogManager() {
// allow plugin - i.e. capture executed SQL for testing/asserts
SpiLoggerFactory loggerFactory = serverConfig.service(SpiLoggerFactory.class);
if (loggerFactory == null) {
loggerFactory = new DLoggerFactory();
}
SpiLogger sql = loggerFactory.create("io.ebean.SQL");
SpiLogger sum = loggerFactory.create("io.ebean.SUM");
SpiLogger txn = loggerFactory.create("io.ebean.TXN");
return new DLogManager(sql, sum, txn);
}
/**
* Create and return the ExpressionFactory based on configuration and database platform.
*/
private ExpressionFactory initExpressionFactory(ServerConfig serverConfig) {
boolean nativeIlike = serverConfig.isExpressionNativeIlike() && databasePlatform.isSupportsNativeIlike();
return new DefaultExpressionFactory(serverConfig.isExpressionEqualsWithNullAsNoop(), nativeIlike);
}
private DocStoreFactory initDocStoreFactory(DocStoreFactory service) {
return service == null ? new NoneDocStoreFactory() : service;
}
/**
* Return the doc store factory.
*/
public DocStoreFactory getDocStoreFactory() {
return docStoreFactory;
}
ClockService getClockService() {
return clockService;
}
public ExtraMetrics getExtraMetrics() {
return extraMetrics;
}
/**
* Check if this is a SpiServerPlugin and if so 'collect' it to give the complete list
* later on the DefaultServer for late call to configure().
*/
public T plugin(T maybePlugin) {
if (maybePlugin instanceof Plugin) {
plugins.add((Plugin) maybePlugin);
}
return maybePlugin;
}
/**
* Return the list of plugins we collected during construction.
*/
public List getPlugins() {
// find additional plugins via ServiceLoader ...
for (Plugin plugin : ServiceLoader.load(Plugin.class)) {
if (!plugins.contains(plugin)) {
plugins.add(plugin);
}
}
return plugins;
}
/**
* Return the ChangeLogPrepare to use with a default implementation if none defined.
*/
public ChangeLogPrepare changeLogPrepare(ChangeLogPrepare prepare) {
return plugin((prepare != null) ? prepare : new DefaultChangeLogPrepare());
}
/**
* Return the ChangeLogRegister to use with a default implementation if none defined.
*/
public ChangeLogRegister changeLogRegister(ChangeLogRegister register) {
boolean includeInserts = serverConfig.isChangeLogIncludeInserts();
return plugin((register != null) ? register : new DefaultChangeLogRegister(includeInserts));
}
/**
* Return the ChangeLogListener to use with a default implementation if none defined.
*/
public ChangeLogListener changeLogListener(ChangeLogListener listener) {
return plugin((listener != null) ? listener : new DefaultChangeLogListener());
}
/**
* Return the ReadAuditLogger implementation to use.
*/
ReadAuditLogger getReadAuditLogger() {
ReadAuditLogger found = bootupClasses.getReadAuditLogger();
return plugin(found != null ? found : new DefaultReadAuditLogger());
}
/**
* Return the ReadAuditPrepare implementation to use.
*/
ReadAuditPrepare getReadAuditPrepare() {
ReadAuditPrepare found = bootupClasses.getReadAuditPrepare();
return plugin(found != null ? found : new DefaultReadAuditPrepare());
}
/**
* For 'As Of' queries return the number of bind variables per predicate.
*/
private Binder getBinder(TypeManager typeManager, DatabasePlatform databasePlatform, DataTimeZone dataTimeZone) {
DbExpressionHandler jsonHandler = getDbExpressionHandler(databasePlatform);
DbHistorySupport historySupport = databasePlatform.getHistorySupport();
if (historySupport == null) {
return new Binder(typeManager, logManager, 0, false, jsonHandler, dataTimeZone, multiValueBind);
}
return new Binder(typeManager, logManager, historySupport.getBindCount(), historySupport.isStandardsBased(), jsonHandler, dataTimeZone, multiValueBind);
}
/**
* Return the JSON expression handler for the given database platform.
*/
private DbExpressionHandler getDbExpressionHandler(DatabasePlatform databasePlatform) {
return DbExpressionHandlerFactory.from(databasePlatform);
}
private MultiValueBind createMultiValueBind(Platform platform) {
// only Postgres at this stage
if (platform.base() == Platform.POSTGRES) {
return new PostgresMultiValueBind();
}
return new MultiValueBind();
}
SpiJsonContext createJsonContext(SpiEbeanServer server) {
return new DJsonContext(server, jsonFactory, typeManager);
}
AutoTuneService createAutoTuneService(SpiEbeanServer server) {
return AutoTuneServiceFactory.create(server, serverConfig);
}
DtoQueryEngine createDtoQueryEngine() {
return new DtoQueryEngine(binder);
}
RelationalQueryEngine createRelationalQueryEngine() {
return new DefaultRelationalQueryEngine(binder, serverConfig.getDatabaseBooleanTrue(), serverConfig.getPlatformConfig().getDbUuid().useBinaryOptimized());
}
OrmQueryEngine createOrmQueryEngine() {
return new DefaultOrmQueryEngine(cQueryEngine, binder);
}
Persister createPersister(SpiEbeanServer server) {
return new DefaultPersister(server, binder, beanDescriptorManager);
}
public SpiCacheManager getCacheManager() {
return cacheManager;
}
public BootupClasses getBootupClasses() {
return bootupClasses;
}
private Platform getPlatform() {
return getDatabasePlatform().getPlatform();
}
public DatabasePlatform getDatabasePlatform() {
return serverConfig.getDatabasePlatform();
}
public ServerConfig getServerConfig() {
return serverConfig;
}
public ExpressionFactory getExpressionFactory() {
return expressionFactory;
}
public Binder getBinder() {
return binder;
}
BeanDescriptorManager getBeanDescriptorManager() {
return beanDescriptorManager;
}
public DeployInherit getDeployInherit() {
return deployInherit;
}
public DeployCreateProperties getDeployCreateProperties() {
return deployCreateProperties;
}
public DeployUtil getDeployUtil() {
return deployUtil;
}
CQueryEngine getCQueryEngine() {
return cQueryEngine;
}
public SpiBackgroundExecutor getBackgroundExecutor() {
return backgroundExecutor;
}
public GeneratedPropertyFactory getGeneratedPropertyFactory() {
boolean offlineMode = serverConfig.isDbOffline() || DbOffline.isSet();
return new GeneratedPropertyFactory(offlineMode, serverConfig, bootupClasses.getIdGenerators());
}
/**
* Create the DocStoreIntegration components for the given server.
*/
DocStoreIntegration createDocStoreIntegration(SpiServer server) {
return plugin(docStoreFactory.create(server));
}
/**
* Create the TransactionManager taking into account autoCommit mode.
*/
TransactionManager createTransactionManager(DocStoreUpdateProcessor indexUpdateProcessor) {
TransactionScopeManager scopeManager = createTransactionScopeManager();
boolean notifyL2CacheInForeground = cacheManager.isLocalL2Caching() || serverConfig.isNotifyL2CacheInForeground();
TransactionManagerOptions options =
new TransactionManagerOptions(notifyL2CacheInForeground, serverConfig, scopeManager, clusterManager, backgroundExecutor,
indexUpdateProcessor, beanDescriptorManager, dataSource(), profileHandler(), logManager,
tableModState, cacheNotify, clockService);
if (serverConfig.isDocStoreOnly()) {
return new DocStoreTransactionManager(options);
}
return new TransactionManager(options);
}
private SpiProfileHandler profileHandler() {
ProfilingConfig profilingConfig = serverConfig.getProfilingConfig();
if (!profilingConfig.isEnabled()) {
return new NoopProfileHandler();
}
SpiProfileHandler handler = serverConfig.service(SpiProfileHandler.class);
if (handler == null) {
handler = new DefaultProfileHandler(profilingConfig);
}
return plugin(handler);
}
/**
* Return the DataSource supplier based on the tenancy mode.
*/
private DataSourceSupplier dataSource() {
switch (serverConfig.getTenantMode()) {
case DB:
case DB_WITH_MASTER:
return new MultiTenantDbSupplier(serverConfig.getCurrentTenantProvider(), serverConfig.getTenantDataSourceProvider());
case SCHEMA:
return new MultiTenantDbSchemaSupplier(serverConfig.getCurrentTenantProvider(), serverConfig.getDataSource(), serverConfig.getReadOnlyDataSource(), serverConfig.getTenantSchemaProvider());
case CATALOG:
return new MultiTenantDbCatalogSupplier(serverConfig.getCurrentTenantProvider(), serverConfig.getDataSource(), serverConfig.getReadOnlyDataSource(), serverConfig.getTenantCatalogProvider());
default:
return new SimpleDataSourceProvider(serverConfig.getDataSource(), serverConfig.getReadOnlyDataSource());
}
}
/**
* Create the TransactionScopeManager taking into account JTA or external transaction manager.
*/
private TransactionScopeManager createTransactionScopeManager() {
ExternalTransactionManager externalTransactionManager = serverConfig.getExternalTransactionManager();
if (externalTransactionManager == null && serverConfig.isUseJtaTransactionManager()) {
externalTransactionManager = new JtaTransactionManager();
}
if (externalTransactionManager != null) {
logger.info("Using Transaction Manager [" + externalTransactionManager.getClass() + "]");
return new ExternalTransactionScopeManager(externalTransactionManager);
} else {
return new DefaultTransactionScopeManager();
}
}
/**
* Create the DataTimeZone implementation to use.
*/
private DataTimeZone initDataTimeZone() {
String tz = serverConfig.getDataTimeZone();
if (tz == null) {
if (isMySql(getPlatform())) {
return new MySqlDataTimeZone();
}
return new NoDataTimeZone();
}
if (getPlatform().base() == Platform.ORACLE) {
return new OracleDataTimeZone(tz);
} else {
return new SimpleDataTimeZone(tz);
}
}
private boolean isMySql(Platform platform) {
return platform.base() == Platform.MYSQL;
}
public DataTimeZone getDataTimeZone() {
return dataTimeZone;
}
public ServerCacheManager cacheManager() {
return new DefaultCacheAdapter(cacheManager);
}
/**
* Return the slow query warning limit in micros.
*/
long getSlowQueryMicros() {
long millis = serverConfig.getSlowQueryMillis();
return (millis < 1) ? Long.MAX_VALUE : millis * 1000L;
}
/**
* Return the SlowQueryListener with a default that logs a warning message.
*/
SlowQueryListener getSlowQueryListener() {
long millis = serverConfig.getSlowQueryMillis();
if (millis < 1) {
return null;
}
SlowQueryListener listener = serverConfig.getSlowQueryListener();
if (listener == null) {
listener = serverConfig.service(SlowQueryListener.class);
if (listener == null) {
listener = new DefaultSlowQueryListener();
}
}
return listener;
}
/**
* Return the platform specific MultiValue bind support.
*/
public MultiValueBind getMultiValueBind() {
return multiValueBind;
}
DtoBeanManager getDtoBeanManager() {
return dtoBeanManager;
}
SpiLogManager getLogManager() {
return logManager;
}
private ServerCachePlugin initServerCachePlugin() {
if (serverConfig.isLocalOnlyL2Cache()) {
localL2Caching = true;
return new DefaultServerCachePlugin();
}
ServerCachePlugin plugin = serverConfig.getServerCachePlugin();
if (plugin == null) {
ServiceLoader cacheFactories = ServiceLoader.load(ServerCachePlugin.class);
Iterator iterator = cacheFactories.iterator();
if (iterator.hasNext()) {
// use the cacheFactory (via classpath service loader)
plugin = iterator.next();
logger.debug("using ServerCacheFactory {}", plugin.getClass());
} else {
// use the built in default l2 caching which is local cache based
localL2Caching = true;
plugin = new DefaultServerCachePlugin();
}
}
return plugin;
}
/**
* Create and return the CacheManager.
*/
private SpiCacheManager initCacheManager() {
if (!online || serverConfig.isDisableL2Cache()) {
// use local only L2 cache implementation as placeholder
return new DefaultServerCacheManager();
}
ServerCacheFactory factory = serverCachePlugin.create(serverConfig, backgroundExecutor);
ServerCacheNotifyPlugin notifyPlugin = serverConfig.service(ServerCacheNotifyPlugin.class);
if (notifyPlugin != null) {
// plugin supplied so use that to send notifications
cacheNotify = notifyPlugin.create(serverConfig);
} else {
cacheNotify = factory.createCacheNotify(tableModState);
}
// reasonable default settings are for a cache per bean type
ServerCacheOptions beanOptions = new ServerCacheOptions();
beanOptions.setMaxSize(serverConfig.getCacheMaxSize());
beanOptions.setMaxIdleSecs(serverConfig.getCacheMaxIdleTime());
beanOptions.setMaxSecsToLive(serverConfig.getCacheMaxTimeToLive());
// reasonable default settings for the query cache per bean type
ServerCacheOptions queryOptions = new ServerCacheOptions();
queryOptions.setMaxSize(serverConfig.getQueryCacheMaxSize());
queryOptions.setMaxIdleSecs(serverConfig.getQueryCacheMaxIdleTime());
queryOptions.setMaxSecsToLive(serverConfig.getQueryCacheMaxTimeToLive());
CacheManagerOptions builder = new CacheManagerOptions(clusterManager, serverConfig, localL2Caching)
.with(beanOptions, queryOptions)
.with(factory, tableModState);
return new DefaultServerCacheManager(builder);
}
public QueryPlanManager initQueryPlanManager(TransactionManager transactionManager) {
if (!serverConfig.isCollectQueryPlans()) {
return QueryPlanManager.NOOP;
}
long threshold = serverConfig.getCollectQueryPlanThresholdMicros();
return new CQueryPlanManager(transactionManager, threshold, queryPlanLogger(databasePlatform.getPlatform()), extraMetrics);
}
/**
* Returns the logger to log query plans for the given platform.
*/
QueryPlanLogger queryPlanLogger(Platform platform) {
switch (platform.base()) {
case POSTGRES:
return new QueryPlanLoggerPostgres();
case SQLSERVER:
return new QueryPlanLoggerSqlServer();
case ORACLE:
return new QueryPlanLoggerOracle();
default:
return new QueryPlanLoggerExplain();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy