2 * inter-VM file locking
4 * License : The MIT License
5 * Copyright(c) 2009 olyutorskii
8 package jp.sfjp.jindolf.config;
11 import java.io.FileNotFoundException;
12 import java.io.FileOutputStream;
13 import java.io.IOException;
14 import java.util.Collections;
15 import java.util.HashSet;
19 * ロックファイルを用いたVM間ロックオブジェクト。
21 * 一度でもロックに成功したロックファイルはVM終了時に消されてしまうので注意。
23 public class InterVMLock{
25 /** 所持するロックオブジェクト一覧。 */
26 private static final Set<InterVMLock> ownedLockSet =
27 Collections.synchronizedSet(new HashSet<InterVMLock>());
30 Runtime runtime = Runtime.getRuntime();
31 runtime.addShutdownHook(new Thread(){
32 @Override public void run(){ clearOwnedLockSet(); }
37 private final File lockFile;
38 private boolean isFileOwner = false;
39 private FileOutputStream stream = null;
44 * この時点ではまだロックファイルの存在は確認されない。
45 * @param lockFile ロックファイル
46 * @throws NullPointerException 引数がnull
48 public InterVMLock(File lockFile) throws NullPointerException{
49 if(lockFile == null) throw new NullPointerException();
50 this.lockFile = lockFile;
56 * 所持するロックオブジェクト一覧への登録。
57 * @param lock 登録するロックオブジェクト
59 private static void addOwnedLock(InterVMLock lock){
60 synchronized(ownedLockSet){
61 if( ! lock.isFileOwner() ) return;
62 ownedLockSet.add(lock);
63 lock.getLockFile().deleteOnExit();
69 * 所持するロックオブジェクト一覧からの脱退。
70 * @param lock 脱退対象のロックオブジェクト
72 private static void removeOwnedLock(InterVMLock lock){
73 synchronized(ownedLockSet){
74 ownedLockSet.remove(lock);
80 * 所持するロックオブジェクトすべてを解放しロックファイルを削除する。
82 private static void clearOwnedLockSet(){
83 synchronized(ownedLockSet){
84 for(InterVMLock lock : ownedLockSet){
85 if( ! lock.isFileOwner() ) continue;
88 lock.getLockFile().delete();
89 }catch(SecurityException e){
102 public File getLockFile(){
103 return this.lockFile;
107 * ロックファイルがディスク上に存在するか判定する。
110 public boolean isExistsFile(){
111 if(this.lockFile.exists()){
118 * このオブジェクトがロックファイルの作者であるか判定する。
121 public synchronized boolean isFileOwner(){
122 return this.isFileOwner;
126 * ロックファイルのオープン中のストリームを返す。
128 * 勝手に書き込んだりクローズしたりしないように。
129 * @return オープン中のストリーム。オープンしてなければnull
131 protected synchronized FileOutputStream getOpenedStream(){
132 if(isFileOwner()) return this.stream;
138 * @return 強制削除に成功すればtrue
140 public synchronized boolean forceRemove(){
141 if(isFileOwner()) release();
143 if( ! isExistsFile() ) return true;
146 boolean result = this.lockFile.delete();
147 if( ! result ) return false;
148 }catch(SecurityException e){
152 if(isExistsFile()) return false;
159 * 生成されるロックファイルはVM終了時に削除されるよう登録される。
160 * このメソッド実行中にVM終了が重なると、
161 * ロックファイルが正しく削除されない場合がありうる。
164 protected synchronized boolean touchLockFile(){
165 boolean result = false;
167 result = this.lockFile.createNewFile();
168 }catch(IOException e){
170 }catch(SecurityException e){
178 this.isFileOwner = true;
179 this.stream = new FileOutputStream(this.lockFile);
180 }catch(FileNotFoundException e){
182 this.isFileOwner = false;
185 this.lockFile.delete();
186 }catch(SecurityException e2){
200 * @return すでにロック済みもしくはロックに成功すればtrue
202 public synchronized boolean tryLock(){
203 if( isFileOwner() ) return true;
205 if(isExistsFile()) return false;
206 if(touchLockFile() != true) return false;
213 * 自分が作者であるロックファイルは閉じられ削除される。
216 public synchronized void release(){
217 if( ! isFileOwner() ) return;
221 }catch(IOException e){
226 this.lockFile.delete();
227 }catch(SecurityException e){
230 removeOwnedLock(this);
231 this.isFileOwner = false;