package com.frameworkset.util;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import com.frameworkset.util.DaemonThread.FileBean;
/**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: </p>
*
* @author biaoping.yin
* @version 1.0
*/
public class DaemonThread extends java.lang.Thread
{
static class FileBean
{
public FileBean(File file,
ResourceInitial init) {
super();
this.file = file;
this.inits = new ArrayList<ResourceInitial>();
inits.add(init);
this.oldModifiedTime = file.lastModified();
}
private boolean removeflag = false;
private File file;
private long lastModifiedTime;
private long oldModifiedTime;
private List<ResourceInitial> inits;
/**
* @return the file
*/
public File getFile() {
return file;
}
/**
* @param file the file to set
*/
public void setFile(File file) {
this.file = file;
}
/**
* @return the lastModifiedTime
*/
public long getLastModifiedTime() {
return lastModifiedTime;
}
/**
* @param lastModifiedTime the lastModifiedTime to set
*/
public void setLastModifiedTime(long lastModifiedTime) {
this.lastModifiedTime = lastModifiedTime;
}
/**
* @return the oldModifiedTime
*/
public long getOldModifiedTime() {
return oldModifiedTime;
}
/**
* @param oldModifiedTime the oldModifiedTime to set
*/
public void setOldModifiedTime(long oldModifiedTime) {
this.oldModifiedTime = oldModifiedTime;
}
public boolean checkChanged()
{
if(file == null)
return false;
boolean exist = file.exists();
if(!exist)
{
//init.destroy();
return false;
}
this.lastModifiedTime = file.lastModified();
if(this.oldModifiedTime != this.lastModifiedTime)
{
//begin 1 resolved java.util.ConcurrentModificationException by biaoping.yin on 2015.03.09
// //System.out.println("Reload changed file:" + file.getAbsolutePath());
// log.debug("Reload changed file:" + file.getAbsolutePath());
// this.oldModifiedTime = this.lastModifiedTime;
// try {
// init.reinit();
// log.debug("Reload changed file " + file.getAbsolutePath() + " sucessed." );
// } catch (Exception e) {
// log.debug("Reload changed file " + file.getAbsolutePath() + " failed:" ,e);
// }
return true;
}
else
{
return false;
}
}
/**
* 1 resolved java.util.ConcurrentModificationException by biaoping.yin on 2015.03.09
*/
public void reinit()
{
//System.out.println("Reload changed file:" + file.getAbsolutePath());
log.debug("Reload changed file:" + file.getAbsolutePath());
this.oldModifiedTime = file.lastModified();
try {
for(int i = 0; inits != null && i < this.inits.size(); i++)
{
ResourceInitial init = inits.get(i);
try {
init.reinit();
} catch (Exception e) {
log.debug("Reload changed file " + file.getAbsolutePath() + " failed:" ,e);
}
}
log.debug("Reload changed file " + file.getAbsolutePath() + " sucessed." );
} catch (Exception e) {
log.debug("Reload changed file " + file.getAbsolutePath() + " failed:" ,e);
}
}
//end 1 resolved java.util.ConcurrentModificationException by biaoping.yin on 2015.03.09
public boolean isRemoveflag() {
return removeflag;
}
public void setRemoveflag(boolean removeflag) {
this.removeflag = removeflag;
}
public void addResourceInit(ResourceInitial init) {
if(!this.contain(init))
this.inits.add(init);
}
private boolean contain(ResourceInitial init)
{
if(init instanceof UUIDResource)
{
String uuid = ((UUIDResource)init).getUUID();
for(int i = 0; i < this.inits.size(); i ++)
{
ResourceInitial initOld = this.inits.get(i);
if(initOld instanceof UUIDResource)
{
if(((UUIDResource)initOld).getUUID().equals(uuid))
return true;
}
}
return false;
}
else
return true;//兼容旧版本,没有实现UUIDResource接口的初始化资源初始化接口只允许存在一个ResourceInitial
}
}
private static Logger log = Logger.getLogger(DaemonThread.class);
// private long lastModifiedTime;
// private long oldModifiedTime;
private long refresh_interval = 5000;
private Map<String,FileBean> files = new HashMap<String,FileBean>();
// private ResourceInitial init;
private boolean started = false;
private boolean stopped = false;
public DaemonThread(String fileName,ResourceInitial init)
{
this(fileName,5000,init);
}
public DaemonThread(long refresh_interval,String name)
{
super(name);
this.refresh_interval = refresh_interval;
this.setDaemon(true);
}
public void addFile(String fileName,ResourceInitial init)
{
File file = new File(fileName);
if(!file.exists())
{
URL confURL = ResourceInitial.class.getClassLoader().getResource(fileName);
if(confURL != null)
file = new File(confURL.getPath() );
}
addFile(file,init);
// this.files.add(new FileBean(file,init));
// log.debug("Add file " + file.getAbsolutePath() + " to damon thread which moniting file modified.");
}
private FileBean containFile(File file)
{
if(this.files == null || files.size() <= 0 )
return null;
if(file == null)
return null;
FileBean f = files.get(file.getAbsolutePath());
if(f == null)
return null;
if(f.isRemoveflag())
f.setRemoveflag(false);
return f;
}
public void addFile(File file,ResourceInitial init)
{
if(!file.exists())
{
log.debug(file.getAbsolutePath()+" 对应的文件不存在,忽略修改检测.");
return;
}
synchronized(lock)
{
FileBean f = this.containFile(file);
if(f == null)
{
this.files.put(file.getAbsolutePath(), new FileBean(file,init));
// log.debug(file.getAbsolutePath() + " has been monitored,ignore this operation.");
// return;
}
else
{
f.addResourceInit(init);
}
log.debug("Add file " + file.getAbsolutePath() + " to damon thread which moniting file modified.");
}
}
public void removeFile(String filepath)
{
File file = new File(filepath);
if(!file.exists())
{
URL confURL = ResourceInitial.class.getClassLoader().getResource(filepath);
if(confURL != null)
file = new File(confURL.getPath() );
}
removeFile( file);
}
public void removeFile(File file)
{
synchronized(lock)
{
if(this.files == null || files.size() <= 0 )
return ;
if(file == null)
return ;
FileBean f = files.get(file.getAbsolutePath());
if(f != null)
{
f.setRemoveflag(true);
log.debug("marked file " + file.getAbsolutePath() + " to be removed from damon thread which moniting file modified.");
}
// for(FileBean f:files)
// {
// if(f.getFile() != null && f.getFile().getAbsolutePath().equals(file.getAbsolutePath()))
// {
//// files.remove(f);
// f.setRemoveflag(true);
// }
// }
}
}
public DaemonThread(String fileName,long refresh_interval,ResourceInitial init)
{
super(fileName);
this.refresh_interval = refresh_interval > 0 ?refresh_interval:10000;
File file = new File(fileName);
if(!file.exists())
{
URL confURL = ResourceInitial.class.getClassLoader().getResource(fileName);
if(confURL != null)
file = new File(confURL.getPath() );
}
// this.oldModifiedTime = file.lastModified();
// this.init = init;
if(!file.exists())
{
log.debug(file.getAbsolutePath()+" 对应的文件不存在,忽略修改检测.");
return;
}
this.files.put(file.getAbsolutePath(),new FileBean(file,init));
log.debug("Add file " + file.getAbsolutePath() + " to damon thread which moniting file modified.");
this.setDaemon(true);
}
private Object lock = new Object();
public DaemonThread(File file,ResourceInitial init)
{
// this.oldModifiedTime = file.lastModified();
// this.file = file;
// this.init = init;
// this.files.add(new FileBean(file,init));
this.files.put(file.getAbsolutePath(),new FileBean(file,init));
log.debug("Add file " + file.getAbsolutePath() + " to damon thread which moniting file modified.");
this.setDaemon(true);
}
public boolean started()
{
return started;
}
public void run()
{
log.info("Start check files is changed or not.if some files is changed,the resources of these files will be refreshed use ResourceInit interface.");
started = true;
for(;;)
{
if(stopped)
break;
//System.out.println("Check module file's last modified time.");
try {
sleep(refresh_interval);
} catch (InterruptedException ex) {
// notifyAll();
break;
}
if(files == null || files.size() == 0)
continue;
List<FileBean> changedFiles = new ArrayList<FileBean>();
synchronized(lock)
{
//modified by biaoping.yin on 2015.03.09:忽略扫描异常,如果出现异常继续扫描
try
{
Iterator<Entry<String, FileBean>> entries = files.entrySet().iterator();
while(entries.hasNext())
{
if(stopped)
break;
Entry<String, FileBean> entry = entries.next();
FileBean f = entry.getValue();
if(f.isRemoveflag())
continue;
try
{
if(f.checkChanged())
changedFiles.add(f);
}
catch(Exception e)
{
String filePath = f.getFile() != null?f.getFile().getAbsolutePath():"null";
String tname = this.getName() != null?this.getName():"null";
log.debug("check file["+filePath+"] modified thread["+tname+"] exception occur:",e);
}
}
}
catch(Exception e)
{
log.debug("check file modified thread["+this.getName()+"] error occur:",e);
}
}
if(changedFiles.size() > 0)
{
for(FileBean f:changedFiles)
{
if(stopped)
break;
try
{
f.reinit();
}
catch(Exception e)
{
String filePath = f.getFile() != null?f.getFile().getAbsolutePath():"null";
String tname = this.getName() != null?this.getName():"null";
log.debug("check file["+filePath+"] modified thread["+tname+"] exception occur:",e);
}
}
}
// boolean exist = file.exists();
// if(!exist)
// {
// //init.destroy();
// break;
// }
// this.lastModifiedTime = file.lastModified();
// if(this.oldModifiedTime != this.lastModifiedTime)
// {
// //System.out.println("Reload changed file:" + file.getAbsolutePath());
// log.debug("Reload changed file:" + file.getAbsolutePath());
// this.oldModifiedTime = this.lastModifiedTime;
// init.reinit();
//
// }
}
}
public void stopped()
{
this.stopped = true;
synchronized(lock){
if(files != null)
{
files.clear();
files = null;
}
lock.notifyAll();
}
// synchronized(this)
// {
// this.notifyAll();
// }
//
}
}