1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.mask.rule;
19
20 import com.cedarsoftware.util.CaseInsensitiveMap;
21 import com.cedarsoftware.util.CaseInsensitiveSet;
22 import org.apache.shardingsphere.infra.rule.PartialRuleUpdateSupported;
23 import org.apache.shardingsphere.infra.rule.attribute.RuleAttributes;
24 import org.apache.shardingsphere.infra.rule.scope.DatabaseRule;
25 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
26 import org.apache.shardingsphere.mask.config.MaskRuleConfiguration;
27 import org.apache.shardingsphere.mask.config.rule.MaskTableRuleConfiguration;
28 import org.apache.shardingsphere.mask.constant.MaskOrder;
29 import org.apache.shardingsphere.mask.rule.attribute.MaskTableMapperRuleAttribute;
30 import org.apache.shardingsphere.mask.spi.MaskAlgorithm;
31
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.Map;
35 import java.util.Optional;
36 import java.util.concurrent.ConcurrentHashMap;
37 import java.util.concurrent.atomic.AtomicReference;
38 import java.util.stream.Collectors;
39
40
41
42
43 public final class MaskRule implements DatabaseRule, PartialRuleUpdateSupported<MaskRuleConfiguration> {
44
45 private final AtomicReference<MaskRuleConfiguration> configuration = new AtomicReference<>();
46
47 private final Map<String, MaskAlgorithm<?, ?>> maskAlgorithms = new CaseInsensitiveMap<>(Collections.emptyMap(), new ConcurrentHashMap<>());
48
49 private final Map<String, MaskTable> tables = new CaseInsensitiveMap<>(Collections.emptyMap(), new ConcurrentHashMap<>());
50
51 private final AtomicReference<RuleAttributes> attributes = new AtomicReference<>();
52
53 public MaskRule(final MaskRuleConfiguration ruleConfig) {
54 configuration.set(ruleConfig);
55 ruleConfig.getMaskAlgorithms().forEach((key, value) -> maskAlgorithms.put(key, TypedSPILoader.getService(MaskAlgorithm.class, value.getType(), value.getProps())));
56 ruleConfig.getTables().forEach(each -> tables.put(each.getName(), new MaskTable(each, maskAlgorithms)));
57 attributes.set(new RuleAttributes(new MaskTableMapperRuleAttribute(tables.keySet())));
58 }
59
60
61
62
63
64
65
66 public Optional<MaskTable> findMaskTable(final String tableName) {
67 return Optional.ofNullable(tables.get(tableName));
68 }
69
70 @Override
71 public RuleAttributes getAttributes() {
72 return attributes.get();
73 }
74
75 @Override
76 public MaskRuleConfiguration getConfiguration() {
77 return configuration.get();
78 }
79
80 @Override
81 public void updateConfiguration(final MaskRuleConfiguration toBeUpdatedRuleConfig) {
82 configuration.set(toBeUpdatedRuleConfig);
83 }
84
85 @Override
86 public boolean partialUpdate(final MaskRuleConfiguration toBeUpdatedRuleConfig) {
87 handleAddedMaskAlgorithm(toBeUpdatedRuleConfig);
88 handleRemovedMaskAlgorithm(toBeUpdatedRuleConfig);
89 Collection<String> toBeUpdatedTablesNames = toBeUpdatedRuleConfig.getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toCollection(CaseInsensitiveSet::new));
90 Collection<String> toBeRemovedTableNames = tables.keySet().stream().filter(each -> !toBeUpdatedTablesNames.contains(each)).collect(Collectors.toList());
91 if (!toBeRemovedTableNames.isEmpty()) {
92 toBeRemovedTableNames.forEach(tables::remove);
93 }
94 for (MaskTableRuleConfiguration maskTableRuleConfiguration : toBeUpdatedRuleConfig.getTables()) {
95 tables.put(maskTableRuleConfiguration.getName(), new MaskTable(maskTableRuleConfiguration, maskAlgorithms));
96 attributes.set(new RuleAttributes(new MaskTableMapperRuleAttribute(tables.keySet())));
97 }
98 return false;
99 }
100
101 private void handleAddedMaskAlgorithm(final MaskRuleConfiguration toBeUpdatedRuleConfig) {
102 toBeUpdatedRuleConfig.getMaskAlgorithms().entrySet().stream()
103 .filter(entry -> !maskAlgorithms.containsKey(entry.getKey()))
104 .forEach(entry -> maskAlgorithms.computeIfAbsent(entry.getKey(), key -> TypedSPILoader.getService(MaskAlgorithm.class, entry.getValue().getType(), entry.getValue().getProps())));
105 }
106
107 private void handleRemovedMaskAlgorithm(final MaskRuleConfiguration toBeUpdatedRuleConfig) {
108 maskAlgorithms.entrySet().stream()
109 .filter(entry -> !toBeUpdatedRuleConfig.getMaskAlgorithms().containsKey(entry.getKey()))
110 .forEach(entry -> maskAlgorithms.remove(entry.getKey()));
111 }
112
113 @Override
114 public int getOrder() {
115 return MaskOrder.ORDER;
116 }
117 }