Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package hudson.plugins.android_emulator;
  
  import  hudson.EnvVars;
  import  hudson.Extension;
  import  hudson.FilePath;
  import  hudson.Launcher;
  import  hudson.Proc;
  import  hudson.Util;
  import  hudson.Launcher.ProcStarter;
 import  hudson.model.AbstractBuild;
 import  hudson.model.AbstractProject;
 import  hudson.model.BuildListener;
 import  hudson.model.Computer;
 import  hudson.model.Hudson;
 import  hudson.model.Result;
 import  hudson.model.TaskListener;
 import  hudson.tasks.BuildWrapper;
 import  hudson.tasks.BuildWrapperDescriptor;
 import  hudson.util.ArgumentListBuilder;
 import  hudson.util.FormValidation;
 
 import java.io.File;
 import java.util.List;
 import java.util.Map;
 
 
 import  org.jvnet.hudson.plugins.port_allocator.PortAllocationManager;
 
 public class AndroidEmulator extends BuildWrapper implements Serializable {
 
     private static final long serialVersionUID = 1L;

    
Duration by which the emulator should start being available via adb.
 
     private static final int ADB_CONNECT_TIMEOUT_MS = 60 * 1000;

    
Duration by which emulator booting should normally complete.
 
     private static final int BOOT_COMPLETE_TIMEOUT_MS = 120 * 1000;
 
     private DescriptorImpl descriptor;
 
     private transient final boolean useNamedEmulator;
     private final String avdName;
     private final String osVersion;
     private final String screenDensity;
     private final String screenResolution;
     private final String deviceLocale;
 
     public AndroidEmulator(String avdNameString osVersionString screenDensity,
                            String screenResolutionString deviceLocale) {
         this. = avdName;
         this. = osVersion;
         this. = screenDensity;
         this. = screenResolution;
         this. = deviceLocale;
         this. = avdName != null;
     }
 
     public boolean getUseNamedEmulator() {
         return ;
     }
 
     public String getOsVersion() {
         return ;
     }
 
     public String getAvdName() {
         return ;
     }
 
     public String getScreenDensity() {
         return ;
     }
 
     public String getScreenResolution() {
         return ;
     }
 
     public String getDeviceLocale() {
         return ;
     }
 
     @Override
     @SuppressWarnings("unchecked")
     public Environment setUp(AbstractBuild buildfinal Launcher launcher, BuildListener listener)
            throws IOExceptionInterruptedException {
        final PrintStream logger = listener.getLogger();
        if ( == null) {
             = Hudson.getInstance().getDescriptorByType(DescriptorImpl.class);
        }
        // Substitute environment and build variables into config
        final EnvVars localVars = Computer.currentComputer().getEnvironment();
        final EnvVars envVars = new EnvVars(localVars);
        envVars.putAll(build.getEnvironment(listener));
        final Map<StringStringbuildVars = build.getBuildVariables();
        String avdName = expandVariables(envVarsbuildVarsthis.);
        String osVersion = expandVariables(envVarsbuildVarsthis.);
        String screenDensity = expandVariables(envVarsbuildVarsthis.);
        String screenResolution = expandVariables(envVarsbuildVarsthis.);
        String deviceLocale = expandVariables(envVarsbuildVarsthis.);
        String androidHome = expandVariables(envVarsbuildVars.);
        androidHome = validateAndroidHome(launcherlocalVarsandroidHome);
        // Despite the nice inline checks and warnings when the user is editing the config,
        // these are not binding, so the user may have saved invalid configuration.
        // Here we check whether or not it's worth proceeding based on the saved values.
        String configError = isConfigValid(avdNameosVersionscreenDensityscreenResolutiondeviceLocale);
        if (configError != null) {
            log(logger, Messages.ERROR_MISCONFIGURED(configError));
            build.setResult(Result.NOT_BUILT);
            return null;
        }
        // Confirm that tools are available on PATH
        if (!validateAndroidToolsInPath(launcherandroidHome)) {
            log(logger, Messages.SDK_TOOLS_NOT_FOUND());
            build.setResult(Result.NOT_BUILT);
            return null;
        }
        // Ok, everything looks good.. let's go
        String displayHome = androidHome == null ? Messages.USING_PATH() : androidHome;
        log(logger, Messages.USING_SDK(displayHome));
        EmulatorConfig emuConfig = EmulatorConfig.create(avdNameosVersionscreenDensity,
                screenResolutiondeviceLocale);
        return doSetUp(buildlauncherloggerandroidHomeemuConfig);
    }
    private Environment doSetUp(final AbstractBuild<?, ?> buildfinal Launcher launcher,
            final PrintStream loggerfinal String androidHomefinal EmulatorConfig emuConfig)
                throws IOExceptionInterruptedException {
        // First ensure that emulator exists
        final Computer computer = Computer.currentComputer();
        final EnvVars environment = computer.getEnvironment();
        final boolean emulatorAlreadyExists;
        try {
            Callable<BooleanIOExceptiontask = emuConfig.getEmulatorCreationTask(androidHome);
            emulatorAlreadyExists = launcher.getChannel().call(task);
        } catch (FileNotFoundException ex) {
            log(logger, Messages.CANNOT_START_EMULATOR(ex.getMessage()));
            build.setResult(Result.NOT_BUILT);
            return null;
        }
        // Use the Port Allocator plugin to reserve the two ports we need
        final PortAllocationManager portAllocator = PortAllocationManager.getManager(computer);
        final int userPort = portAllocator.allocateRandom(build, 0);
        final int adbPort = portAllocator.allocateRandom(build, 0);
        // Compile complete command for starting emulator
        final String avdArgs = emuConfig.getCommandArguments();
        String emulatorArgs = String.format("-ports %s,%s %s"userPortadbPortavdArgs);
        ArgumentListBuilder emulatorCmd = getToolCommand(launcherandroidHome"emulator""emulator.exe"emulatorArgs);
        // Start emulator process
        log(logger, Messages.STARTING_EMULATOR());
        final long bootTime = System.currentTimeMillis();
        final EnvVars buildEnvironment = build.getEnvironment(TaskListener.NULL);
        final ProcStarter procStarter = launcher.launch().stdout(logger).stderr(logger);
        final Proc emulatorProcess = procStarter.envs(buildEnvironment).cmds(emulatorCmd).start();
        // Wait for TCP socket to become available
        boolean socket = waitForSocket(launcheradbPort);
        if (!socket || !emulatorProcess.isAlive()) {
            log(logger, Messages.EMULATOR_DID_NOT_START());
            build.setResult(Result.NOT_BUILT);
            cleanUp(loggerportAllocatoremulatorProcessadbPortuserPort);
            return null;
        }
        // Notify adb of our existence
        final String adbConnectArgs = "connect localhost:"adbPort;
        ArgumentListBuilder adbConnectCmd = getToolCommand(launcherandroidHome"adb""adb.exe"adbConnectArgs);
        int result = procStarter.cmds(adbConnectCmd).stdout(new NullOutputStream()).start().join();
        if (result != 0) { // adb currently only ever returns 0!
            log(logger, Messages.CANNOT_CONNECT_TO_EMULATOR());
            build.setResult(Result.NOT_BUILT);
            cleanUp(loggerportAllocatoremulatorProcessadbPortuserPort);
            return null;
        }
        // Start dumping logs to disk
        final File artifactsDir = build.getArtifactsDir();
        final FilePath logcatFile = build.getWorkspace().createTempFile("logcat_"".log");
        final OutputStream logcatStream = logcatFile.write();
        final String logcatArgs = "-s localhost:"adbPort +" logcat -v time";
        ArgumentListBuilder logcatCmd = getToolCommand(launcherandroidHome"adb""adb.exe"logcatArgs);
        final Proc logWriter = procStarter.cmds(logcatCmd).stdout(logcatStream).stderr(new NullOutputStream()).start();
        // Monitor device for boot completion signal
        log(logger, Messages.WAITING_FOR_BOOT_COMPLETION());
        int bootTimeout = ;
        if (!emulatorAlreadyExists) {
            bootTimeout *= 4;
        }
        boolean bootSucceeded = waitForBootCompletion(loggerlauncherandroidHomeadbPortbootTimeout);
        if (!bootSucceeded) {
            log(logger, Messages.BOOT_COMPLETION_TIMED_OUT(bootTimeout / 1000));
            build.setResult(Result.NOT_BUILT);
            cleanUp(loggerportAllocatoremulatorProcessadbPortuserPort,
                    logWriterlogcatFilelogcatStreamartifactsDir);
            return null;
        }
        final long bootCompleteTime = System.currentTimeMillis();
        log(logger, Messages.EMULATOR_IS_READY((bootCompleteTime - bootTime) / 1000));
        // Return wrapped environment
        return new Environment() {
            @Override
            public void buildEnvVars(Map<StringStringenv) {
                env.put("ANDROID_AVD_DEVICE""localhost:"adbPort);
                env.put("ANDROID_AVD_ADB_PORT", Integer.toString(adbPort));
                env.put("ANDROID_AVD_USER_PORT", Integer.toString(userPort));
                env.put("ANDROID_AVD_NAME"emuConfig.getAvdName());
                if (!emuConfig.isNamedEmulator()) {
                    env.put("ANDROID_AVD_OS"emuConfig.getOsVersion().toString());
                    env.put("ANDROID_AVD_DENSITY"emuConfig.getScreenDensity().toString());
                    env.put("ANDROID_AVD_RESOLUTION"emuConfig.getScreenResolution().toString());
                    env.put("ANDROID_AVD_SKIN"emuConfig.getScreenResolution().getSkinName());
                    env.put("ANDROID_AVD_LOCALE"emuConfig.getDeviceLocale());
                }
            }
            @Override
            @SuppressWarnings("unchecked")
            public boolean tearDown(AbstractBuild build, BuildListener listener)
                    throws IOExceptionInterruptedException {
                cleanUp(loggerportAllocatoremulatorProcessadbPortuserPort,
                        logWriterlogcatFilelogcatStreamartifactsDir);
                return true;
            }
        };
    }

    
Helper method for writing to the build log in a consistent manner.
    private synchronized void log(final PrintStream loggerfinal String message) {
        logger.print("[android] ");
        logger.println(message);
    }
    private void cleanUp(PrintStream logger, PortAllocationManager portAllocator,
            Proc emulatorProcessint adbPortint userPortthrows IOExceptionInterruptedException {
        cleanUp(loggerportAllocatoremulatorProcessadbPortuserPortnullnullnullnull);
    }

    
Called when this wrapper needs to exit, so we need to clean up some processes etc.

Parameters:
logger The build logger.
portAllocator The port allocator used.
emulatorProcess The Android emulator process.
adbPort The ADB port used by the emulator.
userPort The user port used by the emulator.
logcatProcess The adb logcat process.
logcatFile The file the logcat output is being written to.
logcatStream The stream the logcat output is being written to.
artifactsDir The directory where build artifacts should go.
    private void cleanUp(PrintStream logger, PortAllocationManager portAllocator,
            Proc emulatorProcessint adbPortint userPort, Proc logcatProcess,
            FilePath logcatFileOutputStream logcatStreamFile artifactsDir)
                throws IOExceptionInterruptedException {
        // FIXME: Sometimes on Windows neither the emulator.exe nor the adb.exe processes die.
        //        Launcher.kill(EnvVars) does appear to help either.
        //        This is (a) inconsistent; (b) very annoying.
        // Stop emulator process and free up TCP ports
        log(logger, Messages.STOPPING_EMULATOR());
        emulatorProcess.kill();
        portAllocator.free(adbPort);
        portAllocator.free(userPort);
        // Archive the logs
        if (logcatProcess != null) {
            logcatProcess.kill();
            logcatStream.close();
            if (logcatFile.length() != 0) {
                log(logger, Messages.ARCHIVING_LOG());
                logcatFile.copyTo(new FilePath(artifactsDir).child("logcat.txt"));
            }
            logcatFile.delete();
        }
    }

    
Expands the variable in the given string to its value in the environment variables available to this build. The Hudson-specific build variables for this build are then substituted.

Parameters:
envVars Map of the environment variables.
buildVars Map of the build-specific variables.
token The token which may or may not contain variables in the format ${foo}.
Returns:
The given token, with applicable variable expansions done.
    private String expandVariables(EnvVars envVarsMap<String,StringbuildVars,
            String token) {
        String result = Util.fixEmptyAndTrim(token);
        if (result != null) {
            result = Util.replaceMacro(Util.replaceMacro(resultenvVars), buildVars);
        }
        return result;
    }

    
Validates this instance's configuration.

Returns:
A human-readable error message, or null if the config is valid.
    private String isConfigValid(String avdNameString osVersionString screenDensity,
            String screenResolutionString deviceLocale) {
        if (getUseNamedEmulator()) {
            ValidationResult result = .doCheckAvdName(avdNamefalse);
            if (result.isFatal()) {
                return result.getMessage();
            }
        } else {
            ValidationResult result = .doCheckOsVersion(osVersionfalse);
            if (result.isFatal()) {
                return result.getMessage();
            }
            result = .doCheckScreenDensity(screenDensityfalse);
            if (result.isFatal()) {
                return result.getMessage();
            }
            result = .doCheckScreenResolution(screenResolutionnullfalse);
            if (result.isFatal()) {
                return result.getMessage();
            }
            result = .doCheckDeviceLocale(deviceLocalefalse);
            if (result.isFatal()) {
                return result.getMessage();
            }
        }
        return null;
    }

    
Tries to validate the given Android SDK root directory; otherwise tries to locate a copy of the SDK by checking for common environment variables.

Parameters:
launcher The launcher for the remote node.
envVars Environment variables for the build.
androidHome The (variable-expanded) SDK root given in global config.
Returns:
Either a discovered SDK path or, if all else fails, the given androidHome value.
    private String validateAndroidHome(final Launcher launcherfinal EnvVars envVars,
            final String androidHome) {
            @Override
            public String call() throws InterruptedException {
                // Verify existence of provided value
                if (validateHomeDir(androidHome)) {
                    return androidHome;
                }
                // Check for common environment variables
                String[] keys = { "ANDROID_SDK_ROOT""ANDROID_SDK_HOME",
                                  "ANDROID_HOME""ANDROID_SDK" };
                for (String key : keys) {
                    String home = envVars.get(key);
                    if (validateHomeDir(home)) {
                        return home;
                    }
                }
                // If all else fails, return what we were given
                return androidHome;
            }
            private boolean validateHomeDir(String dir) {
                if (Util.fixEmptyAndTrim(dir) == null) {
                    return false;
                }
                return !.doCheckAndroidHome(new File(dir), false).isFatal();
            }
            private static final long serialVersionUID = 1L;
        };
        String result = androidHome;
        try {
            result = launcher.getChannel().call(task);
        } catch (InterruptedException e) {
            // Ignore; will return default value
        } catch (IOException e) {
            // Ignore; will return default value
        }
        return result;
    }

    
Validates whether the required SDK tools can be reached, either from the given root or PATH.

Parameters:
launcher The launcher for the remote node.
androidHome The (variable-expanded) SDK root given in global config.
Returns:
true if all the required tools are available.
    private boolean validateAndroidToolsInPath(Launcher launcherfinal String androidHome) {
        final String executable = "tools/" + (launcher.isUnix() ? "adb" : "adb.exe");
        Callable<BooleanIOExceptiontask = new Callable<BooleanIOException>() {
            @Override
            public Boolean call() throws IOException {
                String sep = System.getProperty("path.separator");
                List<Stringlist = Arrays.asList(System.getenv("PATH").split(sep));
                List<Stringpaths = new ArrayList<String>(list);
                paths.add(0, androidHome);
                for (String path : paths) {
                    if (new File(pathexecutable).exists()) {
                        return true;
                    }
                }
                return false;
            }
            private static final long serialVersionUID = 1L;
        };
        try {
            return launcher.getChannel().call(task);
        } catch (IOException e) {
            // Ignore
        } catch (InterruptedException e) {
            // Ignore
        }
        return false;
    }

    
Retrieves the path to the Android SDK tools directory, based on the given SDK root path.

Parameters:
androidHome The path to the Android SDK root, may be empty or null.
Returns:
The path to the general Android SDK tools directory.
    private String getAndroidToolsDirectory(final String androidHome) {
        final String androidToolsDir;
        // If no home was provided, we'll assume that everything is on the PATH
        if (androidHome == null) {
            androidToolsDir = "";
        } else {
            androidToolsDir = androidHome +"/tools/";
        }
        return androidToolsDir;
    }

    
Generates a ready-to-use ArgumentListBuilder for one of the Android SDK tools.

Parameters:
launcher The launcher for the remote node.
androidHome The Android SDK root.
unixCmd The executable to run on normal systems.
windowsCmd The executable for elsewhere.
args Any extra arguments for the command.
Returns:
Arguments including the full path to the SDK and any extra Windows stuff required.
    private ArgumentListBuilder getToolCommand(Launcher launcherString androidHome,
            String unixCmdString windowsCmdString args) {
        // Figure out where the tools are that we need
        final String androidToolsDir = getAndroidToolsDirectory(androidHome);
        // Build tool command
        final String executable = launcher.isUnix() ? unixCmd : windowsCmd;
        ArgumentListBuilder builder = new ArgumentListBuilder(androidToolsDir + executable);
        if (args != null) {
            builder.add(Util.tokenize(args));
        }
        return builder;
    }

    
Waits for a socket on the remote machine's localhost to become available, or times out.

Parameters:
launcher The launcher for the remote node.
port The port to try and connect to.
timeout How long to keep trying (in milliseconds) before giving up.
Returns:
true if the socket was available, false if we timed-out.
    private boolean waitForSocket(Launcher launcherint portint timeout) {
        try {
            LocalPortOpenTask task = new LocalPortOpenTask(porttimeout);
            return launcher.getChannel().call(task);
        } catch (InterruptedException ex) {
            // Ignore
        } catch (IOException e) {
            // Ignore
        }
        return false;
    }

    
Checks whether the emulator running on the given port has finished booting yet, or times out.

Parameters:
logger The build logger.
launcher The launcher for the remote node.
androidHome The Android SDK root.
port The emulator's ADB port.
timeout How long to keep trying (in milliseconds) before giving up.
Returns:
true if the emulator has booted, false if we timed-out.
    private boolean waitForBootCompletion(final PrintStream loggerfinal Launcher launcher,
            final String androidHomefinal int portfinal int timeout) {
        long start = System.currentTimeMillis();
        int sleep = timeout / (int) Math.sqrt(timeout / 1000);
        final String serialNo = "localhost:"port;
        final String args = "-s "serialNo +" shell getprop dev.bootcomplete";
        ArgumentListBuilder cmd = getToolCommand(launcherandroidHome"adb""adb.exe"args);
        try {
            while (System.currentTimeMillis() < start + timeout) {
                ByteArrayOutputStream stream = new ByteArrayOutputStream(4);
                // Run "getprop"
                launcher.launch().cmds(cmd).stdout(stream).start().join();
                // Check output
                String result = stream.toString().trim();
                if (result.equals("1")) {
                    return true;
                }
                // Otherwise continue...
                Thread.sleep(sleep);
            }
        } catch (InterruptedException ex) {
            log(logger, Messages.INTERRUPTED_DURING_BOOT_COMPLETION());
            ex.printStackTrace(logger);
        } catch (IOException ex) {
            log(logger, Messages.COULD_NOT_CHECK_BOOT_COMPLETION());
            ex.printStackTrace(logger);
        }
        return false;
    }
    @Extension(ordinal=-100) // Negative ordinal makes us execute after other wrappers (i.e. Xvnc)
    public static final class DescriptorImpl extends BuildWrapperDescriptor implements Serializable {
        private static final long serialVersionUID = 1L;
        // From hudson.Util.VARIABLE
        private static final String VARIABLE_REGEX = "\\$([A-Za-z0-9_]+|\\{[A-Za-z0-9_]+\\}|\\$)";

        
The Android SDK home directory. Can include variables, e.g. ${ANDROID_HOME}.

If null, we will just assume the required commands are on the PATH.

        public String androidHome;
        public DescriptorImpl() {
            super(AndroidEmulator.class);
            load();
        }
        @Override
        public String getDisplayName() {
            return Messages.JOB_DESCRIPTION();
        }
        @Override
        public boolean configure(StaplerRequest reqJSONObject jsonthrows FormException {
            req.bindParameters(this"android-emulator.");
            save();
            return true;
        }
        @Override
        public BuildWrapper newInstance(StaplerRequest reqJSONObject formDatathrows FormException {
            String avdName = null;
            String osVersion = null;
            String screenDensity = null;
            String screenResolution = null;
            String deviceLocale = null;
            JSONObject config = formData.getJSONObject("useNamed");
            String useNamedValue = config.getString("value");
            if (Boolean.parseBoolean(useNamedValue)) {
                avdName = config.getString("avdName");
            } else {
                osVersion = config.getString("osVersion");
                screenDensity = config.getString("screenDensity");
                screenResolution = config.getString("screenResolution");
                deviceLocale = config.getString("deviceLocale");
            }
            return new AndroidEmulator(avdNameosVersionscreenDensityscreenResolutiondeviceLocale);
        }
        @Override
        public String getHelpFile() {
            return "/plugin/android-emulator/help-buildConfig.html";
        }
        @Override
        public boolean isApplicable(AbstractProject<?, ?> item) {
            return true;
        }

        
Used in config.jelly: Lists the OS versions available.
        public AndroidPlatform[] getAndroidVersions() {
           return .;
        }

        
Used in config.jelly: Lists the screen densities available.
        public ScreenDensity[] getDeviceDensities() {
            return .;
        }

        
Used in config.jelly: Lists the screen resolutions available.
        public ScreenResolution[] getDeviceResolutions() {
            return .;
        }

        
Used in config.jelly: Lists the locales available.
        public String[] getEmulatorLocales() {
            return .;
        }
        public FormValidation doCheckAvdName(@QueryParameter String value) {
            return doCheckAvdName(valuetrue).getFormValidation();
        }
        private ValidationResult doCheckAvdName(String avdNameboolean allowVariables) {
            if (avdName == null || avdName.equals("")) {
                return ValidationResult.error(Messages.AVD_NAME_REQUIRED());
            }
            String regex = .;
            if (allowVariables) {
                regex = "((". +")*(" +")*)+";
            }
            if (!avdName.matches(regex)) {
                return ValidationResult.error(Messages.INVALID_AVD_NAME());
            }
            return ValidationResult.ok();
        }
        public FormValidation doCheckOsVersion(@QueryParameter String value) {
            return doCheckOsVersion(valuetrue).getFormValidation();
        }
        private ValidationResult doCheckOsVersion(String osVersionboolean allowVariables) {
            if (osVersion == null || osVersion.equals("")) {
                return ValidationResult.error(Messages.OS_VERSION_REQUIRED());
            }
            if (!allowVariables && osVersion.matches()) {
                return ValidationResult.error(Messages.INVALID_OS_VERSION());
            }
            return ValidationResult.ok();
        }
        public FormValidation doCheckScreenDensity(@QueryParameter String value) {
            return doCheckScreenDensity(valuetrue).getFormValidation();
        }
        private ValidationResult doCheckScreenDensity(String densityboolean allowVariables) {
            if (density == null || density.equals("")) {
                return ValidationResult.error(Messages.SCREEN_DENSITY_REQUIRED());
            }
            String regex = .;
            if (allowVariables) {
                regex += "|";
            }
            if (!density.matches(regex)) {
                return ValidationResult.error(Messages.SCREEN_DENSITY_NOT_NUMERIC());
            }
            return ValidationResult.ok();
        }
        public FormValidation doCheckScreenResolution(@QueryParameter String value,
                @QueryParameter String density) {
            return doCheckScreenResolution(valuedensitytrue).getFormValidation();
        }
        private ValidationResult doCheckScreenResolution(String resolutionString density,
                boolean allowVariables) {
            if (resolution == null || resolution.equals("")) {
                return ValidationResult.error(Messages.SCREEN_RESOLUTION_REQUIRED());
            }
            String regex = .;
            if (allowVariables) {
                regex += "|";
            }
            if (!resolution.matches(regex)) {
                return ValidationResult.error(Messages.INVALID_RESOLUTION_FORMAT());
            }
            // Check for shenanigans
            ScreenResolution resolutionValue = ScreenResolution.valueOf(resolution);
            ScreenDensity densityValue = ScreenDensity.valueOf(density);
            if (resolutionValue != null && densityValue != null
                    && !resolutionValue.isCustomResolution() && !densityValue.isCustomDensity()) {
                boolean densityFound = false;
                for (ScreenDensity okDensity : resolutionValue.getApplicableDensities()) {
                    if (okDensity.equals(densityValue)) {
                        densityFound = true;
                        break;
                    }
                }
                if (!densityFound) {
                    return ValidationResult.warning(Messages.SUSPECT_RESOLUTION(resolutiondensityValue));
                }
            }
            return ValidationResult.ok();
        }
        public FormValidation doCheckDeviceLocale(@QueryParameter String value) {
            return doCheckDeviceLocale(valuetrue).getFormValidation();
        }
        private ValidationResult doCheckDeviceLocale(String localeboolean allowVariables) {
            if (locale == null || locale.equals("")) {
                return ValidationResult.warning(Messages.DEFAULT_LOCALE_WARNING(.));
            }
            String regex = .;
            if (allowVariables) {
                regex += "|";
            }
            if (!locale.matches(regex)) {
                return ValidationResult.error(Messages.LOCALE_FORMAT_WARNING());
            }
            return ValidationResult.ok();
        }
        public FormValidation doCheckAndroidHome(@QueryParameter File value) {
            return doCheckAndroidHome(valuetrue).getFormValidation();
        }
        private ValidationResult doCheckAndroidHome(File sdkRootboolean fromWebConfig) {
            // This can be used to check the existence of a file on the server, so needs to be protected
            if (fromWebConfig && !Hudson.getInstance().hasPermission(Hudson.ADMINISTER)) {
                return ValidationResult.ok();
            }
            // Check the utter basics
            if (sdkRoot == null || sdkRoot.getPath().equals("")) {
                return ValidationResult.ok();
            }
            if (!sdkRoot.isDirectory()) {
                if (fromWebConfig && sdkRoot.getPath().matches(".*(" +").*")) {
                    return ValidationResult.ok();
                }
                return ValidationResult.error(Messages.INVALID_DIRECTORY());
            }
            // We'll be using items from the tools and platforms directories
            for (String dirName : new String[] { "tools""platforms" }) {
                File dir = new File(sdkRootdirName);
                if (!dir.exists() || !dir.isDirectory()) {
                    return ValidationResult.error(Messages.INVALID_SDK_DIRECTORY());
                }
            }
            // So long as the basic executables exist, we're happy
            int toolsFound = 0;
            final String[] requiredTools = { "adb""android""emulator" };
            for (String toolName : requiredTools) {
                for (String extension : new String[] { """.bat"".exe" }) {
                    File tool = new File(sdkRoot"tools/"toolName + extension);
                    if (tool.exists() && tool.isFile()) {
                        toolsFound++;
                        break;
                    }
                }
            }
            if (toolsFound != requiredTools.length) {
                return ValidationResult.errorWithMarkup(Messages.REQUIRED_SDK_TOOLS_NOT_FOUND());
            }
            // Give the user a nice warning (not error) if they've not downloaded any platforms yet
            File platformsDir = new File(sdkRoot"platforms");
            if (platformsDir.list().length == 0) {
                return ValidationResult.warning(Messages.SDK_PLATFORMS_EMPTY());
            }
            return ValidationResult.ok();
        }
    }

    
Task that will block until it can either connect to a port on localhost, or it times-out.
    private static final class LocalPortOpenTask implements Callable<BooleanInterruptedException> {
        private static final long serialVersionUID = 1L;
        private final int port;
        private final int timeout;

        

Parameters:
port The local TCP port to attempt to connect to.
timeout How long to keep trying (in milliseconds) before giving up.
        public LocalPortOpenTask(int portint timeout) {
            this. = port;
            this. = timeout;
        }
        public Boolean call() throws InterruptedException {
            final long start = System.currentTimeMillis();
            while (System.currentTimeMillis() < start + ) {
                try {
                    Socket socket = new Socket("127.0.0.1");
                    socket.getOutputStream();
                    socket.close();
                    return true;
                } catch (IOException ex) {
                    // Ignore
                }
                Thread.sleep(1000);
            }
            return false;
        }
    }

    
The Java equivalent of /dev/null.
    private static final class NullOutputStream extends OutputStream {
        @Override
        public void write(int bthrows IOException {
            // La la la
        }
        @Override
        public void write(byte[] bthrows IOException {
            // I can't hear you
        }
        @Override
        public void write(byte[] bint offint lenthrows IOException {
            // Nope, still can't hear you
        }
    }
New to GrepCode? Check out our FAQ X