225 lines
6.8 KiB
Java
225 lines
6.8 KiB
Java
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You 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.ha.deploy;
|
|
|
|
import java.io.File;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
|
|
import org.apache.juli.logging.Log;
|
|
import org.apache.juli.logging.LogFactory;
|
|
import org.apache.tomcat.util.res.StringManager;
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* @author Peter Rossbach
|
|
* @version 1.1
|
|
*/
|
|
public class WarWatcher {
|
|
|
|
/*--Static Variables----------------------------------------*/
|
|
private static final Log log = LogFactory.getLog(WarWatcher.class);
|
|
private static final StringManager sm = StringManager.getManager(WarWatcher.class);
|
|
|
|
/*--Instance Variables--------------------------------------*/
|
|
/**
|
|
* Directory to watch for war files
|
|
*/
|
|
protected final File watchDir;
|
|
|
|
/**
|
|
* Parent to be notified of changes
|
|
*/
|
|
protected final FileChangeListener listener;
|
|
|
|
/**
|
|
* Currently deployed files
|
|
*/
|
|
protected final Map<String, WarInfo> currentStatus = new HashMap<>();
|
|
|
|
/*--Constructor---------------------------------------------*/
|
|
|
|
public WarWatcher(FileChangeListener listener, File watchDir) {
|
|
this.listener = listener;
|
|
this.watchDir = watchDir;
|
|
}
|
|
|
|
/*--Logic---------------------------------------------------*/
|
|
|
|
/**
|
|
* check for modification and send notification to listener
|
|
*/
|
|
public void check() {
|
|
if (log.isDebugEnabled())
|
|
log.debug(sm.getString("warWatcher.checkingWars", watchDir));
|
|
File[] list = watchDir.listFiles(new WarFilter());
|
|
if (list == null) {
|
|
log.warn(sm.getString("warWatcher.cantListWatchDir",
|
|
watchDir));
|
|
|
|
list = new File[0];
|
|
}
|
|
//first make sure all the files are listed in our current status
|
|
for (int i = 0; i < list.length; i++) {
|
|
if(!list[i].exists())
|
|
log.warn(sm.getString("warWatcher.listedFileDoesNotExist",
|
|
list[i], watchDir));
|
|
|
|
addWarInfo(list[i]);
|
|
}
|
|
|
|
// Check all the status codes and update the FarmDeployer
|
|
for (Iterator<Map.Entry<String,WarInfo>> i =
|
|
currentStatus.entrySet().iterator(); i.hasNext();) {
|
|
Map.Entry<String,WarInfo> entry = i.next();
|
|
WarInfo info = entry.getValue();
|
|
if(log.isTraceEnabled())
|
|
log.trace(sm.getString("warWatcher.checkingWar",
|
|
info.getWar()));
|
|
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
|
|
i.remove();
|
|
}
|
|
if(log.isTraceEnabled())
|
|
log.trace(sm.getString("warWatcher.checkWarResult",
|
|
Integer.valueOf(check),
|
|
info.getWar()));
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* add cluster war to the watcher state
|
|
* @param warfile The WAR to add
|
|
*/
|
|
protected void addWarInfo(File warfile) {
|
|
WarInfo info = currentStatus.get(warfile.getAbsolutePath());
|
|
if (info == null) {
|
|
info = new WarInfo(warfile);
|
|
info.setLastState(-1); //assume file is non existent
|
|
currentStatus.put(warfile.getAbsolutePath(), info);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clear watcher state
|
|
*/
|
|
public void clear() {
|
|
currentStatus.clear();
|
|
}
|
|
|
|
|
|
/*--Inner classes-------------------------------------------*/
|
|
|
|
/**
|
|
* File name filter for war files
|
|
*/
|
|
protected static class WarFilter implements java.io.FilenameFilter {
|
|
@Override
|
|
public boolean accept(File path, String name) {
|
|
if (name == null)
|
|
return false;
|
|
return name.endsWith(".war");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* File information on existing WAR files
|
|
*/
|
|
protected static class WarInfo {
|
|
protected final File war;
|
|
|
|
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;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return war.getAbsolutePath().hashCode();
|
|
}
|
|
|
|
@Override
|
|
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;
|
|
}
|
|
|
|
}
|
|
|
|
} |