OSDN Git Service

ver.0.3.0変更分のマージ
authoryuki <yuki@bdf3b611-c98c-6041-8292-703d9c9adbe7>
Mon, 30 Nov 2009 15:58:51 +0000 (15:58 +0000)
committeryuki <yuki@bdf3b611-c98c-6041-8292-703d9c9adbe7>
Mon, 30 Nov 2009 15:58:51 +0000 (15:58 +0000)
git-svn-id: http://192.168.11.7/svn/repository/NicoBrowser/trunk@246 bdf3b611-c98c-6041-8292-703d9c9adbe7

NicoBrowser.bat [new file with mode: 0644]
README.html
nbproject/project.properties
src/nicobrowser/Config.java
src/nicobrowser/gui/config/ConfigFrame.form [new file with mode: 0644]
src/nicobrowser/gui/config/ConfigFrame.java [new file with mode: 0644]
src/nicobrowser/main/Main.java
src/resources/feedurl.txt
test/nicobrowser/ConfigTest.java

diff --git a/NicoBrowser.bat b/NicoBrowser.bat
new file mode 100644 (file)
index 0000000..ccd9c1b
--- /dev/null
@@ -0,0 +1,9 @@
+SET LOGFILE=NicoBrowser.log\r
+\r
+ECHO: >> %LOGFILE%\r
+ECHO ==== START ==== >> %LOGFILE%\r
+DATE /T >> %LOGFILE%\r
+TIME /T >> %LOGFILE%\r
+ECHO: >> %LOGFILE%\r
+java -jar NicoBrowser.jar 2>&1 >> %LOGFILE%\r
+exit\r
index 2e87de3..b520b95 100644 (file)
@@ -1,3 +1,193 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="ja"><head><meta content="text/html; charset=UTF-8" http-equiv="content-type"><title>README</title></head>\r
-<body><p></p><ul class="readonly" id="mozToc"><!--mozToc h2 1 h3 2--><li><a href="#mozTocId600802">機能・特徴</a></li><li><a href="#mozTocId344177">使い方の一例</a></li><li><a href="#mozTocId180645">操作方法</a></li><li><a href="#mozTocId136534">バージョンアップに関する注意事項</a><ul><li><a href="#mozTocId920310">2009/05/24版以前を使用していた場合の注意事項</a></li><li><a href="#mozTocId116237">2009/03/23版以前を使用していた場合の注意事項</a></li></ul></li><li><a href="#mozTocId730811">nicobrowser.propertiesの説明</a></li><li><a href="#mozTocId935686">feedurl.txtの説明</a></li><li><a href="#mozTocId627544">未解決の課題</a></li><li><a href="#mozTocId130181">更新履歴</a></li></ul><h2><a class="mozTocH2" name="mozTocId600802"></a>機能・特徴</h2><ul><li>ニコニコ動画に投稿された動画の自動ダウンロード</li><ul><li>ランキングの上位から自動ダウンロード</li><li>指定したマイリストから自動ダウンロード</li></ul><li>ダウンロード履歴管理</li><ul><li>一度ダウンロードした動画は重複してダウンロードされない</li><li>エコノミーモードでダウンロードしていた場合でも、高画質ファイルが取得できるのであれば再ダウンロードする</li></ul><li>Pure Javaであるため、Windows, MacOS, Linux上で動作可能</li></ul><h2><a class="mozTocH1" name="mozTocId344177"></a>使い方の一例</h2><p><a href="http://feather.cocolog-nifty.com/weblog/2008/03/post_7d4b.html">http://feather.cocolog-nifty.com/weblog/2008/03/post_7d4b.html</a></p><p><br></p><h2><a class="mozTocH1" name="mozTocId180645"></a>操作方法</h2><p>コマンドラインで以下を実行。</p><p style="font-weight: bold;"><code>java -jar NicoBrowser.jar</code></p><p>1回目の起動でコンフィグファイルがアプリケーションディレクトリに作成される。Windowsであれば、例えば以下のディレクトリ。</p><p>C:\Documents and Settings\user\.nicobrowser</p><p>nicobrowser.propertiesを開き、IDとパスワードを設定する。</p><p>設定後、再度実行すればダウンロード開始。</p><h2><a class="mozTocH2" name="mozTocId136534"></a>バージョンアップに関する注意事項</h2><h3><a class="mozTocH3" name="mozTocId920310"></a>2009/05/24版以前を使用していた場合の注意事項</h3><p>アップデート後(つまり今回のファイルで上書きした後)、1回目の起動前に以下のコマンドを実行する必要がある。実行しないとDB関連のエラーとなり処理が継続できない。</p><p style="font-weight: bold;"><code>java -jar NicoBrowser.jar sync</code></p><p>(引数にsyncをつけて実行する)</p><h3><a class="mozTocH2" name="mozTocId116237"></a>2009/03/23版以前を使用していた場合の注意事項</h3><p>nicobrowser.propertiesの互換性は無いため、一旦リネーム(or 削除)してから<br>実行する必要がある。こうすることで、新しいnicobrowser.propertiesが作成される。</p><p>path.dbの設定は、従来は"ファイル名"の指定だったが、現在は"ディレクトリ名"の指定に変わっていることに注意。</p><p>本体libディレクトリ以下について、構成が大きく変わっているため、libは上書きでなく置換することを推奨。</p><h2><a class="mozTocH2" name="mozTocId730811"></a>nicobrowser.propertiesの説明</h2><p>path.db=<br>履歴管理DBを保存するディレクトリ。日本語名不可。</p><p>path.savefile=<br>ダウンロードしたflvファイルを保存するディレクトリ。日本語名不可。</p><p>encoding=<br>feedurl.txtの文字エンコーディング。</p><p>nicovideo.mail=<br>ニコニコ動画のメールアドレス(ID)。</p><p>nicovideo.password=<br>ニコニコ動画のパスワード。</p><p>download.retry=<br>指定した回数ダウンロード試行に失敗した場合、次回以降ダウンロード対象から除外する。</p><p>download.wait=<br>連続してダウンロードを行う際、ここで指定した秒数待ち合わせて次のファイルへ進む。</p><p>download.mylist=<br>指定した公開マイリストに登録されているコンテンツをダウンロード対象に含める。</p><p>例えば<br>http://www.nicovideo.jp/mylist/4573744<br>http://www.nicovideo.jp/mylist/739988/1395449<br>上記2個のマイリストを対象とする場合、<br>download.mylist=<span style="font-weight: bold;">4573744,739988/1395449</span><br>と、URLの mylist/ 以下をカンマで区切って指定する。</p><h2><a class="mozTocH2" name="mozTocId935686"></a>feedurl.txtの説明</h2><p>1行ごとに、対象とするRSSフィードのURLと抽出数をカンマ区切りで設定する。<br>書式についてはファイル内のコメント参照。</p><h2><a class="mozTocH2" name="mozTocId627544"></a>未解決の課題</h2><p>webサイト参照。</p><h2><a class="mozTocH2" name="mozTocId130181"></a>更新履歴</h2><p>200911/26 ver.0.2.0<br>download.waitプロパティを追加。</p><p>2009/11/13 ver.0.1.1<br>Log4Jのインストールバージョン誤りを修正。</p><p>2009/11/13 ver.0.1<br>永続化する情報に作者(投稿者)情報を追加。ipum用の対応。</p><p>2009/05/24<br>デイリーランキング以外のフィードへ対応。<br>一部のswfに対してアクセスできない問題の対応(新プレイヤ対応)。<br>ログ出力の見直し。</p><p>2009/03/23<br>動画ファイル取得時403をもらった場合、ファイルをダウンロードしないように対応。</p><p>2009/01/11<br>視聴権限が無い動画を取得しようとした場合にアプリケーションが終了してしまう問題を修正。</p><p>2008/08/03<br>ランキングのRSSをzioさん作ニコRSS<br>http://zio3.net/nicoRss/Handler.ashx<br>から本家<br>http://www.nicovideo.jp/ranking/mylist/daily/all?rss=atom<br>に変更した。</p><p>2008/04/09<br>前回ダウンロード要求から5秒待ってから次のダウンロード要求を行うようウェイト処理を追加した。<br>ターゲットをJDK6からJDK5に変更した。</p><p>2008/03/21<br>公開マイリストを指定したダウンロードを可能とした。</p><p>2008/03/15<br>ダウンロードする最低ランキングを指定可能とした。<br>ファイル名にドットが入っていた場合にもアンダーバーに<br>置換するよう置換規則を追加(Craving Explorerに合わせた)。</p></body></html>
\ No newline at end of file
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\r
+<html lang="ja">\r
+<head>\r
+  <meta content="text/html; charset=UTF-8" http-equiv="content-type">\r
+  <title>README</title>\r
+</head>\r
+<body>\r
+<ul class="readonly" id="mozToc">\r
+<!--mozToc h2 1 h3 2-->\r
+  <li><a href="#mozTocId600802">機能・特徴</a></li>\r
+  <li><a href="#mozTocId344177">使い方の一例</a></li>\r
+  <li><a href="#mozTocId180645">操作方法</a>\r
+    <ul>\r
+      <li><a href="#mozTocId241225">基本操作\r
+        </a></li>\r
+      <li><a href="#mozTocId84970">起動引数</a></li>\r
+    </ul>\r
+  </li>\r
+  <li><a href="#mozTocId782665">設定ファイルについて\r
+    </a>\r
+    <ul>\r
+      <li><a href="#mozTocId730811">nicobrowser.properties\r
+の説明</a></li>\r
+      <li><a href="#mozTocId935686">feedurl.txt\r
+の説明</a></li>\r
+    </ul>\r
+  </li>\r
+  <li><a href="#mozTocId136534">バージョンアップに関する注意事項</a>\r
+    <ul>\r
+      <li><a href="#mozTocId920310">2009/05/24版以前を使用していた場合\r
+の注意事項</a></li>\r
+      <li><a href="#mozTocId116237">2009/03/23版以前を使用していた場合\r
+の注意事項</a></li>\r
+    </ul>\r
+  </li>\r
+  <li><a href="#mozTocId627544">未解決の課題</a></li>\r
+  <li><a href="#mozTocId130181">更新履歴</a></li>\r
+</ul>\r
+<p><br>\r
+</p>\r
+<h2><a class="mozTocH2" name="mozTocId600802"></a>機能・特徴</h2>\r
+<ul>\r
+  <li>ニコニコ動画に投稿された動画の自動ダウンロード</li>\r
+  <ul>\r
+    <li>ランキングの上位から自動ダウンロード</li>\r
+    <li>指定したマイリストから自動ダウンロード</li>\r
+  </ul>\r
+  <li>ダウンロード履歴管理</li>\r
+  <ul>\r
+    <li>一度ダウンロードした動画は重複してダウンロードされない</li>\r
+    <li>エコノミーモードでダウンロードしていた場合でも、高画質ファイルが取得できるのであれば再ダウンロードする</li>\r
+  </ul>\r
+  <li>Pure Javaであるため、Windows, MacOS, Linux上で動作可能</li>\r
+  <li><a\r
+ href="http://feather.cocolog-nifty.com/weblog/2009/11/ipum---1377.html">ipum</a>と\r
+の連携でサムネイル付き音楽ファイルの自動生成が可能</li>\r
+</ul>\r
+<p><br>\r
+</p>\r
+<h2><a class="mozTocH1" name="mozTocId344177"></a>使い方の一例</h2>\r
+<p><a\r
+ href="http://feather.cocolog-nifty.com/weblog/2008/03/post_7d4b.html">http://feather.cocolog-nifty.com/weblog/2008/03/post_7d4b.html</a></p>\r
+<p><br>\r
+</p>\r
+<h2><a class="mozTocH1" name="mozTocId180645"></a>操作方法</h2>\r
+<h3><a class="mozTocH3" name="mozTocId241225"></a>基本操作<br>\r
+</h3>\r
+<p>コマンドラインで以下を実行。</p>\r
+<p style="font-weight: bold;"><code>java -jar\r
+NicoBrowser.jar</code></p>\r
+<p>1回目の起動では、このコマンドでコンフィグ設定画面が開く。ここでID、パスワードを入力し保存する。</p>\r
+<p>設定後、再度実行すればダウンロードが開始される。</p>\r
+<p>詳細なダウンロード設定については「<a href="#mozTocId782665">設定ファイルに\r
+ついて</a>」の項を参照。<br>\r
+</p>\r
+<h3><a class="mozTocH3" name="mozTocId84970"></a>起動引数</h3>\r
+<table style="text-align: left; width: 337px; height: 88px;" border="1"\r
+ cellpadding="2" cellspacing="2">\r
+  <tbody>\r
+    <tr>\r
+      <td style="vertical-align: top;">-h<br>\r
+      </td>\r
+      <td style="vertical-align: top;">引数についてのヘルプを表示<br>\r
+      </td>\r
+    </tr>\r
+    <tr>\r
+      <td style="vertical-align: top;">-p<br>\r
+      </td>\r
+      <td style="vertical-align: top;">コンフィグ設定画面を起動<br>\r
+      </td>\r
+    </tr>\r
+    <tr>\r
+      <td style="vertical-align: top; width: 30px;">-v<br>\r
+      </td>\r
+      <td style="vertical-align: top;">バージョン情報を表示<br>\r
+      </td>\r
+    </tr>\r
+  </tbody>\r
+</table>\r
+<p>例えば以下のように実行する:<br>\r
+</p>\r
+<p><span style="font-weight: bold;">java -jar\r
+NicoBrowser.jar -p<br>\r
+</span></p>\r
+<p><span style="font-weight: bold;"><br>\r
+</span></p>\r
+<h2><a class="mozTocH2" name="mozTocId782665"></a>設定ファイルについて<br>\r
+</h2>\r
+コンフィグファイルはアプリケーションディレクトリに作成される。Windowsであれば、例えば以下のディレクトリ。\r
+<p>C:\Documents and Settings\user\.nicobrowser</p>\r
+このディレクトリ以下のファイルを編集することで、好みのランキングやマイリストをダウンロード指定することが出来る。\r
+<h3><a class="mozTocH2" name="mozTocId730811"></a>nicobrowser.properties\r
+の説明</h3>\r
+<p>path.db=<br>\r
+履歴管理DBを保存するディレクトリ。</p>\r
+<p>path.savefile=<br>\r
+ダウンロードしたflvファイルを保存するディレクトリ。</p>\r
+<p>encoding=<br>\r
+feedurl.txtの文字エンコーディング。</p>\r
+<p>nicovideo.mail=<br>\r
+ニコニコ動画のメールアドレス(ID)。</p>\r
+<p>nicovideo.password=<br>\r
+ニコニコ動画のパスワード。</p>\r
+<p>download.retry=<br>\r
+指定した回数ダウンロード試行に失敗した場合、次回以降ダウンロード対象から除外する。</p>\r
+<p>download.wait=<br>\r
+連続してダウンロードを行う際、ここで指定した秒数待ち合わせて次のファイルへ進む。</p>\r
+<p>download.mylist=<br>\r
+指定した公開マイリストに登録されているコンテンツをダウンロード対象に含める。</p>\r
+<p>例えば<br>\r
+http://www.nicovideo.jp/mylist/4573744<br>\r
+http://www.nicovideo.jp/mylist/739988/1395449<br>\r
+上記2個のマイリストを対象とする場合、<br>\r
+download.mylist=<span style="font-weight: bold;">4573744,739988/1395449</span><br>\r
+と、URLの mylist/ 以下をカンマで区切って指定する。</p>\r
+<h3><a class="mozTocH2" name="mozTocId935686"></a>feedurl.txt\r
+の説明</h3>\r
+<p>1行ごとに、対象とするRSSフィードのURLと抽出数をカンマ区切りで設定する。<br>\r
+書式についてはファイル内のコメント参照。<br>\r
+</p>\r
+<p><br>\r
+</p>\r
+<h2><a class="mozTocH2" name="mozTocId136534"></a>バージョンアップに関する注意事項</h2>\r
+<h3><a class="mozTocH3" name="mozTocId920310"></a>2009/05/24版以前を使用していた場合\r
+の注意事項</h3>\r
+<p>アップデート後(つまり今回のファイルで上書きした後)、1回目の起動前に以下のコマンドを実行する必要がある。実行しないとDB関連\r
+のエラーとなり処理が継続できない。</p>\r
+<p style="font-weight: bold;"><code>java -jar\r
+NicoBrowser.jar sync</code></p>\r
+<p>(引数にsyncをつけて実行する)</p>\r
+<h3><a class="mozTocH2" name="mozTocId116237"></a>2009/03/23版以前を使用していた場合\r
+の注意事項</h3>\r
+<p>nicobrowser.propertiesの互換性は無いため、一旦リネーム(or 削除)してから<br>\r
+実行する必要がある。こうすることで、新しいnicobrowser.propertiesが作成される。</p>\r
+<p>path.dbの設定は、従来は"ファイル名"の指定だったが、現在は"ディレクトリ名"の指定に変わっていることに注意。</p>\r
+<p>本体libディレクトリ以下について、構成が大きく変わっているため、libは上書きでなく置換することを推奨。<br>\r
+</p>\r
+<h2><a class="mozTocH2" name="mozTocId627544"></a>未解決の課題</h2>\r
+<p>webサイト参照。</p>\r
+<h2><a class="mozTocH2" name="mozTocId130181"></a>更新履歴</h2>\r
+<p>2009/11/30 ver.0.3.0<br>\r
+コンフィグ設定画面を追加。</p>\r
+<p>2009/11/26 ver.0.2.0<br>\r
+download.waitプロパティを追加。</p>\r
+<p>2009/11/13 ver.0.1.1<br>\r
+Log4Jのインストールバージョン誤りを修正。</p>\r
+<p>2009/11/13 ver.0.1<br>\r
+永続化する情報に作者(投稿者)情報を追加。ipum用の対応。</p>\r
+<p>2009/05/24<br>\r
+デイリーランキング以外のフィードへ対応。<br>\r
+一部のswfに対してアクセスできない問題の対応(新プレイヤ対応)。<br>\r
+ログ出力の見直し。</p>\r
+<p>2009/03/23<br>\r
+動画ファイル取得時403をもらった場合、ファイルをダウンロードしないように対応。</p>\r
+<p>2009/01/11<br>\r
+視聴権限が無い動画を取得しようとした場合にアプリケーションが終了してしまう問題を修正。</p>\r
+<p>2008/08/03<br>\r
+ランキングのRSSをzioさん作ニコRSS<br>\r
+http://zio3.net/nicoRss/Handler.ashx<br>\r
+から本家<br>\r
+http://www.nicovideo.jp/ranking/mylist/daily/all?rss=atom<br>\r
+に変更した。</p>\r
+<p>2008/04/09<br>\r
+前回ダウンロード要求から5秒待ってから次のダウンロード要求を行うようウェイト処理を追加した。<br>\r
+ターゲットをJDK6からJDK5に変更した。</p>\r
+<p>2008/03/21<br>\r
+公開マイリストを指定したダウンロードを可能とした。</p>\r
+<p>2008/03/15<br>\r
+ダウンロードする最低ランキングを指定可能とした。<br>\r
+ファイル名にドットが入っていた場合にもアンダーバーに<br>\r
+置換するよう置換規則を追加(Craving Explorerに合わせた)。</p>\r
+</body>\r
+</html>\r
index e5493b7..1c1324e 100644 (file)
@@ -1,5 +1,5 @@
 application.homepage=http://feather.cocolog-nifty.com/\r
-application.title=DEMO:\u30cb\u30b3\u30cb\u30b3\u52d5\u753b\u30b3\u30f3\u30c6\u30f3\u30c4\u60c5\u5831\u30d6\u30e9\u30a6\u30b6\r
+application.title=NicoBrowser - \u30e9\u30f3\u30ad\u30f3\u30b0\u3001\u516c\u958b\u30de\u30a4\u30ea\u30b9\u30c8\u304b\u3089\u306e\u30cb\u30b3\u30cb\u30b3\u52d5\u753b\u81ea\u52d5\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\r
 application.vendor=yukihane\r
 build.classes.dir=${build.dir}/classes\r
 build.classes.excludes=\r
@@ -19,8 +19,8 @@ debug.test.classpath=\
 dist.dir=dist\r
 dist.jar=${dist.dir}/NicoBrowser.jar\r
 dist.javadoc.dir=${dist.dir}/javadoc\r
+endorsed.classpath=\r
 excludes=\r
-file.reference.commons-io-1.4.jar=F:\\data\\java\\commons\\commons-io-1.4\\commons-io-1.4.jar\r
 file.reference.liquibase-1.9.5.jar=F:\\data\\java\\liquibase-1.9.5\\liquibase-1.9.5.jar\r
 includes=**\r
 jar.compress=false\r
