/* * RED5 Open Source Flash Server - http://code.google.com/p/red5/ * * Copyright (c) 2006-2011 by respective authors (see below). All rights reserved. * * This library is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or (at your option) any later * version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.red5.server.service; import java.io.File; import java.io.FilenameFilter; import java.lang.management.ManagementFactory; import javax.management.JMX; import javax.management.MBeanServer; import javax.management.ObjectName; import org.red5.server.api.scheduling.IScheduledJob; import org.red5.server.api.scheduling.ISchedulingService; import org.red5.server.jmx.mxbeans.LoaderMXBean; import org.red5.server.util.FileUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This service provides the means to auto-deploy a war. * * @author Paul Gregoire (mondain@gmail.com) */ public final class WarDeployer { private Logger log = LoggerFactory.getLogger(WarDeployer.class); private ISchedulingService scheduler; //how often to check for wars private int checkInterval = 600000; //ten minutes //where we deploy from - where the war files are located private String deploymentDirectory; private static String jobName; //that wars are currently being installed private static boolean deploying; { log.info("War deployer service created"); } public void setCheckInterval(int checkInterval) { this.checkInterval = checkInterval; } public int getCheckInterval() { return checkInterval; } public ISchedulingService getScheduler() { return scheduler; } public void setScheduler(ISchedulingService scheduler) { this.scheduler = scheduler; } public String getDeploymentDirectory() { return deploymentDirectory; } public void setDeploymentDirectory(String deploymentDirectory) { this.deploymentDirectory = deploymentDirectory; } public void init() { //create the job and schedule it jobName = scheduler.addScheduledJobAfterDelay(checkInterval, new DeployJob(), 20000); // log.debug("Source directory: {}", deploymentDirectory); //check the deploy from directory File dir = new File(deploymentDirectory); if (!dir.exists()) { log.warn("Source directory not found"); } else { if (!dir.isDirectory()) { log.warn("Source directory is not a directory"); } } dir = null; } public void shutdown() { scheduler.removeScheduledJob(jobName); } /** * Returns the LoaderMBean. * @return LoadeerMBean */ @SuppressWarnings("cast") public LoaderMXBean getLoader() { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // proxy class LoaderMXBean proxy = null; ObjectName oName; try { oName = new ObjectName("org.red5.server:type=TomcatLoader"); if (mbs.isRegistered(oName)) { proxy = JMX.newMXBeanProxy(mbs, oName, LoaderMXBean.class, true); log.debug("Loader was found"); } else { log.warn("Loader not found"); } } catch (Exception e) { log.error("Exception getting loader", e); } return proxy; } /** * Filters directory content */ protected class DirectoryFilter implements FilenameFilter { /** * Check whether file matches filter rules * * @param dir Directory * @param name File name * @return true If file does match filter rules, false otherwise */ public boolean accept(File dir, String name) { File f = new File(dir, name); log.trace("Filtering: {} name: {}", dir.getName(), name); // filter out all but war files boolean result = f.getName().endsWith("war"); //nullify f = null; return result; } } private class DeployJob implements IScheduledJob { public void execute(ISchedulingService service) { log.trace("Executing job"); if (deploying) { return; } deploying = true; log.debug("Starting scheduled deployment of wars"); //short name String application = null; //file name String applicationWarName = null; //get webapp location String webappsDir = System.getProperty("red5.webapp.root"); log.debug("Webapp folder: {}", webappsDir); //look for web application archives File dir = new File(deploymentDirectory); //get a list of wars File[] files = dir.listFiles(new DirectoryFilter()); for (File f : files) { //get the war name applicationWarName = f.getName(); int dashIndex = applicationWarName.indexOf('-'); if (dashIndex != -1) { //strip everything except the applications name application = applicationWarName.substring(0, dashIndex); } else { //grab every char up to the last '.' application = applicationWarName.substring(0, applicationWarName.lastIndexOf('.')); } log.debug("Application name: {}", application); //setup context String contextPath = '/' + application; String contextDir = webappsDir + contextPath; log.debug("Web context: {} context directory: {}", contextPath, contextDir); //verify this is a unique app File appDir = new File(webappsDir, application); if (appDir.exists()) { if (appDir.isDirectory()) { log.debug("Application directory exists"); } else { log.warn("Application destination is not a directory"); } log.info("Application {} already installed, please un-install before attempting another install", application); } else { log.debug("Unwaring and starting..."); //un-archive it to app dir FileUtil.unzip(deploymentDirectory + '/' + applicationWarName, contextDir); //get the webapp loader LoaderMXBean loader = getLoader(); if (loader != null) { //load and start the context loader.startWebApplication(application); //remove the war file File warFile = new File(deploymentDirectory, applicationWarName); if (warFile.delete()) { log.debug("{} was deleted", warFile.getName()); } else { log.debug("{} was not deleted", warFile.getName()); warFile.deleteOnExit(); } warFile = null; } } appDir = null; } dir = null; //reset sentinel deploying = false; } } }