1 package com.atlassian.sal.core.pluginsettings;
2
3 import java.io.*;
4 import java.util.*;
5 import java.util.Map.Entry;
6
7 import com.atlassian.sal.api.pluginsettings.PluginSettings;
8 import com.google.common.collect.Lists;
9 import com.google.common.base.Function;
10 import org.apache.commons.lang.Validate;
11 import org.apache.log4j.Logger;
12
13
14
15
16
17 public abstract class AbstractStringPluginSettings implements PluginSettings
18 {
19 private static final Logger log = Logger.getLogger(AbstractStringPluginSettings.class);
20
21 private static final String PROPERTIES_ENCODING = "ISO8859_1";
22 private static final String PROPERTIES_IDENTIFIER = "java.util.Properties";
23 private static final String LIST_IDENTIFIER = "#java.util.List";
24 private static final String MAP_IDENTIFIER = "#java.util.Map";
25
26
27
28
29
30
31
32
33
34
35
36 public Object put(String key, Object value)
37 {
38 Validate.notNull(key, "The plugin settings key cannot be null");
39 if (value == null)
40 {
41 return remove(key);
42 }
43
44 final Object oldValue = get(key);
45 if (value instanceof Properties)
46 {
47 final ByteArrayOutputStream bout = new ByteArrayOutputStream();
48 try
49 {
50
51 final Properties properties = (Properties) value;
52 properties.store(bout, PROPERTIES_IDENTIFIER);
53 putActual(key, new String(bout.toByteArray(), PROPERTIES_ENCODING));
54 }
55 catch (final IOException e)
56 {
57 throw new IllegalArgumentException("Unable to serialize properties", e);
58 }
59 }
60 else if (value instanceof String)
61 {
62 putActual(key, (String) value);
63 }
64 else if (value instanceof List)
65 {
66 final StringBuilder sb = new StringBuilder();
67 sb.append(LIST_IDENTIFIER).append(EscapeUtils.NEW_LINE);
68 for (final Iterator i = ((List) value).iterator(); i.hasNext();)
69 {
70 sb.append(EscapeUtils.escape(i.next().toString()));
71 if (i.hasNext())
72 sb.append(EscapeUtils.NEW_LINE);
73 }
74 putActual(key, sb.toString());
75 }
76 else if (value instanceof Map)
77 {
78 final StringBuilder sb = new StringBuilder();
79 sb.append(MAP_IDENTIFIER).append(EscapeUtils.NEW_LINE);
80 for (final Iterator<Entry> i = ((Map) value).entrySet().iterator(); i.hasNext();)
81 {
82 final Entry entry = i.next();
83 sb.append(EscapeUtils.escape(entry.getKey().toString()));
84 sb.append(EscapeUtils.VERTICAL_TAB);
85 sb.append(EscapeUtils.escape(entry.getValue().toString()));
86 if (i.hasNext())
87 sb.append(EscapeUtils.NEW_LINE);
88 }
89 putActual(key, sb.toString());
90 }
91 else
92 {
93 throw new IllegalArgumentException("Property type: " + value.getClass() + " not supported");
94 }
95 return oldValue;
96 }
97
98
99
100
101
102
103
104
105 public Object get(String key)
106 {
107 Validate.notNull(key, "The plugin settings key cannot be null");
108 final String val = getActual(key);
109 if (val != null && val.startsWith("#" + PROPERTIES_IDENTIFIER))
110 {
111 final Properties p = new Properties();
112 try
113 {
114 p.load(new ByteArrayInputStream(val.getBytes(PROPERTIES_ENCODING)));
115 }
116 catch (final IOException e)
117 {
118 throw new IllegalArgumentException("Unable to deserialize properties", e);
119 }
120 return p;
121 }
122 else if (val != null && val.startsWith(LIST_IDENTIFIER))
123 {
124 final String[] lines = val.split(EscapeUtils.NEW_LINE + "");
125
126
127 final List<String> rawItems = Arrays.asList(lines).subList(1, lines.length);
128
129
130 final List<String> items = Lists.transform(rawItems, new Function<String, String>()
131 {
132 public String apply(String from)
133 {
134 return EscapeUtils.unescape(from);
135 }
136 });
137 return new ArrayList<String>(items);
138 }
139 else if (val != null && val.startsWith(MAP_IDENTIFIER))
140 {
141 String nval = val.substring(MAP_IDENTIFIER.length() + 1);
142 final HashMap<String, String> map = new HashMap<String, String>();
143 final String[] items = nval.split(EscapeUtils.NEW_LINE + "");
144 for (String item : items)
145 {
146 if (item.length() > 0)
147 {
148 String[] pair = item.split(EscapeUtils.VERTICAL_TAB + "");
149 if (pair.length != 2)
150 {
151 log.error("Could not parse map element: << " + item + " >> \n" +
152 "Full list: \n" + nval);
153 }
154 else
155 {
156 map.put(EscapeUtils.unescape(pair[0]),
157 EscapeUtils.unescape(pair[1]));
158 }
159 }
160 }
161
162 return map;
163 }
164 else
165 {
166 return val;
167 }
168 }
169
170
171
172
173
174
175
176 public Object remove(String key)
177 {
178 Validate.notNull(key, "The plugin settings key cannot be null");
179 Object oldValue = get(key);
180 if (oldValue != null)
181 {
182 removeActual(key);
183 }
184 return oldValue;
185 }
186
187
188
189
190
191
192
193 protected abstract void putActual(String key, String val);
194
195
196
197
198
199
200
201 protected abstract String getActual(String key);
202
203
204
205
206
207
208 protected abstract void removeActual(String key);
209
210 }