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.domain;
19
20 import com.google.common.base.CaseFormat;
21 import com.google.common.base.Objects;
22 import lombok.Getter;
23 import org.apache.shardingsphere.infra.datasource.pool.metadata.DataSourcePoolMetaData;
24 import org.apache.shardingsphere.infra.datasource.pool.props.domain.custom.CustomDataSourcePoolProperties;
25 import org.apache.shardingsphere.infra.datasource.pool.props.domain.synonym.ConnectionPropertySynonyms;
26 import org.apache.shardingsphere.infra.datasource.pool.props.domain.synonym.PoolPropertySynonyms;
27 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
28
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.LinkedHashMap;
32 import java.util.LinkedList;
33 import java.util.Map;
34 import java.util.Map.Entry;
35 import java.util.Optional;
36
37
38
39
40 @Getter
41 public final class DataSourcePoolProperties {
42
43 private static final String UNDERSCORE = "_";
44
45 private final String poolClassName;
46
47 private final ConnectionPropertySynonyms connectionPropertySynonyms;
48
49 private final PoolPropertySynonyms poolPropertySynonyms;
50
51 private final CustomDataSourcePoolProperties customProperties;
52
53 public DataSourcePoolProperties(final String poolClassName, final Map<String, Object> props) {
54 Optional<DataSourcePoolMetaData> metaData = TypedSPILoader.findService(DataSourcePoolMetaData.class, poolClassName);
55 this.poolClassName = metaData.map(optional -> optional.getType().toString()).orElse(poolClassName);
56 Map<String, String> propertySynonyms = metaData.map(DataSourcePoolMetaData::getPropertySynonyms).orElse(Collections.emptyMap());
57 Map<String, Object> effectiveProps = convertToCamelKeys(props);
58 connectionPropertySynonyms = new ConnectionPropertySynonyms(effectiveProps, propertySynonyms);
59 poolPropertySynonyms = new PoolPropertySynonyms(effectiveProps, propertySynonyms);
60 Collection<String> transientFieldNames = metaData.map(DataSourcePoolMetaData::getTransientFieldNames).orElse(Collections.emptyList());
61 customProperties = new CustomDataSourcePoolProperties(effectiveProps, getStandardPropertyKeys(), transientFieldNames, propertySynonyms);
62 }
63
64 private Map<String, Object> convertToCamelKeys(final Map<String, Object> props) {
65 Map<String, Object> result = new LinkedHashMap<>(props.size(), 1F);
66 for (Entry<String, Object> entry : props.entrySet()) {
67 result.put(entry.getKey().contains(UNDERSCORE) ? CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, entry.getKey()) : entry.getKey(), entry.getValue());
68 }
69 return result;
70 }
71
72 private Collection<String> getStandardPropertyKeys() {
73 Collection<String> result = new LinkedList<>(connectionPropertySynonyms.getStandardPropertyKeys());
74 result.addAll(poolPropertySynonyms.getStandardPropertyKeys());
75 return result;
76 }
77
78
79
80
81
82
83 public Map<String, Object> getAllStandardProperties() {
84 Map<String, Object> result = new LinkedHashMap<>(
85 connectionPropertySynonyms.getStandardProperties().size() + poolPropertySynonyms.getStandardProperties().size() + customProperties.getProperties().size(), 1F);
86 result.putAll(connectionPropertySynonyms.getStandardProperties());
87 result.putAll(poolPropertySynonyms.getStandardProperties());
88 result.putAll(customProperties.getProperties());
89 return result;
90 }
91
92
93
94
95
96
97 public Map<String, Object> getAllLocalProperties() {
98 Map<String, Object> result = new LinkedHashMap<>(
99 connectionPropertySynonyms.getLocalProperties().size() + poolPropertySynonyms.getLocalProperties().size() + customProperties.getProperties().size(), 1F);
100 result.putAll(connectionPropertySynonyms.getLocalProperties());
101 result.putAll(poolPropertySynonyms.getLocalProperties());
102 result.putAll(customProperties.getProperties());
103 return result;
104 }
105
106 @Override
107 public boolean equals(final Object obj) {
108 return this == obj || null != obj && getClass() == obj.getClass() && equalsByProperties((DataSourcePoolProperties) obj);
109 }
110
111 private boolean equalsByProperties(final DataSourcePoolProperties props) {
112 return poolClassName.equals(props.poolClassName) && equalsByLocalProperties(props.getAllLocalProperties());
113 }
114
115 private boolean equalsByLocalProperties(final Map<String, Object> localProps) {
116 for (Entry<String, Object> entry : getAllLocalProperties().entrySet()) {
117 if (!localProps.containsKey(entry.getKey())) {
118 continue;
119 }
120 if (entry.getValue() instanceof Map) {
121 return entry.getValue().equals(localProps.get(entry.getKey()));
122 }
123 if (!String.valueOf(entry.getValue()).equals(String.valueOf(localProps.get(entry.getKey())))) {
124 return false;
125 }
126 }
127 return true;
128 }
129
130 @Override
131 public int hashCode() {
132 StringBuilder stringBuilder = new StringBuilder();
133 for (Entry<String, Object> entry : getAllLocalProperties().entrySet()) {
134 stringBuilder.append(entry.getKey()).append(entry.getValue());
135 }
136 return Objects.hashCode(poolClassName, stringBuilder.toString());
137 }
138 }