Home » geronimo-2.2-source-release » org.apache.geronimo.deployment.hot » [javadoc | source]

    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   package org.apache.geronimo.deployment.hot;
   18   
   19   import java.io.File;
   20   import java.io.IOException;
   21   import java.util.Iterator;
   22   import java.util.Set;
   23   
   24   import javax.enterprise.deploy.spi.DeploymentManager;
   25   import javax.enterprise.deploy.spi.Target;
   26   import javax.enterprise.deploy.spi.TargetModuleID;
   27   import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException;
   28   import javax.enterprise.deploy.spi.factories.DeploymentFactory;
   29   import javax.enterprise.deploy.spi.status.ProgressObject;
   30   
   31   import org.slf4j.Logger;
   32   import org.slf4j.LoggerFactory;
   33   import org.apache.geronimo.common.DeploymentException;
   34   import org.apache.geronimo.common.FileUtils;
   35   import org.apache.geronimo.deployment.cli.DeployUtils;
   36   import org.apache.geronimo.deployment.plugin.factories.DeploymentFactoryWithKernel;
   37   import org.apache.geronimo.deployment.plugin.jmx.JMXDeploymentManager;
   38   import org.apache.geronimo.deployment.util.DeploymentUtil;
   39   import org.apache.geronimo.gbean.AbstractName;
   40   import org.apache.geronimo.gbean.AbstractNameQuery;
   41   import org.apache.geronimo.gbean.GBeanInfo;
   42   import org.apache.geronimo.gbean.GBeanInfoBuilder;
   43   import org.apache.geronimo.gbean.GBeanLifecycle;
   44   import org.apache.geronimo.kernel.Kernel;
   45   import org.apache.geronimo.kernel.config.Configuration;
   46   import org.apache.geronimo.kernel.config.ConfigurationManager;
   47   import org.apache.geronimo.kernel.config.DeploymentWatcher;
   48   import org.apache.geronimo.kernel.config.PersistentConfigurationList;
   49   import org.apache.geronimo.kernel.repository.Artifact;
   50   import org.apache.geronimo.kernel.repository.MissingDependencyException;
   51   import org.apache.geronimo.system.serverinfo.ServerInfo;
   52   
   53   /**
   54    * A directory-scanning hot deployer
   55    *
   56    * @version $Rev: 779811 $ $Date: 2009-05-28 18:22:32 -0700 (Thu, 28 May 2009) $
   57    */
   58   public class DirectoryHotDeployer implements HotDeployer, DeploymentWatcher, GBeanLifecycle { //todo: write unit tests
   59       private static final Logger log = LoggerFactory.getLogger(DirectoryHotDeployer.class);
   60   
   61       // Try to make this stand out as the user is likely to get a ton of errors if this comes up
   62       private static final String BAD_LAYOUT_MESSAGE = "CANNOT DEPLOY: It looks like you unpacked an application or module " +
   63               "directly into the hot deployment directory.  THIS DOES NOT WORK.  You need to unpack into a " +
   64               "subdirectory directly under the hot deploy directory.  For example, if the hot deploy directory " +
   65               "is 'deploy/' and your file is 'webapp.war' then you could unpack it into a directory 'deploy/webapp.war/'";
   66       private DirectoryMonitor monitor;
   67       private String path;
   68       private ServerInfo serverInfo;
   69       private ConfigurationManager configManager;
   70       private int pollIntervalMillis;
   71       private String deploymentURI = "deployer:geronimo:inVM";
   72       private String deploymentUser;
   73       private String deploymentPassword;
   74       private transient Kernel kernel;
   75       private transient DeploymentFactory factory;
   76       private transient TargetModuleID[] startupModules = null;
   77       private transient boolean serverRunning = false;
   78   
   79       public DirectoryHotDeployer(String path, int pollIntervalMillis, ServerInfo serverInfo, ConfigurationManager configManager, Kernel kernel) {
   80           this.path = path;
   81           this.serverInfo = serverInfo;
   82           this.pollIntervalMillis = pollIntervalMillis;
   83           this.kernel = kernel;
   84           this.configManager = configManager;
   85       }
   86   
   87       public void deployed(Artifact id) {
   88           // no action when something is deployed
   89       }
   90   
   91       public void undeployed(Artifact id) {
   92           // check to see whether the artifact was hot deployed, and if so, delete it
   93           monitor.removeModuleId(id);
   94       }
   95   
   96       public String getPath() {
   97           return path;
   98       }
   99   
  100       public void setPath(String path) {
  101           this.path = path;
  102       }
  103   
  104       public ServerInfo getServerInfo() {
  105           return serverInfo;
  106       }
  107   
  108       public void setServerInfo(ServerInfo serverInfo) {
  109           this.serverInfo = serverInfo;
  110       }
  111   
  112       public int getPollIntervalMillis() {
  113           return pollIntervalMillis;
  114       }
  115   
  116       public void setPollIntervalMillis(int pollIntervalMillis) {
  117           this.pollIntervalMillis = pollIntervalMillis;
  118       }
  119   
  120       public String getDeploymentURI() {
  121           return deploymentURI;
  122       }
  123   
  124       public void setDeploymentURI(String deploymentURI) {
  125           if (deploymentURI != null && !deploymentURI.trim().equals("")) {
  126               this.deploymentURI = deploymentURI.trim();
  127           }
  128       }
  129   
  130       public String getDeploymentUser() {
  131           return deploymentUser;
  132       }
  133   
  134       public void setDeploymentUser(String deploymentUser) {
  135           this.deploymentUser = deploymentUser;
  136       }
  137   
  138       public String getDeploymentPassword() {
  139           return deploymentPassword;
  140       }
  141   
  142       public void setDeploymentPassword(String deploymentPassword) {
  143           this.deploymentPassword = deploymentPassword;
  144       }
  145   
  146       public void doStart() throws Exception {
  147           if (factory == null) {
  148               factory = new DeploymentFactoryWithKernel(kernel);
  149           }
  150           File dir = serverInfo.resolveServer(path);
  151           if (!dir.exists()) {
  152               if (!dir.mkdirs()) {
  153                   throw new IllegalStateException("Hot deploy directory " + dir.getAbsolutePath() + " does not exist and cannot be created!");
  154               }
  155           } else if (!dir.canRead() || !dir.isDirectory()) {
  156               throw new IllegalStateException("Hot deploy directory " + dir.getAbsolutePath() + " is not a readable directory!");
  157           }
  158           DeploymentManager mgr = null;
  159           try {
  160               mgr = getDeploymentManager();
  161               Target[] targets = mgr.getTargets();
  162               startupModules = mgr.getAvailableModules(null, targets);
  163               mgr.release();
  164               mgr = null;
  165               monitor = new DirectoryMonitor(dir, this, pollIntervalMillis);
  166               log.debug("Hot deploy scanner intialized; starting main loop.");
  167               Thread t = new Thread(monitor, "Geronimo hot deploy scanner");
  168               t.setDaemon(true);
  169               t.start();
  170           } finally {
  171               if (mgr != null) mgr.release();
  172           }
  173       }
  174   
  175       public void doStop() throws Exception {
  176           monitor.close();
  177       }
  178   
  179       public void doFail() {
  180           if (monitor != null) {
  181               monitor.close();
  182           }
  183       }
  184   
  185       public boolean isFileDeployed(File file, String configId) {
  186           DeploymentManager mgr = null;
  187           try {
  188               if (startupModules != null) {
  189                   DeployUtils.identifyTargetModuleIDs(startupModules, configId, true).toArray(new TargetModuleID[0]);
  190               }
  191               else {
  192                   mgr = getDeploymentManager();
  193                   Target[] targets = mgr.getTargets();
  194                   TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
  195                   DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
  196                   mgr.release();
  197                   mgr = null;
  198               }
  199               return true;
  200           } catch (DeploymentException e) {
  201               log.debug("Found new file in deploy directory on startup with ID " + configId);
  202           } catch (Exception e) {
  203               log.error("Unable to check status", e);
  204           } finally {
  205               if (mgr != null) {
  206                   mgr.release();
  207                   mgr = null;
  208               }
  209           }
  210           return false;
  211       }
  212   
  213       public boolean isServerRunning() {
  214           if (serverRunning) {
  215               return true;
  216           }
  217   
  218           // a bit of a hack, but the PersistentConfigurationList is the only thing that knows whether the server is full started!
  219           Set configLists = kernel.listGBeans(new AbstractNameQuery(PersistentConfigurationList.class.getName()));
  220           for (Iterator i = configLists.iterator(); i.hasNext();) {
  221               AbstractName configListName = (AbstractName) i.next();
  222               try {
  223                   Boolean result = (Boolean) kernel.getAttribute(configListName, "kernelFullyStarted");
  224                   if (!result.booleanValue()) {
  225                       return false;
  226                   }
  227               } catch (Exception e) {
  228                   log.warn("Hot deployer unable to determine whether kernel is started", e);
  229               }
  230           }
  231           serverRunning = true;
  232           return true;
  233       }
  234   
  235       public long getDeploymentTime(File file, String configId) {
  236           try {
  237               Artifact art = configManager.getArtifactResolver().resolveInClassLoader(Artifact.create(configId));
  238               Configuration config = configManager.getConfiguration(art);
  239               return config.getCreated();
  240           } catch (MissingDependencyException e) {
  241               log.error("Unknown configuration "+configId);
  242               return -1;
  243           }
  244       }
  245   
  246       public void started() {
  247           startupModules = null;
  248           log.debug("Initialization complete; directory scanner entering normal scan mode");
  249       }
  250   
  251       public boolean validateFile(File file, String configId) {
  252           //todo: some more detailed evaluation
  253           if (file.isDirectory() && (file.getName().equals("WEB-INF") || file.getName().equals("META-INF"))) {
  254               log.error("(" + file.getName() + ") " + BAD_LAYOUT_MESSAGE);
  255               return false;
  256           }
  257           return true;
  258       }
  259   
  260       public String fileAdded(File file) {
  261           log.info("Deploying " + file.getName());
  262           DeploymentManager mgr = null;
  263           TargetModuleID[] modules = null;
  264           boolean completed = false;
  265           try {
  266               mgr = getDeploymentManager();
  267               Target[] targets = mgr.getTargets();
  268               if (null == targets) {
  269                   throw new IllegalStateException("No target to distribute to");
  270               }
  271               targets = new Target[] {targets[0]};
  272   
  273               ProgressObject po;
  274   
  275               if (FileUtils.isJarFile(file) || file.isDirectory()) {
  276                   po = mgr.distribute(targets, file, null);
  277               } else {
  278                   po = mgr.distribute(targets, null, file);
  279               }
  280               waitForProgress(po);
  281               if (po.getDeploymentStatus().isCompleted()) {
  282                   modules = po.getResultTargetModuleIDs();
  283                   po = mgr.start(modules);
  284                   waitForProgress(po);
  285                   if (po.getDeploymentStatus().isCompleted()) {
  286                       completed = true;
  287                   } else {
  288                       log.warn("Unable to start some modules for " + file.getAbsolutePath());
  289                   }
  290                   modules = po.getResultTargetModuleIDs();
  291                   for (int i = 0; i < modules.length; i++) {
  292                       TargetModuleID result = modules[i];
  293                       log.info(DeployUtils.reformat("Deployed " + result.getModuleID() + (targets.length > 1 ? " to " + result.getTarget().getName() : "") + (result.getWebURL() == null ? "" : " @ " + result.getWebURL()), 4, 72));
  294                       if (result.getChildTargetModuleID() != null) {
  295                           for (int j = 0; j < result.getChildTargetModuleID().length; j++) {
  296                               TargetModuleID child = result.getChildTargetModuleID()[j];
  297                               log.info(DeployUtils.reformat("  `-> " + child.getModuleID() + (child.getWebURL() == null ? "" : " @ " + child.getWebURL()), 4, 72));
  298                           }
  299                       }
  300                   }
  301               } else {
  302               	 //Try to delete the module , that failed to successfully hot-deploy  
  303               	log.error("Unable to deploy: " + po.getDeploymentStatus().getMessage());
  304               	String delfile=file.getAbsolutePath();
  305                   File fd = new File(delfile);
  306                   if(fd.isDirectory()){
  307                  	    log.info("Deleting the Directory: "+delfile);
  308                  	    if(DeploymentUtil.recursiveDelete(fd))
  309                  		    log.debug("Successfully deleted the Directory: "+delfile);
  310                  	    else
  311                  		    log.error("Couldn't delete the hot deployed directory"+delfile);
  312                   }else if(fd.isFile()){
  313                  	    log.info("Deleting the File: "+delfile);
  314                  	    if(fd.delete()){
  315                  		log.debug("Successfully deleted the File: "+delfile); 
  316                  	}else
  317                  		log.error("Couldn't delete the hot deployed directory"+delfile); 
  318                   }
  319                               
  320                   return null;
  321               }
  322           } catch (DeploymentManagerCreationException e) {
  323               log.error("Unable to open deployer", e);
  324           } catch (IOException e) {
  325               log.error("Unable to determine if file is a jar", e);
  326           } finally {
  327               if (mgr != null) mgr.release();
  328           }
  329           if (completed && modules != null) {
  330               if (modules.length == 1) {
  331                   return modules[0].getModuleID();
  332               } else {
  333                   return "";
  334               }
  335           } else if (modules != null) { //distribute completed but not start or something like that
  336               return "";
  337           } else {
  338               return null;
  339           }
  340       }
  341       
  342       private DeploymentManager getDeploymentManager() throws DeploymentManagerCreationException {
  343           DeploymentManager manager = factory.getDeploymentManager(deploymentURI, deploymentUser, deploymentPassword);
  344           if (manager instanceof JMXDeploymentManager) {
  345               ((JMXDeploymentManager) manager).setLogConfiguration(false, true);
  346           }
  347           return manager;
  348       }
  349   
  350       public boolean fileRemoved(File file, String configId) {
  351           log.info("Undeploying " + file.getName());
  352           DeploymentManager mgr = null;
  353           try {
  354               mgr = getDeploymentManager();
  355               Target[] targets = mgr.getTargets();
  356               TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
  357               ids = (TargetModuleID[]) DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
  358               ProgressObject po = mgr.undeploy(ids);
  359               waitForProgress(po);
  360               if (po.getDeploymentStatus().isCompleted()) {
  361                   TargetModuleID[] modules = po.getResultTargetModuleIDs();
  362                   for (int i = 0; i < modules.length; i++) {
  363                       TargetModuleID result = modules[i];
  364                       log.info(DeployUtils.reformat("Undeployed " + result.getModuleID() + (targets.length > 1 ? " to " + result.getTarget().getName() : ""), 4, 72));
  365                   }
  366               } else {
  367                   log.error("Unable to undeploy " + file.getAbsolutePath() + "(" + configId + ")" + po.getDeploymentStatus().getMessage());
  368                   return false;
  369               }
  370           } catch (DeploymentManagerCreationException e) {
  371               log.error("Unable to open deployer", e);
  372               return false;
  373           } catch (Exception e) {
  374               log.error("Unable to undeploy", e);
  375               return false;
  376           } finally {
  377               if (mgr != null) mgr.release();
  378           }
  379           return true;
  380       }
  381   
  382       public String getModuleId(String config) {
  383           DeploymentManager mgr = null;
  384           TargetModuleID[] modules = null;
  385           try {
  386               mgr = getDeploymentManager();
  387               Target[] targets = mgr.getTargets();
  388               TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
  389               for(int j=0;j<ids.length;j++) {
  390                   String moduleId=ids[j].getModuleID();
  391                   String[] parts = moduleId.split("/", -1);
  392                   if (parts.length != 4) {
  393                       continue;
  394                   }
  395                   if(parts[1] != null && parts[1].equals(config))
  396                       return ids[j].getModuleID();                
  397               }
  398           } catch(Exception ex){
  399               log.error("Unable to getModuleId",ex);
  400           }
  401           return config;
  402       }
  403   
  404       public String fileUpdated(File file, String configId) {
  405           log.info("Redeploying " + file.getName());
  406           DeploymentManager mgr = null;
  407           TargetModuleID[] modules = null;
  408           try {
  409               mgr = getDeploymentManager();
  410               Target[] targets = mgr.getTargets();
  411               TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
  412               ids = (TargetModuleID[]) DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
  413               ProgressObject po;
  414               if (FileUtils.isJarFile(file) || file.isDirectory()) {
  415                   po = mgr.redeploy(ids, file, null);
  416               } else {
  417                   po = mgr.redeploy(ids, null, file);
  418               }
  419               waitForProgress(po);
  420               if (po.getDeploymentStatus().isCompleted()) {
  421                   modules = po.getResultTargetModuleIDs();
  422                   for (int i = 0; i < modules.length; i++) {
  423                       TargetModuleID result = modules[i];
  424                       log.info(DeployUtils.reformat("Redeployed " + result.getModuleID() + (targets.length > 1 ? " to " + result.getTarget().getName() : "") + (result.getWebURL() == null ? "" : " @ " + result.getWebURL()), 4, 72));
  425                       if (result.getChildTargetModuleID() != null) {
  426                           for (int j = 0; j < result.getChildTargetModuleID().length; j++) {
  427                               TargetModuleID child = result.getChildTargetModuleID()[j];
  428                               log.info(DeployUtils.reformat("  `-> " + child.getModuleID() + (child.getWebURL() == null ? "" : " @ " + child.getWebURL()), 4, 72));
  429                           }
  430                       }
  431                   }
  432               } else {
  433                   log.error("Unable to undeploy " + file.getAbsolutePath() + "(" + configId + ")" + po.getDeploymentStatus().getMessage());
  434               }
  435           } catch (DeploymentManagerCreationException e) {
  436               log.error("Unable to open deployer", e);
  437           } catch (Exception e) {
  438               log.error("Unable to undeploy", e);
  439           } finally {
  440               if (mgr != null) mgr.release();
  441           }
  442           if (modules != null) {
  443               if (modules.length == 1) {
  444                   return modules[0].getModuleID();
  445               } else {
  446                   return "";
  447               }
  448           } else {
  449               return null;
  450           }
  451       }
  452   
  453       private void waitForProgress(ProgressObject po) {
  454           while (po.getDeploymentStatus().isRunning()) {
  455               try {
  456                   Thread.sleep(100);
  457               } catch (InterruptedException e) {
  458                   log.error(e.getMessage(), e);
  459               }
  460           }
  461       }
  462   
  463       public static final GBeanInfo GBEAN_INFO;
  464   
  465       static {
  466           GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(DirectoryHotDeployer.class);
  467   
  468           infoFactory.addAttribute("path", String.class, true, true);
  469           infoFactory.addAttribute("pollIntervalMillis", int.class, true, true);
  470   
  471           // The next 3 args can be used to configure the hot deployer for a remote (out of VM) server
  472           infoFactory.addAttribute("deploymentURI", String.class, true, true);
  473           infoFactory.addAttribute("deploymentUser", String.class, true, true);
  474           infoFactory.addAttribute("deploymentPassword", String.class, true, true);
  475   
  476           infoFactory.addReference("ConfigManager", ConfigurationManager.class, "ConfigurationManager");
  477           infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean");
  478           infoFactory.addAttribute("kernel", Kernel.class, false, false);
  479           infoFactory.addInterface(HotDeployer.class);
  480   
  481           infoFactory.setConstructor(new String[]{"path", "pollIntervalMillis", "ServerInfo", "ConfigManager", "kernel"});
  482   
  483           GBEAN_INFO = infoFactory.getBeanInfo();
  484       }
  485   
  486       public static GBeanInfo getGBeanInfo() {
  487           return GBEAN_INFO;
  488       }
  489   }

Home » geronimo-2.2-source-release » org.apache.geronimo.deployment.hot » [javadoc | source]