@@ -32,9 +32,14 @@ javac.classpath=\
     ${libs.Log4J.classpath}:\\r
     ${libs.HttpClient4.0.classpath}:\\r
     ${libs.NekoHtml.classpath}:\\r
-    ${file.reference.commons-io-1.4.jar}:\\r
     ${libs.groovy-all.classpath}:\\r
-    ${file.reference.liquibase-1.9.5.jar}\r
+    ${libs.Commons-IO.classpath}:\\r
+    ${libs.Commons-CLI.classpath}:\\r
+    ${file.reference.liquibase-1.9.5.jar}:\\r
+    ${libs.swing-layout.classpath}:\\r
+    ${libs.Commons-Lang.classpath}:\\r
+    ${libs.Commons-Configuration.classpath}:\\r
+    ${libs.Commons-Collections.classpath}\r
 # Space-separated list of extra javac options\r
 javac.compilerargs=\r
 javac.deprecation=false\r
@@ -52,7 +57,6 @@ javadoc.noindex=false
 javadoc.nonavbar=false\r
 javadoc.notree=false\r
 javadoc.private=false\r
-javadoc.reference.commons-io-1.4.jar=F:\\data\\java\\commons\\commons-io-1.4\\docs\r
 javadoc.splitindex=true\r
 javadoc.use=true\r
 javadoc.version=false\r
@@ -90,7 +94,6 @@ run.test.classpath=\
     ${javac.test.classpath}:\\r
     ${build.test.classes.dir}\r
 source.encoding=UTF-8\r
-source.reference.commons-io-1.4.jar=F:\\data\\java\\commons\\commons-io-1.4\\commons-io-1.4-sources.jar\r
 src.dir=src\r
 test.src.dir=test\r
 compile.on.save.unsupported.groovy=true\r
index 61aea9f..544a046 100644 (file)
@@ -3,13 +3,15 @@ package nicobrowser;
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
-import java.util.Properties;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -46,22 +48,23 @@ public final class Config {
     }
     private static Log log = LogFactory.getLog(Config.class);
     private static Config instance;
-    private final Properties properties;
+    private final PropertiesConfiguration properties;
     private static final String APPLICATION_NAME = "nicobrowser";
     private static final String CONFIG_NAME = APPLICATION_NAME + ".properties";
     private static final String FEEDURL_NAME = "feedurl.txt";
     private static final File APP_HOME = new File(System.getProperty("user.home", "."), "." + APPLICATION_NAME);
     private static final File CONFIG_FILE = new File(APP_HOME, CONFIG_NAME);
     private static final File FEEDURL_FILE = new File(APP_HOME, FEEDURL_NAME);
-    private static final String P_PATH_DB = "path.db";
-    private static final String P_PATH_SAVEFILE = "path.savefile";
-    private static final String P_FILE_ENCODING = "encoding";
-    private static final String P_NICOVIDEO_MAIL = "nicovideo.mail";
-    private static final String P_NICOVIDEO_PASSWORD = "nicovideo.password";
-    private static final String P_DOWNLOAD_RETRY = "download.retry";
-    private static final String P_DOWNLOAD_WAIT = "download.wait";
+    public static final String P_PATH_DB = "path.db";
+    public static final String P_PATH_SAVEFILE = "path.savefile";
+    public static final String P_FILE_ENCODING = "encoding";
+    public static final String P_NICOVIDEO_MAIL = "nicovideo.mail";
+    public static final String P_NICOVIDEO_PASSWORD = "nicovideo.password";
+    public static final String P_DOWNLOAD_RETRY = "download.retry";
+    public static final String P_DOWNLOAD_WAIT = "download.wait";
+    public static final String P_DOWNLOAD_MYLIST = "download.mylist";
+    private static final int DEFAULT_MAX_RETRY = 3;
     private static final int DEFAULT_WAIT_TIME = 15;
