| Method from org.apache.catalina.cluster.deploy.FarmWarDeployer Detail: |
public boolean accept(ClusterMessage msg) {
return (msg instanceof FileMessage) || (msg instanceof UndeployMessage);
}
Before the cluster invokes messageReceived the cluster will ask the
receiver to accept or decline the message, In the future, when messages
get big, the accept method will only take a message header |
protected void addServiced(String name) throws Exception {
String[] params = { name };
String[] signature = { "java.lang.String" };
mBeanServer.invoke(oname, "addServiced", params, signature);
}
Invoke the check method on the deployer. |
public void backgroundProcess() {
if (started) {
count = (count + 1) % processDeployFrequency;
if (count == 0 && watchEnabled) {
watcher.check();
}
}
}
|
protected void check(String name) throws Exception {
String[] params = { name };
String[] signature = { "java.lang.String" };
mBeanServer.invoke(oname, "check", params, signature);
}
Invoke the check method on the deployer. |
public void cleanDeployDir() {
throw new java.lang.UnsupportedOperationException(
"Method cleanDeployDir() not yet implemented.");
}
|
protected boolean copy(File from,
File to) {
try {
if (!to.exists())
to.createNewFile();
java.io.FileInputStream is = new java.io.FileInputStream(from);
java.io.FileOutputStream os = new java.io.FileOutputStream(to,
false);
byte[] buf = new byte[4096];
while (true) {
int len = is.read(buf);
if (len < 0)
break;
os.write(buf, 0, len);
}
is.close();
os.close();
} catch (IOException e) {
log.error("Unable to copy file from:" + from + " to:" + to, e);
return false;
}
return true;
}
Copy a file to the specified temp directory. This is required only
because Jasper depends on it. |
public boolean equals(Object listener) {
return super.equals(listener);
}
|
public void fileModified(File newWar) {
try {
File deployWar = new File(getDeployDir(), newWar.getName());
copy(newWar, deployWar);
String contextName = "/"
+ deployWar.getName().substring(0,
deployWar.getName().lastIndexOf(".war"));
if (log.isInfoEnabled())
log.info("Installing webapp[" + contextName + "] from "
+ deployWar.getAbsolutePath());
try {
remove(contextName, false);
} catch (Exception x) {
log.error("No removal", x);
}
install(contextName, deployWar.toURL());
} catch (Exception x) {
log.error("Unable to install WAR file", x);
}
}
|
public void fileRemoved(File removeWar) {
try {
String contextName = "/"
+ removeWar.getName().substring(0,
removeWar.getName().lastIndexOf(".war"));
if (log.isInfoEnabled())
log.info("Removing webapp[" + contextName + "]");
remove(contextName, true);
} catch (Exception x) {
log.error("Unable to remove WAR file", x);
}
}
|
protected File getAppBase() {
if (appBase != null) {
return appBase;
}
File file = new File(host.getAppBase());
if (!file.isAbsolute())
file = new File(System.getProperty("catalina.base"), host
.getAppBase());
try {
appBase = file.getCanonicalFile();
} catch (IOException e) {
appBase = file;
}
return (appBase);
}
Return a File object representing the "application root" directory for
our associated Host. |
public CatalinaCluster getCluster() {
return cluster;
}
|
protected String getConfigFile(String path) {
String basename = null;
if (path.equals("")) {
basename = "ROOT";
} else {
basename = path.substring(1).replace('/", '#");
}
return (basename);
}
Given a context path, get the config file name. |
public String getDeployDir() {
return deployDir;
}
|
protected String getDocBase(String path) {
String basename = null;
if (path.equals("")) {
basename = "ROOT";
} else {
basename = path.substring(1);
}
return (basename);
}
Given a context path, get the config file name. |
public synchronized FileMessageFactory getFactory(FileMessage msg) throws FileNotFoundException, IOException {
File tmpFile = new File(msg.getFileName());
File writeToFile = new File(getTempDir(), tmpFile.getName());
FileMessageFactory factory = (FileMessageFactory) fileFactories.get(msg
.getFileName());
if (factory == null) {
factory = FileMessageFactory.getInstance(writeToFile, true);
fileFactories.put(msg.getFileName(), factory);
}
return factory;
}
create factory for all transported war files |
public int getProcessDeployFrequency() {
return (this.processDeployFrequency);
}
Return the frequency of watcher checks. |
public String getTempDir() {
return tempDir;
}
|
public String getWatchDir() {
return watchDir;
}
|
public boolean getWatchEnabled() {
return watchEnabled;
}
|
public int hashCode() {
return super.hashCode();
}
|
public void install(String contextPath,
URL war) throws IOException {
Member[] members = getCluster().getMembers();
Member localMember = getCluster().getLocalMember();
FileMessageFactory factory = FileMessageFactory.getInstance(new File(
war.getFile()), false);
FileMessage msg = new FileMessage(localMember, war.getFile(),
contextPath);
if(log.isDebugEnabled())
log.debug("Send cluster war deployment [ path:"
+ contextPath + " war: " + war + " ] started.");
msg = factory.readMessage(msg);
while (msg != null) {
for (int i = 0; i < members.length; i++) {
if (log.isDebugEnabled())
log.debug("Send cluster war fragment [ path: "
+ contextPath + " war: " + war + " to: " + members[i] + " ]");
getCluster().send(msg, members[i]);
} //for
msg = factory.readMessage(msg);
} //while
if(log.isDebugEnabled())
log.debug("Send cluster war deployment [ path: "
+ contextPath + " war: " + war + " ] finished.");
}
Install a new web application, whose web application archive is at the
specified URL, into this container and all the other members of the
cluster with the specified context path. A context path of "" (the empty
string) should be used for the root application for this container.
Otherwise, the context path must start with a slash.
If this application is successfully installed locally, a ContainerEvent
of type INSTALL_EVENT will be sent to all registered
listeners, with the newly created Context as an argument. |
protected boolean isServiced(String name) throws Exception {
String[] params = { name };
String[] signature = { "java.lang.String" };
Boolean result = (Boolean) mBeanServer.invoke(oname, "isServiced",
params, signature);
return result.booleanValue();
}
Invoke the check method on the deployer. |
public boolean isWatchEnabled() {
return watchEnabled;
}
|
public void messageReceived(ClusterMessage msg) {
try {
if (msg instanceof FileMessage && msg != null) {
FileMessage fmsg = (FileMessage) msg;
if (log.isDebugEnabled())
log.debug("receive cluster deployment [ path: "
+ fmsg.getContextPath() + " war: "
+ fmsg.getFileName() + " ]");
FileMessageFactory factory = getFactory(fmsg);
// TODO correct second try after app is in service!
if (factory.writeMessage(fmsg)) {
//last message received war file is completed
String name = factory.getFile().getName();
if (!name.endsWith(".war"))
name = name + ".war";
File deployable = new File(getDeployDir(), name);
try {
String path = fmsg.getContextPath();
if (!isServiced(path)) {
addServiced(path);
try {
remove(path);
factory.getFile().renameTo(deployable);
check(path);
} finally {
removeServiced(path);
}
if (log.isDebugEnabled())
log.debug("deployment from " + path
+ " finished.");
} else
log.error("Application " + path
+ " in used. touch war file " + name
+ " again!");
} catch (Exception ex) {
log.error(ex);
} finally {
removeFactory(fmsg);
}
} //end if
} else if (msg instanceof UndeployMessage && msg != null) {
try {
UndeployMessage umsg = (UndeployMessage) msg;
String path = umsg.getContextPath();
if (log.isDebugEnabled())
log.debug("receive cluster undeployment from " + path);
if (!isServiced(path)) {
addServiced(path);
try {
remove(path);
} finally {
removeServiced(path);
}
if (log.isDebugEnabled())
log.debug("undeployment from " + path
+ " finished.");
} else
log
.error("Application "
+ path
+ " in used. Sorry not remove from backup cluster nodes!");
} catch (Exception ex) {
log.error(ex);
}
} //end if
} catch (java.io.IOException x) {
log.error("Unable to read farm deploy file message.", x);
}
}
Callback from the cluster, when a message is received, The cluster will
broadcast it invoking the messageReceived on the receiver. |
protected void remove(String path) throws Exception {
// TODO Handle remove also work dir content !
// Stop the context first to be nicer
Context context = (Context) host.findChild(path);
if (context != null) {
if(log.isDebugEnabled())
log.debug("Undeploy local context " +path );
((Lifecycle) context).stop();
File war = new File(getAppBase(), getDocBase(path) + ".war");
File dir = new File(getAppBase(), getDocBase(path));
File xml = new File(configBase, getConfigFile(path) + ".xml");
if (war.exists()) {
war.delete();
} else if (dir.exists()) {
undeployDir(dir);
} else {
xml.delete();
}
// Perform new deployment and remove internal HostConfig state
check(path);
}
}
Invoke the remove method on the deployer. |
public void remove(String contextPath,
boolean undeploy) throws IOException {
if (log.isInfoEnabled())
log.info("Cluster wide remove of web app " + contextPath);
// send to other nodes
Member[] members = getCluster().getMembers();
Member localMember = getCluster().getLocalMember();
UndeployMessage msg = new UndeployMessage(localMember, System
.currentTimeMillis(), "Undeploy:" + contextPath + ":"
+ System.currentTimeMillis(), contextPath, undeploy);
if (log.isDebugEnabled())
log.debug("Send cluster wide undeployment from "
+ contextPath );
cluster.send(msg);
// remove locally
if (undeploy) {
try {
if (!isServiced(contextPath)) {
addServiced(contextPath);
try {
remove(contextPath);
} finally {
removeServiced(contextPath);
}
} else
log.error("Local remove from " + contextPath
+ "failed, other manager has app in service!");
} catch (Exception ex) {
log.error("local remove from " + contextPath + " failed", ex);
}
}
}
Remove an existing web application, attached to the specified context
path. If this application is successfully removed, a ContainerEvent of
type REMOVE_EVENT will be sent to all registered
listeners, with the removed Context as an argument.
Deletes the web application war file and/or directory if they exist in
the Host's appBase. |
public void removeFactory(FileMessage msg) {
fileFactories.remove(msg.getFileName());
}
Remove file (war) from messages) |
protected void removeServiced(String name) throws Exception {
String[] params = { name };
String[] signature = { "java.lang.String" };
mBeanServer.invoke(oname, "removeServiced", params, signature);
}
Invoke the check method on the deployer. |
public void setCluster(CatalinaCluster cluster) {
this.cluster = cluster;
}
|
public void setDeployDir(String deployDir) {
this.deployDir = deployDir;
}
|
public void setProcessDeployFrequency(int processExpiresFrequency) {
if (processExpiresFrequency < = 0) {
return;
}
this.processDeployFrequency = processExpiresFrequency;
}
Set the watcher checks frequency. |
public void setTempDir(String tempDir) {
this.tempDir = tempDir;
}
|
public void setWatchDir(String watchDir) {
this.watchDir = watchDir;
}
|
public void setWatchEnabled(boolean watchEnabled) {
this.watchEnabled = watchEnabled;
}
|
public void start() throws Exception {
if (started)
return;
getCluster().addClusterListener(this);
if (watchEnabled) {
watcher = new WarWatcher(this, new File(getWatchDir()));
if (log.isInfoEnabled())
log.info("Cluster deployment is watching " + getWatchDir()
+ " for changes.");
} //end if
// Check to correct engine and host setup
host = (Host) getCluster().getContainer();
Engine engine = (Engine) host.getParent();
try {
oname = new ObjectName(engine.getName() + ":type=Deployer,host="
+ host.getName());
} catch (Exception e) {
log.error("Can't construct MBean object name" + e);
}
configBase = new File(System.getProperty("catalina.base"), "conf");
if (engine != null) {
configBase = new File(configBase, engine.getName());
}
if (host != null) {
configBase = new File(configBase, host.getName());
}
// Retrieve the MBean server
mBeanServer = Registry.getRegistry(null, null).getMBeanServer();
started = true;
count = 0;
if (log.isInfoEnabled())
log.info("Cluster FarmWarDeployer started.");
}
|
public void stop() throws LifecycleException {
started = false;
getCluster().removeClusterListener(this);
count = 0;
if (watcher != null) {
watcher.clear();
watcher = null;
}
if (log.isInfoEnabled())
log.info("Cluster FarmWarDeployer stopped.");
}
|
protected void undeployDir(File dir) {
String files[] = dir.list();
if (files == null) {
files = new String[0];
}
for (int i = 0; i < files.length; i++) {
File file = new File(dir, files[i]);
if (file.isDirectory()) {
undeployDir(file);
} else {
file.delete();
}
}
dir.delete();
}
Delete the specified directory, including all of its contents and
subdirectories recursively. |