📄 farmwardeployer.java
字号:
/* * Copyright 1999,2004-2005 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.ha.deploy;import java.io.File;import java.io.IOException;import java.net.URL;import java.util.HashMap;import javax.management.MBeanServer;import javax.management.ObjectName;import org.apache.catalina.Context;import org.apache.catalina.Engine;import org.apache.catalina.Host;import org.apache.catalina.Lifecycle;import org.apache.catalina.LifecycleException;import org.apache.catalina.ha.CatalinaCluster;import org.apache.catalina.ha.ClusterDeployer;import org.apache.catalina.ha.ClusterListener;import org.apache.catalina.ha.ClusterMessage;import org.apache.catalina.tribes.Member;import org.apache.commons.modeler.Registry;/** * <p> * A farm war deployer is a class that is able to deploy/undeploy web * applications in WAR form within the cluster. * </p> * Any host can act as the admin, and will have three directories * <ul> * <li>deployDir - the directory where we watch for changes</li> * <li>applicationDir - the directory where we install applications</li> * <li>tempDir - a temporaryDirectory to store binary data when downloading a * war from the cluster</li> * </ul> * Currently we only support deployment of WAR files since they are easier to * send across the wire. * * @author Filip Hanik * @author Peter Rossbach * @version $Revision: 390639 $ */public class FarmWarDeployer extends ClusterListener implements ClusterDeployer, FileChangeListener { /*--Static Variables----------------------------------------*/ public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory .getLog(FarmWarDeployer.class); /** * The descriptive information about this implementation. */ private static final String info = "FarmWarDeployer/1.2"; /*--Instance Variables--------------------------------------*/ protected CatalinaCluster cluster = null; protected boolean started = false; //default 5 seconds protected HashMap fileFactories = new HashMap(); protected String deployDir; protected String tempDir; protected String watchDir; protected boolean watchEnabled = false; protected WarWatcher watcher = null; /** * Iteration count for background processing. */ private int count = 0; /** * Frequency of the Farm watchDir check. Cluster wide deployment will be * done once for the specified amount of backgrondProcess calls (ie, the * lower the amount, the most often the checks will occur). */ protected int processDeployFrequency = 2; /** * Path where context descriptors should be deployed. */ protected File configBase = null; /** * The associated host. */ protected Host host = null; /** * The host appBase. */ protected File appBase = null; /** * MBean server. */ protected MBeanServer mBeanServer = null; /** * The associated deployer ObjectName. */ protected ObjectName oname = null; /*--Constructor---------------------------------------------*/ public FarmWarDeployer() { } /** * Return descriptive information about this deployer implementation and the * corresponding version number, in the format * <code><description>/<version></code>. */ public String getInfo() { return (info); } /*--Logic---------------------------------------------------*/ 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."); } // 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."); } /* * stop cluster wide deployments * * @see org.apache.catalina.cluster.ClusterDeployer#stop() */ 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."); } public void cleanDeployDir() { throw new java.lang.UnsupportedOperationException( "Method cleanDeployDir() not yet implemented."); } /** * Callback from the cluster, when a message is received, The cluster will * broadcast it invoking the messageReceived on the receiver. * * @param msg * ClusterMessage - the message received from the cluster */ 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); } } } 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); } } } catch (java.io.IOException x) { log.error("Unable to read farm deploy file message.", x); } } /** * create factory for all transported war files * * @param msg * @return Factory for all app message (war files) * @throws java.io.FileNotFoundException * @throws java.io.IOException */ public synchronized FileMessageFactory getFactory(FileMessage msg) throws java.io.FileNotFoundException, java.io.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; } /** * Remove file (war) from messages) * * @param msg */ public void removeFactory(FileMessage msg) { fileFactories.remove(msg.getFileName()); } /** * 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 * * @param msg * ClusterMessage * @return boolean - returns true to indicate that messageReceived should be * invoked. If false is returned, the messageReceived method will * not be invoked. */ public boolean accept(ClusterMessage msg) { return (msg instanceof FileMessage) || (msg instanceof UndeployMessage); } /** * 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. * <p> * If this application is successfully installed locally, a ContainerEvent * of type <code>INSTALL_EVENT</code> will be sent to all registered * listeners, with the newly created <code>Context</code> as an argument. * * @param contextPath * The context path to which this application should be installed * (must be unique) * @param war * A URL of type "jar:" that points to a WAR file, or type * "file:" that points to an unpacked directory structure * containing the web application to be installed * * @exception IllegalArgumentException * if the specified context path is malformed (it must be "" * or start with a slash) * @exception IllegalStateException * if the specified context path is already attached to an * existing web application * @exception IOException * if an input/output error was encountered during * installation */ 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]); } msg = factory.readMessage(msg); } if(log.isDebugEnabled()) log.debug("Send cluster war deployment [ path: " + contextPath + " war: " + war + " ] finished."); } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -