OSDN Git Service

iniファイルをプログラムディレクトリからホームディレクトリに移動させる記述を追加。
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / config / FileManager.java
1 package cx.fbn.nevernote.config;
2
3 import java.io.File;
4 import java.io.FileFilter;
5 import java.util.regex.Pattern;
6
7 /**
8  * Provides access to NeverNote standard runtime directories.
9  *
10  * @author Nick Clarke
11  */
12 public class FileManager {
13
14     private static final Pattern ALL_PATH_SEPARATORS_REGEX = Pattern.compile("[/\\\\]");
15
16     private final String programDirPath;
17     private final File programDir;
18     
19     private final String homeDirPath;
20     private final File homeDir;
21
22     private final String dbDirPath;
23     private final File dbDir;
24
25     private final File logsDir;
26
27     private final String imagesDirPath;
28     private final File imagesDir;
29
30     private final String spellDirPath;
31     private final File spellDir;
32     
33     private final String spellDirPathUser;
34     private final File spellDirUser;
35     
36     private final String qssDirPath;
37     private final File qssDir;
38     
39     private final String qssDirPathUser;
40     private final File qssDirUser;
41
42     private final String resDirPath;
43     private final File resDir;
44
45     private final File xmlDir;
46
47     private final String translateDirPath;
48     private final File translateDir;
49
50     /**
51      * Check or create the db, log and res directories.
52      *
53      * @param homeDirPath the installation dir containing db/log/res directories, must exist
54      * @throws InitializationException for missing directories or file permissions problems
55      */
56     public FileManager(String homeDirPath, String programDirPath) throws InitializationException {
57         if (homeDirPath == null) {
58             throw new IllegalArgumentException("homeDirPath must not be null");
59         }
60         if (programDirPath == null) {
61             throw new IllegalArgumentException("programDirPath must not be null");
62         }
63
64         this.homeDir = new File(toPlatformPathSeparator(homeDirPath));
65         this.programDir = new File(toPlatformPathSeparator(programDirPath));
66         createDirOrCheckWriteable(homeDir);
67         this.homeDirPath = slashTerminatePath(homeDir.getPath());
68         this.programDirPath = slashTerminatePath(programDir.getPath());
69         
70         // Read-only
71         imagesDir = new File(programDir, "images");
72         checkExistingReadableDir(imagesDir);
73         imagesDirPath = slashTerminatePath(imagesDir.getPath());
74
75         qssDir = new File(programDir, "qss");
76         checkExistingReadableDir(qssDir);
77         qssDirPath = slashTerminatePath(qssDir.getPath());
78         
79         qssDirUser = new File(homeDir, "qss");
80         createDirOrCheckWriteable(qssDirUser);
81         qssDirPathUser = slashTerminatePath(qssDirUser.getPath());
82
83         spellDir = new File(programDir, "spell");
84         checkExistingReadableDir(spellDir);
85         spellDirPath = slashTerminatePath(spellDir.getPath());
86         
87
88         spellDirUser = new File(homeDir, "spell");
89         createDirOrCheckWriteable(spellDirUser);
90         spellDirPathUser = slashTerminatePath(spellDirUser.getPath());
91         
92         xmlDir = new File(programDir, "xml");
93         checkExistingReadableDir(xmlDir);
94
95         translateDir = new File(programDir, "translations");
96         checkExistingReadableDir(translateDir);
97         translateDirPath= slashTerminatePath(translateDir.getPath());
98
99         // Read-write
100         dbDir = new File(homeDir, "db");
101         createDirOrCheckWriteable(dbDir);
102         dbDirPath = slashTerminatePath(dbDir.getPath());
103
104         logsDir = new File(homeDir, "logs");
105         createDirOrCheckWriteable(logsDir);
106
107         resDir = new File(homeDir, "res");
108         createDirOrCheckWriteable(resDir);
109         resDirPath = slashTerminatePath(resDir.getPath());
110     }
111
112     /**
113      * Get a file below the base user home directory.
114      */
115     public File getProgramDirFile(String relativePath) {
116         return new File(programDir, toPlatformPathSeparator(relativePath));
117     }
118
119     /**
120      * Get a path below the base user home directory, using native {@link File#separator}.
121      * This will contain backslashes on Windows.
122      */
123     public String getProgramDirPath(String relativePath) {
124         return programDirPath + toPlatformPathSeparator(relativePath);
125     }
126     
127     /**
128      * Get a file below the base user home directory.
129      */
130     public File getHomeDirFile(String relativePath) {
131         return new File(homeDir, toPlatformPathSeparator(relativePath));
132     }
133
134     /**
135      * Get a path below the base user home directory, using native {@link File#separator}.
136      * This will contain backslashes on Windows.
137      */
138     public String getHomeDirPath(String relativePath) {
139         return homeDirPath + toPlatformPathSeparator(relativePath);
140     }
141
142     /**
143      * Get a file below the 'db' directory.
144      */
145     public File getDbDirFile(String relativePath) {
146         return new File(dbDir, toPlatformPathSeparator(relativePath));
147     }
148
149     /**
150      * Get a path below the 'spell' directory, using native {@link File#separator}.
151      * This will contain backslashes on Windows.
152      */
153     public String getSpellDirPath(String relativePath) {
154         return dbDirPath + toPlatformPathSeparator(relativePath);
155     }
156
157     /**
158      * Get a file below the 'spell' directory.
159      */
160     public File getSpellDirFile(String relativePath) {
161         return new File(spellDir, toPlatformPathSeparator(relativePath));
162     }
163     
164     /** 
165      * Get the spell directory for the jazzy word list
166      */
167     public String getSpellDirPath() {
168         return spellDirPath;
169     }
170
171     /**
172      * Get a file below the 'spell' directory for user dictionaries.
173      */
174     public File getSpellDirFileUser(String relativePath) {
175         return new File(spellDirUser, toPlatformPathSeparator(relativePath));
176     }
177     
178     /** 
179      * Get the spell directory for the jazzy word list (user dictionary).
180      */
181     public String getSpellDirPathUser() {
182         return spellDirPathUser;
183     }
184     
185     /**
186      * Get a path below the 'db' directory, using native {@link File#separator}.
187      * This will contain backslashes on Windows.
188      */    
189     public String getDbDirPath(String relativePath) {
190         return dbDirPath + toPlatformPathSeparator(relativePath);
191     }
192     
193     /**
194      * Get a file below the 'images' directory.
195      */
196     public File getImageDirFile(String relativePath) {
197         return new File(imagesDir, toPlatformPathSeparator(relativePath));
198     }
199
200     /**
201      * Get a path below the 'images' directory, using native {@link File#separator}.
202      * This will contain backslashes on Windows.
203      */
204     public String getImageDirPath(String relativePath) {
205         return imagesDirPath + toPlatformPathSeparator(relativePath);
206     }
207
208     /**
209      * Get a file below the 'logs' directory.
210      */
211     public File getLogsDirFile(String relativePath) {
212         return new File(logsDir, toPlatformPathSeparator(relativePath));
213     }
214
215     /**
216      * Get a path below the 'qss' directory, using native {@link File#separator}.
217      * This will contain backslashes on Windows.
218      */
219     public String getQssDirPath(String relativePath) {
220         return qssDirPath + toPlatformPathSeparator(relativePath);
221     }
222
223     /**
224      * Get a path below the 'qss' directory, using native {@link File#separator}.
225      * This will contain backslashes on Windows.
226      */
227     public String getQssDirPathUser(String relativePath) {
228         return qssDirPathUser + toPlatformPathSeparator(relativePath);
229     }
230     
231     /**
232      * Get a path to the 'res' directory, terminated with native {@link File#separator}.
233      * This will contain backslashes on Windows.
234      */
235     public String getResDirPath() {
236         return resDirPath;
237     }
238
239     /**
240      * Get a path below the 'res' directory, using native {@link File#separator}.
241      * This will contain backslashes on Windows.
242      */
243     public String getResDirPath(String relativePath) {
244         return resDirPath + toPlatformPathSeparator(relativePath);
245     }
246     
247     /**
248      * Get a path below the 'res' directory, using native {@link File#separator}.
249      * This will contain backslashes on Windows.  This is different from the 
250      * one above in that it will encode the relative path
251      */
252     public String getResDirPathSpecialChar(String relativePath) {
253                 return resDirPath + toPlatformPathSeparator(relativePath).replace("#", "%23");
254     }
255
256     /**
257      * Get a file below the 'xml' directory.
258      */
259     public File getXMLDirFile(String relativePath) {
260         return new File(xmlDir, toPlatformPathSeparator(relativePath));
261     }
262
263     /**
264      * Get a path below the 'translate' directory, using native {@link File#separator}.
265      * This will contain backslashes on Windows.
266      */
267     public String getTranslateFilePath(String relativePath) {
268         return translateDirPath + toPlatformPathSeparator(relativePath);
269     }
270
271     public static String toPlatformPathSeparator(String relativePath) {
272         // Sometimes a space in the file name comes across as a %20.  This is to put it back as a space.
273         relativePath = relativePath.replace("%20", " ");
274         return ALL_PATH_SEPARATORS_REGEX.matcher(relativePath).replaceAll(
275                                 // Must double-escape backslashes,
276                                 // because they have special meaning in the replacement string of Matcher.replaceAll
277                                 (File.separator.equals("\\") ? "\\\\" : File.separator));
278     }
279
280     public static String slashTerminatePath(String path) {
281         if (!path.substring(path.length() - 1).equals(File.separator)) {
282             return path + File.separator;
283         }
284         return path;
285     }
286
287     /**
288      * Delete first-level files (but not directories) from the directory.
289      *
290      * @throws InitializationException for file deletion failures
291      */
292     private static void deleteTopLevelFiles(File dir, boolean exitOnFail) throws InitializationException {
293         File[] toDelete = dir.listFiles(new FileFilter() {
294             @Override
295             public boolean accept(File pathname) {
296                 return pathname.isFile();
297             }
298         });
299         for (File f : toDelete) {
300             if (!f.delete() && exitOnFail) {
301                 throw new InitializationException("Failed to delete file: '" + f + "'");
302             }
303         }
304     }
305
306     /**
307      * @throws InitializationException for bad file permissions, or a file instead of a directory
308      */
309     private static void createDirOrCheckWriteable(File dir) throws InitializationException {
310         if (dir.isDirectory()) {
311             // Dir exists, check permissions
312             if (!dir.canRead()) {
313                 throw new InitializationException("Directory '" + dir + "' does not have read permission");
314             }
315             if (!dir.canWrite()) {
316                 throw new InitializationException("Directory '" + dir + "' does not have write permission");
317             }
318         } else if (!dir.exists()) {
319             if (!dir.mkdirs()) {
320                 throw new InitializationException("Failed to create directory '" + dir + "'");
321             }
322         } else {
323             throw new InitializationException("Expected directory '" + dir + "' but found a file instead");
324         }
325     }
326
327     /**
328      * @throws InitializationException if non-existent, bad file permissions, or a file instead of a directory
329      */
330     private static void checkExistingReadableDir(File dir) throws InitializationException {
331         if (dir.isDirectory()) {
332             // Dir exists, check permissions
333             if (!dir.canRead()) {
334                 throw new InitializationException("Directory '" + dir + "' does not have read permission");
335             }
336         } else if (!dir.exists()) {
337             throw new InitializationException("Directory '" + dir + "' does not exist");
338         } else {
339             throw new InitializationException("Expected directory '" + dir + "' but found a file instead");
340         }
341     }
342
343     /**
344      * @throws InitializationException if non-existent, bad file permissions, or a file instead of a directory
345      */
346     @SuppressWarnings("unused")
347         private static void checkExistingWriteableDir(File dir) throws InitializationException {
348         checkExistingReadableDir(dir);
349         if (!dir.canWrite()) {
350             throw new InitializationException("Directory '" + dir + "' does not have write permission");
351         }
352     }
353
354     /**
355      * Called at startup to purge files from 'res' directory.
356      */
357     public void purgeResDirectory(boolean exitOnFail) throws InitializationException {
358         deleteTopLevelFiles(resDir, exitOnFail);
359     }
360 }