James Moger
2011-10-24 4c837a1de9f7706c7bfb0cbb14a7082f916826ae
commit | author | age
f13c4c 1 /*
JM 2  * Copyright 2011 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
5fe7df 16 package com.gitblit;
JM 17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
97a20e 21 import java.util.Map;
5fe7df 22 import java.util.Properties;
97a20e 23 import java.util.regex.Pattern;
JM 24
25 import com.gitblit.utils.FileUtils;
5fe7df 26
JM 27 /**
892570 28  * Dynamically loads and reloads a properties file by keeping track of the last
JM 29  * modification date.
30  * 
31  * @author James Moger
5fe7df 32  * 
JM 33  */
f339f5 34 public class FileSettings extends IStoredSettings {
2a7306 35
8c9a20 36     protected final File propertiesFile;
db653a 37
f339f5 38     private final Properties properties = new Properties();
5fe7df 39
892570 40     private volatile long lastModified;
5fe7df 41
28d6b2 42     public FileSettings(String file) {
f339f5 43         super(FileSettings.class);
28d6b2 44         this.propertiesFile = new File(file);
JM 45     }
db653a 46
892570 47     /**
JM 48      * Returns a properties object which contains the most recent contents of
49      * the properties file.
50      */
87cc1e 51     @Override
f339f5 52     protected synchronized Properties read() {
892570 53         if (propertiesFile.exists() && (propertiesFile.lastModified() > lastModified)) {
2a7306 54             FileInputStream is = null;
5fe7df 55             try {
f339f5 56                 Properties props = new Properties();
28d6b2 57                 is = new FileInputStream(propertiesFile);
f339f5 58                 props.load(is);
85c2e6 59
f339f5 60                 // load properties after we have successfully read file
JM 61                 properties.clear();
62                 properties.putAll(props);
892570 63                 lastModified = propertiesFile.lastModified();
5fe7df 64             } catch (FileNotFoundException f) {
2a7306 65                 // IGNORE - won't happen because file.exists() check above
5fe7df 66             } catch (Throwable t) {
f339f5 67                 logger.error("Failed to read " + propertiesFile.getName(), t);
2a7306 68             } finally {
JM 69                 if (is != null) {
70                     try {
71                         is.close();
72                     } catch (Throwable t) {
73                         // IGNORE
74                     }
75                 }
5fe7df 76             }
JM 77         }
78         return properties;
79     }
2a7306 80
892570 81     /**
97a20e 82      * Updates the specified settings in the settings file.
JM 83      */
84     public synchronized boolean saveSettings(Map<String, String> settings) {
85         String content = FileUtils.readContent(propertiesFile, "\n");
86         for (Map.Entry<String, String> setting:settings.entrySet()) {
87             String regex = "(?m)^(" + regExEscape(setting.getKey()) + "\\s*+=\\s*+)"
88                     + "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$";            
89             content = content.replaceAll(regex, setting.getKey() + " = " + setting.getValue());
90         }
91         FileUtils.writeContent(propertiesFile, content);
92         return true;
93     }
94     
95     private String regExEscape(String input) {
96         return input.replace(".", "\\.");
97     }
98
99     /**
892570 100      * @return the last modification date of the properties file
JM 101      */
102     protected long lastModified() {
103         return lastModified;
85c2e6 104     }
JM 105
87cc1e 106     @Override
JM 107     public String toString() {
28d6b2 108         return propertiesFile.getAbsolutePath();
87cc1e 109     }
5fe7df 110 }