Java用WebDAVクライントライブラリsardine
WindowsXPでコマンドラインから使えるWebDAVクライアントを探していたのですが、
あまりニーズにあったものが見つけられませんでした。
まず、cadaverを試しましたが、Cygwin版と本家とで微妙な差異があって
トラブルシューティングできずに諦めました。
他にもWindowsXPで動作するものを探しましたが、
GUIでしか操作できないものがほとんどでした。
Javaのようなプラットホーム非依存な言語のライブラリなら
Windowsでもうまくいくのではないかと思って、Javaのライブラリを探してみました。
メンテナンスされていないものが多い中、sardineが
使いやすいようにみえました。
これはJava用ライブラリですが、
ちょっとしたファイルのコピーがしたいだけなので、
Groovyで使うことにしました。
こういうスクリプト的なことをやるにはJavaはめんどうなので。
WebDav.groovy
sardineの機能を使いやすいようにまとめたクラスです。
Groovyの@Grabを使うことで、pom.xmlのようなものが無くても、
スクリプトファイルだけで依存関係を解決できます。
(ただし、初回実行時には依存ライブラリをダウンロードするのでとても遅くなります)
@Grab(group = 'com.googlecode.sardine', module = 'sardine', version = '314') @GrabResolver(name = 'sardine-google-svn-repo', root = 'http://sardine.googlecode.com/svn/maven/') import com.googlecode.sardine.Sardine import com.googlecode.sardine.SardineFactory import org.apache.http.client.ClientProtocolException import com.googlecode.sardine.DavResource import com.googlecode.sardine.impl.SardineException class WebDav { final File localRootDir final ConfigObject conf // 依存関係に含めてくれていないのでしょうがなく追加 @Grapes([ @Grab(group = 'org.slf4j', module = 'slf4j-simple', version = '1.6.4'), @Grab(group = 'org.slf4j', module = 'slf4j-api', version = '1.6.4') ]) final Sardine sardine /** * コンストラクタ * @param configScript 設定スクリプト */ WebDav(String configScript) { // 設定ファイル File configFile = new File(configScript) assert configFile.exists() : configFile.absolutePath conf = new ConfigSlurper().parse(configFile.toURL()) println "conf = $conf" // ローカルディレクトリ localRootDir = new File(conf.local.dir as String) assert localRootDir.exists() : localRootDir.absolutePath // Sardineインスタンス sardine = SardineFactory.begin( conf.webdav.user as String, conf.webdav.pass as String ) } boolean exists(String davResource) { try { getResource(davResource) return true } catch (SardineException e) { if (e.statusCode == 404) return false throw e } } boolean isDirectory(String davResource) { return getResource(davResource).directory } private DavResource getResource(String resource) { def list = sardine.list(toRemoteUrl(resource), 0) assert list.size() == 1 return list[0] } List<String> list() { return list("") } List<String> list(String dir){ return sardine.list(toRemoteUrl(dir)).collect { it.path } } void put(String resource) { def file = toLocalFile(resource) if (!file.exists()) { throw new FileNotFoundException(file.getAbsolutePath()) } file.withInputStream { input -> String to = toRemoteUrl(resource) println "put file [${file.absolutePath}] to [${to}]" URI uri = URI.create(to) sardine.enablePreemptiveAuthentication(uri.host) sardine.put(to, input, "text/plain") } } void get(String resource) { def file = toLocalFile(resource) if (!file.exists()) { assert file.createNewFile() : file.absolutePath } file.withOutputStream { output -> String from = toRemoteUrl(resource) println "get resource [${from}] to [${file.absolutePath}]" sardine.get(from).eachByte { b -> output.write(b as int) } } } private String toRemoteUrl(String resource) { return "${conf.webdav.url}/${resource}" } private File toLocalFile(String pathFromRootDir) { return new File(localRootDir, pathFromRootDir); } }
ストリームのようなリソースの扱いにクロージャが使えるので、
シンプルに記述できます。try-finallyがひとつもありませんがちゃんと解放処理はされています。
slf4jというライブラリを使っているのに、依存関係に含めてくれていないので
しょうがなくこちらで足している箇所があります。sardinのソースリポジトリを見ると、
どうもEclipseメインで開発しているぽいので、きっと依存関係に入れ忘れたんでしょう。
config.groovy(設定ファイル)
環境依存値をまとめて書いています。 ConfigSlurperを使うことでJSONのような記述が可能になります。 webdav { url = "https://url/of/webdav/server/" user = "scott" pass = "tiger" } local { dir = "temp" }
実行スクリプト(Hoge.groovy)
こんなかんじで呼び出します。
def dav = new WebDav("config.groovy") dav.get("index.org") //dav.put("index.org")
実行
> ls Hoge.groovy WebDav.groovy config.groovy temp/ > groovy Hoge.groovy
これで、WebDAV上のindex.orgファイルがtempフォルダにコピーされます。