Package org.jboss.errai.cdi.server.gwt

Source Code of org.jboss.errai.cdi.server.gwt.JBossLauncher

package org.jboss.errai.cdi.server.gwt;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.BindException;

import javax.xml.stream.XMLStreamException;

import org.apache.commons.io.IOUtils;
import org.jboss.errai.cdi.server.as.JBossServletContainerAdaptor;
import org.jboss.errai.cdi.server.gwt.util.SimpleTranslator;
import org.jboss.errai.cdi.server.gwt.util.SimpleTranslator.AttributeEntry;
import org.jboss.errai.cdi.server.gwt.util.SimpleTranslator.Tag;
import org.jboss.errai.cdi.server.gwt.util.StackTreeLogger;

import com.google.gwt.core.ext.ServletContainer;
import com.google.gwt.core.ext.ServletContainerLauncher;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;

/**
* For starting a {@link JBossServletContainerAdaptor} controlling a standalone
* Jboss/Wildfly AS.
*
* @author Max Barkley <mbarkley@redhat.com>
*/
public class JBossLauncher extends ServletContainerLauncher {

  // Property names
  private final String JBOSS_HOME_PROPERTY = "errai.jboss.home";
  private final String JBOSS_DEBUG_PORT_PROPERTY = "errai.jboss.debug.port";
  private final String TEMPLATE_CONFIG_FILE_PROPERTY = "errai.jboss.config.file";
  private final String CLASS_HIDING_JAVA_AGENT_PROPERTY = "errai.jboss.javaagent.path";
  private final String APP_CONTEXT_PROPERTY = "errai.dev.context";
  private final String JBOSS_JAVA_OPTS_PROPERTY = "errai.jboss.javaopts";

  private final String TMP_CONFIG_FILE = "standalone-errai-dev.xml";
  private static final String STANDALONE_CONFIGURATION = "standalone" + File.separator + "configuration";

  StackTreeLogger logger;

  @Override
  public ServletContainer start(TreeLogger treeLogger, int port, File appRootDir) throws BindException, Exception {
    logger = new StackTreeLogger(treeLogger);

    logger.branch(Type.INFO, "Starting launcher...");

    // Get properties
    final String JBOSS_HOME = System.getProperty(JBOSS_HOME_PROPERTY);
    final String DEBUG_PORT = System.getProperty(JBOSS_DEBUG_PORT_PROPERTY, "8001");
    final String TEMPLATE_CONFIG_FILE = System.getProperty(TEMPLATE_CONFIG_FILE_PROPERTY, "standalone-full.xml");
    final String CLASS_HIDING_JAVA_AGENT = System.getProperty(CLASS_HIDING_JAVA_AGENT_PROPERTY);
    final String DEPLOYMENT_CONTEXT = System.getProperty(APP_CONTEXT_PROPERTY, "webapp");
    String JAVA_OPTS = System.getProperty(JBOSS_JAVA_OPTS_PROPERTY, "");

    validateJbossHome(JBOSS_HOME);
    validateClassHidingJavaAgent(CLASS_HIDING_JAVA_AGENT);

    try {
      createTempConfigFile(TEMPLATE_CONFIG_FILE, TMP_CONFIG_FILE, JBOSS_HOME, port);
      logger.log(Type.INFO,
              String.format("Created temporary config file %s, copied from %s.", TMP_CONFIG_FILE, TEMPLATE_CONFIG_FILE));
    }
    catch (IOException e) {
      logger.log(
              Type.ERROR,
              String.format("Unable to create temporary config file %s from %s", TMP_CONFIG_FILE, TEMPLATE_CONFIG_FILE),
              e);
    }

    final String JBOSS_START = getStartScriptName(JBOSS_HOME);

    Process process;
    try {
      logger.branch(Type.INFO, String.format("Preparing JBoss AS instance (%s)", JBOSS_START));
      final File startScript = new File(JBOSS_START);
      if (!startScript.canExecute() && !startScript.setExecutable(true)) {
        logger.log(Type.ERROR, "Can not execute " + JBOSS_START);
        throw new UnableToCompleteException();
      }
      ProcessBuilder builder = new ProcessBuilder(JBOSS_START, "-c", TMP_CONFIG_FILE);

      logger.log(Type.INFO, String.format("Adding JBOSS_HOME=%s to instance environment", JBOSS_HOME));
      // Necessary for JBoss AS instance to startup
      builder.environment().put("JBOSS_HOME", JBOSS_HOME);

      // Allows JVM to be debugged
      builder.environment().put(
              "JAVA_OPTS",
              String.format("%s -Xrunjdwp:transport=dt_socket,address=%s,server=y,suspend=n -javaagent:%s", JAVA_OPTS,
                      DEBUG_PORT, CLASS_HIDING_JAVA_AGENT).trim());

      process = builder.start();

      logger.log(Type.INFO, "Redirecting stdout and stderr to share with this process");
      inheritIO(process.getInputStream(), System.out);
      inheritIO(process.getErrorStream(), System.err);

      logger.log(Type.INFO, "Executing AS instance...");
    }
    catch (IOException e) {
      logger.log(TreeLogger.Type.ERROR, "Failed to start JBoss AS process", e);
      logger.unbranch();
      throw new UnableToCompleteException();
    }

    logger.unbranch();

    logger.branch(Type.INFO, "Creating servlet container controller...");

    try {
      JBossServletContainerAdaptor controller = new JBossServletContainerAdaptor(port, appRootDir, DEPLOYMENT_CONTEXT,
              logger.peek(), process);
      logger.log(Type.INFO, "Controller created");
      logger.unbranch();
      return controller;
    }
    catch (UnableToCompleteException e) {
      logger.log(Type.ERROR, "Could not start servlet container controller", e);
      throw new UnableToCompleteException();
    }
  }

