Browse Source

Make ApiFactory non-static

Add config manager and related classes
Move database to config directory
Change title to "No character selected" from "initialising"
master
Chris Smith 15 years ago
parent
commit
cb9699a890

+ 370
- 0
src/com/dmdirc/util/ConfigFile.java View File

@@ -0,0 +1,370 @@
1
+/*
2
+ * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.util;
24
+
25
+import java.io.File;
26
+import java.io.FileNotFoundException;
27
+import java.io.IOException;
28
+import java.io.InputStream;
29
+import java.util.ArrayList;
30
+import java.util.GregorianCalendar;
31
+import java.util.HashMap;
32
+import java.util.List;
33
+import java.util.Map;
34
+
35
+/**
36
+ * Reads and writes a standard DMDirc config file.
37
+ *
38
+ * @author chris
39
+ */
40
+public class ConfigFile extends TextFile {
41
+
42
+    /** A list of domains in this config file. */
43
+    private final List<String> domains = new ArrayList<String>();
44
+
45
+    /** The values associated with each flat domain. */
46
+    private final MapList<String, String> flatdomains = new MapList<String, String>();
47
+
48
+    /** The key/value sets associated with each key domain. */
49
+    private final Map<String, Map<String, String>> keydomains
50
+            = new HashMap<String, Map<String, String>>();
51
+    
52
+    /** Whether or not we should automatically create domains. */
53
+    private boolean automake;
54
+
55
+    /**
56
+     * Creates a new read-only Config File from the specified input stream.
57
+     * 
58
+     * @param is The input stream to read
59
+     */
60
+    public ConfigFile(final InputStream is) {
61
+        super(is);
62
+    }
63
+
64
+    /**
65
+     * Creates a new Config File from the specified file.
66
+     * 
67
+     * @param file The file to read/write
68
+     */
69
+    public ConfigFile(final File file) {
70
+        super(file);
71
+    }
72
+
73
+    /**
74
+     * Creates a new Config File from the specified file.
75
+     * 
76
+     * @param filename The name of the file to read/write
77
+     */
78
+    public ConfigFile(final String filename) {
79
+        super(filename);
80
+    }
81
+
82
+
83
+    /**
84
+     * Sets the "automake" value of this config file. If automake is set to
85
+     * true, any calls to getKeyDomain will automatically create the domain
86
+     * if it did not previously exist.
87
+     * 
88
+     * @param automake The new value of the automake setting of this file
89
+     */
90
+    public void setAutomake(final boolean automake) {
91
+        this.automake = automake;
92
+    }
93
+
94
+    /**
95
+     * Reads the data from the file.
96
+     * 
97
+     * @throws FileNotFoundException if the file is not found
98
+     * @throws IOException if an i/o exception occured when reading
99
+     * @throws InvalidConfigFileException if the config file isn't valid
100
+     */
101
+    public void read() throws FileNotFoundException, IOException, InvalidConfigFileException {
102
+        String domain = null;
103
+        boolean keydomain = false;
104
+        int offset;
105
+        
106
+        keydomains.clear();
107
+        flatdomains.clear();
108
+        domains.clear();
109
+        
110
+        readLines();
111
+
112
+        for (String line : getLines()) {
113
+            String tline = line;
114
+            
115
+            while (!tline.isEmpty() && (tline.charAt(0) == '\t' || 
116
+                    tline.charAt(0) == ' ')) {
117
+                tline = tline.substring(1);
118
+            }
119
+
120
+            if (tline.indexOf('#') == 0 || tline.isEmpty()) {
121
+                continue;
122
+            } else if (
123
+                    (tline.endsWith(":") && !tline.endsWith("\\:"))
124
+                    && findEquals(tline) == -1) {
125
+                domain = unescape(tline.substring(0, tline.length() - 1));
126
+
127
+                domains.add(domain);
128
+
129
+                keydomain = keydomains.containsKey(domain)
130
+                        || flatdomains.containsValue("keysections", domain);
131
+                
132
+                if (keydomain && !keydomains.containsKey(domain)) {
133
+                    keydomains.put(domain, new HashMap<String, String>());
134
+                } else if (!keydomain && !flatdomains.containsKey(domain)) {
135
+                    flatdomains.add(domain);
136
+                }
137
+            } else if (domain != null && keydomain
138
+                    && (offset = findEquals(tline)) != -1) {
139
+                final String key = unescape(tline.substring(0, offset));
140
+                final String value = unescape(tline.substring(offset + 1));
141
+
142
+                keydomains.get(domain).put(key, value);
143
+            } else if (domain != null && !keydomain) {
144
+                flatdomains.add(domain, unescape(tline));
145
+            } else {
146
+                throw new InvalidConfigFileException("Unknown or unexpected" +
147
+                        " line encountered: " + tline);
148
+            }
149
+        }
150
+    }
151
+
152
+    /**
153
+     * Writes the contents of this ConfigFile to disk.
154
+     * 
155
+     * @throws IOException if the write operation fails
156
+     */
157
+    public void write() throws IOException {
158
+        if (!isWritable()) {
159
+            throw new UnsupportedOperationException("Cannot write to a file "
160
+                    + "that isn't writable");
161
+        }
162
+        
163
+        final List<String> lines = new ArrayList<String>();
164
+
165
+        lines.add("# This is a DMDirc configuration file.");
166
+        lines.add("# Written on: " + new GregorianCalendar().getTime().toString());
167
+
168
+        writeMeta(lines);
169
+
170
+        for (String domain : domains) {
171
+            if ("keysections".equals(domain)) {
172
+                continue;
173
+            }
174
+
175
+            lines.add("");
176
+
177
+            lines.add(escape(domain) + ':');
178
+
179
+            if (flatdomains.containsKey(domain)) {
180
+                for (String entry : flatdomains.get(domain)) {
181
+                    lines.add("  " + escape(entry));
182
+                }
183
+            } else {
184
+                for (Map.Entry<String, String> entry : keydomains.get(domain).entrySet()) {
185
+                    lines.add("  " + escape(entry.getKey()) + "="
186
+                            + escape(entry.getValue()));
187
+                }
188
+            }
189
+        }
190
+
191
+        writeLines(lines);
192
+    }
193
+    
194
+    /**
195
+     * Appends the meta-data (keysections) to the specified list of lines.
196
+     * 
197
+     * @param lines The set of lines to be appended to
198
+     */
199
+    private void writeMeta(final List<String> lines) {
200
+        lines.add("");
201
+        lines.add("# This section indicates which sections below take key/value");
202
+        lines.add("# pairs, rather than a simple list. It should be placed above");
203
+        lines.add("# any sections that take key/values.");
204
+        lines.add("keysections:");
205
+
206
+        for (String domain : domains) {
207
+            if ("keysections".equals(domain)) {
208
+                continue;
209
+            } else if (keydomains.containsKey(domain)) {
210
+                lines.add("  " + domain);
211
+            }
212
+        }
213
+    }
214
+    
215
+    /**
216
+     * Retrieves all the key domains for this config file.
217
+     * 
218
+     * @return This config file's key domains
219
+     */
220
+    public Map<String, Map<String, String>> getKeyDomains() {
221
+        return keydomains;
222
+    }
223
+    
224
+    /**
225
+     * Retrieves the key/values of the specified key domain.
226
+     * 
227
+     * @param domain The domain to be retrieved
228
+     * @return A map of keys to values in the specified domain
229
+     */
230
+    public Map<String, String> getKeyDomain(final String domain) {
231
+        if (automake && !isKeyDomain(domain)) {
232
+            domains.add(domain);
233
+            keydomains.put(domain, new HashMap<String, String>());
234
+        }
235
+        
236
+        return keydomains.get(domain);
237
+    }
238
+    
239
+    /**
240
+     * Retrieves the content of the specified flat domain.
241
+     * 
242
+     * @param domain The domain to be retrieved
243
+     * @return A list of lines in the specified domain
244
+     */
245
+    public List<String> getFlatDomain(final String domain) {
246
+        return flatdomains.get(domain);
247
+    }
248
+    
249
+    /**
250
+     * Determines if this config file has the specified domain.
251
+     * 
252
+     * @param domain The domain to check for
253
+     * @return True if the domain is known, false otherwise
254
+     */
255
+    public boolean hasDomain(final String domain) {
256
+        return keydomains.containsKey(domain) || flatdomains.containsKey(domain);
257
+    }
258
+
259
+    /**
260
+     * Determines if this config file has the specified domain, and the domain
261
+     * is a key domain.
262
+     * 
263
+     * @param domain The domain to check for
264
+     * @return True if the domain is known and keyed, false otherwise
265
+     */
266
+    public boolean isKeyDomain(final String domain) {
267
+        return keydomains.containsKey(domain);
268
+    }
269
+
270
+    /**
271
+     * Determines if this config file has the specified domain, and the domain
272
+     * is a flat domain.
273
+     * 
274
+     * @param domain The domain to check for
275
+     * @return True if the domain is known and flat, false otherwise
276
+     */
277
+    public boolean isFlatDomain(final String domain) {
278
+        return flatdomains.containsKey(domain);
279
+    }
280
+    
281
+    /**
282
+     * Adds a new flat domain to this config file.
283
+     * 
284
+     * @param name The name of the domain to be added
285
+     * @param data The content of the domain
286
+     */
287
+    public void addDomain(final String name, final List<String> data) {
288
+        domains.add(name);
289
+        flatdomains.add(name, data);
290
+    }
291
+
292
+    /**
293
+     * Adds a new key domain to this config file.
294
+     * 
295
+     * @param name The name of the domain to be added
296
+     * @param data The content of the domain
297
+     */    
298
+    public void addDomain(final String name, final Map<String, String> data) {
299
+        domains.add(name);
300
+        keydomains.put(name, data);
301
+    }
302
+    
303
+    /**
304
+     * Unescapes any escaped characters in the specified input string.
305
+     * 
306
+     * @param input The string to unescape
307
+     * @return The string with all escape chars (\) resolved
308
+     */
309
+    protected static String unescape(final String input) {
310
+        boolean escaped = false;
311
+        final StringBuilder temp = new StringBuilder();
312
+
313
+        for (int i = 0; i < input.length(); i++) {
314
+            final char ch = input.charAt(i);
315
+
316
+            if (escaped) {
317
+                if (ch == 'n') {
318
+                    temp.append('\n');
319
+                } else if (ch == 'r') {
320
+                    temp.append('\r');
321
+                } else {
322
+                    temp.append(ch);
323
+                }
324
+                
325
+                escaped = false;
326
+            } else if (ch == '\\') {
327
+                escaped = true;
328
+            } else {
329
+                temp.append(ch);
330
+            }
331
+        }
332
+        
333
+        return temp.toString();
334
+    }
335
+    
336
+    /**
337
+     * Escapes the specified input string by prefixing all occurances of
338
+     * \, \n, \r, =, # and : with backslashes.
339
+     * 
340
+     * @param input The string to be escaped
341
+     * @return A backslash-armoured version of the string
342
+     */
343
+    protected static String escape(final String input) {
344
+        return input.replaceAll("\\\\", "\\\\\\\\").replaceAll("\n", "\\\\n")
345
+                .replaceAll("\r", "\\\\r").replaceAll("=", "\\\\=")
346
+                .replaceAll(":", "\\\\:").replaceAll("#", "\\\\#");
347
+    }
348
+    
349
+    /**
350
+     * Finds the first non-escaped instance of '=' in the specified string.
351
+     * 
352
+     * @param input The string to be searched
353
+     * @return The offset of the first non-escaped instance of '=', or -1.
354
+     */
355
+    protected static int findEquals(final String input) {
356
+        boolean escaped = false;
357
+        
358
+        for (int i = 0; i < input.length(); i++) {
359
+            if (escaped) {
360
+                escaped = false;
361
+            } else if (input.charAt(i) == '\\') {
362
+                escaped = true;
363
+            } else if (input.charAt(i) == '=') {
364
+                return i;
365
+            }
366
+        }
367
+        
368
+        return -1;
369
+    }
370
+}

