org.codehaus.mojo.javascript.titanium.TitaniumUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.mojo.javascript.titanium.TitaniumUtils.java

Source

/*
 * Copyright 2011 SOFTEC sa. All rights reserved.
 *
 * This source code is licensed under the Creative Commons
 * Attribution-NonCommercial-NoDerivs 3.0 Luxembourg
 * License.
 *
 * To view a copy of this license, visit
 * http://creativecommons.org/licenses/by-nc-nd/3.0/lu/
 * or send a letter to Creative Commons, 171 Second Street,
 * Suite 300, San Francisco, California, 94105, USA.
 */

package org.codehaus.mojo.javascript.titanium;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.codehaus.mojo.javascript.TitaniumPackageMojo;
import org.codehaus.mojo.javascript.TitaniumSettings;
import org.codehaus.mojo.javascript.VirtualDevice;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Titanium utility class.
 * Contains helper methods related to Titanium.
 */
public class TitaniumUtils {
    /**
     * The android home environment variable name.
     */
    public static final String ENV_ANDROID_HOME = "ANDROID_HOME";

    /**
     * Retrieve the Android SDK home folder based on the ANDROID_HOME environment variable.
     * @return The android SDK home folder.
     * @throws MojoExecutionException When the android environment is not specified.
     */
    public static String getAndroidHome() throws MojoExecutionException {
        final String androidHome = System.getenv(ENV_ANDROID_HOME);
        if (androidHome == null || androidHome.isEmpty()) {
            throw new MojoExecutionException(
                    "No Android SDK path could be found. You may configure it by setting the " + ENV_ANDROID_HOME
                            + " environment variable.");
        }
        final File androidHomeFile = new File(androidHome);
        if (!androidHomeFile.exists() || !androidHomeFile.isDirectory()) {
            throw new MojoExecutionException("The android SDK path is not valid");
        }
        return androidHome;
    }

    /**
     * Retrieve the list of the available platforms for the specified Android SDK folder.
     * @param androidSdkHome The Android SDK home folder.
     * @return A list of android API version.
     * @throws MojoExecutionException When the android SDK folder doesn't exist.
     */
    public static List<Integer> getAvailableAndroidPlatformVersions(File androidSdkHome)
            throws MojoExecutionException {
        if (androidSdkHome == null) {
            throw new MojoExecutionException("No android SDK home folder specified");
        }
        if (!androidSdkHome.exists()) {
            throw new MojoExecutionException(
                    "The specified android SDK home folder doesn't exist: " + androidSdkHome.getAbsolutePath());
        }
        if (!androidSdkHome.isDirectory()) {
            throw new MojoExecutionException(
                    "The specified android sdk location is not a folder: " + androidSdkHome.getAbsolutePath());
        }
        File sdk = new File(androidSdkHome, "platforms");
        Pattern pattern = Pattern.compile("android-([0-9]+)");
        List<Integer> result = new ArrayList<Integer>();
        File[] sdkFiles = sdk.listFiles();
        if (sdkFiles != null) {
            for (File file : sdkFiles) {
                if (file.isDirectory() && file.getName().startsWith("android-")) {
                    Matcher matcher = pattern.matcher(file.getName());
                    if (matcher.find()) {
                        result.add(new Integer(matcher.group(1)));
                    }
                }
            }
        }
        Collections.sort(result);
        return result;
    }

    /**
     * Retrieve the latest android API version of the specified android SDK
     * @param androidSdkHome The android SDK home folder.
     * @return The latest android API version
     * @throws MojoExecutionException When The androidSdkHome is not valid.
     */
    public static String getLatestAndroidPlatformVersion(File androidSdkHome) throws MojoExecutionException {
        List<Integer> platforms = getAvailableAndroidPlatformVersions(androidSdkHome);
        Integer lastVersion = platforms.get(platforms.size() - 1);
        return lastVersion.toString();
    }

    public static boolean isAndroidEmulatorRunning(File androidSdkHome) throws IOException {
        if (androidSdkHome == null) {
            return false;
        }

        File adb = new File(androidSdkHome, "platform-tools" + File.separator + "adb");
        if (!adb.exists()) {
            return false;
        }

        boolean isEmulatorRunning = false;

        ProcessBuilder pb = new ProcessBuilder(adb.getAbsolutePath(), "devices");
        pb.redirectErrorStream(true);
        Process p = pb.start();

        BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line = null;

        while ((line = reader.readLine()) != null) {
            line = line.trim();
            if (line.startsWith("List of devices")) {
                continue;
            } else if (line.startsWith("emulator-")) {
                String[] tokens = line.split("\\s");
                String name = tokens[0];
                String status = tokens[1];
                int port = Integer.parseInt(name.substring(name.indexOf("-") + 1));
                if (status.equals("device") && port == 5560) {
                    isEmulatorRunning = true;
                }
            }
        }

        return isEmulatorRunning;

    }