  private void validateClassHidingJavaAgent(final String CLASS_HIDING_JAVA_AGENT) throws UnableToCompleteException {
    if (CLASS_HIDING_JAVA_AGENT == null) {
      logger.log(
              Type.ERROR,
              String.format(
                      "The local path to the artifact errai.org.jboss:class-local-class-hider:jar must be given as the property %s",
                      CLASS_HIDING_JAVA_AGENT_PROPERTY));
      throw new UnableToCompleteException();
    }
  }

  private void validateJbossHome(final String JBOSS_HOME) throws UnableToCompleteException {
    if (JBOSS_HOME == null || JBOSS_HOME.equals("")) {
      logger.log(
              Type.ERROR,
              String.format(
                      "No value for %s was given: The root directory of your Jboss installation must be provided through the property %s in your pom.xml",
                      JBOSS_HOME_PROPERTY, JBOSS_HOME_PROPERTY));
      throw new UnableToCompleteException();
    }
   
    /*
     * Check that start script and configuration folder exist.
     */
    final File[] files = new File[] {
            new File(JBOSS_HOME),
            new File(getStartScriptName(JBOSS_HOME)),
            new File(JBOSS_HOME, STANDALONE_CONFIGURATION)
    };
   
    boolean isValid = true;
    for (int i = 0; i < files.length; i++) {
      if (!files[i].exists()) {
        isValid = false;
        break;
      }
    }
   
    if (!isValid) {
      logger.branch(Type.ERROR, String.format("The errai.jboss.home directory, %s, does not appear to be home to a Jboss or Wildfly instance.", JBOSS_HOME));
     
      for (int i = 0; i < files.length; i++) {
        if (!files[i].exists()) {
          logger.log(Type.ERROR, String.format("%s not found.", files[i].getAbsolutePath()));
        }
      }
      logger.unbranch();
     
      throw new UnableToCompleteException();
    }
  }

  private void createTempConfigFile(String fromName, String toName, String jBossHome, int port) throws IOException,
          UnableToCompleteException {
    File configDir = new File(jBossHome, STANDALONE_CONFIGURATION);
    File from = new File(configDir, fromName);
    File to = new File(configDir, toName);

    if (!from.exists()) {
      logger.log(
              Type.ERROR,
              String.format(
                      "Config file %s does not exit. It must be created or another one must be specified with the %s JVM property.",
                      from.getAbsolutePath(), TEMPLATE_CONFIG_FILE_PROPERTY));
      throw new UnableToCompleteException();
    }

    if (to.exists()) {
      logger.log(Type.WARN,
              String.format("Temporary config file %s already exists and will be deleted", to.getAbsolutePath()));
      to.delete();
    }

    to.createNewFile();
    to.deleteOnExit();

    InputStream inStream = new FileInputStream(from);
    OutputStream outStream = new FileOutputStream(to);

    // Replace default http port with provided port
    SimpleTranslator trans = new SimpleTranslator();
    trans.addFilter(new Tag("socket-binding", new AttributeEntry("name", "http")));
    trans.addNewTag("socket-binding-group", new Tag("socket-binding", new AttributeEntry("name", "http"),
            new AttributeEntry("port", String.valueOf(port))));

    try {
      trans.translate(inStream, outStream);
    }
    catch (XMLStreamException e) {
      logger.log(Type.ERROR, "Could not create copy of configuration from " + from.getAbsolutePath(), e);
      throw new UnableToCompleteException();
    }
    finally {
      inStream.close();
      outStream.close();
    }
  }

  private String getStartScriptName(String jbossHome) {
    final String script = System.getProperty("os.name").toLowerCase().contains("windows") ? "standalone.bat"
            : "standalone.sh";

    return String.format("%s%cbin%c%s", jbossHome, File.separatorChar, File.separatorChar, script);
  }

  private void inheritIO(final InputStream in, final OutputStream to) {
    new Thread() {
      @Override
      public void run() {
        try {
          IOUtils.copy(in, to);
        }
        catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    }.start();
  }
}
TOP

Related Classes of org.jboss.errai.cdi.server.gwt.JBossLauncher

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.