1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.appender.db.jdbc;
18
19 import java.sql.DriverManager;
20 import java.sql.SQLException;
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.commons.dbcp2.ConnectionFactory;
24 import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
25 import org.apache.commons.dbcp2.PoolableConnection;
26 import org.apache.commons.dbcp2.PoolableConnectionFactory;
27 import org.apache.commons.dbcp2.PoolingDriver;
28 import org.apache.commons.pool2.ObjectPool;
29 import org.apache.commons.pool2.impl.GenericObjectPool;
30 import org.apache.logging.log4j.core.Core;
31 import org.apache.logging.log4j.core.config.Property;
32 import org.apache.logging.log4j.core.config.plugins.Plugin;
33 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
34
35
36
37
38
39
40 @Plugin(name = "PoolingDriver", category = Core.CATEGORY_NAME, elementType = "connectionSource", printObject = true)
41 public final class PoolingDriverConnectionSource extends AbstractDriverManagerConnectionSource {
42
43
44
45
46
47
48
49 public static class Builder<B extends Builder<B>> extends AbstractDriverManagerConnectionSource.Builder<B>
50 implements org.apache.logging.log4j.core.util.Builder<PoolingDriverConnectionSource> {
51
52 public static final String DEFAULT_POOL_NAME = "example";
53 private String poolName = DEFAULT_POOL_NAME;
54
55 @Override
56 public PoolingDriverConnectionSource build() {
57 try {
58 return new PoolingDriverConnectionSource(getDriverClassName(), getConnectionString(), getUserName(),
59 getPassword(), getProperties(), poolName);
60 } catch (final SQLException e) {
61 getLogger().error("Exception constructing {} to '{}'", getClass(), getConnectionString(), e);
62 return null;
63 }
64 }
65
66 public B setPoolName(final String poolName) {
67 this.poolName = poolName;
68 return asBuilder();
69 }
70 }
71
72 public static final String URL_PREFIX = "jdbc:apache:commons:dbcp:";
73
74
75 @PluginBuilderFactory
76 public static <B extends Builder<B>> B newPoolingDriverConnectionSourceBuilder() {
77 return new Builder<B>().asBuilder();
78 }
79
80 private final String poolingDriverClassName = "org.apache.commons.dbcp2.PoolingDriver";
81
82 private final String poolName;
83
84 public PoolingDriverConnectionSource(final String driverClassName, final String connectionString,
85 final char[] userName, final char[] password, final Property[] properties, final String poolName)
86 throws SQLException {
87 super(driverClassName, connectionString, URL_PREFIX + poolName, userName, password, properties);
88 this.poolName = poolName;
89 setupDriver(connectionString);
90 }
91
92 @Override
93 public String getActualConnectionString() {
94
95 return super.getActualConnectionString();
96 }
97
98 private PoolingDriver getPoolingDriver() throws SQLException {
99 final PoolingDriver driver = (PoolingDriver) DriverManager.getDriver(URL_PREFIX);
100 if (driver == null) {
101 getLogger().error("No JDBC driver for '{}'", URL_PREFIX);
102 }
103 return driver;
104 }
105
106 private void setupDriver(final String connectionString) throws SQLException {
107
108
109
110
111
112
113
114 final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(connectionString, null);
115
116
117
118
119
120
121 final PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,
122 null);
123
124
125
126
127
128
129
130
131 @SuppressWarnings("resource")
132
133 final ObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnectionFactory);
134
135
136 poolableConnectionFactory.setPool(connectionPool);
137
138 loadDriver(poolingDriverClassName);
139 final PoolingDriver driver = getPoolingDriver();
140 if (driver != null) {
141 getLogger().debug("Registering DBCP pool '{}'", poolName);
142 driver.registerPool(poolName, connectionPool);
143 }
144
145
146
147
148 }
149
150 @Override
151 public boolean stop(long timeout, TimeUnit timeUnit) {
152 try {
153 final PoolingDriver driver = getPoolingDriver();
154 if (driver != null) {
155 getLogger().debug("Closing DBCP pool '{}'", poolName);
156 driver.closePool(poolName);
157 }
158 return true;
159 } catch (Exception e) {
160 getLogger().error("Exception stopping connection source for '{}' → '{}'", getConnectionString(),
161 getActualConnectionString(), e);
162 return false;
163 }
164 }
165 }