-    private static final String P_DOWNLOAD_MYLIST = "download.mylist";
 
     /**
      * プログラム実行に必要なコンフィグファイルを作成する.
@@ -91,6 +94,41 @@ public final class Config {
         return result;
     }
 
+    /**
+     * 新しいプロパティを設定する. 新しいプロパティに値がない場合, 現在のままとなる.
+     * @param p 新規プロパティ.
+     * @throws IOException
+     */
+    public void updateConfigFile(Configuration p) throws IOException {
+        updatePropertyValue(p, P_NICOVIDEO_MAIL);
+        updatePropertyValue(p, P_NICOVIDEO_PASSWORD);
+        updatePropertyValue(p, P_FILE_ENCODING);
+
+        updatePropertyValue(p, P_PATH_DB);
+        updatePropertyValue(p, P_PATH_SAVEFILE);
+
+        updatePropertyValue(p, P_DOWNLOAD_RETRY);
+        updatePropertyValue(p, P_DOWNLOAD_WAIT);
+
+        updatePropertyValue(p, P_DOWNLOAD_MYLIST);
+
+        try {
+            properties.save();
+        } catch (ConfigurationException ex) {
+            throw new IOException(ex);
+        }
+    }
+
+    /**
+     * 新しいプロパティを設定する. 新しいプロパティに値がない場合, 現在のままとなる.
+     * @param newProp 新規プロパティ.
+     * @param key 設定するプロパティキー.
+     */
+    private void updatePropertyValue(Configuration newProp, String key) {
+        String value = newProp.getString(key, properties.getString(key));
+        properties.setProperty(key, value);
+    }
+
     private static void createNewConfigFile(File file) throws IOException {
         ArrayList<CharSequence> props = new ArrayList<CharSequence>();
 
@@ -109,9 +147,9 @@ public final class Config {
 
         props.add(P_FILE_ENCODING + "=" + System.getProperty("file.encoding"));
 
-        props.add(P_NICOVIDEO_MAIL + "=set.your@mail.address");
-        props.add(P_NICOVIDEO_PASSWORD + "=set_your_password");
-        props.add(P_DOWNLOAD_RETRY + "=3");
+        props.add(P_NICOVIDEO_MAIL + "=");
+        props.add(P_NICOVIDEO_PASSWORD + "=s");
+        props.add(P_DOWNLOAD_RETRY + "=" + DEFAULT_MAX_RETRY);
         props.add(P_DOWNLOAD_WAIT + "=" + DEFAULT_WAIT_TIME);
         props.add(P_DOWNLOAD_MYLIST + "=");
 
@@ -132,22 +170,11 @@ public final class Config {
     }
 
     private Config() {
-        properties = new Properties();
-        FileInputStream fis = null;
         try {
-            fis = new FileInputStream(CONFIG_FILE);
-            properties.load(fis);
-        } catch (IOException ex) {
+            properties = new PropertiesConfiguration(CONFIG_FILE);
+        } catch (Exception ex) {
             log.fatal("コンフィグの読み込みに失敗: " + CONFIG_FILE);
             throw new RuntimeException(ex);
-        } finally {
-            if (fis != null) {
-                try {
-                    fis.close();
-                } catch (IOException ex) {
-                    log.warn("", ex);
-                }
-            }
         }
 
         try {
@@ -169,29 +196,29 @@ public final class Config {
      * @return ニコニコ動画ログインID.
      */
     public String getNicoMail() {
-        return properties.getProperty(P_NICOVIDEO_MAIL);
+        return properties.getString(P_NICOVIDEO_MAIL);
     }
 
     /**
      * @return ニコニコ動画ログインパスワード.
      */
     public String getNicoPassword() {
-        return properties.getProperty(P_NICOVIDEO_PASSWORD);
+        return properties.getString(P_NICOVIDEO_PASSWORD);
     }
 
-    /** @return DBパス */
+    /** @return DBパス. コンフィグで設定した値(保存ディレクトリ)でなく, DBファイルのパスが変えることに注意. */
     public String getDbFile() {
-        return new File(properties.getProperty(P_PATH_DB), "nicodb").getAbsolutePath();
+        return new File(properties.getString(P_PATH_DB), "nicodb").getAbsolutePath();
     }
 
     /** @return 保存先の指定. */
     public String getSrcSaveDir() {
-        return properties.getProperty(P_PATH_SAVEFILE);
+        return properties.getString(P_PATH_SAVEFILE);
     }
 
     /** @return feedurl.txtの文字エンコーディング. */
     public String getEncoding() {
-        String res = properties.getProperty(P_FILE_ENCODING, System.getProperty("file.encoding"));
+        String res = properties.getString(P_FILE_ENCODING, System.getProperty("file.encoding"));
         return res;
     }
 
@@ -200,8 +227,7 @@ public final class Config {
      * @return リトライ回数.
      */
     public int getMaxRetry() {
-        String res = properties.getProperty(P_DOWNLOAD_RETRY);
-        return Integer.parseInt(res);
+        return properties.getInt(P_DOWNLOAD_RETRY, DEFAULT_MAX_RETRY);
     }
 
     /**
@@ -209,25 +235,12 @@ public final class Config {
      * @return 待ち時間(秒).
      */
     public int getWaitTime() {
-        int res = DEFAULT_WAIT_TIME;
-        try {
-            res = Integer.parseInt(properties.getProperty(P_DOWNLOAD_WAIT));
-        } catch (NumberFormatException e) {
-        }
-        return res;
+        return properties.getInt(P_DOWNLOAD_WAIT, DEFAULT_WAIT_TIME);
     }
 
     public List<String> getDownLoadMyList() {
-        List<String> list = new ArrayList<String>();
-        String res = properties.getProperty(P_DOWNLOAD_MYLIST);
-        String[] nums = res.split(",");
-        for (int i = 0; i < nums.length; i++) {
-            String text = nums[i].trim();
-            if (!text.isEmpty()) {
-                list.add(text);
-            }
-        }
-        return list;
+        String[] res = properties.getStringArray(P_DOWNLOAD_MYLIST);
+        return Arrays.asList(res);
     }
 
     public List<NicoFeed> getNicoFeeds() {
@@ -250,4 +263,12 @@ public final class Config {
         }
         return list;
     }
+
+    public static File getConfigfile() {
+        return CONFIG_FILE;
+    }
+
+    public static File getFeedUrlFile() {
+        return FEEDURL_FILE;
+    }
 }
diff --git a/src/nicobrowser/gui/config/ConfigFrame.form b/src/nicobrowser/gui/config/ConfigFrame.form
new file mode 100644 (file)
index 0000000..a92a3fc
--- /dev/null
@@ -0,0 +1,366 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
+  <Properties>
+    <Property name="defaultCloseOperation" type="int" value="3"/>
+    <Property name="title" type="java.lang.String" value="NicoBrowser - &#x30b3;&#x30f3;&#x30d5;&#x30a3;&#x30b0;&#x8a2d;&#x5b9a;"/>
+    <Property name="resizable" type="boolean" value="false"/>
+  </Properties>
+  <SyntheticProperties>
+    <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+    <SyntheticProperty name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-126,0,0,1,-107"/>
+  </SyntheticProperties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
+          <Component id="jPanel2" alignment="0" max="32767" attributes="0"/>
+          <Component id="jPanel4" alignment="0" max="32767" attributes="0"/>
+          <Component id="jPanel3" alignment="0" max="32767" attributes="0"/>
+          <Component id="jPanel5" alignment="0" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <Component id="jPanel1" min="-2" pref="90" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jPanel2" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jPanel4" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jPanel3" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jPanel5" min="-2" max="-2" attributes="0"/>
+              <EmptySpace min="-2" max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JPanel" name="jPanel1">
+      <Properties>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+            <TitledBorder title="&#x60c5;&#x5831;"/>
+          </Border>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="configFileLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                      <Component id="feedFileLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="feedFileField" alignment="0" pref="301" max="32767" attributes="0"/>
+                      <Component id="configFileField" alignment="0" pref="301" max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+              <Group type="102" alignment="0" attributes="0">
+                  <Component id="jLabel5" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="configFileField" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="configFileLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="feedFileField" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="feedFileLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Component id="jLabel5" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JTextField" name="configFileField">
+          <Properties>
+            <Property name="editable" type="boolean" value="false"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JTextField" name="feedFileField">
+          <Properties>
+            <Property name="editable" type="boolean" value="false"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="configFileLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="&#x30b3;&#x30f3;&#x30d5;&#x30a3;&#x30b0;,&#x30de;&#x30a4;&#x30ea;&#x30b9;&#x30c8;"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="feedFileLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="&#x30d5;&#x30a3;&#x30fc;&#x30c9;(RSS)"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel5">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="&#x30de;&#x30a4;&#x30ea;&#x30b9;&#x30c8;&#x3001;&#x30d5;&#x30a3;&#x30fc;&#x30c9;&#x306e;&#x8a2d;&#x5b9a;&#x306f;&#x4e0a;&#x8a18;&#x306e;&#x30d5;&#x30a1;&#x30a4;&#x30eb;&#x3092;&#x76f4;&#x63a5;&#x30a8;&#x30c7;&#x30a3;&#x30bf;&#x3067;&#x958b;&#x3044;&#x3066;&#x7de8;&#x96c6;&#x3057;&#x3066;&#x304f;&#x3060;&#x3055;&#x3044;"/>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="jPanel2">
+      <Properties>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+            <TitledBorder title="&#x30cb;&#x30b3;&#x30cb;&#x30b3;&#x52d5;&#x753b;&#x30a2;&#x30ab;&#x30a6;&#x30f3;&#x30c8;"/>
+          </Border>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="idLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                      <Component id="passLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="passField" pref="302" max="32767" attributes="0"/>
+                      <Component id="idField" alignment="0" pref="302" max="32767" attributes="0"/>
+                  </Group>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="idLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="idField" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="passLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="passField" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="idLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="ID(&#x30e1;&#x30fc;&#x30eb;&#x30a2;&#x30c9;&#x30ec;&#x30b9;)"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="passLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="&#x30d1;&#x30b9;&#x30ef;&#x30fc;&#x30c9;"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JTextField" name="idField">
+        </Component>
+        <Component class="javax.swing.JPasswordField" name="passField">
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="jPanel4">
+      <Properties>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+            <TitledBorder title="&#x4fdd;&#x5b58;&#x5148;"/>
+          </Border>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="jLabel4" alignment="0" min="-2" max="-2" attributes="0"/>
+                      <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="dbPathField" alignment="1" pref="281" max="32767" attributes="0"/>
+                      <Component id="flvPathField" alignment="1" pref="281" max="32767" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="flvPathButton" alignment="1" min="-2" max="-2" attributes="0"/>
+                      <Component id="dbPathButton" alignment="1" min="-2" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="dbPathButton" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="dbPathField" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="flvPathButton" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="flvPathField" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="jLabel3">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="&#x5c65;&#x6b74;DB"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel4">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="&#x52d5;&#x753b;&#x30d5;&#x30a1;&#x30a4;&#x30eb;"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JTextField" name="dbPathField">
+        </Component>
+        <Component class="javax.swing.JTextField" name="flvPathField">
+        </Component>
+        <Component class="javax.swing.JButton" name="dbPathButton">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="..."/>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="dbPathButtonActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JButton" name="flvPathButton">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="..."/>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="flvPathButtonActionPerformed"/>
+          </Events>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="jPanel3">
+      <Properties>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+            <TitledBorder title="&#x52d5;&#x4f5c;"/>
+          </Border>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <Group type="103" groupAlignment="0" max="-2" attributes="0">
+                      <Group type="102" alignment="0" attributes="0">
+                          <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="waitSpinner" min="-2" pref="46" max="-2" attributes="0"/>
+                      </Group>
+                      <Group type="102" alignment="0" attributes="1">
+                          <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                          <Component id="retrySpinner" max="32767" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace pref="240" max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="waitSpinner" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="retrySpinner" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="jLabel1">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="&#x30c0;&#x30a6;&#x30f3;&#x30ed;&#x30fc;&#x30c9;&#x9593;&#x9694;(&#x79d2;)"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel2">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="&#x5931;&#x6557;&#x6642;&#x30ea;&#x30c8;&#x30e9;&#x30a4;&#x56de;&#x6570;"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JSpinner" name="waitSpinner">
+        </Component>
+        <Component class="javax.swing.JSpinner" name="retrySpinner">
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="jPanel5">
+      <Properties>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+            <TitledBorder/>
+          </Border>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="1" attributes="0">
+                  <EmptySpace pref="332" max="32767" attributes="0"/>
+                  <Component id="savaButton" min="-2" max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Component id="savaButton" min="-2" max="-2" attributes="0"/>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JButton" name="savaButton">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="&#x4fdd;&#x5b58;"/>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="savaButtonActionPerformed"/>
+          </Events>
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>
diff --git a/src/nicobrowser/gui/config/ConfigFrame.java b/src/nicobrowser/gui/config/ConfigFrame.java
new file mode 100644 (file)
index 0000000..d36891d
--- /dev/null
@@ -0,0 +1,385 @@
+/* $Id$ */
+
+/*
+ * ConfigFrame.java
+ *
+ * Created on 2009/11/30, 16:35:22
+ */
+package nicobrowser.gui.config;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.JTextField;
+import javax.swing.UIManager;
+import nicobrowser.Config;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.io.FilenameUtils;
+
+/**
+ *
+ * @author yuki
+ */
+public class ConfigFrame extends javax.swing.JFrame {
+
+    private final Config config;
+
+    /** Creates new form ConfigFrame */
+    public ConfigFrame() {
+        initComponents();
+        configFileField.setText(Config.getConfigfile().getAbsolutePath());
+        feedFileField.setText(Config.getFeedUrlFile().getAbsolutePath());
+        config = Config.getInstance();
+
+        // ニコニコ動画アカウント
+        idField.setText(config.getNicoMail());
+        passField.setText(config.getNicoPassword());
+
+        // 保存先
+        String dbPath = FilenameUtils.getFullPathNoEndSeparator(config.getDbFile());
+        dbPathField.setText(dbPath);
+        flvPathField.setText(config.getSrcSaveDir());
+
+        // 動作
+        waitSpinner.setValue(config.getWaitTime());
+        retrySpinner.setValue(config.getMaxRetry());
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jPanel1 = new javax.swing.JPanel();
+        configFileField = new javax.swing.JTextField();
+        feedFileField = new javax.swing.JTextField();
+        configFileLabel = new javax.swing.JLabel();
+        feedFileLabel = new javax.swing.JLabel();
+        jLabel5 = new javax.swing.JLabel();
+        jPanel2 = new javax.swing.JPanel();
+        idLabel = new javax.swing.JLabel();
+        passLabel = new javax.swing.JLabel();
+        idField = new javax.swing.JTextField();
+        passField = new javax.swing.JPasswordField();
+        jPanel4 = new javax.swing.JPanel();
+        jLabel3 = new javax.swing.JLabel();
+        jLabel4 = new javax.swing.JLabel();
+        dbPathField = new javax.swing.JTextField();
+        flvPathField = new javax.swing.JTextField();
+        dbPathButton = new javax.swing.JButton();
+        flvPathButton = new javax.swing.JButton();
+        jPanel3 = new javax.swing.JPanel();
+        jLabel1 = new javax.swing.JLabel();
+        jLabel2 = new javax.swing.JLabel();
+        waitSpinner = new javax.swing.JSpinner();
+        retrySpinner = new javax.swing.JSpinner();
+        jPanel5 = new javax.swing.JPanel();
+        savaButton = new javax.swing.JButton();
+
+        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+        setTitle("NicoBrowser - コンフィグ設定");
+        setResizable(false);
+
+        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("情報"));
+
+        configFileField.setEditable(false);
+
+        feedFileField.setEditable(false);
+
+        configFileLabel.setText("コンフィグ,マイリスト");
+
+        feedFileLabel.setText("フィード(RSS)");
+
+        jLabel5.setText("マイリスト、フィードの設定は上記のファイルを直接エディタで開いて編集してください");
+
+        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
+        jPanel1.setLayout(jPanel1Layout);
+        jPanel1Layout.setHorizontalGroup(
+            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel1Layout.createSequentialGroup()
+                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(configFileLabel)
+                    .add(feedFileLabel))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(feedFileField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 301, Short.MAX_VALUE)
+                    .add(configFileField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 301, Short.MAX_VALUE)))
+            .add(jPanel1Layout.createSequentialGroup()
+                .add(jLabel5)
+                .addContainerGap())
+        );
+        jPanel1Layout.setVerticalGroup(
+            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel1Layout.createSequentialGroup()
+                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(configFileField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                    .add(configFileLabel))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(feedFileField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                    .add(feedFileLabel))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jLabel5)
+                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("ニコニコ動画アカウント"));
+
+        idLabel.setText("ID(メールアドレス)");
+
+        passLabel.setText("パスワード");
+
+        org.jdesktop.layout.GroupLayout jPanel2Layout = new org.jdesktop.layout.GroupLayout(jPanel2);
+        jPanel2.setLayout(jPanel2Layout);
+        jPanel2Layout.setHorizontalGroup(
+            jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel2Layout.createSequentialGroup()
+                .add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(idLabel)
+                    .add(passLabel))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(passField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 302, Short.MAX_VALUE)
+                    .add(idField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 302, Short.MAX_VALUE)))
+        );
+        jPanel2Layout.setVerticalGroup(
+            jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel2Layout.createSequentialGroup()
+                .add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(idLabel)
+                    .add(idField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(passLabel)
+                    .add(passField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
+        );
+
+        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder("保存先"));
+
+        jLabel3.setText("履歴DB");
+
+        jLabel4.setText("動画ファイル");
+
+        dbPathButton.setText("...");
+        dbPathButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                dbPathButtonActionPerformed(evt);
+            }
+        });
+
+        flvPathButton.setText("...");
+        flvPathButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                flvPathButtonActionPerformed(evt);
+            }
+        });
+
+        org.jdesktop.layout.GroupLayout jPanel4Layout = new org.jdesktop.layout.GroupLayout(jPanel4);
+        jPanel4.setLayout(jPanel4Layout);
+        jPanel4Layout.setHorizontalGroup(
+            jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel4Layout.createSequentialGroup()
+                .add(jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(jLabel4)
+                    .add(jLabel3))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(org.jdesktop.layout.GroupLayout.TRAILING, dbPathField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE)
+                    .add(org.jdesktop.layout.GroupLayout.TRAILING, flvPathField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(org.jdesktop.layout.GroupLayout.TRAILING, flvPathButton)
+                    .add(org.jdesktop.layout.GroupLayout.TRAILING, dbPathButton)))
+        );
+        jPanel4Layout.setVerticalGroup(
+            jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel4Layout.createSequentialGroup()
+                .add(jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(jLabel3)
+                    .add(dbPathButton)
+                    .add(dbPathField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(jLabel4)
+                    .add(flvPathButton)
+                    .add(flvPathField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
+        );
+
+        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("動作"));
+
+        jLabel1.setText("ダウンロード間隔(秒)");
+
+        jLabel2.setText("失敗時リトライ回数");
+
+        org.jdesktop.layout.GroupLayout jPanel3Layout = new org.jdesktop.layout.GroupLayout(jPanel3);
+        jPanel3.setLayout(jPanel3Layout);
+        jPanel3Layout.setHorizontalGroup(
+            jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel3Layout.createSequentialGroup()
+                .add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
+                    .add(jPanel3Layout.createSequentialGroup()
+                        .add(jLabel1)
+                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                        .add(waitSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 46, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
+                    .add(jPanel3Layout.createSequentialGroup()
+                        .add(jLabel2)
+                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
+                        .add(retrySpinner)))
+                .addContainerGap(240, Short.MAX_VALUE))
+        );
+        jPanel3Layout.setVerticalGroup(
+            jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel3Layout.createSequentialGroup()
+                .add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(jLabel1)
+                    .add(waitSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(jLabel2)
+                    .add(retrySpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
+        );
+
+        jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
+
+        savaButton.setText("保存");
+        savaButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                savaButtonActionPerformed(evt);
+            }
+        });
+
+        org.jdesktop.layout.GroupLayout jPanel5Layout = new org.jdesktop.layout.GroupLayout(jPanel5);
+        jPanel5.setLayout(jPanel5Layout);
+        jPanel5Layout.setHorizontalGroup(
+            jPanel5Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel5Layout.createSequentialGroup()
+                .addContainerGap(332, Short.MAX_VALUE)
+                .add(savaButton))
+        );
+        jPanel5Layout.setVerticalGroup(
+            jPanel5Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(savaButton)
+        );
+
+        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
+        getContentPane().setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+            .add(jPanel2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+            .add(jPanel4, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+            .add(jPanel3, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+            .add(jPanel5, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(layout.createSequentialGroup()
+                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 90, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                .add(jPanel5, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap())
+        );
+
+        pack();
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void dbPathButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dbPathButtonActionPerformed
+        setPathField(dbPathField);
+    }//GEN-LAST:event_dbPathButtonActionPerformed
+
+    private void flvPathButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_flvPathButtonActionPerformed
+        setPathField(flvPathField);
+    }//GEN-LAST:event_flvPathButtonActionPerformed
+
+    private void savaButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_savaButtonActionPerformed
+        PropertiesConfiguration p = new PropertiesConfiguration();
+
+        p.setProperty(Config.P_NICOVIDEO_MAIL, idField.getText());
+        p.setProperty(Config.P_NICOVIDEO_PASSWORD, String.valueOf(passField.getPassword()));
+
+        p.setProperty(Config.P_PATH_DB, dbPathField.getText());
+        p.setProperty(Config.P_PATH_SAVEFILE, flvPathField.getText());
+
+        p.setProperty(Config.P_DOWNLOAD_WAIT, waitSpinner.getValue().toString());
+        p.setProperty(Config.P_DOWNLOAD_RETRY, retrySpinner.getValue().toString());
+        try {
+            config.updateConfigFile(p);
+            JOptionPane.showMessageDialog(this, Config.getConfigfile().getAbsolutePath() + "\nを更新しました");
+        } catch (IOException ex) {
+            Logger.getLogger(ConfigFrame.class.getName()).log(Level.SEVERE, null, ex);
+            JOptionPane.showMessageDialog(this, "保存に失敗しました", "エラー", JOptionPane.ERROR_MESSAGE);
+        }
+    }//GEN-LAST:event_savaButtonActionPerformed
+
+    private void setPathField(JTextField field) {
+        String current = field.getText();
+        JFileChooser fc = new JFileChooser(current);
+        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+        int ret = fc.showDialog(this, "選択");
+        if (ret == JFileChooser.APPROVE_OPTION) {
+            String selectPath = fc.getSelectedFile().getAbsolutePath();
+            field.setText(selectPath);
+        }
+    }
+
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String args[]) {
+        setLookAndFeel();
+        java.awt.EventQueue.invokeLater(new Runnable() {
+
+            public void run() {
+                new ConfigFrame().setVisible(true);
+            }
+        });
+    }
+
+    public static void setLookAndFeel() {
+        UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
+        String lafClassName = UIManager.getSystemLookAndFeelClassName();
+        try {
+            UIManager.setLookAndFeel(lafClassName);
+        } catch (Exception ex) {
+        }
+    }
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JTextField configFileField;
+    private javax.swing.JLabel configFileLabel;
+    private javax.swing.JButton dbPathButton;
+    private javax.swing.JTextField dbPathField;
+    private javax.swing.JTextField feedFileField;
+    private javax.swing.JLabel feedFileLabel;
+    private javax.swing.JButton flvPathButton;
+    private javax.swing.JTextField flvPathField;
+    private javax.swing.JTextField idField;
+    private javax.swing.JLabel idLabel;
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JLabel jLabel2;
+    private javax.swing.JLabel jLabel3;
+    private javax.swing.JLabel jLabel4;
+    private javax.swing.JLabel jLabel5;
+    private javax.swing.JPanel jPanel1;
+    private javax.swing.JPanel jPanel2;
+    private javax.swing.JPanel jPanel3;
+    private javax.swing.JPanel jPanel4;
+    private javax.swing.JPanel jPanel5;
+    private javax.swing.JPasswordField passField;
+    private javax.swing.JLabel passLabel;
+    private javax.swing.JSpinner retrySpinner;
+    private javax.swing.JButton savaButton;
+    private javax.swing.JSpinner waitSpinner;
+    // End of variables declaration//GEN-END:variables
+}
index 9468374..aaca44b 100644 (file)
@@ -1,7 +1,6 @@
 /*$Id$*/
 package nicobrowser.main;
 
