OSDN Git Service

0516334f446d3853ed685e035f3099c5aaa7baf3
[coroid/NicoBrowser.git] / src / nicobrowser / config / Config.java
1 /*$Id$*/
2 package nicobrowser.config;
3
4 import java.io.BufferedReader;
5 import java.io.File;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.InputStreamReader;
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.List;
12 import java.util.logging.Level;
13 import java.util.logging.Logger;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
16 import org.apache.commons.configuration.Configuration;
17 import org.apache.commons.configuration.ConfigurationException;
18 import org.apache.commons.configuration.PropertiesConfiguration;
19 import org.apache.commons.io.FileUtils;
20 import org.apache.commons.lang.StringUtils;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 public final class Config {
25
26     private static Log log = LogFactory.getLog(Config.class);
27     private static Config instance;
28     private final PropertiesConfiguration properties;
29     private static final String APPLICATION_NAME = "nicobrowser";
30     private static final String CONFIG_NAME = APPLICATION_NAME + ".properties";
31     private static final String FEEDURL_NAME = "feedurl.txt";
32     private static final String MYLIST_CONFIG_NAME = "mylist.txt";
33     private static final File APP_HOME = new File(System.getProperty("user.home", "."), "." + APPLICATION_NAME);
34     private static final File CONFIG_FILE = new File(APP_HOME, CONFIG_NAME);
35     private static final File FEEDURL_FILE = new File(APP_HOME, FEEDURL_NAME);
36     private static final File MYLIST_CONFIG_FILE = new File(APP_HOME, MYLIST_CONFIG_NAME);
37     public static final String P_PATH_DB = "path.db";
38     public static final String P_PATH_SAVEFILE = "path.savefile";
39     public static final String P_SAVEFILE_PATTERN = "savefilename.pattern";
40     public static final String P_SAVEFILE_REPLACE_FROM = "savefilename.replace.from";
41     public static final String P_SAVEFILE_REPLACE_TO = "savefilename.replace.to";
42     public static final String P_FILE_ENCODING = "encoding";
43     public static final String P_NICOVIDEO_MAIL = "nicovideo.mail";
44     public static final String P_NICOVIDEO_PASSWORD = "nicovideo.password";
45     public static final String P_DOWNLOAD_RETRY = "download.retry";
46     public static final String P_DOWNLOAD_WAIT = "download.wait";
47     public static final String P_DOWNLOAD_LOW = "download.low";
48     public static final String P_DOWNLOAD_MYLIST = "download.mylist";
49     private static final int DEFAULT_MAX_RETRY = 3;
50     private static final int DEFAULT_WAIT_TIME = 15;
51     private static final boolean DEFAULT_LOW_FILE = true;
52
53     /**
54      * プログラム実行に必要なコンフィグファイルを作成する.
55      * @return 今回コンフィグを作成したのであればtrue. 既に存在していたため, ファイル作成を行わなかった場合にはfalse.
56      * @throws java.io.IOException ファイル作成に失敗した.
57      */
58     public static boolean createNewConfigFiles() throws IOException {
59         boolean result = false;
60         if (!CONFIG_FILE.exists()) {
61             createNewConfigFile(CONFIG_FILE);
62             result = true;
63             log.info("コンフィグファイルを作成しました: " + CONFIG_FILE.getCanonicalPath());
64         }
65         if (!FEEDURL_FILE.exists()) {
66             InputStream resource = null;
67             try {
68                 resource = ClassLoader.getSystemResourceAsStream("resources/" + FEEDURL_NAME);
69                 createNewFileFromResource(resource, FEEDURL_FILE);
70                 result = true;
71                 log.info("FEED URLファイルを作成しました: " + FEEDURL_FILE.getCanonicalPath());
72             } finally {
73                 if (resource != null) {
74                     resource.close();
75                 }
76             }
77         }
78         if (!MYLIST_CONFIG_FILE.exists()) {
79             InputStream resource = null;
80             try {
81                 resource = ClassLoader.getSystemResourceAsStream("resources/" + MYLIST_CONFIG_NAME);
82                 createNewFileFromResource(resource, MYLIST_CONFIG_FILE);
83                 log.info("MYLISTファイルを作成しました: " + MYLIST_CONFIG_FILE.getCanonicalPath());
84             } finally {
85                 if (resource != null) {
86                     resource.close();
87                 }
88             }
89         }
90         return result;
91     }
92
93     /**
94      * 新しいプロパティを設定する. 新しいプロパティに値がない場合, 現在のままとなる.
95      * @param p 新規プロパティ.
96      * @throws IOException
97      */
98     public void updateConfigFile(Configuration p) throws ConfigurationException {
99         updatePropertyValue(p, P_NICOVIDEO_MAIL);
100         updatePropertyValue(p, P_NICOVIDEO_PASSWORD);
101         updatePropertyValue(p, P_FILE_ENCODING);
102
103         updatePropertyValue(p, P_PATH_DB);
104         updatePropertyValue(p, P_PATH_SAVEFILE);
105         updatePropertyValue(p, P_SAVEFILE_PATTERN);
106         updatePropertyValue(p, P_SAVEFILE_REPLACE_FROM);
107         updatePropertyValue(p, P_SAVEFILE_REPLACE_TO);
108
109         updatePropertyValue(p, P_DOWNLOAD_RETRY);
110         updatePropertyValue(p, P_DOWNLOAD_WAIT);
111         updatePropertyValue(p, P_DOWNLOAD_LOW);
112
113         updatePropertyValueArray(p, P_DOWNLOAD_MYLIST);
114
115         properties.save();
116     }
117
118     /**
119      * 新しいプロパティを設定する. 新しいプロパティに値がない場合, 現在のままとなる.
120      * @param newProp 新規プロパティ.
121      * @param key 設定するプロパティキー.
122      */
123     private void updatePropertyValue(Configuration newProp, String key) {
124         String value = newProp.getString(key, properties.getString(key));
125         properties.setProperty(key, value);
126     }
127
128     private void updatePropertyValueArray(Configuration newProp, String key) {
129         String[] values = newProp.getStringArray(key);
130         if (values.length < 1) {
131             values = properties.getStringArray(key);
132         }
133         properties.setProperty(key, values);
134     }
135
136     private static void createNewConfigFile(File file) throws IOException {
137         ArrayList<CharSequence> props = new ArrayList<CharSequence>();
138
139         StringBuilder dbpath = new StringBuilder(P_PATH_DB + "=");
140         File dbDir = new File(APP_HOME, "db");
141         dbDir.mkdirs();
142         //Windowsのパス区切りバックスペースをエスケープするための処理も入れている.
143         dbpath.append(dbDir.getAbsolutePath().replaceAll("\\\\", "\\\\\\\\"));
144         props.add(dbpath);
145
146         StringBuilder savepath = new StringBuilder(P_PATH_SAVEFILE + "=");
147         File saveDir = new File(APP_HOME, "flv");
148         saveDir.mkdirs();
149         savepath.append(saveDir.getAbsolutePath().replaceAll("\\\\", "\\\\\\\\"));
150         props.add(savepath);
151
152         props.add(P_SAVEFILE_PATTERN + "={title}");
153         props.add(P_SAVEFILE_REPLACE_FROM + "=\\/\\\\:*?\\\"<>|.");
154         props.add(P_SAVEFILE_REPLACE_TO + "=_");
155
156         props.add(P_FILE_ENCODING + "=" + System.getProperty("file.encoding"));
157
158         props.add(P_NICOVIDEO_MAIL + "=");
159         props.add(P_NICOVIDEO_PASSWORD + "=");
160         props.add(P_DOWNLOAD_RETRY + "=" + DEFAULT_MAX_RETRY);
161         props.add(P_DOWNLOAD_WAIT + "=" + DEFAULT_WAIT_TIME);
162         props.add(P_DOWNLOAD_LOW + "=" + DEFAULT_LOW_FILE);
163         props.add(P_DOWNLOAD_MYLIST + "=");
164
165         FileUtils.writeLines(file, props);
166     }
167
168     /**
169      * リソースから新しいファイルを作成します. リソースファイルはUTF-8で記述する必要があります.
170      * 出力されるファイルはOSのネイティブエンコーディングになります.
171      * @param resource 入力リソース.
172      * @param dest 出力ファイル.
173      * @throws IOException 出力できなかった場合.
174      */
175     private static void createNewFileFromResource(InputStream resource, File dest) throws IOException {
176         List<String> list = new ArrayList<String>();
177         BufferedReader br = new BufferedReader(new InputStreamReader(resource, "UTF-8"));
178         while (true) {
179             String text = br.readLine();
180             if (text == null) {
181                 break;
182             }
183             list.add(text);
184         }
185         FileUtils.writeLines(dest, list);
186     }
187
188     private Config() {
189         try {
190             properties = new PropertiesConfiguration(CONFIG_FILE);
191         } catch (Exception ex) {
192             log.fatal("コンフィグの読み込みに失敗: " + CONFIG_FILE);
193             throw new RuntimeException(ex);
194         }
195
196         try {
197             List urls = FileUtils.readLines(FEEDURL_FILE);
198         } catch (IOException ex) {
199             log.fatal("コンフィグの読み込みに失敗: " + CONFIG_FILE);
200             throw new RuntimeException(ex);
201         }
202     }
203
204     public static Config getInstance() {
205         if (instance == null) {
206             instance = new Config();
207         }
208         return instance;
209     }
210
211     /**
212      * @return ニコニコ動画ログインID.
213      */
214     public String getNicoMail() {
215         return properties.getString(P_NICOVIDEO_MAIL);
216     }
217
218     /**
219      * @return ニコニコ動画ログインパスワード.
220      */
221     public String getNicoPassword() {
222         return properties.getString(P_NICOVIDEO_PASSWORD);
223     }
224
225     /** @return DBパス. コンフィグで設定した値(保存ディレクトリ)でなく, DBファイルのパスが変えることに注意. */
226     public String getDbFile() {
227         return new File(properties.getString(P_PATH_DB), "nicodb").getAbsolutePath();
228     }
229
230     /** @return 保存先の指定. */
231     public String getSrcSaveDir() {
232         return properties.getString(P_PATH_SAVEFILE);
233     }
234
235     /**@return 保存ファイル名の命名規則. */
236     public String getFileNamePattern() {
237         return properties.getString(P_SAVEFILE_PATTERN, "{title}");
238     }
239
240     public String getFileNameReplaceFrom() {
241         return properties.getString(P_SAVEFILE_REPLACE_FROM, "/\\:*?\"<>|.");
242     }
243
244     public String getFileNameReplaceTo() {
245         return properties.getString(P_SAVEFILE_REPLACE_TO, "_");
246     }
247
248     /** @return feedurl.txtの文字エンコーディング. */
249     public String getEncoding() {
250         String res = properties.getString(P_FILE_ENCODING, System.getProperty("file.encoding"));
251         return res;
252     }
253
254     /**
255      * 失敗したダウンロードファイルの最大リトライ回数を取得する.
256      * @return リトライ回数.
257      */
258     public int getMaxRetry() {
259         return properties.getInt(P_DOWNLOAD_RETRY, DEFAULT_MAX_RETRY);
260     }
261
262     /**
263      * 前回ダウンロード開始から最低何秒後から次回ダウンロードを開始するか.
264      * @return 待ち時間(秒).
265      */
266     public int getWaitTime() {
267         return properties.getInt(P_DOWNLOAD_WAIT, DEFAULT_WAIT_TIME);
268     }
269
270     /**
271      * エコノミー動画をダウンロードする必要があるか.
272      * @return エコノミー動画もダウンロード対称にする場合はtrue.
273      */
274     public boolean needLowFile() {
275         return properties.getBoolean(P_DOWNLOAD_LOW, DEFAULT_LOW_FILE);
276     }
277
278     public List<String> getDownLoadMyList() {
279         final List<String> mylists = new ArrayList<String>();
280         try {
281             final List<?> lines = FileUtils.readLines(MYLIST_CONFIG_FILE);
282             final Pattern p = Pattern.compile("(^\\d+)");
283             for (Object l : lines) {
284                 Matcher m = p.matcher(l.toString());
285                 if (m.find()) {
286                     mylists.add(m.group(1));
287                 }
288             }
289         } catch (IOException ex) {
290             Logger.getLogger(Config.class.getName()).log(Level.SEVERE, "読み込みに失敗: " + MYLIST_CONFIG_NAME, ex);
291         }
292         String[] res = properties.getStringArray(P_DOWNLOAD_MYLIST);
293         mylists.addAll(Arrays.asList(res));
294         return mylists;
295     }
296
297     public List<NicoFeed> getNicoFeeds() {
298         List<NicoFeed> list = new ArrayList<NicoFeed>();
299         try {
300             List<?> lines = FileUtils.readLines(FEEDURL_FILE, getEncoding());
301             for (Object line : lines) {
302                 final String str = line.toString();
303                 if (StringUtils.isBlank(str) || str.startsWith("#")) {
304                     // 空行, コメント行はスキップ.
305                     continue;
306                 }
307
308                 String[] values = str.split(",");
309                 NicoFeed feed = new NicoFeed(values[0].trim(), Integer.parseInt(values[1].trim()));
310                 list.add(feed);
311             }
312         } catch (IOException ex) {
313             log.error("ファイルが見つかりません: " + FEEDURL_FILE);
314         }
315         return list;
316     }
317
318     public static File getConfigfile() {
319         return CONFIG_FILE;
320     }
321
322     public static File getFeedUrlFile() {
323         return FEEDURL_FILE;
324     }
325
326     public static File getMylistConfigFile() {
327         return MYLIST_CONFIG_FILE;
328     }
329
330     public static File getAppHome() {
331         return APP_HOME;
332     }
333 }