1 package com.atlassian.sal.core.features;
2
3 import com.atlassian.sal.api.features.DarkFeatureManager;
4 import com.google.common.base.Functions;
5 import com.google.common.base.Predicate;
6 import com.google.common.collect.Collections2;
7 import com.google.common.collect.ImmutableSet;
8 import com.google.common.collect.Maps;
9 import com.google.common.collect.Sets;
10
11 import java.io.File;
12 import java.io.FileReader;
13 import java.io.IOException;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Map;
19 import java.util.Properties;
20 import java.util.Set;
21
22 public class SystemDarkFeatureInitializer {
23
24
25
26
27
28
29 public static SystemDarkFeatures getSystemStartupDarkFeatures() {
30 final String propertiesFile = System.getProperty(DarkFeatureManager.DARKFEATURES_PROPERTIES_FILE_PROPERTY, DarkFeatureManager.DARKFEATURES_PROPERTIES_FILE_PROPERTY_DEFAULT);
31
32 final String disableAllPropertiesFlag = System.getProperty(DarkFeatureManager.DISABLE_ALL_DARKFEATURES_PROPERTY);
33 if (Boolean.parseBoolean(disableAllPropertiesFlag)) {
34 return SystemDarkFeatures.disableAll();
35 }
36
37 final Set<String> enabledPropertyDarkFeatures = getPropertyDarkFeaturesWithValue(true);
38 final Set<String> enabledPropertiesFileDarkFeatures = getPropertiesFileDarkFeatures(propertiesFile, true);
39
40 final Set<String> disabledPropertyDarkFeatures = getPropertyDarkFeaturesWithValue(false);
41 final Set<String> disabledPropertiesFileDarkFeatures = getPropertiesFileDarkFeatures(propertiesFile, false);
42
43
44 Set<String> enabled = Sets.union(Sets.difference(enabledPropertiesFileDarkFeatures, disabledPropertyDarkFeatures), enabledPropertyDarkFeatures);
45 Set<String> disabled = Sets.union(Sets.difference(disabledPropertiesFileDarkFeatures, enabledPropertyDarkFeatures), disabledPropertyDarkFeatures);
46
47 return SystemDarkFeatures.darkFeatures(enabled, disabled);
48 }
49
50 private static Set<String> getPropertiesFileDarkFeatures(String filename, boolean b) {
51 final File propertiesFile = new File(filename);
52
53 Properties properties = new Properties();
54 try {
55 properties.load(new FileReader(propertiesFile));
56 } catch (IOException e) {
57 return Collections.emptySet();
58 }
59
60 return new HashSet<>(getKeysForBooleanValue(filterOnAndStripKeyPrefix(properties), b));
61 }
62
63 private static Set<String> getPropertyDarkFeaturesWithValue(boolean b) {
64 return new HashSet<>(getKeysForBooleanValue(filterOnAndStripKeyPrefix(System.getProperties()), b));
65 }
66
67 private static Collection<String> getKeysForBooleanValue(final Map<Object, Object> properties, final Boolean b) {
68 return Collections2.transform(Maps.filterValues(properties, new Predicate<Object>() {
69 @Override
70 public boolean apply(Object input) {
71
72 return input.toString().toLowerCase().matches(b.toString());
73 }
74 }).keySet(), Functions.toStringFunction());
75 }
76
77 private static Map<Object, Object> filterOnAndStripKeyPrefix(Map<Object, Object> properties) {
78 final Set<Map.Entry<Object, Object>> entries = Maps.filterKeys(properties, new Predicate<Object>() {
79 @Override
80 public boolean apply(Object entry) {
81 return entry.toString().startsWith(DarkFeatureManager.ATLASSIAN_DARKFEATURE_PREFIX);
82 }
83 }).entrySet();
84
85 Map<Object, Object> prefixStrippedEntries = new HashMap<>();
86 for (Map.Entry<Object, Object> entry : entries) {
87 prefixStrippedEntries.put(entry.getKey().toString().substring(DarkFeatureManager.ATLASSIAN_DARKFEATURE_PREFIX.length()), entry.getValue());
88 }
89
90 return prefixStrippedEntries;
91 }
92
93 public static class SystemDarkFeatures {
94 private final Set<String> enabled;
95 private final Set<String> disabled;
96 private final boolean disableAll;
97
98 private SystemDarkFeatures(Set<String> enabled, Set<String> disabled, boolean disableAll) {
99 this.enabled = ImmutableSet.copyOf(enabled);
100 this.disabled = ImmutableSet.copyOf(disabled);
101 this.disableAll = disableAll;
102 }
103
104 public static SystemDarkFeatures disableAll() {
105 return new SystemDarkFeatures(Collections.emptySet(), Collections.emptySet(), true);
106 }
107
108 public static SystemDarkFeatures darkFeatures(Set<String> enabled, Set<String> disabled) {
109 return new SystemDarkFeatures(enabled, disabled, false);
110 }
111
112 public Set<String> getEnabled() {
113 return enabled;
114 }
115
116 public Set<String> getDisabled() {
117 return disabled;
118 }
119
120 public boolean isDisableAll() {
121 return disableAll;
122 }
123 }
124 }