1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.infra.datasource.pool.props.creator;
19
20 import lombok.AccessLevel;
21 import lombok.NoArgsConstructor;
22 import org.apache.shardingsphere.infra.datasource.pool.CatalogSwitchableDataSource;
23 import org.apache.shardingsphere.infra.datasource.pool.config.ConnectionConfiguration;
24 import org.apache.shardingsphere.infra.datasource.pool.config.DataSourceConfiguration;
25 import org.apache.shardingsphere.infra.datasource.pool.config.PoolConfiguration;
26 import org.apache.shardingsphere.infra.datasource.pool.creator.DataSourcePoolReflection;
27 import org.apache.shardingsphere.infra.datasource.pool.metadata.DataSourcePoolMetaData;
28 import org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePoolProperties;
29 import org.apache.shardingsphere.infra.datasource.pool.props.domain.custom.CustomDataSourcePoolProperties;
30 import org.apache.shardingsphere.infra.datasource.pool.props.domain.synonym.ConnectionPropertySynonyms;
31 import org.apache.shardingsphere.infra.datasource.pool.props.domain.synonym.PoolPropertySynonyms;
32 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
33
34 import javax.sql.DataSource;
35 import java.util.LinkedHashMap;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.Optional;
39 import java.util.Properties;
40
41
42
43
44 @NoArgsConstructor(access = AccessLevel.PRIVATE)
45 public final class DataSourcePoolPropertiesCreator {
46
47
48
49
50
51
52
53 public static DataSourcePoolProperties create(final DataSourceConfiguration config) {
54 return new DataSourcePoolProperties(config.getConnection().getDataSourceClassName(), createProperties(config));
55 }
56
57
58
59
60
61
62
63 public static DataSourcePoolProperties create(final DataSource dataSource) {
64 DataSource realDataSource = dataSource instanceof CatalogSwitchableDataSource ? ((CatalogSwitchableDataSource) dataSource).getDataSource() : dataSource;
65 return new DataSourcePoolProperties(realDataSource.getClass().getName(), createProperties(realDataSource));
66 }
67
68 @SuppressWarnings({"unchecked", "rawtypes"})
69 private static Map<String, Object> createProperties(final DataSourceConfiguration config) {
70 Map<String, Object> result = new LinkedHashMap<>();
71 result.put("dataSourceClassName", config.getConnection().getDataSourceClassName());
72 result.put("url", config.getConnection().getUrl());
73 result.put("username", config.getConnection().getUsername());
74 result.put("password", config.getConnection().getPassword());
75 result.put("connectionTimeoutMilliseconds", config.getPool().getConnectionTimeoutMilliseconds());
76 result.put("idleTimeoutMilliseconds", config.getPool().getIdleTimeoutMilliseconds());
77 result.put("maxLifetimeMilliseconds", config.getPool().getMaxLifetimeMilliseconds());
78 result.put("maxPoolSize", config.getPool().getMaxPoolSize());
79 result.put("minPoolSize", config.getPool().getMinPoolSize());
80 result.put("readOnly", config.getPool().getReadOnly());
81 if (null != config.getPool().getCustomProperties()) {
82 result.putAll((Map) config.getPool().getCustomProperties());
83 }
84 return result;
85 }
86
87 private static Map<String, Object> createProperties(final DataSource dataSource) {
88 Map<String, Object> props = new DataSourcePoolReflection(dataSource).convertToProperties();
89 Map<String, Object> result = new LinkedHashMap<>(props.size(), 1F);
90 Optional<DataSourcePoolMetaData> metaData = TypedSPILoader.findService(DataSourcePoolMetaData.class, dataSource.getClass().getName());
91 for (Entry<String, Object> entry : props.entrySet()) {
92 String propertyName = entry.getKey();
93 Object propertyValue = entry.getValue();
94 if (!metaData.isPresent() || isValidProperty(propertyName, propertyValue, metaData.get()) && !metaData.get().getTransientFieldNames().contains(propertyName)) {
95 result.put(propertyName, propertyValue);
96 }
97 }
98 return result;
99 }
100
101 private static boolean isValidProperty(final String key, final Object value, final DataSourcePoolMetaData metaData) {
102 return null == value || !metaData.getSkippedProperties().containsKey(key) || !value.equals(metaData.getSkippedProperties().get(key));
103 }
104
105
106
107
108
109
110
111 public static DataSourceConfiguration createConfiguration(final DataSourcePoolProperties props) {
112 return new DataSourceConfiguration(getConnectionConfiguration(props.getConnectionPropertySynonyms()), getPoolConfiguration(props.getPoolPropertySynonyms(), props.getCustomProperties()));
113 }
114
115 private static ConnectionConfiguration getConnectionConfiguration(final ConnectionPropertySynonyms connectionPropSynonyms) {
116 Map<String, Object> standardProps = connectionPropSynonyms.getStandardProperties();
117 return new ConnectionConfiguration(
118 (String) standardProps.get("dataSourceClassName"), (String) standardProps.get("url"), (String) standardProps.get("username"), (String) standardProps.get("password"));
119 }
120
121 private static PoolConfiguration getPoolConfiguration(final PoolPropertySynonyms poolPropSynonyms, final CustomDataSourcePoolProperties customProps) {
122 Map<String, Object> standardProps = poolPropSynonyms.getStandardProperties();
123 Long connectionTimeoutMilliseconds = toLong(standardProps, "connectionTimeoutMilliseconds");
124 Long idleTimeoutMilliseconds = toLong(standardProps, "idleTimeoutMilliseconds");
125 Long maxLifetimeMilliseconds = toLong(standardProps, "maxLifetimeMilliseconds");
126 Integer maxPoolSize = toInt(standardProps, "maxPoolSize");
127 Integer minPoolSize = toInt(standardProps, "minPoolSize");
128 Boolean readOnly = toBoolean(standardProps, "readOnly");
129 Properties newCustomProps = new Properties();
130 newCustomProps.putAll(customProps.getProperties());
131 return new PoolConfiguration(connectionTimeoutMilliseconds, idleTimeoutMilliseconds, maxLifetimeMilliseconds, maxPoolSize, minPoolSize, readOnly, newCustomProps);
132 }
133
134 private static Long toLong(final Map<String, Object> props, final String name) {
135 if (!props.containsKey(name)) {
136 return null;
137 }
138 try {
139 return Long.parseLong(String.valueOf(props.get(name)));
140 } catch (final NumberFormatException ex) {
141 return null;
142 }
143 }
144
145 private static Integer toInt(final Map<String, Object> props, final String name) {
146 if (!props.containsKey(name)) {
147 return null;
148 }
149 try {
150 return Integer.parseInt(String.valueOf(props.get(name)));
151 } catch (final NumberFormatException ex) {
152 return null;
153 }
154 }
155
156 @SuppressWarnings("SameParameterValue")
157 private static Boolean toBoolean(final Map<String, Object> props, final String name) {
158 return props.containsKey(name) ? Boolean.parseBoolean(String.valueOf(props.get(name))) : null;
159 }
160 }