
com.frameworkset.util.DaemonThread Maven / Gradle / Ivy
package com.frameworkset.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.URL;
import java.util.*;
import java.util.Map.Entry;
/**
* Title:
*
* Description:
*
* Copyright: Copyright (c) 2005
*
* Company:
*
* @author biaoping.yin
* @version 1.0
*/
public class DaemonThread extends java.lang.Thread
{
static class WrapperResourceInit implements ResourceInitial,UUIDResource{
private ResourceInitial resourceInitial;
private String fileName;
public WrapperResourceInit(ResourceInitial resourceInitial,String fileName){
this.resourceInitial = resourceInitial;
this.fileName = fileName;
}
@Override
public void reinit() {
resourceInitial.reinit();
}
@Override
public String getUUID() {
if(resourceInitial instanceof UUIDResource)
return ((UUIDResource)resourceInitial).getUUID();
return this.fileName;
}
}
static class FileBean
{
public FileBean(File file,
WrapperResourceInit init) {
super();
this.file = file;
this.inits = new ArrayList();
inits.add(init);
this.oldModifiedTime = file.lastModified();
}
private boolean removeflag = false;
private File file;
// private long lastModifiedTime;
private long oldModifiedTime;
private List 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 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;
}
long lastModifiedTime = file.lastModified();
if(this.oldModifiedTime != lastModifiedTime)
{
return true;
}
else
{
return false;
}
}
/**
* 1 resolved java.util.ConcurrentModificationException by biaoping.yin on 2015.03.09
*/
public synchronized void reinit()
{
//System.out.println("Reload changed file:" + file.getAbsolutePath());
if(log.isInfoEnabled()) {
log.info("Reload resources in changed file:" + file.getAbsolutePath());
}
long lastModifiedTime = file.lastModified();
if(lastModifiedTime == this.oldModifiedTime)
return;
else {
//检查文件是否已经读写完毕,通过文件长度来判断(不一定准确)
long length = file.length();
long last = length;
do {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
length = file.length();
if (last == length) {
lastModifiedTime = file.lastModified();
break;
} else {
last = length;
}
}
while(true);
}
this.oldModifiedTime = lastModifiedTime;
for(int i = 0; inits != null && i < this.inits.size(); i++)
{
WrapperResourceInit init = inits.get(i);
try {
init.reinit();
if(log.isInfoEnabled()) {
log.info("Reload changed resource file " + init.getUUID()+"@"+ file.getAbsolutePath() + " sucessed.");
}
} catch (Exception e) {
if(log.isErrorEnabled())
log.error("Reload changed resource file " + init.getUUID()+"@"+ 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(WrapperResourceInit 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 = LoggerFactory.getLogger(DaemonThread.class);
// private long lastModifiedTime;
// private long oldModifiedTime;
private long refresh_interval = 5000;
private Map files = new HashMap();
// 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)
{
if(this.stopped || fileName == null)
return;
try {
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, fileName, init);
}
catch (Exception e){
if (log.isErrorEnabled())
log.error("addFile file to monitor Thread failed,fileName:"+fileName ,e);
}
// this.files.add(new FileBean(file,init));
// log.debug("Add file " + file.getAbsolutePath() + " to damon thread that moniting changed files.");
}
private FileBean containFile(File file,String fileName)
{
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;
}
/**
*
* @param file 触发文件更新的文件句柄
* @param fileName 实际的文件,有可能和file不一致(file可能为jar或者其他合法的压缩包文件,包含多个需要刷新的file)
* @param init
*/
public void addFile(File file,String fileName,ResourceInitial init)
{
if(this.stopped || file == null )
return;
if( !file.exists())
{
if(log.isInfoEnabled() )
log.info(fileName+"@"+file.getAbsolutePath()+" 对应的文件不存在,忽略修改检测.");
return;
}
try {
synchronized (lock) {
FileBean f = this.containFile(file, fileName);
if (f == null) {
this.files.put(file.getAbsolutePath(), new FileBean(file, new WrapperResourceInit(init, fileName)));
// log.debug(file.getAbsolutePath() + " has been monitored,ignore this operation.");
// return;
} else {
f.addResourceInit(new WrapperResourceInit(init, fileName));
}
if (log.isInfoEnabled())
log.info("Add file " + fileName + "@" + file.getAbsolutePath() + " to monitor thread that moniting changed files.");
}
}
catch (Exception e){
if (log.isErrorEnabled())
log.error("Add file " + fileName + "@" + file.getAbsolutePath() + " to monitor thread that moniting changed files failed:",e);
}
}
/**
* determine the OS name
*
* @return The name of the OS
*/
public static final String getOS() {
String osname = System.getProperty("os.name");
return osname;
}
public static Boolean isWindow = null;
/**
* @return True if the OS is a Windows derivate.
*/
public static final boolean isWindows() {
if(isWindow != null)
return isWindow.booleanValue();
synchronized (DaemonThread.class){
if(isWindow != null)
return isWindow.booleanValue();
isWindow = getOS().startsWith("Windows");
}
return isWindow;
}
/**
*
* @param file 触发文件更新的文件句柄
* @param init
*/
public void addFile(File file,ResourceInitial init)
{
if(this.stopped || file == null)
return;
String fileName = file.getAbsolutePath();
addFile( file, fileName, init);
}
public void addFile(URL fileURL,String fileName,ResourceInitial init)
{
if(this.stopped )
return;
if(fileName == null){
log.info("Ignore addFile Null file to change monitor Thread:fileName:"+fileName + ",fileURL:"+fileURL);
return;
}
try {
File file = new File(fileName);
if (!file.exists()) {
if (fileURL != null) {
String fileUrl = fileURL.getPath();
if (log.isInfoEnabled()) {
log.info("Use out package file URL to monitor: " + fileUrl);
}
file = new File(fileUrl);
if (!file.exists()) {
int idx = fileUrl.indexOf("!");
if (idx > 0) {
fileUrl = fileUrl.substring(0, idx);
idx = fileUrl.indexOf("file:");
if (idx == -1) {
idx = fileUrl.indexOf("file:");
}
if (idx >= 0) {
if (isWindows()) {
fileUrl = fileUrl.substring(idx + 6);
} else {
fileUrl = fileUrl.substring(idx + 5);
}
}
file = new File(fileUrl);
}
}
}
}
addFile(file, fileName, init);
}
catch (Exception e){
if (log.isErrorEnabled())
log.error("addFile file to monitor Thread failed,fileName:"+fileName + ",fileURL:"+fileURL ,e);
}
}
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);
if(log.isInfoEnabled())
log.info("marked file " + file.getAbsolutePath() + " to be removed from monitor thread that moniting changed files.");
}
// 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())
{
if(log.isInfoEnabled())
log.info(file.getAbsolutePath()+" 对应的文件不存在,忽略修改检测.");
return;
}
this.files.put(file.getAbsolutePath(),new FileBean(file,new WrapperResourceInit(init,file.getAbsolutePath())));
if(log.isInfoEnabled())
log.info("Add file " + file.getAbsolutePath() + " to monitor thread that moniting changed files.");
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,new WrapperResourceInit(init,file.getAbsolutePath())));
if(log.isInfoEnabled())
log.info("Add file " + file.getAbsolutePath() + " to monitor thread that moniting changed files.");
this.setDaemon(true);
}
public boolean started()
{
return started;
}
public void run()
{
if(log.isInfoEnabled())
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){
if(log.isTraceEnabled()) {
String tname = this.getName() != null ? this.getName() : "null";
log.trace("Thread[" + tname + "] Ignore Monitor change Files : No file to be monitor.");
}
continue;
}
List changedFiles = new ArrayList();
synchronized(lock)
{
//modified by biaoping.yin on 2015.03.09:忽略扫描异常,如果出现异常继续扫描
try
{
Iterator> entries = files.entrySet().iterator();
while(entries.hasNext())
{
if(stopped)
break;
Entry entry = entries.next();
FileBean f = entry.getValue();
if(f.isRemoveflag())
continue;
try
{
if(log.isTraceEnabled()){
String filePath = f.getFile() != null?f.getFile().getAbsolutePath():"";
log.trace("Thread["+this.getName()+"] Check file["+filePath+"] .");
}
if(f.checkChanged()){
if(log.isInfoEnabled()){
String filePath = f.getFile() != null?f.getFile().getAbsolutePath():"";
log.info("Thread["+this.getName()+"] Monitor file["+filePath+"] changed.");
}
changedFiles.add(f);
}
}
catch(Exception e)
{
if(log.isInfoEnabled()) {
String filePath = f.getFile() != null ? f.getFile().getAbsolutePath() : "null";
String tname = this.getName() != null ? this.getName() : "null";
log.info("Thread[" + tname + "] Monitor changed file[" + filePath + "] exception:", e);
}
}
}
}
catch(Exception e)
{
if(log.isInfoEnabled())
log.info("Thread["+this.getName()+"] Monitor changed files exception:",e);
}
}
if(changedFiles.size() > 0)
{
for(FileBean f:changedFiles)
{
if(stopped)
break;
try
{
f.reinit();
}
catch(Exception e)
{
if(log.isInfoEnabled()) {
String filePath = f.getFile() != null ? f.getFile().getAbsolutePath() : "null";
String tname = this.getName() != null ? this.getName() : "null";
log.info("Thread[" + tname + "] Reinit Monitor changed file[" + filePath + "] exception:", e);
}
}
}
}
}
}
public void stopped()
{
if(this.stopped)
return;
this.stopped = true;
synchronized(lock){
if(files != null)
{
files.clear();
// files = null;
}
lock.notifyAll();
}
// synchronized(this)
// {
// this.notifyAll();
// }
//
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy