OSDN Git Service

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