blob: 8768034cf85f9a75b74228b5c154c2eb6b6d41eb [file] [log] [blame]
/*
* Copyright 1999,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.cluster.deploy;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
/**
* <p>The <b>WarWatcher</b> watches the deployDir for changes made to
* the directory (adding new WAR files->deploy or remove WAR files->undeploy)
* And notifies a listener of the changes made</p>
*
* @author Filip Hanik
* @version 1.0
*/
public class WarWatcher implements Runnable {
/*--Static Variables----------------------------------------*/
public static org.apache.commons.logging.Log log =
org.apache.commons.logging.LogFactory.getLog( WarWatcher.class );
/*--Instance Variables--------------------------------------*/
/**
* Directory to watch for war files
*/
protected File deployDir = null;
/**
* Parent to be notified of changes
*/
protected FileChangeListener listener = null;
/**
*
* Check interval
*/
protected long interval = 5000; //5 seconds
/**
* Run status
*/
protected boolean alive = true;
/**
* Currently deployed files
*/
protected Map currentStatus = new HashMap();
/*--Constructor---------------------------------------------*/
public WarWatcher(FileChangeListener listener,
File deployDir,
long interval) {
this.listener = listener;
this.deployDir = deployDir;
this.interval = interval;
}
/*--Logic---------------------------------------------------*/
public void run() {
while ( alive ) {
try {
File[] list = deployDir.listFiles(new WarFilter());
if ( list == null ) list = new File[0];
//first make sure all the files are listed in our current status
for ( int i=0; i<list.length; i++ ) {
addWarInfo(list[i]);
}//for
//check all the status codes and update the FarmDeployer
for ( Iterator i=currentStatus.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry)i.next();
WarInfo info = (WarInfo)entry.getValue();
int check = info.check();
if ( check == 1 ) {
listener.fileModified(info.getWar());
} else if ( check == -1 ) {
listener.fileRemoved(info.getWar());
//no need to keep in memory
currentStatus.remove(info.getWar());
}//end if
}//for
//sleep for the set interval
Thread.sleep(interval);
} catch ( Exception x ) {
log.error("Unable to watch for WAR deployments in cluster.",x);
}
}//while
}//run
protected void addWarInfo(File f) {
WarInfo info = (WarInfo)currentStatus.get(f.getAbsolutePath());
if ( info == null ) {
info = new WarInfo(f);
info.setLastState(-1); //assume file is non existent
currentStatus.put(f.getAbsolutePath(),info);
}
}
public void stop() {
alive = false;
currentStatus.clear();
listener = null;
}
/*--Inner classes-------------------------------------------*/
/**
* File name filter for war files
*/
protected class WarFilter implements java.io.FilenameFilter {
public boolean accept(File path, String name) {
if ( name == null ) return false;
return name.endsWith(".war");
}
}
/**
* File information on existing WAR files
*/
protected class WarInfo {
protected File war = null;
protected long lastChecked = 0;
protected long lastState = 0;
public WarInfo(File war) {
this.war = war;
this.lastChecked = war.lastModified();
if ( !war.exists() ) lastState = -1;
}
public boolean modified() {
return war.exists() &&
war.lastModified() > lastChecked;
}
public boolean exists() {
return war.exists();
}
/**
* Returns
* 1 if the file has been added/modified,
* 0 if the file is unchanged and
* -1 if the file has been removed
* @return int 1=file added; 0=unchanged; -1=file removed
*/
public int check() {
//file unchanged by default
int result = 0;
if ( modified() ) {
//file has changed - timestamp
result = 1;
lastState = result;
} else if ( (!exists()) && (!(lastState==-1)) ) {
//file was removed
result = -1;
lastState = result;
} else if ( (lastState==-1) && exists() ) {
//file was added
result = 1;
lastState = result;
}
this.lastChecked = System.currentTimeMillis();
return result;
}
public File getWar() {
return war;
}
public int hashCode() {
return war.getAbsolutePath().hashCode();
}
public boolean equals(Object other) {
if ( other instanceof WarInfo ) {
WarInfo wo = (WarInfo)other;
return wo.getWar().equals(getWar());
} else {
return false;
}
}
protected void setLastState(int lastState) {
this.lastState = lastState;
}
}
}