com.motorola.studio.android.devices.services.console.EmulatorConsoleHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.motorola.studio.android.devices.services.console.EmulatorConsoleHandler.java

Source

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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.motorola.studio.android.devices.services.console;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.sequoyah.device.framework.model.IInstance;
import org.eclipse.sequoyah.device.framework.model.handler.IServiceHandler;
import org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;

import com.motorola.studio.android.adt.ISerialNumbered;
import com.motorola.studio.android.common.utilities.EclipseUtils;
import com.motorola.studio.android.devices.services.DeviceServicesPlugin;
import com.motorola.studio.android.devices.services.DeviceServicesPlugin.IConsoleKilledListener;
import com.motorola.studio.android.devices.services.i18n.ServicesNLS;
import com.motorola.studio.android.utilities.TelnetFrameworkAndroid;

/**
 * Class responsible to implement the handler for the service
 * "Emulator Console"
 */
public class EmulatorConsoleHandler extends ServiceHandler {
    private static final Map<String, Integer> consolesCache = new HashMap<String, Integer>();

    private static final Map<String, TelnetFrameworkAndroid> telnetsCache = new HashMap<String, TelnetFrameworkAndroid>();

    private final IConsoleKilledListener listener = new IConsoleKilledListener() {
        public void consoleKilled(String name) {
            if (telnetsCache.containsKey(name)) {
                TelnetFrameworkAndroid telnet = telnetsCache.get(name);
                if (telnet.isConnected()) {
                    try {
                        telnet.disconnect();
                    } catch (IOException e) {
                        EclipseUtils.showInformationDialog(ServicesNLS.GEN_Warning,
                                ServicesNLS.WARN_EmulatorConsoleHandler_CouldNotCloseTheConsoleConnection);
                    }
                }
                telnetsCache.remove(name);
                DeviceServicesPlugin.removeConsoleKilledListener(listener);
            }
        }
    };

    public static final String CONSOLE_NAME = "Emulator Console";

    private static final String LOCALHOST = "localhost";

    /**
     * Constructor
     */
    public EmulatorConsoleHandler() {

    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#newInstance()
     */
    @Override
    public IServiceHandler newInstance() {
        return new EmulatorConsoleHandler();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#runService(org.eclipse.sequoyah.device.framework.model.IInstance, java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
     */
    @Override
    public IStatus runService(final IInstance instance, Map<Object, Object> arguments, IProgressMonitor monitor) {
        IStatus status = Status.OK_STATUS;
        if (instance instanceof ISerialNumbered) {
            // Retrieve the emulator port from its serial number
            Pattern pattern = Pattern.compile("emulator-([0-9]+)");
            final String[] serialNumber = new String[1];

            serialNumber[0] = ((ISerialNumbered) instance).getSerialNumber();
            if (serialNumber[0] == null) {
                PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {

                    public void run() {
                        ProgressMonitorDialog dialog = new ProgressMonitorDialog(
                                new Shell(PlatformUI.getWorkbench().getDisplay()));
                        try {
                            dialog.run(false, false, new IRunnableWithProgress() {

                                public void run(IProgressMonitor monitor)
                                        throws InvocationTargetException, InterruptedException {
                                    int limit = 20;

                                    SubMonitor theMonitor = SubMonitor.convert(monitor);
                                    theMonitor.beginTask(ServicesNLS.ADBShellHandler_WaitingDeviceToLoad, limit);

                                    int times = 0;

                                    while ((serialNumber[0] == null) && (times < limit)) {
                                        theMonitor.worked(1);
                                        Thread.sleep(500);
                                        serialNumber[0] = ((ISerialNumbered) instance).getSerialNumber();
                                        times++;
                                    }

                                    theMonitor.setWorkRemaining(0);
                                }
                            });
                        } catch (Exception e) {
                            //do nothing
                        }
                    }
                });
            }

            // Fix a condition that Studio holds the UI thread forever 
            if (serialNumber[0] == null) {
                status = new Status(IStatus.ERROR, DeviceServicesPlugin.PLUGIN_ID,
                        ServicesNLS.ERR_EmulatorConsoleHandler_CouldNotOpenTheConsoleShell);
                return status;
            }

            Matcher matcher = pattern.matcher(serialNumber[0]);
            if (matcher.matches()) {
                String port = matcher.group(1);
                final TelnetFrameworkAndroid telnet = new TelnetFrameworkAndroid();
                try {
                    Integer i = consolesCache.get(serialNumber[0]);
                    i = (i == null ? 1 : ++i);
                    consolesCache.put(serialNumber[0], i);

                    telnet.connect(LOCALHOST, Integer.parseInt(port));
                    InputStream in = telnet.getInputStream();
                    OutputStream out = telnet.getOutputStream();

                    String consoleName = CONSOLE_NAME + " - " + serialNumber[0];

                    if (i != null) {
                        consoleName += " (" + i + ")";
                    }

                    telnetsCache.put(consoleName, telnet);
                    DeviceServicesPlugin.addConsoleKilledListener(listener);
                    DeviceServicesPlugin.redirectStreamsToConsole(in, out, consoleName);
                } catch (IOException e) {
                    status = new Status(IStatus.ERROR, DeviceServicesPlugin.PLUGIN_ID,
                            ServicesNLS.ERR_EmulatorConsoleHandler_CouldNotOpenTheConsoleShell, e);
                }
            }
        } else {
            status = new Status(IStatus.ERROR, DeviceServicesPlugin.PLUGIN_ID,
                    ServicesNLS.ERR_EmulatorConsoleHandler_CouldNotRetrieveTheEmulatorPort);
        }

        return status;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#updatingService(org.eclipse.sequoyah.device.framework.model.IInstance, org.eclipse.core.runtime.IProgressMonitor)
     */
    @Override
    public IStatus updatingService(IInstance instance, IProgressMonitor monitor) {
        return Status.OK_STATUS;
    }
}