    /**
     * Create a new Android AVD.
     *
     * @param androidSdkHome The android SDK home folder.
     * @param avdId The android API version.
     * @param skin The skin of the emulator.
     * @param log The logging system.
     * @return true if the avd was successfully created, false if the avd already existed.
     * @throws MojoExecutionException When an error occured during the AVD creation.
     */
    public static boolean createAvd(File androidSdkHome, String avdId, String skin, Log log)
            throws MojoExecutionException {
        String avdName = "titanium_" + avdId + "_" + skin;

        String homeDir = System.getProperty("user.home");
        File avdDir = new File(homeDir, ".android" + File.separator + "avd" + File.separator + avdName + ".avd");

        if (!avdDir.exists()) {
            File androidCmd = new File(androidSdkHome, "tools" + File.separator + "android");
            File sdCard = new File(homeDir, ".titanium" + File.separatorChar + avdName + ".sdcard");

            createSdCard(androidSdkHome, sdCard, "64M");
            ProcessBuilder pb = new ProcessBuilder(androidCmd.getAbsolutePath(), "--verbose", "create", "avd", "-n",
                    avdName, "-t", avdId, "-s", skin, "--force", "--sdcard", sdCard.getAbsolutePath());

            try {
                Process p = pb.start();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
                //log.info("Start create AVD");
                //TitaniumPackageMojo.logProcess(p, log);
                log.info("Sending no");
                writer.write("no");
                writer.write("\n");
                writer.flush();
                TitaniumBuilder.logProcess(p, log);
                p.waitFor();
            } catch (IOException ioe) {
                throw new MojoExecutionException("Error while creating avd", ioe);
            } catch (InterruptedException ie) {
                throw new MojoExecutionException("Error while creating avd", ie);
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * Create a new SD Card.
     *
     * @param androidSdkHome The android SDK home folder.
     * @param sdCard The SD card file name.
     * @param size The size of the SD Card (i.e.: 64M)
     * @throws MojoExecutionException When an error occured while creating the SD card.
     */
    private static void createSdCard(File androidSdkHome, File sdCard, String size) throws MojoExecutionException {
        File mkSdCardCmd = new File(androidSdkHome, "tools" + File.separatorChar + "mksdcard");

        ProcessBuilder pb = new ProcessBuilder(mkSdCardCmd.getAbsolutePath(), size, sdCard.getAbsolutePath());

        try {
            pb.start().waitFor();
        } catch (Throwable t) {
            throw new MojoExecutionException("Error while creating AVD SDCard", t);
        }
    }

    private static boolean isWindows() {
        return isOs("win");
    }

    private static boolean isMac() {
        return isOs("mac");
    }

    private static boolean isUnix() {
        return (isOs("nix") || isOs("nux"));
    }

    private static boolean isOs(final String osName) {
        final String os = System.getProperty("os.name").toLowerCase();
        return (os.indexOf(osName) >= 0);
    }

    public static String getOsClassifier() {
        if (isWindows()) {
            return "win32";
        } else if (isMac()) {
            return "osx";
        } else if (isUnix()) {
            return "linux";
        } else {
            return "";
        }
    }

    public static String getTitaniumSdkPath(String version) {
        final String homeFolder = System.getProperty("user.home");
        String sdkPath = null;
        File sdkFile = null;

        if (isMac()) {
            sdkPath = homeFolder + "/Library/Application Support/Titanium/mobilesdk/osx/" + version + "/";
            sdkFile = new File(sdkPath);
            if (!sdkFile.exists()) {
                sdkPath = "/Library/Application Support/Titanium/mobilesdk/osx/" + version + "/";
                sdkFile = new File(sdkPath);
                if (!sdkFile.exists()) {
                    sdkPath = null;
                }
            }
        } else if (isWindows()) {
            final String userProfileFolder = System.getenv("ALLUSERSPROFILE");
            sdkPath = userProfileFolder + "\\Titanium\\mobilesdk\\win32\\" + version + "\\";
            sdkFile = new File(sdkPath);
            if (!sdkFile.exists()) {
                sdkPath = "C:\\Documents and Settings\\All Users\\Application Data\\Titanium\\mobilesdk\\win32\\"
                        + version + "\\";
                sdkFile = new File(sdkPath);
                if (!sdkFile.exists()) {
                    sdkPath = null;
                }
            }
        } else if (isUnix()) {
            sdkPath = homeFolder + "/.titanium/mobilesdk/linux/" + version + "/";
            sdkFile = new File(sdkPath);
            if (!sdkFile.exists()) {
                sdkPath = null;
            }
        }

        return sdkPath;
    }

    public static List<String> getAvailableTitaniumSdkVersions() {
        String basePath = getTitaniumBaseSdkPath();
        if (basePath == null) {
            return null;
        }

        File baseFolder = new File(basePath);
        File[] files = baseFolder.listFiles();
        if (files != null && files.length > 0) {
            List<String> versions = new ArrayList<String>();
            for (File f : files) {
                if (f.isDirectory()) {
                    versions.add(f.getName());
                }
            }
            if (!versions.isEmpty()) {
                return versions;
            }
        }
        return null;
    }

    public static String getLatestAvailableTitaniumSdkVersion() {
        List<String> versions = getAvailableTitaniumSdkVersions();
        if (versions != null) {
            Collections.sort(versions);
            return versions.get(versions.size() - 1);
        }
        return null;
    }

    public static String getTitaniumBaseSdkPath() {
        final String homeFolder = System.getProperty("user.home");
        String sdkPath = null;
        File sdkFile = null;

        if (isMac()) {
            sdkPath = homeFolder + "/Library/Application Support/Titanium/mobilesdk/osx/";
            sdkFile = new File(sdkPath);
            if (!sdkFile.exists()) {
                sdkPath = "/Library/Application Support/Titanium/mobilesdk/osx/";
                sdkFile = new File(sdkPath);
                if (!sdkFile.exists()) {
                    sdkPath = null;
                }
            }
        } else if (isWindows()) {
            final String userProfileFolder = System.getenv("ALLUSERSPROFILE");
            sdkPath = userProfileFolder + "\\Titanium\\mobilesdk\\win32\\";
            sdkFile = new File(sdkPath);
            if (!sdkFile.exists()) {
                sdkPath = "C:\\Documents and Settings\\All Users\\Application Data\\Titanium\\mobilesdk\\win32\\";
                sdkFile = new File(sdkPath);
                if (!sdkFile.exists()) {
                    sdkPath = null;
                }
            }
        } else if (isUnix()) {
            sdkPath = homeFolder + "/.titanium/mobilesdk/linux/";
            sdkFile = new File(sdkPath);
            if (!sdkFile.exists()) {
                sdkPath = null;
            }
        }

        return sdkPath;
    }

    public static String getTitaniumArtifactSdkPath(String version, File targetDir) {
        File sdkPath = new File(targetDir,
                "mobilesdk" + File.separator + TitaniumUtils.getOsClassifier() + File.separator + version);

        if (sdkPath.exists()) {
            return sdkPath.getAbsolutePath();
        } else {
            return null;
        }
    }

    public static boolean isAndroidVersionValid(File androidSdkHome, String version) throws MojoExecutionException {
        List<Integer> versions = getAvailableAndroidPlatformVersions(androidSdkHome);
        for (Integer v : versions) {
            if (v.toString().equals(version)) {
                return true;
            }
        }
        return false;
    }

    public static void checkVirtualDevice(String platform, TitaniumSettings settings, VirtualDevice virtualDevice)
            throws MojoExecutionException {
        if (platform.equals("android")) {
            if (virtualDevice.getAndroidAPI() == null) {
                virtualDevice.setAndroidAPI(getLatestAndroidPlatformVersion(settings.getAndroidSdk()));
            } else {
                if (!isAndroidVersionValid(settings.getAndroidSdk(), virtualDevice.getAndroidAPI())) {
                    throw new MojoExecutionException("The specified android version is not present");
                }
            }

            if (virtualDevice.getSkin() == null) {
                if (new Integer(virtualDevice.getAndroidAPI()).intValue() < 10) {
                    virtualDevice.setSkin("HVGA");
                } else {
                    virtualDevice.setSkin("WXGA");
                }
            }
        } else if (platform.equals("iphone")) {
            if (virtualDevice.getFamily() == null) {
                virtualDevice.setFamily("iphone");
            }
        } else if (platform.equals("ipad")) {
            if (virtualDevice.getFamily() == null) {
                virtualDevice.setFamily("ipad");
            }
        } else if (platform.equals("universal")) {
            if (virtualDevice.getFamily() == null) {
                virtualDevice.setFamily("iphone");
            }
        }
    }

    public static boolean isIphoneVersionValid(String version) {
        List<String> platforms = listAvailableIosPlatformVersions();
        for (String platform : platforms) {
            if (platform.equals(version)) {
                return true;
            }
        }
        return false;
    }

    public static List<String> listAvailableIosPlatformVersions() {
        List<String> results = new ArrayList<String>();
        try {
            ProcessBuilder pb = new ProcessBuilder("xcodebuild", "-showsdks");
            pb.redirectErrorStream(true);
            Process p = pb.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = null;
            Pattern pattern = Pattern.compile("-sdk iphoneos(([0-9]+.?)+)");
            while ((line = reader.readLine()) != null) {
                Matcher m = pattern.matcher(line);
                while (m.find()) {
                    results.add(m.group(1));
                }
            }
        } catch (Throwable t) {
        }
        return results;
    }

    public static String getLatestIosPlatformVersion() {
        List<String> platforms = listAvailableIosPlatformVersions();
        if (!platforms.isEmpty()) {
            return platforms.get(0);
        }
        return "4.3";
    }
}