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
30 public static SystemDarkFeatures getSystemStartupDarkFeatures()
31 {
32 final String propertiesFile = System.getProperty(DarkFeatureManager.DARKFEATURES_PROPERTIES_FILE_PROPERTY, DarkFeatureManager.DARKFEATURES_PROPERTIES_FILE_PROPERTY_DEFAULT);
33
34 final String disableAllPropertiesFlag = System.getProperty(DarkFeatureManager.DISABLE_ALL_DARKFEATURES_PROPERTY);
35 if (Boolean.parseBoolean(disableAllPropertiesFlag))
36 {
37 return SystemDarkFeatures.disableAll();
38 }
39
40 final Set<String> enabledPropertyDarkFeatures = getPropertyDarkFeaturesWithValue(true);
41 final Set<String> enabledPropertiesFileDarkFeatures = getPropertiesFileDarkFeatures(propertiesFile, true);
42
43 final Set<String> disabledPropertyDarkFeatures = getPropertyDarkFeaturesWithValue(false);
44 final Set<String> disabledPropertiesFileDarkFeatures = getPropertiesFileDarkFeatures(propertiesFile, false);
45
46
47 Set<String> enabled = Sets.union(Sets.difference(enabledPropertiesFileDarkFeatures, disabledPropertyDarkFeatures), enabledPropertyDarkFeatures);
48 Set<String> disabled = Sets.union(Sets.difference(disabledPropertiesFileDarkFeatures, enabledPropertyDarkFeatures), disabledPropertyDarkFeatures);
49
50 return SystemDarkFeatures.darkFeatures(enabled, disabled);
51 }
52
53 private static Set<String> getPropertiesFileDarkFeatures(String filename, boolean b)
54 {
55 final File propertiesFile = new File(filename);
56
57 Properties properties = new Properties();
58 try
59 {
60 properties.load(new FileReader(propertiesFile));
61 }
62 catch (IOException e)
63 {
64 return Collections.emptySet();
65 }
66
67 return new HashSet<String>(getKeysForBooleanValue(filterOnAndStripKeyPrefix(properties), b));
68 }
69
70 private static Set<String> getPropertyDarkFeaturesWithValue(boolean b)
71 {
72 return new HashSet<String>(getKeysForBooleanValue(filterOnAndStripKeyPrefix(System.getProperties()), b));
73 }
74
75 private static Collection<String> getKeysForBooleanValue(final Map<Object, Object> properties, final Boolean b)
76 {
77 return Collections2.transform(Maps.filterValues(properties, new Predicate<Object>()
78 {
79 @Override
80 public boolean apply(Object input)
81 {
82
83 return input.toString().toLowerCase().matches(b.toString());
84 }
85 }).keySet(), Functions.toStringFunction());
86 }
87
88 private static Map<Object, Object> filterOnAndStripKeyPrefix(Map<Object, Object> properties)
89 {
90 final Set<Map.Entry<Object, Object>> entries = Maps.filterKeys(properties, new Predicate<Object>()
91 {
92 @Override
93 public boolean apply(Object entry)
94 {
95 return entry.toString().startsWith(DarkFeatureManager.ATLASSIAN_DARKFEATURE_PREFIX);
96 }
97 }).entrySet();
98
99 Map<Object, Object> prefixStrippedEntries = new HashMap<Object, Object>();
100 for (Map.Entry<Object, Object> entry : entries)
101 {
102 prefixStrippedEntries.put(entry.getKey().toString().substring(DarkFeatureManager.ATLASSIAN_DARKFEATURE_PREFIX.length()), entry.getValue());
103 }
104
105 return prefixStrippedEntries;
106 }
107
108 public static class SystemDarkFeatures
109 {
110 private final Set<String> enabled;
111 private final Set<String> disabled;
112 private final boolean disableAll;
113
114 private SystemDarkFeatures(Set<String> enabled, Set<String> disabled, boolean disableAll)
115 {
116 this.enabled = ImmutableSet.copyOf(enabled);
117 this.disabled = ImmutableSet.copyOf(disabled);
118 this.disableAll = disableAll;
119 }
120
121 public static SystemDarkFeatures disableAll()
122 {
123 return new SystemDarkFeatures(Collections.<String>emptySet(), Collections.<String>emptySet(), true);
124 }
125
126 public static SystemDarkFeatures darkFeatures(Set<String> enabled, Set<String> disabled)
127 {
128 return new SystemDarkFeatures(enabled, disabled, false);
129 }
130
131 public Set<String> getEnabled()
132 {
133 return enabled;
134 }
135
136 public Set<String> getDisabled()
137 {
138 return disabled;
139 }
140
141 public boolean isDisableAll()
142 {
143 return disableAll;
144 }
145 }
146 }