+ 47
- 0
src/com/dmdirc/util/InvalidConfigFileException.java View File

@@ -0,0 +1,47 @@
1
+/*
2
+ * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.util;
24
+
25
+/**
26
+ * Thrown to indicate that a config file is invalid.
27
+ * @author chris
28
+ */
29
+public class InvalidConfigFileException extends Exception {
30
+    
31
+    /**
32
+     * A version number for this class. It should be changed whenever the class
33
+     * structure is changed (or anything else that would prevent serialized
34
+     * objects being unserialized with the new class).
35
+     */    
36
+    private static final long serialVersionUID = 1;
37
+
38
+    /**
39
+     * Creates a new InvalidConfigFileException.
40
+     * 
41
+     * @param string A description of the exception that occured.
42
+     */
43
+    public InvalidConfigFileException(String string) {
44
+        super(string);
45
+    }
46
+
47
+}

+ 252
- 0
src/com/dmdirc/util/MapList.java View File

@@ -0,0 +1,252 @@
1
+/*
2
+ * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.util;
24
+
25
+import java.util.ArrayList;
26
+import java.util.Collection;
27
+import java.util.HashMap;
28
+import java.util.List;
29
+import java.util.Map;
30
+import java.util.Set;
31
+
32
+/**
33
+ * Wraps a Map&lt;S, List&lt;T&gt;&gt; with various convenience methods for
34
+ * accessing the data. Implements a Map-like interface for easier transition.
35
+ * 
36
+ * @param <S> the type of keys maintained by this map
37
+ * @param <T> the type of mapped values
38
+ * @author chris
39
+ */
40
+public class MapList<S,T> {
41
+    
42
+    /** Our internal map. */
43
+    protected final Map<S, List<T>> map;
44
+
45
+    /**
46
+     * Creates a new, empty MapList.
47
+     */
48
+    public MapList() {
49
+        map = new HashMap<S, List<T>>();
50
+    }
51
+
52
+    /**
53
+     * Creates a new MapList with the values from the specified list.
54
+     * 
55
+     * @param list The MapList whose values should be used
56
+     */
57
+    public MapList(final MapList<S,T> list) {
58
+        map = list.getMap();
59
+    }
60
+
61
+    /**
62
+     * Determines if this MapList is empty. An empty MapList is one that either
63
+     * contains no keys, or contains only keys which have no associated values.
64
+     * 
65
+     * @return True if this MapList is empty, false otherwise
66
+     */
67
+    public boolean isEmpty() {
68
+        for (List<T> list : map.values()) {
69
+            if (!list.isEmpty()) {
70
+                return false;
71
+            }
72
+        }
73
+        
74
+        return true;
75
+    }
76
+
77
+    /**
78
+     * Determines if this MapList contains the specified key.
79
+     * 
80
+     * @param key The key to look for
81
+     * @return True if this MapList contains the specified key, false otherwise
82
+     */
83
+    public boolean containsKey(final S key) {
84
+        return map.containsKey(key);
85
+    }
86
+
87
+    /**
88
+     * Determines if this MapList contains the specified value as a child of
89
+     * the specified key.
90
+     * 
91
+     * @param key The key to search under
92
+     * @param value The value to look for
93
+     * @return True if this MapList contains the specified key/value pair, 
94
+     * false otherwise
95
+     */
96
+    public boolean containsValue(final S key, final T value) {
97
+        return map.containsKey(key) && map.get(key).contains(value);
98
+    }
99
+
100
+    /**
101
+     * Retrieves the list of values associated with the specified key.
102
+     * 
103
+     * @param key The key whose values are being retrieved
104
+     * @return The values belonging to the specified key
105
+     */
106
+    public List<T> get(final S key) {
107
+        return map.get(key);
108
+    }
109
+    
110
+    /**
111
+     * Retrieves the value at the specified offset of the specified key.
112
+     * 
113
+     * @param key The key whose values are being retrieved
114
+     * @param index The index of the value to retrieve
115
+     * @return The specified value of the key
116
+     */    
117
+    public T get(final S key, final int index) {
118
+        return map.get(key).get(index);
119
+    }    
120
+    
121
+    /**
122
+     * Retrieves the list of values associated with the specified key, creating
123
+     * the key if neccessary.
124
+     * 
125
+     * @param key The key to retrieve
126
+     * @return A list of the specified key's values
127
+     */
128
+    public List<T> safeGet(final S key) {
129
+        if (!map.containsKey(key)) {
130
+            map.put(key, new ArrayList<T>());
131
+        }
132
+        
133
+        return map.get(key);
134
+    }
135
+    
136
+    /**
137
+     * Adds the specified key to the MapList.
138
+     * 
139
+     * @param key The key to be added
140
+     */
141
+    public void add(final S key) {
142
+        safeGet(key);
143
+    }    
144
+
145
+    /**
146
+     * Adds the specified value as a child of the specified key. If the key
147
+     * didn't previous exist, it is created.
148
+     * 
149
+     * @param key The key to which the value is being added
150
+     * @param value The value to be added
151
+     */
152
+    public void add(final S key, final T value) {
153
+        safeGet(key).add(value);
154
+    }
155
+
156
+    /**
157
+     * Adds the specified set of values to the specified key. If the key
158
+     * didn't previous exist, it is created.
159
+     * 
160
+     * @param key The key to which the value is being added
161
+     * @param values The values to be added
162
+     */    
163
+    public void add(final S key, final Collection<T> values) {
164
+        safeGet(key).addAll(values);
165
+    }    
166
+
167
+    /**
168
+     * Removes the specified key and all of its values.
169
+     * 
170
+     * @param key The key to remove
171
+     */    
172
+    public void remove(final S key) {
173
+        map.remove(key);
174
+    }
175
+    
176
+    /**
177
+     * Removes the specified value from all keys.
178
+     * 
179
+     * @param value The value to remove
180
+     */
181
+    public void removeFromAll(final T value) {
182
+        for (List<T> list : map.values()) {
183
+            list.remove(value);
184
+        }
185
+    }
186
+
187
+    /**
188
+     * Removes the specified value from the specified key.
189
+     * 
190
+     * @param key The key whose value is being removed
191
+     * @param value The value to be removed
192
+     */
193
+    public void remove(final S key, final T value) {
194
+        if (map.containsKey(key)) {
195
+            map.get(key).remove(value);
196
+        }
197
+    }    
198
+
199
+    /**
200
+     * Entirely clears this MapList.
201
+     */
202
+    public void clear() {
203
+        map.clear();
204
+    }
205
+    
206
+    /**
207
+     * Clears all values of the specified key.
208
+     * 
209
+     * @param key The key to be cleared
210
+     */
211
+    public void clear(final S key) {
212
+        safeGet(key).clear();
213
+    }    
214
+
215
+    /**
216
+     * Returns the set of all keys belonging to this MapList.
217
+     * 
218
+     * @return This MapList's keyset
219
+     */
220
+    public Set<S> keySet() {
221
+        return map.keySet();
222
+    }
223
+
224
+    /**
225
+     * Returns a collection of all values belonging to the specified key.
226
+     * 
227
+     * @param key The key whose values are being sought
228
+     * @return A collection of values belonging to the key
229
+     */
230
+    public Collection<T> values(final S key) {
231
+        return map.get(key);
232
+    }
233
+    
234
+    /**
235
+     * Retrieves the entry set for this MapList.
236
+     * 
237
+     * @return This MapList's entry set
238
+     */
239
+    public Set<Map.Entry<S, List<T>>> entrySet() {
240
+        return map.entrySet();
241
+    }
242
+    
243
+    /**
244
+     * Retrieves the map behind this maplist.
245
+     * 
246
+     * @return This MapList's map.
247
+     */
248
+    public Map<S, List<T>> getMap() {
249
+        return new HashMap<S, List<T>>(map);
250
+    }
251
+
252
+}

