Package net.kindleit.gae

Source Code of net.kindleit.gae.EngineGoalBase

/* Copyright 2009 Kindleit.net Software Development
*
* 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 net.kindleit.gae;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;

import com.google.appengine.tools.KickStart;
import com.google.appengine.tools.admin.AppCfg;


/** Base MOJO class for working with the Google App Engine SDK.
*
* @author rhansen@kindleit.net
*/
public abstract class EngineGoalBase extends AbstractMojo {

  private static final String GAE_PROPS = "gae.properties";

  protected static final String[] ARG_TYPE = new String[0];

  /** The Maven project reference.
   *
   * @parameter expression="${project}"
   * @required
   * @readonly
   */
  protected MavenProject project;

  /** The Maven settings reference.
  *
  * @parameter expression="${settings}"
  * @required
  * @readonly
  */
protected Settings settings;

  /** Overrides where the Project War Directory is located.
   *
   * @parameter expression="${project.build.directory}/${project.build.finalName}"
   * @required
   */
  protected String appDir;

  /** Specifies where the Google App Engine SDK is located.
  *
  * @parameter expression="${gae.home}" default-value="${settings.localRepository}/com/google/appengine/appengine-java-sdk/${gae.version}/appengine-java-sdk-${gae.version}"
  * @required
  */
protected String sdkDir;

  /** Split large jar files (> 10M) into smaller fragments.
   *
   * @parameter expression="${gae.deps.split}" default-value="false"
   */
  protected boolean splitJars;

  /** The username to use. Will prompt if omitted.
   *
   * @parameter expression="${gae.email}"
   * @deprecated use maven settings.xml/server/username and "serverId" parameter
   */
  @Deprecated
  protected String emailAccount;

  /** The server id in maven settings.xml to use for emailAccount(username)
   * and password when connecting to GAE.
   *
   * If password present in settings "--passin" is set automatically.
   *
   * @parameter expression="${gae.serverId}"
   */
  protected String serverId;

  /** The server to connect to.
   *
   * @parameter expression="${gae.server}"
   */
  protected String uploadServer;

  /** Overrides the Host header sent with all RPCs.
   *
   * @parameter expression="${gae.host}"
   */
  protected String hostString;

  /** Do not delete temporary directory used in uploading.
   *
   * @parameter expression="${gae.keepTemps}" default-value="false"
   */
  protected boolean keepTempUploadDir;

  /** Always read the login password from stdin.
   *
   * @parameter expression="${gae.passin}" default-value="false"
   */
  protected boolean passIn;

  /** Tell AppCfg to use a proxy.
   *
   * By default will use first active proxy in maven settings.xml
   *
   * @parameter expression="${gae.proxy}"
   */
  protected String proxy;

  protected Properties gaeProperties;

  public EngineGoalBase() {
    gaeProperties = new Properties();
    try {
      gaeProperties.load(EngineGoalBase.class.getResourceAsStream(GAE_PROPS));
    } catch (final IOException e) {
      throw new RuntimeException("Unable to load version", e);
    }
  }

  protected boolean hasServerSettings() {
      if (serverId == null) {
          return false;
      } else {
          final Server srv = settings.getServer(serverId);
          return srv != null;
      }
  }

  /** Passes command to the Google App Engine AppCfg runner.
  *
  * @param command command to run through AppCfg
  * @param commandArguments arguments to the AppCfg command.
   * @throws MojoExecutionException If {@link #assureSystemProperties()} fails
  */
  protected final void runAppCfg(final String command,
      final String ... commandArguments) throws MojoExecutionException {

    final List<String> args = new ArrayList<String>();
    args.addAll(getAppCfgArgs());
    args.add(command);
    args.addAll(Arrays.asList(commandArguments));
    assureSystemProperties();

    getLog().debug("execute AppCfg " + args.toString());

    if (hasServerSettings() && settings.getServer(serverId).getPassword() != null) {
        forkPasswordExpectThread(args.toArray(ARG_TYPE),
            settings.getServer(serverId).getPassword());
    } else {
        AppCfg.main(args.toArray(ARG_TYPE));
    }
  }

