001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017 018package org.apache.logging.log4j.core.appender.db.jdbc; 019 020import java.util.Arrays; 021import java.util.Collection; 022import java.util.List; 023 024import org.apache.commons.dbcp2.PoolableConnectionFactory; 025import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; 026import org.apache.logging.log4j.core.Core; 027import org.apache.logging.log4j.core.config.plugins.Plugin; 028import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; 029import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; 030import org.apache.logging.log4j.core.config.plugins.PluginElement; 031import org.apache.logging.log4j.status.StatusLogger; 032import org.apache.logging.log4j.util.Strings; 033 034/** 035 * Configures an Apache Commons DBCP {@link PoolableConnectionFactory}. 036 * 037 * @since 2.11.2 038 */ 039@Plugin(name = "PoolableConnectionFactory", category = Core.CATEGORY_NAME, printObject = true) 040public class PoolableConnectionFactoryConfig { 041 042 public static class Builder implements org.apache.logging.log4j.core.util.Builder<PoolableConnectionFactoryConfig> { 043 044 private static final PoolableConnectionFactory DEFAULT = new PoolableConnectionFactory(null, null); 045 046 /** 047 * Internal constant to indicate the level is not set. 048 */ 049 private static final int UNKNOWN_TRANSACTION_ISOLATION = -1; 050 051 // All of these instance variables match DBCP WRT Boolean vs. boolean. 052 // All of these defaults are the same as in PoolableConnectionFactory. 053 054 @PluginBuilderAttribute 055 private boolean cacheState; 056 057 // TODO 058 @PluginElement("ConnectionInitSqls") 059 private String[] connectionInitSqls; 060 061 @PluginBuilderAttribute 062 private Boolean defaultAutoCommit; 063 064 @PluginBuilderAttribute 065 private String defaultCatalog; 066 067 @PluginBuilderAttribute 068 private Integer defaultQueryTimeoutSeconds = DEFAULT.getDefaultQueryTimeout(); 069 070 @PluginBuilderAttribute 071 private Boolean defaultReadOnly; 072 073 @PluginBuilderAttribute 074 private int defaultTransactionIsolation = UNKNOWN_TRANSACTION_ISOLATION; 075 076 // TODO 077 @PluginElement("DisconnectionSqlCodes") 078 private String[] disconnectionSqlCodes = (String[]) (DEFAULT.getDisconnectionSqlCodes() == null ? null 079 : DEFAULT.getDisconnectionSqlCodes().toArray()); 080 081 @PluginBuilderAttribute 082 private boolean autoCommitOnReturn = DEFAULT.isEnableAutoCommitOnReturn(); 083 084 @PluginBuilderAttribute 085 private boolean fastFailValidation = DEFAULT.isFastFailValidation(); 086 087 @PluginBuilderAttribute 088 private long maxConnLifetimeMillis = -1; 089 090 @PluginBuilderAttribute 091 private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; 092 093 @PluginBuilderAttribute 094 private boolean poolStatements; 095 096 @PluginBuilderAttribute 097 private boolean rollbackOnReturn = DEFAULT.isRollbackOnReturn(); 098 099 @PluginBuilderAttribute 100 private String validationQuery; 101 102 @PluginBuilderAttribute 103 private int validationQueryTimeoutSeconds = -1; 104 105 private List<String> asList(final String[] array) { 106 return array == null ? null : Arrays.asList(array); 107 } 108 109 @Override 110 public PoolableConnectionFactoryConfig build() { 111 return new PoolableConnectionFactoryConfig(cacheState, asList(connectionInitSqls), defaultAutoCommit, 112 defaultCatalog, defaultQueryTimeoutSeconds, defaultReadOnly, defaultTransactionIsolation, 113 asList(disconnectionSqlCodes), autoCommitOnReturn, fastFailValidation, maxConnLifetimeMillis, 114 maxOpenPreparedStatements, poolStatements, rollbackOnReturn, validationQuery, 115 validationQueryTimeoutSeconds); 116 } 117 118 public Builder setAutoCommitOnReturn(final boolean autoCommitOnReturn) { 119 this.autoCommitOnReturn = autoCommitOnReturn; 120 return this; 121 } 122 123 public Builder setCacheState(final boolean cacheState) { 124 this.cacheState = cacheState; 125 return this; 126 } 127 128 public Builder setConnectionInitSqls(final String... connectionInitSqls) { 129 this.connectionInitSqls = connectionInitSqls; 130 return this; 131 } 132 133 public Builder setDefaultAutoCommit(final Boolean defaultAutoCommit) { 134 this.defaultAutoCommit = defaultAutoCommit; 135 return this; 136 } 137 138 public Builder setDefaultCatalog(final String defaultCatalog) { 139 this.defaultCatalog = defaultCatalog; 140 return this; 141 } 142 143 public Builder setDefaultQueryTimeoutSeconds(final Integer defaultQueryTimeoutSeconds) { 144 this.defaultQueryTimeoutSeconds = defaultQueryTimeoutSeconds; 145 return this; 146 } 147 148 public Builder setDefaultReadOnly(final Boolean defaultReadOnly) { 149 this.defaultReadOnly = defaultReadOnly; 150 return this; 151 } 152 153 public Builder setDefaultTransactionIsolation(final int defaultTransactionIsolation) { 154 this.defaultTransactionIsolation = defaultTransactionIsolation; 155 return this; 156 } 157 158 public Builder setDisconnectionSqlCodes(final String... disconnectionSqlCodes) { 159 this.disconnectionSqlCodes = disconnectionSqlCodes; 160 return this; 161 } 162 163 public Builder setFastFailValidation(final boolean fastFailValidation) { 164 this.fastFailValidation = fastFailValidation; 165 return this; 166 } 167 168 public Builder setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { 169 this.maxConnLifetimeMillis = maxConnLifetimeMillis; 170 return this; 171 } 172 173 public Builder setMaxOpenPreparedStatements(final int maxOpenPreparedStatements) { 174 this.maxOpenPreparedStatements = maxOpenPreparedStatements; 175 return this; 176 } 177 178 public Builder setPoolStatements(final boolean poolStatements) { 179 this.poolStatements = poolStatements; 180 return this; 181 } 182 183 public Builder setRollbackOnReturn(final boolean rollbackOnReturn) { 184 this.rollbackOnReturn = rollbackOnReturn; 185 return this; 186 } 187 188 public Builder setValidationQuery(final String validationQuery) { 189 this.validationQuery = validationQuery; 190 return this; 191 } 192 193 public Builder setValidationQueryTimeoutSeconds(final int validationQueryTimeoutSeconds) { 194 this.validationQueryTimeoutSeconds = validationQueryTimeoutSeconds; 195 return this; 196 } 197 } 198 199 // ALL of these instance variables match DBCP WRT Boolean vs. boolean. 200 201 @PluginBuilderFactory 202 public static Builder newBuilder() { 203 return new Builder(); 204 } 205 206 private final boolean cacheState; 207 private final Collection<String> connectionInitSqls; 208 private final Boolean defaultAutoCommit; 209 private final String defaultCatalog; 210 private final Integer defaultQueryTimeoutSeconds; 211 private final Boolean defaultReadOnly; 212 private final int defaultTransactionIsolation; 213 private final Collection<String> disconnectionSqlCodes; 214 private final boolean autoCommitOnReturn; 215 private final boolean fastFailValidation; 216 private final long maxConnLifetimeMillis; 217 private final int maxOpenPreparedStatements; 218 private final boolean poolStatements; 219 private final boolean rollbackOnReturn; 220 private final String validationQuery; 221 222 private final int validationQueryTimeoutSeconds; 223 224 private PoolableConnectionFactoryConfig(final boolean cacheState, final Collection<String> connectionInitSqls, 225 final Boolean defaultAutoCommit, final String defaultCatalog, final Integer defaultQueryTimeoutSeconds, 226 final Boolean defaultReadOnly, final int defaultTransactionIsolation, 227 final Collection<String> disconnectionSqlCodes, final boolean enableAutoCommitOnReturn, 228 final boolean fastFailValidation, final long maxConnLifetimeMillis, final int maxOpenPreparedStatements, 229 final boolean poolStatements, final boolean rollbackOnReturn, final String validationQuery, 230 final int validationQueryTimeoutSeconds) { 231 super(); 232 this.cacheState = cacheState; 233 this.connectionInitSqls = connectionInitSqls; 234 this.defaultAutoCommit = defaultAutoCommit; 235 this.defaultCatalog = Strings.trimToNull(defaultCatalog); 236 this.defaultQueryTimeoutSeconds = defaultQueryTimeoutSeconds; 237 this.defaultReadOnly = defaultReadOnly; 238 this.defaultTransactionIsolation = defaultTransactionIsolation; 239 this.disconnectionSqlCodes = disconnectionSqlCodes; 240 this.autoCommitOnReturn = enableAutoCommitOnReturn; 241 this.fastFailValidation = fastFailValidation; 242 this.maxConnLifetimeMillis = maxConnLifetimeMillis; 243 this.maxOpenPreparedStatements = maxOpenPreparedStatements; 244 this.poolStatements = poolStatements; 245 this.rollbackOnReturn = rollbackOnReturn; 246 this.validationQuery = Strings.trimToNull(validationQuery); 247 this.validationQueryTimeoutSeconds = validationQueryTimeoutSeconds; 248 } 249 250 public void init(final PoolableConnectionFactory poolableConnectionFactory) { 251 if (poolableConnectionFactory != null) { 252 StatusLogger.getLogger().debug("Initializing PoolableConnectionFactory {} with {}", 253 poolableConnectionFactory, this); 254 poolableConnectionFactory.setCacheState(cacheState); 255 poolableConnectionFactory.setConnectionInitSql(connectionInitSqls); 256 poolableConnectionFactory.setDefaultAutoCommit(defaultAutoCommit); 257 poolableConnectionFactory.setDefaultCatalog(defaultCatalog); 258 poolableConnectionFactory.setDefaultQueryTimeout(defaultQueryTimeoutSeconds); 259 poolableConnectionFactory.setDefaultReadOnly(defaultReadOnly); 260 poolableConnectionFactory.setDefaultTransactionIsolation(defaultTransactionIsolation); 261 poolableConnectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes); 262 poolableConnectionFactory.setEnableAutoCommitOnReturn(autoCommitOnReturn); 263 poolableConnectionFactory.setFastFailValidation(fastFailValidation); 264 poolableConnectionFactory.setMaxConnLifetimeMillis(maxConnLifetimeMillis); 265 poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements); 266 poolableConnectionFactory.setPoolStatements(poolStatements); 267 poolableConnectionFactory.setRollbackOnReturn(rollbackOnReturn); 268 poolableConnectionFactory.setValidationQuery(validationQuery); 269 poolableConnectionFactory.setValidationQueryTimeout(validationQueryTimeoutSeconds); 270 } 271 272 } 273 274 @Override 275 public String toString() { 276 return String.format( 277 "PoolableConnectionFactoryConfig [cacheState=%s, connectionInitSqls=%s, defaultAutoCommit=%s, defaultCatalog=%s, defaultQueryTimeoutSeconds=%s, defaultReadOnly=%s, defaultTransactionIsolation=%s, disconnectionSqlCodes=%s, enableAutoCommitOnReturn=%s, fastFailValidation=%s, maxConnLifetimeMillis=%s, maxOpenPreparedStatements=%s, poolStatements=%s, rollbackOnReturn=%s, validationQuery=%s, validationQueryTimeoutSeconds=%s]", 278 cacheState, connectionInitSqls, defaultAutoCommit, defaultCatalog, defaultQueryTimeoutSeconds, 279 defaultReadOnly, defaultTransactionIsolation, disconnectionSqlCodes, autoCommitOnReturn, 280 fastFailValidation, maxConnLifetimeMillis, maxOpenPreparedStatements, poolStatements, rollbackOnReturn, 281 validationQuery, validationQueryTimeoutSeconds); 282 } 283 284}