+ 165
- 0
src/com/dmdirc/util/TextFile.java View File

@@ -0,0 +1,165 @@
1
+/*
2
+ * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.util;
24
+
25
+import java.io.BufferedReader;
26
+import java.io.BufferedWriter;
27
+import java.io.File;
28
+import java.io.FileReader;
29
+import java.io.FileWriter;
30
+import java.io.IOException;
31
+import java.io.InputStream;
32
+import java.io.InputStreamReader;
33
+import java.util.ArrayList;
34
+import java.util.List;
35
+
36
+/**
37
+ * Allows reading and writing to a plain text file via a list of lines.
38
+ * 
39
+ * @author chris
40
+ */
41
+public class TextFile {
42
+    
43
+    /** The file we're dealing with. */
44
+    private File file;
45
+    
46
+    /** The input stream we're dealing with. */
47
+    private InputStream is;
48
+    
49
+    /** The lines we've read from the file. */
50
+    private List<String> lines;
51
+    
52
+    /**
53
+     * Creates a new instance of TextFile for the specified file.
54
+     * 
55
+     * @param filename The file to be read/written
56
+     */
57
+    public TextFile(final String filename) {
58
+        file = new File(filename);
59
+    }
60
+
61
+    /**
62
+     * Creates a new instance of TextFile for the specified File.
63
+     * 
64
+     * @param file The file to read
65
+     */
66
+    public TextFile(final File file) {
67
+        this.file = file;
68
+    }
69
+    
70
+    /**
71
+     * Creates a new instance of TextFile for an input stream.
72
+     * 
73
+     * @param is The input stream to read from
74
+     */
75
+    public TextFile(final InputStream is) {
76
+        this.is = is;
77
+    }
78
+    
79
+    /**
80
+     * Retrieves the contents of the file as a list of lines. If getLines() or
81
+     * readLines() has previously been called, a cached version is returned.
82
+     * 
83
+     * @return A list of lines in the file
84
+     * @throws IOException if an I/O exception occurs
85
+     */
86
+    public List<String> getLines() throws IOException {
87
+        if (lines == null) {
88
+            readLines();
89
+        }
90
+        
91
+        return lines;
92
+    }
93
+    
94
+    /**
95
+     * Reads the contents of the file into this TextFile's line cache.
96
+     * 
97
+     * @throws IOException If an I/O exception occurs
98
+     */
99
+    public void readLines() throws IOException {
100
+        final BufferedReader reader = new BufferedReader(
101
+                file == null ? new InputStreamReader(is) : new FileReader(file));
102
+        lines = new ArrayList<String>();
103
+        
104
+        String line;
105
+        
106
+        while ((line = reader.readLine()) != null) {
107
+            lines.add(line);
108
+        }
109
+        
110
+        reader.close();
111
+    }
112
+    
113
+    /**
114
+     * Determines if this file is writable or not.
115
+     * 
116
+     * @return True if the file is writable, false otherwise
117
+     */
118
+    public boolean isWritable() {
119
+        return file != null;
120
+    }
121
+    
122
+    /**
123
+     * Writes the specified list of lines to the file.
124
+     * 
125
+     * @param lines The lines to be written
126
+     * @throws IOException if an I/O exception occurs
127
+     */
128
+    public void writeLines(final List<String> lines) throws IOException {
129
+        if (file == null) {
130
+            throw new UnsupportedOperationException("Cannot write to TextFile "
131
+                    + "opened with an InputStream");
132
+        }
133
+        
134
+        final BufferedWriter writer = new BufferedWriter(new FileWriter(file));
135
+        
136
+        for (String line : lines) {
137
+            writer.write(line);
138
+            writer.newLine();
139
+        }
140
+        
141
+        writer.close();
142
+    }
143
+
144
+    /**
145
+     * Retrieves the File for this TextFile, if there is one.
146
+     * 
147
+     * @return This TextFile's file, or null
148
+     */
149
+    public File getFile() {
150
+        return file;
151
+    }
152
+    
153
+    /**
154
+     * Deletes the file associated with this textfile, if there is one.
155
+     */
156
+    public void delete() {
157
+        if (file == null) {
158
+            throw new UnsupportedOperationException("Cannot delete TextFile "
159
+                    + "opened with an InputStream");
160
+        }
161
+        
162
+        file.delete();
163
+    }
164
+
165
+}

