All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jayway.maven.plugins.android.AbstractEmulatorMojo Maven / Gradle / Ivy

/*
 * Copyright (C) 2009, 2010 Jayway AB
 * Copyright (C) 2007-2008 JVending Masa
 *
 * 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 com.jayway.maven.plugins.android;

import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.MojoExecutionException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;


/**
 * AbstractEmulatorMojo contains all code related to the interaction with the Android emulator. At this stage that is
 * starting and stopping the emulator.
 *
 * @author Manfred Moser 
 * @see com.jayway.maven.plugins.android.Emulator
 * @see com.jayway.maven.plugins.android.standalonemojos.EmulatorStartMojo
 * @see com.jayway.maven.plugins.android.standalonemojos.EmulatorStopMojo
 */
public abstract class AbstractEmulatorMojo extends AbstractAndroidMojo {

    /**
     * operating system name.
     */
    public static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.US);

    /**
     * The Android emulator configuration to use. All values are optional.
     * <emulator>
     * <avd>Default</avd>
     * <wait>20000</wait>
     * <options>-no-skin</options>
     * </emulator>
     * 
* * @parameter */ private Emulator emulator; /** * Name of the Android Virtual Device (emulatorAvd) that will be started by the emulator. Default value is "Default" * * @parameter expression="${android.emulator.avd}" * @readonly * @see Emulator#avd */ private String emulatorAvd; /** * Wait time for the emulator start up. * * @parameter expression="${android.emulator.wait}" * @readonly * @see Emulator#wait */ private String emulatorWait; /** * Additional command line options for the emulator start up. This option can be used to pass any additional * options desired to the invocation of the emulator. Use emulator -help for more details. An example would be * "-no-skin". * * @parameter expression="${android.emulator.options}" * @readonly * @see Emulator#options */ private String emulatorOptions; /** * parsed value for avd that will be used for the invocation. */ private String parsedAvd; /** * parsed value for options that will be used for the invocation. */ private String parsedOptions; /** * parsed value for wait that will be used for the invocation. */ private String parsedWait; private static final String STOP_EMULATOR_MSG = "Stopping android emulator with pid: "; private static final String START_EMULATOR_MSG = "Starting android emulator with script: "; private static final String START_EMULATOR_WAIT_MSG = "Waiting for emulator start:"; private static final String NO_EMULATOR_RUNNING = "unknown"; private static final String NO_DEMON_RUNNING_MACOSX = "* daemon not running"; /** * Folder that contains the startup script and the pid file. */ private static final String scriptFolder = System.getProperty("java.io.tmpdir"); /** * file name for the pid file. */ private static final String pidFileName = scriptFolder + System.getProperty("file.separator") + "maven-android-plugin-emulator.pid"; /** * Are we running on a flavour of Windows. * * @return */ private boolean isWindows() { boolean result; if (OS_NAME.toLowerCase().contains("windows")) { result = true; } else { result = false; } getLog().debug("isWindows: " + result); return result; } /** * Start the Android Emulator with the specified options. * * @throws org.apache.maven.plugin.MojoExecutionException * * @see #emulatorAvd * @see #emulatorWait * @see #emulatorOptions */ protected void startAndroidEmulator() throws MojoExecutionException { parseParameters(); CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor(); executor.setLogger(this.getLog()); try { String filename; if (isWindows()) { filename = writeEmulatorStartScriptWindows(); } else { filename = writeEmulatorStartScriptUnix(); } String emulatorName = getRunningEmulatorName(); // normally only #NO_EMULATOR_RUNNING is returned // however when starting emulator within intellij on macosx with launchd configuration the first time // #NO_DEMON_RUNNING_MACOSX is the start of the first line but needs to be treated the same if (emulatorName.equals(NO_EMULATOR_RUNNING) || emulatorName.startsWith(NO_DEMON_RUNNING_MACOSX)) { getLog().info(START_EMULATOR_MSG + filename); executor.executeCommand(filename, null); getLog().info(START_EMULATOR_WAIT_MSG + parsedWait); // wait for the emulator to start up Thread.sleep(new Long(parsedWait)); } else { getLog().info("Emulator " + emulatorName + " already running. Skipping start and wait."); } } catch (Exception e) { throw new MojoExecutionException("", e); } } /** * Get the name of the running emulator. * * @return emulator name or "unknown" if none found running with adb tool. * @throws MojoExecutionException * @throws ExecutionException * @see #NO_EMULATOR_RUNNING */ private String getRunningEmulatorName() throws MojoExecutionException, ExecutionException { CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor(); executor.setLogger(this.getLog()); List commands = new ArrayList(); commands.add("-e"); commands.add("get-serialno"); executor.executeCommand(getAndroidSdk().getAdbPath(), commands); return executor.getStandardOut(); } /** * Writes the script to start the emulator in the background for windows based environments. This is not fully * operational. Need to implement pid file write. * * @return absolute path name of start script * @throws IOException * @throws MojoExecutionException * @see "http://stackoverflow.com/questions/2328776/how-do-i-write-a-pidfile-in-a-windows-batch-file" */ private String writeEmulatorStartScriptWindows() throws MojoExecutionException { String filename = scriptFolder + "\\maven-android-plugin-emulator-start.vbs"; File file = new File(filename); PrintWriter writer = null; try { writer = new PrintWriter(new FileWriter(file)); // command needs to be assembled before unique window title since it parses settings and sets up parsedAvd // and others. String command = assembleStartCommandLine(); String uniqueWindowTitle = "MavenAndroidPlugin-AVD" + parsedAvd; writer.println("Dim oShell"); writer.println("Set oShell = WScript.CreateObject(\"WScript.shell\")"); String cmdPath = System.getenv("COMSPEC"); if (cmdPath == null){ cmdPath = "cmd.exe"; } String cmd = cmdPath + " /X /C START /SEPARATE \"\"" + uniqueWindowTitle + "\"\" " + command.trim(); writer.println("oShell.run \"" + cmd + "\""); writer.println("wscript.sleep 1000"); String cmd1 = cmdPath + " /X /C @ECHO OFF & FOR /F \"\"tokens=2\"\" %I in ('%WINDIR%\\SYSTEM32\\TASKLIST.EXE /NH /FI \"\"WINDOWTITLE eq " + uniqueWindowTitle + "\"\"') DO ECHO %I> " + pidFileName; writer.println("oShell.run \"" + cmd1 + "\""); } catch (IOException e) { getLog().error("Failure writing file " + filename); } finally { if (writer != null) { writer.flush(); writer.close(); } } file.setExecutable(true); return filename; } /** * Writes the script to start the emulator in the background for unix based environments and write process id into * pidfile. * * @return absolute path name of start script * @throws IOException * @throws MojoExecutionException */ private String writeEmulatorStartScriptUnix() throws MojoExecutionException { String filename = scriptFolder + "/maven-android-plugin-emulator-start.sh"; File sh; sh = new File("/bin/bash"); if (!sh.exists()) { sh = new File("/usr/bin/bash"); } if (!sh.exists()) { sh = new File("/bin/sh"); } File file = new File(filename); PrintWriter writer = null; try { writer = new PrintWriter(new FileWriter(file)); writer.println("#!" + sh.getAbsolutePath()); writer.print(assembleStartCommandLine()); writer.print(" 1>/dev/null 2>&1 &"); // redirect outputs and run as background task writer.println(); writer.println("echo $! > " + pidFileName); // process id from stdout into pid file } catch (IOException e) { getLog().error("Failure writing file " + filename); } finally { if (writer != null) { writer.flush(); writer.close(); } } file.setExecutable(true); return filename; } /** * Stop the running Android Emulator. * * @throws org.apache.maven.plugin.MojoExecutionException * */ protected void stopAndroidEmulator() throws MojoExecutionException { parseParameters(); CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor(); executor.setLogger(this.getLog()); FileReader fileReader = null; BufferedReader bufferedReader = null; try { fileReader = new FileReader(pidFileName); bufferedReader = new BufferedReader(fileReader); String pid; pid = bufferedReader.readLine(); // just read the first line, don't worry about anything else if (isWindows()) { stopEmulatorWindows(executor, pid); } else { stopEmulatorUnix(executor, pid); } } catch (Exception e) { throw new MojoExecutionException("", e); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { getLog().error("Failure closing reader"); } } if (fileReader != null) { try { fileReader.close(); } catch (IOException e) { getLog().error("Failure closing reader"); } } } } /** * Stop the emulator by using the taskkill command. * * @param executor * @param pid * @throws ExecutionException */ private void stopEmulatorWindows(CommandExecutor executor, String pid) throws ExecutionException { String stopCommand = "%WINDIR%\\SYSTEM32\\TASKKILL"; // this assumes that the command is on the path List commands = new ArrayList(); // separate the commands as per the command line interface commands.add("/PID"); commands.add(pid); getLog().info(STOP_EMULATOR_MSG + pid); executor.executeCommand(stopCommand, commands); } /** * Stop the emulator under Unix by using the kill command. * * @param executor * @param pid * @throws ExecutionException */ private void stopEmulatorUnix(CommandExecutor executor, String pid) throws ExecutionException { String stopCommand = "kill"; List commands = new ArrayList(); commands.add(pid); getLog().info(STOP_EMULATOR_MSG + pid); executor.executeCommand(stopCommand, commands); } /** * Assemble the command line for starting the emulator based on the parameters supplied in the pom file and on the * command line. It should not be that painful to do work with command line and pom supplied values but evidently * it is. * * @return * @throws MojoExecutionException * @see com.jayway.maven.plugins.android.Emulator */ private String assembleStartCommandLine() throws MojoExecutionException { StringBuilder startCommandline = new StringBuilder() .append(getAndroidSdk().getEmulatorPath()) .append(" -avd ") .append(parsedAvd) .append(" "); if (!StringUtils.isEmpty(parsedOptions)) { startCommandline.append(parsedOptions); } getLog().info("Android emulator command: " + startCommandline); return startCommandline.toString(); } private void parseParameters() { // exist in pom file if (emulator != null) { // exists in pom file if (emulator.getAvd() != null) { parsedAvd = emulator.getAvd(); } else { parsedAvd = determineAvd(); } // exists in pom file if (emulator.getOptions() != null) { parsedOptions = emulator.getOptions(); } else { parsedOptions = determineOptions(); } // exists in pom file if (emulator.getWait() != null) { parsedWait = emulator.getWait(); } else { parsedWait = determineWait(); } } // commandline options else { parsedAvd = determineAvd(); parsedOptions = determineOptions(); parsedWait = determineWait(); } } /** * Get wait value for emulator from command line option. * * @return if available return command line value otherwise return default value (5000). */ private String determineWait() { String wait; if (emulatorWait != null) { wait = emulatorWait; } else { wait = "5000"; } return wait; } /** * Get options value for emulator from command line option. * * @return if available return command line value otherwise return default value (""). */ private String determineOptions() { String options; if (emulatorOptions != null) { options = emulatorOptions; } else { options = ""; } return options; } /** * Get avd value for emulator from command line option. * * @return if available return command line value otherwise return default value ("Default"). */ private String determineAvd() { String avd; if (emulatorAvd != null) { avd = emulatorAvd; } else { avd = "Default"; } return avd; } }



© 2015 - 2024 Weber Informatics LLC | Privacy Policy