Package org.red5.server.service

Source Code of org.red5.server.service.Installer

/*
* 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.FileOutputStream;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.UUID;

import javax.management.JMX;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.util.EntityUtils;
import org.red5.compatibility.flex.messaging.messages.AcknowledgeMessage;
import org.red5.compatibility.flex.messaging.messages.AsyncMessage;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.service.ServiceUtils;
import org.red5.server.jmx.mxbeans.LoaderMXBean;
import org.red5.server.util.FileUtil;
import org.red5.server.util.HttpConnectionUtil;
import org.slf4j.Logger;

/**
* This service provides the means to list, download, install, and un-install
* applications from a given url.
*
* @author Paul Gregoire (mondain@gmail.com)
* @author Dominick Accattato (daccattato@gmail.com)
*/
public final class Installer {

  private static Logger log = Red5LoggerFactory.getLogger(Installer.class);

  private String applicationRepositoryUrl;

  {
    log.info("Installer service created");
  }

  public String getApplicationRepositoryUrl() {
    return applicationRepositoryUrl;
  }

  public void setApplicationRepositoryUrl(String applicationRepositoryUrl) {
    this.applicationRepositoryUrl = applicationRepositoryUrl;
  }

  /**
   * Returns the LoaderMBean.
   * @return LoaderMBean
   */
  @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;   
  }

  /**
   * Returns a Map containing all of the application wars in the snapshot repository.
   *
   * @return async message
   */
  public AsyncMessage getApplicationList() {
    AcknowledgeMessage result = new AcknowledgeMessage();
    // create a singular HttpClient object
    HttpClient client = HttpConnectionUtil.getClient();
    //setup GET
    HttpGet method = null;
    try {
      //get registry file
      method = new HttpGet(applicationRepositoryUrl + "registry.xml");
      // execute the method
      HttpResponse response = client.execute(method);
      int code = response.getStatusLine().getStatusCode();
      log.debug("HTTP response code: {}", code);
      if (code == 200) {
        HttpEntity entity = response.getEntity();
        if (entity != null) {
          String responseText = EntityUtils.toString(entity);
          log.debug("Response: {}", responseText);
          //prepare response for flex     
          result.body = responseText;
          IConnection conn = Red5.getConnectionLocal();
          result.clientId = conn.getClient().getId();
          result.messageId = UUID.randomUUID().toString();
          result.timestamp = System.currentTimeMillis();
          //send the servers java version so the correct apps are installed
          String javaVersion = System.getProperty("java.version").substring(0, 3);
          log.info("JRE version detected: {}", javaVersion);
          // allow any jre version greater than 1.5 to equal 1.6 for client compatibility
          // fix for issue #189
          if (Double.valueOf(javaVersion) > 1.5d) {
            javaVersion = "1.6";
          }
          if (!ServiceUtils.invokeOnConnection(conn, "onJavaVersion", new Object[] { javaVersion })) {
            log.warn("Client call to onJavaVersion failed");
          }
        }
      } else {
        log.warn("Service returned an error");
        if (log.isDebugEnabled()) {
          HttpConnectionUtil.handleError(response);
        }
      }
    } catch (HttpHostConnectException he) {
      log.error("Http error connecting to {}", applicationRepositoryUrl, he);
      method.abort();
    } catch (IOException ioe) {
      log.error("Unable to connect to {}", applicationRepositoryUrl, ioe);
      method.abort();
    }
    return result;
  }

  /**
   * Installs a given application.
   *
   * @param applicationWarName app war name
   * @return true if installed; false otherwise
   */
  @SuppressWarnings("deprecation")
  public boolean install(String applicationWarName) {
    IConnection conn = Red5.getConnectionLocal();
    boolean result = false;
    //strip everything except the applications name
    String application = applicationWarName.substring(0, applicationWarName.indexOf('-'));
    log.debug("Application name: {}", application);
    //get webapp location
    String webappsDir = System.getProperty("red5.webapp.root");
    log.debug("Webapp folder: {}", webappsDir);
    //setup context
    String contextPath = '/' + application;
    String contextDir = webappsDir + contextPath;
    //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");
      }
      ServiceUtils.invokeOnConnection(conn, "onAlert",
          new Object[] { String.format("Application %s already installed, please un-install before attempting another install", application) });
    } else {
      //use the system temp directory for moving files around
      String srcDir = System.getProperty("java.io.tmpdir");
      log.debug("Source directory: {}", srcDir);
      //look for archive containing application (war, zip, etc..)
      File dir = new File(srcDir);
      if (!dir.exists()) {
        log.warn("Source directory not found");
        //use another directory
        dir = new File(System.getProperty("red5.root"), "/webapps/installer/WEB-INF/cache");
        if (!dir.exists()) {
          if (dir.mkdirs()) {
            log.info("Installer cache directory created");
          }
        }
      } else {
        if (!dir.isDirectory()) {
          log.warn("Source directory is not a directory");
        }
      }
      //get a list of temp files
      File[] files = dir.listFiles();
      for (File f : files) {
        String fileName = f.getName();
        if (fileName.equals(applicationWarName)) {
          log.debug("File found matching application name");
          result = true;
          break;
        }
      }
      dir = null;
      //if the file was not found then download it
      if (!result) {
        // create a singular HttpClient object
        HttpClient client = HttpConnectionUtil.getClient();
        //setup GET
        HttpGet method = null;
        FileOutputStream fos = null;
        try {
          //try the war version first
          method = new HttpGet(applicationRepositoryUrl + applicationWarName);
          // set transfer encoding
          method.getParams().setParameter("http.protocol.strict-transfer-encoding", Boolean.TRUE);
          //we dont want any transformation - RFC2616
          method.addHeader("Accept-Encoding", "identity");
          // execute the method
          HttpResponse response = client.execute(method);
          int code = response.getStatusLine().getStatusCode();
          log.debug("HTTP response code: {}", code);
          if (code == 200) {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
              //create output file
              fos = new FileOutputStream(srcDir + '/' + applicationWarName);
              log.debug("Writing response to {}/{}", srcDir, applicationWarName);
              // have to receive the response as a byte array.  This has the advantage of writing to the file system
              // faster and it also works on macs ;)
              byte[] buf = EntityUtils.toByteArray(entity);
              fos.write(buf);
              fos.flush();
              // we should be good to go
              result = true;
            }
          }
        } catch (HttpHostConnectException he) {
          log.error("Http error connecting to {}", applicationRepositoryUrl, he);
          method.abort();
        } catch (IOException ioe) {
          log.error("Unable to connect to {}", applicationRepositoryUrl, ioe);
          method.abort();
        } finally {
          if (fos != null) {
            try {
              fos.close();
            } catch (IOException e) {
            }
          }
        }
      }
      //if we've found or downloaded the war
      if (result) {
        //get the webapp loader
        LoaderMXBean loader = getLoader();
        if (loader != null) {
          //un-archive it to app dir
          FileUtil.unzip(srcDir + '/' + applicationWarName, contextDir);
          //load and start the context
          loader.startWebApplication(application);
        } else {
          //just copy the war to the webapps dir
          try {
            FileUtil.moveFile(srcDir + '/' + applicationWarName, webappsDir + '/' + application + ".war");
            ServiceUtils.invokeOnConnection(conn, "onAlert",
                new Object[] { String.format("Application %s will not be available until container is restarted", application) });
          } catch (IOException e) {
          }
        }
      }
      ServiceUtils.invokeOnConnection(conn, "onAlert", new Object[] { String.format("Application %s was %s", application, (result ? "installed" : "not installed")) });
    }
    appDir = null;
    return result;
  }

  /**
   * Un-installs a given application.
   *
   * @param applicationName name to uninstall
   * @return true if uninstalled; else false
   */
  public boolean uninstall(String applicationName) {
    ServiceUtils.invokeOnConnection(Red5.getConnectionLocal(), "onAlert", new Object[] { "Uninstall function not available" });

    return false;
  }

}
TOP

Related Classes of org.red5.server.service.Installer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.