1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 1999-2004 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.util;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.sql.*;
import org.jivesoftware.database.DbConnectionManager;
/**
* Retrieves and stores Jive properties. Properties are stored in the database.
*
* @author Matt Tucker
*/
public class JiveProperties implements Map {
private static final String LOAD_PROPERTIES = "SELECT name, propValue FROM jiveProperty";
private static final String INSERT_PROPERTY = "INSERT INTO jiveProperty(name, propValue) VALUES(?,?)";
private static final String UPDATE_PROPERTY = "UPDATE jiveProperty SET propValue=? WHERE name=?";
private static final String DELETE_PROPERTY = "DELETE FROM jiveProperty WHERE name LIKE ?";
private static JiveProperties instance;
private Map<String, String> properties;
/**
* Returns a singleton instance of JiveProperties.
*
* @return an instance of JiveProperties.
*/
public static synchronized JiveProperties getInstance() {
if (instance == null) {
instance = new JiveProperties();
}
return instance;
}
private JiveProperties() {
init();
}
/**
* For internal use only. This method allows for the reloading of all properties from the
* values in the datatabase. This is required since it's quite possible during the setup
* process that a database connection will not be available till after this class is
* initialized. Thus, if there are existing properties in the database we will want to reload
* this class after the setup process has been completed.
*/
public void init() {
if (properties == null) {
properties = new ConcurrentHashMap<String, String>();
}
else {
properties.clear();
}
loadProperties();
}
public int size() {
return properties.size();
}
public void clear() {
throw new UnsupportedOperationException();
}
public boolean isEmpty() {
return properties.isEmpty();
}
public boolean containsKey(Object key) {
return properties.containsKey(key);
}
public boolean containsValue(Object value) {
return properties.containsValue(value);
}
public Collection values() {
return Collections.unmodifiableCollection(properties.values());
}
public void putAll(Map t) {
for (Iterator i=t.entrySet().iterator(); i.hasNext(); ) {
Map.Entry entry = (Map.Entry)i.next();
put(entry.getKey(), entry.getValue());
}
}
public Set entrySet() {
return Collections.unmodifiableSet(properties.entrySet());
}
public Set keySet() {
return Collections.unmodifiableSet(properties.keySet());
}
public Object get(Object key) {
return properties.get(key);
}
/**
* Return all children property names of a parent property as a Collection
* of String objects. For example, given the properties <tt>X.Y.A</tt>,
* <tt>X.Y.B</tt>, and <tt>X.Y.C</tt>, then the child properties of
* <tt>X.Y</tt> are <tt>X.Y.A</tt>, <tt>X.Y.B</tt>, and <tt>X.Y.C</tt>. The method
* is not recursive; ie, it does not return children of children.
*
* @param parentKey the name of the parent property.
* @return all child property names for the given parent.
*/
public Collection<String> getChildrenNames(String parentKey) {
Collection<String> results = new HashSet<String>();
for (String key : properties.keySet()) {
if (key.startsWith(parentKey + ".")) {
if (key.equals(parentKey)) {
continue;
}
int dotIndex = key.indexOf(".", parentKey.length()+1);
if (dotIndex < 1) {
if (!results.contains(key)) {
results.add(key);
}
}
else {
String name = parentKey + key.substring(parentKey.length(), dotIndex);
results.add(name);
}
}
}
return results;
}
/**
* Returns all property names as a Collection of String values.
*
* @return all property names.
*/
public Collection<String> getPropertyNames() {
return properties.keySet();
}
public synchronized Object remove(Object key) {
Object value = properties.remove(key);
// Also remove any children.
Collection propNames = getPropertyNames();
for (Iterator i=propNames.iterator(); i.hasNext(); ) {
String name = (String)i.next();
if (name.startsWith((String)key)) {
properties.remove(name);
}
}
deleteProperty((String)key);
// Generate event.
PropertyEventDispatcher.dispatchEvent((String)key,
PropertyEventDispatcher.EventType.property_deleted, Collections.emptyMap());
return value;
}
public synchronized Object put(Object key, Object value) {
if (key == null || value == null) {
throw new NullPointerException("Key or value cannot be null. Key=" +
key + ", value=" + value);
}
if (!(key instanceof String) || !(value instanceof String)) {
throw new IllegalArgumentException("Key and value must be of type String.");
}
if (((String)key).endsWith(".")) {
key = ((String)key).substring(0, ((String)key).length()-1);
}
key =((String)key).trim();
if (properties.containsKey(key)) {
if (!properties.get(key).equals(value)) {
updateProperty((String)key, (String)value);
}
}
else {
insertProperty((String)key, (String)value);
}
// Generate event.
Map params = new HashMap();
params.put("value", value);
PropertyEventDispatcher.dispatchEvent((String)key,
PropertyEventDispatcher.EventType.property_set, params);
return properties.put((String)key, (String)value);
}
private void insertProperty(String name, String value) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(INSERT_PROPERTY);
pstmt.setString(1, name);
pstmt.setString(2, value);
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
finally {
try { if (pstmt != null) { pstmt.close(); } }
catch (Exception e) { Log.error(e); }
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
}
private void updateProperty(String name, String value) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(UPDATE_PROPERTY);
pstmt.setString(1, value);
pstmt.setString(2, name);
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
finally {
try { if (pstmt != null) { pstmt.close(); } }
catch (Exception e) { Log.error(e); }
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
}
private void deleteProperty(String name) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(DELETE_PROPERTY);
pstmt.setString(1, name + "%");
pstmt.executeUpdate();
}
catch (SQLException e) {
Log.error(e);
}
finally {
try { if (pstmt != null) { pstmt.close(); } }
catch (Exception e) { Log.error(e); }
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
}
private void loadProperties() {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_PROPERTIES);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
String name = rs.getString(1);
String value = rs.getString(2);
properties.put(name, value);
}
rs.close();
}
catch (Exception e) {
Log.error(e);
}
finally {
try { if (pstmt != null) { pstmt.close(); } }
catch (Exception e) { Log.error(e); }
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
}
}