+ 13
- 4
src/uk/co/md87/evetool/ApiFactory.java View File

@@ -34,22 +34,31 @@ import uk.co.md87.evetool.api.EveApi;
34 34
  * Factory class to create instances of the {@link EveApi} class. Uses an
35 35
  * embedded Derby database server by default.
36 36
  *
37
- * TODO: Make non-static
38 37
  * @author chris
39 38
  */
40 39
 public class ApiFactory {
41 40
 
42 41
     /** The URL of the database. */
43
-    private static String dbURL = "jdbc:derby:db/eveApi;create=true";
42
+    private final String dbURL;
44 43
 
44
+    /** The cached connection. */
45 45
     private static Connection dbConn;
46 46
 
47
+    /**
48
+     * Creates a new API Factory which will use the specified config manager.
49
+     *
50
+     * @param manager The config manager to use
51
+     */
52
+    public ApiFactory(final ConfigManager manager) {
53
+        dbURL = "jdbc:derby:" + manager.getConfigDir() + "/db;create=true";
54
+    }
55
+
47 56
     /**
48 57
      * Creates a database connection for use by the API.
49 58
      *
50 59
      * @return A Database Connection
51 60
      */
52
-    public static synchronized Connection getConnection() {
61
+    public synchronized Connection getConnection() {
53 62
         try {
54 63
             return dbConn == null ? dbConn = DriverManager.getConnection(dbURL) : dbConn;
55 64
         } catch (SQLException ex) {
@@ -64,7 +73,7 @@ public class ApiFactory {
64 73
      *
65 74
      * @return An instance of the EVE API.
66 75
      */
67
-    public static EveApi getApi() {
76
+    public EveApi getApi() {
68 77
         return new EveApi(getConnection());
69 78
     }
70 79
 

+ 108
- 0
src/uk/co/md87/evetool/ConfigManager.java View File

@@ -0,0 +1,108 @@
1
+/*
2
+ * Copyright (c) 2009 Chris Smith
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package uk.co.md87.evetool;
24
+
25
+import com.dmdirc.util.ConfigFile;
26
+import com.dmdirc.util.InvalidConfigFileException;
27
+import java.io.File;
28
+import java.io.IOException;
29
+import java.util.logging.Level;
30
+import java.util.logging.Logger;
31
+
32
+/**
33
+ *
34
+ * TODO: Document ConfigManager
35
+ * @author chris
36
+ */
37
+public class ConfigManager {
38
+
39
+    /** Logger to use for this class. */
40
+    private static final Logger LOGGER = Logger.getLogger(ConfigManager.class.getName());
41
+
42
+    private final ConfigFile configFile;
43
+ 
44
+    public ConfigManager() {
45
+        final File dir = new File(getConfigDir());
46
+
47
+        if (!dir.exists()) {
48
+            dir.mkdirs();
49
+        }
50
+
51
+        configFile = new ConfigFile(new File(dir, "evetool.config"));
52
+        configFile.setAutomake(true);
53
+        
54
+        try {
55
+            configFile.read();
56
+        } catch (IOException ex) {
57
+            LOGGER.log(Level.WARNING, "Error reading config file", ex);
58
+        } catch (InvalidConfigFileException ex) {
59
+            LOGGER.log(Level.WARNING, "Error parsing config file", ex);
60
+        }
61
+
62
+        Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook()));
63
+    }
64
+
65
+    public String getGeneralSetting(final String key) {
66
+        return configFile.getKeyDomain("general").get(key);
67
+    }
68
+
69
+    public void save() {
70
+        try {
71
+            configFile.write();
72
+        } catch (IOException ex) {
73
+            LOGGER.log(Level.SEVERE, "Error writing config file", ex);
74
+        }
75
+    }
76
+
77
+    /**
78
+     * Returns the application's config directory.
79
+     *
80
+     * @return configuration directory
81
+     */
82
+    public String getConfigDir() {
83
+        final String fs = System.getProperty("file.separator");
84
+        final String osName = System.getProperty("os.name");
85
+        if (osName.startsWith("Mac OS")) {
86
+            return System.getProperty("user.home") + fs + "Library" + fs
87
+                    + "Preferences" + fs + "evetool" + fs;
88
+        } else if (osName.startsWith("Windows")) {
89
+            if (System.getenv("APPDATA") == null) {
90
+                return System.getProperty("user.home") + fs + "evetool" + fs;
91
+            } else {
92
+                return System.getenv("APPDATA") + fs + "evetool" + fs;
93
+            }
94
+        } else {
95
+            return System.getProperty("user.home") + fs + ".evetool" + fs;
96
+        }
97
+    }
98
+
99
+    private class ShutdownHook implements Runnable {
100
+
101
+        /** {@inheritDoc} */
102
+        @Override
103
+        public void run() {
104
+            save();
105
+        }
106
+
107
+    }
108
+}

+ 11
- 5
src/uk/co/md87/evetool/Main.java View File

@@ -54,12 +54,16 @@ public class Main {
54 54
      */
55 55
     public static void main(final String[] args) {
56 56
         initLogging();
57
+
58
+        final ConfigManager config = new ConfigManager();
59
+        final ApiFactory factory = new ApiFactory(config);
60
+
57 61
         readVersion();
58
-        initTables();
62
+        initTables(factory);
59 63
 
60
-        final AccountManager manager = new AccountManager(ApiFactory.getConnection());
64
+        final AccountManager manager = new AccountManager(factory.getConnection());
61 65
 
62
-        new MainWindow(manager, new ApiFactory()).setVisible(true);
66
+        new MainWindow(manager, new ApiFactory(config)).setVisible(true);
63 67
     }
64 68
 
65 69
     /**
@@ -75,9 +79,11 @@ public class Main {
75 79
 
76 80
     /**
77 81
      * Initialises tables used by the program.
82
+     *
83
+     * @param factory The ApiFactory to use for the database connection
78 84
      */
79
-    protected static void initTables() {
80
-        new TableCreator(ApiFactory.getConnection(), "/uk/co/md87/evetool/sql/",
85
+    protected static void initTables(final ApiFactory factory) {
86
+        new TableCreator(factory.getConnection(), "/uk/co/md87/evetool/sql/",
81 87
                 TABLES).checkTables();
82 88
     }
83 89
 

+ 1
- 1
src/uk/co/md87/evetool/ui/MainWindow.java View File

@@ -70,7 +70,7 @@ public class MainWindow extends JFrame {
70 70
     private final Map<String, ContentPanel.Page> pages;
71 71
 
72 72
     public MainWindow(final AccountManager manager, final ApiFactory factory) {
73
-        super("EVE Tool - Initialising...");
73
+        super("EVE Tool - No character selected");
74 74
 
75 75
         UIManager.put("swing.boldMetal", false);
76 76
 

Loading…
Cancel
Save