-import nicobrowser.update.DBUpdater;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -14,23 +13,58 @@ import javax.persistence.EntityManagerFactory;
 import javax.persistence.EntityTransaction;
 import javax.persistence.Persistence;
 import javax.persistence.Query;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
 import nicobrowser.Config;
 import nicobrowser.GetFlvResult;
 import nicobrowser.Config.NicoFeed;
 import nicobrowser.NicoHttpClient;
 import nicobrowser.entity.NicoContent;
 import nicobrowser.entity.NicoContent.Status;
+import nicobrowser.gui.config.ConfigFrame;
+import nicobrowser.update.DBUpdater;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 public class Main {
 
+    public static final String VERSION = "version 0.3.0";
     private static Log log = LogFactory.getLog(Main.class);
 
     public static void main(String[] args) throws IOException {
-        boolean res = Config.createNewConfigFiles();
+        final boolean res = Config.createNewConfigFiles();
+
+        CommandLineParser parser = new PosixParser();
+        Options options = createOptions();
+
+        try {
+            // parse the command line arguments
+            CommandLine line = parser.parse(options, args);
+
+            if (line.hasOption("help")) {
+                new HelpFormatter().printHelp("java -jar NicoBrowser.jar [option]", options);
+                return;
+            } else if (line.hasOption("version")) {
+                System.out.println(VERSION);
+                return;
+            } else if (line.hasOption("property")) {
+                propertyOpen();
+                return;
+            }
+        } catch (ParseException exp) {
+            HelpFormatter formatter = new HelpFormatter();
+            formatter.printHelp("java -jar NicoBrowser.jar [option]", options);
+            return;
+        }
+
         if (res) {
-            System.out.println("コンフィグファイルを作成しました. 編集後, 再実行してください.");
+            propertyOpen();
             return;
         }
 
@@ -44,6 +78,26 @@ public class Main {
         new Main().start();
     }
 
+    private static Options createOptions() throws IllegalArgumentException {
+        Options options = new Options();
+        options.addOption("h", "help", false, "このメッセージを表示します");
+        options.addOption("p", "property", false, "コンフィグ設定画面を起動します");
+        options.addOption("v", "version", false, "バージョン情報を表示します");
+        return options;
+    }
+
+    private static void propertyOpen() {
+        SwingUtilities.invokeLater(new Runnable() {
+
+            public void run() {
+                ConfigFrame.setLookAndFeel();
+                JFrame frame = new ConfigFrame();
+                frame.setLocationByPlatform(true);
+                frame.setVisible(true);
+            }
+        });
+    }
+
     public void start() {
         log.info("program start");
 
index 70c38b9..71ceca5 100644 (file)
@@ -1,4 +1,5 @@
-http://www.nicovideo.jp/ranking/mylist/daily/all?rss=atom, 20\r
+# カテゴリ合算 の マイリスト ランキング(デイリー)の上位20件\r
+http://www.nicovideo.jp/ranking/mylist/daily/all?rss=2.0, 20\r
 \r
 \r
 # URL, 抽出数\r
@@ -7,18 +8,12 @@ http://www.nicovideo.jp/ranking/mylist/daily/all?rss=atom, 20
 # 抽出数は100以内.\r
 # 行頭が#の行はコメント扱い.\r
 \r
-\r
 ### 記述例 ###\r
-### フィードのURLについては http://nicowiki.com/?RSSフィード一覧 などを参照のこと.\r
-\r
-# 新着投稿動画\r
-# http://www.nicovideo.jp/newarrival?rss=2.0, 100\r
-\r
-# 新着動画(カテゴリ:科学)\r
-# http://www.nicovideo.jp/tag/科学?sort=f&rss=2.0, 3\r
+### 記述するURLは\r
+### http://yukihane.dip.jp/dist/NicoBrowser/feedurllist.html\r
+### http://nicowiki.com/RSS%E3%83%95%E3%82%A3%E3%83%BC%E3%83%89%E4%B8%80%E8%A6%A7.html\r
+### などを参考のこと\r
 \r
-# 新着コメント動画\r
-# http://www.nicovideo.jp/recent?rss=2.0,10\r
 \r
-# 自然のマイリストランキング(月間)\r
-# http://www.nicovideo.jp/ranking/mylist/monthly/nature?rss=2.0,10\r
+# 新着投稿動画 15件\r
+# http://www.nicovideo.jp/newarrival?rss=2.0, 15\r
index dafe6a5..50af87d 100644 (file)
@@ -254,7 +254,7 @@ public class ConfigTest {
 
         Config config = Config.getInstance();
         int res = config.getWaitTime();
-        assertEquals(10, res);
+        assertEquals(15, res);
     }
 
     @Test