1 package cx.fbn.nevernote.config;
4 import java.io.FileFilter;
5 import java.util.regex.Pattern;
8 * Provides access to NeverNote standard runtime directories.
12 public class FileManager {
14 private static final Pattern ALL_PATH_SEPARATORS_REGEX = Pattern.compile("[/\\\\]");
16 private final String homeDirPath;
17 private final File homeDir;
19 private final String dbDirPath;
20 private final File dbDir;
22 private final File logsDir;
24 private final String imagesDirPath;
25 private final File imagesDir;
27 private final String qssDirPath;
28 private final File qssDir;
30 private final String resDirPath;
31 private final File resDir;
33 private final File xmlDir;
36 * Check or create the db, log and res directories, and purge files from 'res' .
38 * @param homeDirPath the installation dir containing db/log/res directories, must exist
40 public FileManager(String homeDirPath) throws InitializationException {
41 if (homeDirPath == null) {
42 throw new IllegalArgumentException("homeDirPath must not be null");
45 this.homeDir = new File(toPlatformPathSeparator(homeDirPath));
46 checkExistingWriteableDir(homeDir);
47 this.homeDirPath = slashTerminatePath(homeDir.getPath());
50 imagesDir = new File(homeDir, "images");
51 checkExistingReadableDir(imagesDir);
52 imagesDirPath = slashTerminatePath(imagesDir.getPath());
54 qssDir = new File(homeDir, "qss");
55 checkExistingReadableDir(qssDir);
56 qssDirPath = slashTerminatePath(qssDir.getPath());
58 xmlDir = new File(homeDir, "xml");
59 checkExistingReadableDir(xmlDir);
62 dbDir = new File(homeDir, "db");
63 createDirOrCheckWriteable(dbDir);
64 dbDirPath = slashTerminatePath(dbDir.getPath());
66 logsDir = new File(homeDir, "logs");
67 createDirOrCheckWriteable(logsDir);
69 resDir = new File(homeDir, "res");
70 createDirOrCheckWriteable(resDir);
71 resDirPath = slashTerminatePath(resDir.getPath());
73 deleteTopLevelFiles(resDir);
77 * Get a file below the base installation directory.
79 public File getHomeDirFile(String relativePath) {
80 return new File(homeDir, toPlatformPathSeparator(relativePath));
84 * Get a path below the base installation directory, using native {@link File#separator}.
85 * This will contain backslashes on Windows.
87 public String getHomeDirPath(String relativePath) {
88 return homeDirPath + toPlatformPathSeparator(relativePath);
92 * Get a file below the 'db' directory.
94 public File getDbDirFile(String relativePath) {
95 return new File(dbDir, toPlatformPathSeparator(relativePath));
99 * Get a path below the 'db' directory, using native {@link File#separator}.
100 * This will contain backslashes on Windows.
102 public String getDbDirPath(String relativePath) {
103 return dbDirPath + toPlatformPathSeparator(relativePath);
107 * Get a file below the 'images' directory.
109 public File getImageDirFile(String relativePath) {
110 return new File(imagesDir, toPlatformPathSeparator(relativePath));
114 * Get a path below the 'images' directory, using native {@link File#separator}.
115 * This will contain backslashes on Windows.
117 public String getImageDirPath(String relativePath) {
118 return imagesDirPath + toPlatformPathSeparator(relativePath);
122 * Get a file below the 'logs' directory.
124 public File getLogsDirFile(String relativePath) {
125 return new File(logsDir, toPlatformPathSeparator(relativePath));
129 * Get a path below the 'qss' directory, using native {@link File#separator}.
130 * This will contain backslashes on Windows.
132 public String getQssDirPath(String relativePath) {
133 return qssDirPath + toPlatformPathSeparator(relativePath);
137 * Get a path to the 'res' directory, terminated with native {@link File#separator}.
138 * This will contain backslashes on Windows.
140 public String getResDirPath() {
145 * Get a path below the 'res' directory, using native {@link File#separator}.
146 * This will contain backslashes on Windows.
148 public String getResDirPath(String relativePath) {
149 return resDirPath + toPlatformPathSeparator(relativePath);
153 * Get a file below the 'xml' directory.
155 public File getXMLDirFile(String relativePath) {
156 return new File(xmlDir, toPlatformPathSeparator(relativePath));
159 private static String toPlatformPathSeparator(String relativePath) {
160 return ALL_PATH_SEPARATORS_REGEX.matcher(relativePath).replaceAll(File.separator);
163 private static String slashTerminatePath(String path) {
164 if (!path.substring(path.length() - 1).equals(File.separator)) {
165 return path + File.separator;
171 * Delete first-level files (but not directories) from the directory.
173 * @throws InitializationException for file deletion failures
175 private static void deleteTopLevelFiles(File dir) throws InitializationException {
176 File[] toDelete = dir.listFiles(new FileFilter() {
178 public boolean accept(File pathname) {
179 return pathname.isFile();
182 for (File f : toDelete) {
184 throw new InitializationException("Failed to delete file: '" + f + "'");
190 * @throws InitializationException for bad file permissions, or a file instead of a directory
192 private static void createDirOrCheckWriteable(File dir) throws InitializationException {
193 if (dir.isDirectory()) {
194 // Dir exists, check permissions
195 if (!dir.canRead()) {
196 throw new InitializationException("Directory '" + dir + "' does not have read permission");
198 if (!dir.canWrite()) {
199 throw new InitializationException("Directory '" + dir + "' does not have write permission");
201 } else if (!dir.exists()) {
203 throw new InitializationException("Failed to create directory '" + dir + "'");
206 throw new InitializationException("Expected directory '" + dir + "' but found a file instead");
211 * @throws InitializationException if non-existent, bad file permissions, or a file instead of a directory
213 private static void checkExistingReadableDir(File dir) throws InitializationException {
214 if (dir.isDirectory()) {
215 // Dir exists, check permissions
216 if (!dir.canRead()) {
217 throw new InitializationException("Directory '" + dir + "' does not have read permission");
219 } else if (!dir.exists()) {
220 throw new InitializationException("Directory '" + dir + "' does not exist");
222 throw new InitializationException("Expected directory '" + dir + "' but found a file instead");
227 * @throws InitializationException if non-existent, bad file permissions, or a file instead of a directory
229 private static void checkExistingWriteableDir(File dir) throws InitializationException {
230 checkExistingReadableDir(dir);
231 if (!dir.canWrite()) {
232 throw new InitializationException("Directory '" + dir + "' does not have write permission");