001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.commons.io.res.util; 020 021import java.util.HashMap; 022import java.util.Map; 023 024import lucee.commons.io.res.Resource; 025import lucee.commons.io.res.ResourceLock; 026import lucee.commons.lang.SerializableObject; 027import lucee.commons.lang.SystemOut; 028import lucee.runtime.config.Config; 029import lucee.runtime.engine.ThreadLocalPageContext; 030 031public final class ResourceLockImpl implements ResourceLock { 032 033 private static final long serialVersionUID = 6888529579290798651L; 034 035 private long lockTimeout; 036 private boolean caseSensitive; 037 038 public ResourceLockImpl(long timeout,boolean caseSensitive) { 039 this.lockTimeout=timeout; 040 this.caseSensitive=caseSensitive; 041 } 042 043 private Object token=new SerializableObject(); 044 private Map<String,Thread> resources=new HashMap<String,Thread>(); 045 046 @Override 047 public void lock(Resource res) { 048 String path=getPath(res); 049 050 synchronized(token) { 051 _read(path); 052 resources.put(path,Thread.currentThread()); 053 } 054 } 055 056 private String getPath(Resource res) { 057 return caseSensitive?res.getPath():res.getPath().toLowerCase(); 058 } 059 060 @Override 061 public void unlock(Resource res) { 062 String path=getPath(res); 063 //if(path.endsWith(".dmg"))print.err("unlock:"+path); 064 synchronized(token) { 065 resources.remove(path); 066 token.notifyAll(); 067 } 068 } 069 070 @Override 071 public void read(Resource res) { 072 String path=getPath(res); 073 synchronized(token) { 074 //print.ln("......."); 075 _read(path); 076 } 077 } 078 079 private void _read(String path) { 080 long start=-1,now; 081 Thread t; 082 do { 083 if((t=resources.get(path))==null) { 084 //print.ln("read ok"); 085 return; 086 } 087 if(t==Thread.currentThread()) { 088 //aprint.err(path); 089 Config config = ThreadLocalPageContext.getConfig(); 090 if(config!=null) 091 SystemOut.printDate(config.getErrWriter(),"conflict in same thread: on "+path); 092 //SystemOut.printDate(config.getErrWriter(),"conflict in same thread: on "+path+"\nStacktrace:\n"+StringUtil.replace(ExceptionUtil.getStacktrace(new Throwable(), false),"java.lang.Throwable\n","",true)); 093 return; 094 } 095 // bugfix when lock von totem thread, wird es ignoriert 096 if(!t.isAlive()) { 097 resources.remove(path); 098 return; 099 } 100 if(start==-1)start=System.currentTimeMillis(); 101 try { 102 token.wait(lockTimeout); 103 now=System.currentTimeMillis(); 104 if((start+lockTimeout)<=now) { 105 Config config = ThreadLocalPageContext.getConfig(); 106 if(config!=null) 107 SystemOut.printDate(config.getErrWriter(),"timeout after "+(now-start)+" ms ("+(lockTimeout)+" ms) occured while accessing file ["+path+"]"); 108 else 109 SystemOut.printDate("timeout ("+(lockTimeout)+" ms) occured while accessing file ["+path+"]"); 110 return; 111 } 112 } 113 catch (InterruptedException e) { 114 } 115 } 116 while(true); 117 } 118 119 @Override 120 public long getLockTimeout() { 121 return lockTimeout; 122 } 123 124 /** 125 * @param lockTimeout the lockTimeout to set 126 */ 127 public void setLockTimeout(long lockTimeout) { 128 this.lockTimeout = lockTimeout; 129 } 130 131 /** 132 * @param caseSensitive the caseSensitive to set 133 */ 134 public void setCaseSensitive(boolean caseSensitive) { 135 this.caseSensitive = caseSensitive; 136 } 137}