  private void forkPasswordExpectThread(final String[] args, final String password) {
      getLog().info("Use Settings configuration from server id {" + serverId + "}");
      // Parent for all threads created by AppCfg
      final ThreadGroup threads = new ThreadGroup("AppCfgThreadGroup");

       // Main execution Thread that belong to ThreadGroup threads
      final Thread thread = new Thread(threads, "AppCfgMainThread") {

          @Override
          public void run() {
              final PrintStream outOrig = System.out;
              final InputStream inOrig = System.in;

              final PipedInputStream inReplace = new PipedInputStream();
              OutputStream stdin;
              try {
                stdin = new PipedOutputStream(inReplace);
              } catch (final IOException e) {
                  getLog().error("Unable to redirect input", e);
                  return;
              }
              System.setIn(inReplace);

              final BufferedWriter stdinWriter = new BufferedWriter(new OutputStreamWriter(stdin));

              System.setOut(new PrintStream(new PasswordExpectOutputStream(threads, outOrig, new Runnable() {
                public void run() {
                    try {
                        stdinWriter.write(password);
                        stdinWriter.newLine();
                        stdinWriter.flush();
                    } catch (final IOException e) {
                        getLog().error("Unable to enter password", e);
                    }
                }}), true));

              try {
                  AppCfg.main(args);
              } catch (final Throwable e) {
                  getLog().error("Unable to execute AppCfg", e);
              } finally {
                  System.setOut(outOrig);
                  System.setIn(inOrig);
              }
          }
      };
      thread.start();
      try {
          thread.join();
      } catch (final InterruptedException e) {
          getLog().error("Interrupted waiting for process supervisor thread to finish", e);
      }
  }

  /** Passes command to the Google App Engine KickStart runner.
  *
  * @param startClass command to run through KickStart
  * @param commandArguments arguments to the KickStart command.
  * @throws MojoExecutionException If {@link #assureSystemProperties()} fails
  */
  protected final void runKickStart(final String startClass,
    final String ... commandArguments) throws MojoExecutionException {

    final List<String> args = new ArrayList<String>();
    args.add(startClass);
    args.addAll(getCommonArgs());
    args.addAll(Arrays.asList(commandArguments));

    assureSystemProperties();
    KickStart.main(args.toArray(ARG_TYPE));
  }





  /** Groups alterations to System properties for the proper execution
   * of the actual GAE code.
   * @throws MojoExecutionException When the gae.home variable cannot be set. */
  protected void assureSystemProperties() throws MojoExecutionException {
    // explicitly specify SDK root, as auto-discovery fails when
    // appengine-tools-api.jar is loaded from Maven repo, not SDK
    String sdk = System.getProperty("appengine.sdk.root");
    if (sdk == null) {
      if (sdkDir == null) {
        throw new MojoExecutionException(this, "${gae.home} property not set",
            gaeProperties.getProperty("home_undefined"));
      }
      System.setProperty("appengine.sdk.root", sdk = sdkDir);
    }

    if (!new File(sdk).isDirectory()) {
      throw new MojoExecutionException(this, "${gae.home} is not a directory",
          gaeProperties.getProperty("home_invalid"));
    }


    // hack for getting appengine-tools-api.jar on a runtime classpath
    // (KickStart checks java.class.path system property for classpath entries)
    final String classpath = System.getProperty("java.class.path");
    final String toolsJar = sdkDir + "/lib/appengine-tools-api.jar";
    if (!classpath.contains(toolsJar)) {
      System.setProperty("java.class.path",
          classpath + File.pathSeparator + toolsJar);
    }
  }

  /** Generate all common Google AppEngine Task Parameters for use in all the
   * goals.
   *
   * @return List of arguments to add.
   */
  protected final List<String> getAppCfgArgs () {
    final List<String> args = getCommonArgs();

    addBooleanOption(args, "--disable_prompt", !settings.getInteractiveMode());
    addEmailOption(args);
    addStringOption(args, "--host=", hostString);
    addProxyOption(args);
    addBooleanOption(args, "--passin", passIn);
    addBooleanOption(args, "--enable_jar_splitting", splitJars);
    addBooleanOption(args, "--retain_upload_dir", keepTempUploadDir);

    return args;
  }

  protected final List<String> getCommonArgs() {
    final List<String> args = new ArrayList<String>(8);

    args.add("--sdk_root=" + sdkDir);
    addStringOption(args, "--server=", uploadServer);

    return args;
  }

  private void addEmailOption(final List<String> args) {
    if (hasServerSettings() && emailAccount == null) {
        addStringOption(args, "--email=",
            settings.getServer(serverId).getUsername());
        if (settings.getServer(serverId).getPassword() != null) {
            // Force GAE tools to read from System.in instead of System.console()
            passIn = true;
        }
    } else {
        addStringOption(args, "--email=", emailAccount);
    }
  }

  private void addProxyOption(final List<String> args) {
    if (hasServerSettings() && proxy == null) {
        final Proxy activCfgProxy = settings.getActiveProxy();
        if (activCfgProxy != null) {
            addStringOption(args, "--proxy=",
                activCfgProxy.getHost() + ":" + activCfgProxy.getPort());
        }
    } else {
        addStringOption(args, "--proxy=", proxy);
    }
  }

  private final void addBooleanOption(final List<String> args, final String key,
      final boolean var) {
    if (var) {
      args.add(key);
    }
  }

  private final void addStringOption(final List<String> args, final String key,
      final String var) {
    if (var != null && var.length() > 0) {
      args.add(key + var);
    }
  }

}
TOP

Related Classes of net.kindleit.gae.EngineGoalBase

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.