com.symbian.driver.core.controller.SymbianVisitor.java Source code

Java tutorial

Introduction

Here is the source code for com.symbian.driver.core.controller.SymbianVisitor.java

Source

/*
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/

package com.symbian.driver.core.controller;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

import javax.naming.TimeLimitExceededException;

import org.apache.commons.cli.ParseException;

import com.symbian.driver.CmdPC;
import com.symbian.driver.CmdSymbian;
import com.symbian.driver.FlashROM;
import com.symbian.driver.Phase;
import com.symbian.driver.Rtest;
import com.symbian.driver.StartTrace;
import com.symbian.driver.StopTrace;
import com.symbian.driver.Task;
import com.symbian.driver.TestExecuteScript;
import com.symbian.driver.Transfer;
import com.symbian.driver.core.controller.event.TaskFinishedEvent;
import com.symbian.driver.core.controller.tasks.CmdPCTask;
import com.symbian.driver.core.controller.tasks.CmdSymbianTask;
import com.symbian.driver.core.controller.tasks.ExecuteTransferSet;
import com.symbian.driver.core.controller.tasks.FlashROMTask;
import com.symbian.driver.core.controller.tasks.RTest;
import com.symbian.driver.core.controller.tasks.StartTraceTask;
import com.symbian.driver.core.controller.tasks.StopTraceTask;
import com.symbian.driver.core.controller.tasks.TEFTask;
import com.symbian.driver.core.controller.tasks.TransferTask;
import com.symbian.driver.core.controller.utils.ModelUtils;
import com.symbian.driver.core.environment.TDConfig;
import com.symbian.driver.core.extension.IVisitor;
import com.symbian.driver.core.extension.IVisitor.ESeverity;
import com.symbian.driver.core.pluginProxies.CoreDumpProxy;
import com.symbian.driver.core.pluginProxies.RebootProxy;
import com.symbian.driver.core.processors.EmulatorPreProcessor;
import com.symbian.driver.core.processors.HardwarePreProcessor;
import com.symbian.driver.core.processors.PreProcessor;
import com.symbian.driver.util.DriverSwitch;
import com.symbian.utils.Epoc;

/**
 * Walks through the EMF tree processing all device/Symbian/run commands.
 * 
 * Specifically this class visits the following tags:
 * <ul>
 * <li><code>CmdSymbian</code>;</li>
 * <li><code>Reference</code>;</li>
 * <li><code>RetrieveFromSymbian</code>;</li>
 * <li><code>RTest</code>;</li>
 * <li><code>TestExeucteScript</code> and;</li>
 * <li><code>TransferToSymbian</code>.</li>
 * </ul>
 * 
 * @author EngineeringTools
 */
public class SymbianVisitor extends Visitor {

    /** Symbian Device (Emulator/Hardware). */
    private static PreProcessor sSymbianDevice = null;

    private static boolean iRebooted = false;

    /**
     * Starts the Run Visitor.
     * 
     * If <code>WINSCW</code> or <code>WINS</code> then starts the emulator
     * using the WINTAP Address in the configuration. Otherwise it starts the
     * Hardware board. If ncessary it will also start RDebug and install TEF
     * dependencies.
     * 
     * @param aTask
     * @throws Exception
     */
    public boolean start(final Task aTask) {
        boolean lReturn = true;
        boolean lEmulator = false;
        try {
            TDConfig CONFIG = TDConfig.getInstance();
            lEmulator = Epoc.isTargetEmulator(CONFIG.getPreference(TDConfig.PLATFORM));
            if (lEmulator) {
                // Start Emulator
                LOGGER.fine("Creating Emulator Pre Processor");
                sSymbianDevice = new EmulatorPreProcessor();
            } else {
                // Start Hardware
                LOGGER.fine("Creating Hardware Pre Processor");
                sSymbianDevice = new HardwarePreProcessor();
            }

            // Start the Symbian Device (Emulator or Hardware
            LOGGER.fine("Starting Pre Processor");
            if (sSymbianDevice.start()) {

                // Increment the Run Number
                CONFIG.incrementRunNumber();
                LOGGER.info("Run number: " + CONFIG.getPreferenceInteger(TDConfig.RUN_NUMBER));

                // Start Test Driver
                if (!super.start(aTask, iSymbianSwitch, sSymbianDevice, true)) {
                    lReturn = false;
                }
            } else {
                lReturn = false;
                LOGGER.log(Level.SEVERE, "Could not start symbian device.");
                //sSymbianDevice.stop();
            }

        } catch (IOException lIOException) {
            LOGGER.log(Level.SEVERE, lIOException.getMessage(), lIOException);
            lReturn = false;
        } catch (EmptyStackException lEmptyStackException) {
            // For the Install and UID Stack Execpetions
            LOGGER.log(Level.FINE, "Stack Exception for UID/Install stack.", lEmptyStackException);
            lReturn = false;
        } catch (StringIndexOutOfBoundsException lStringIndexOutOfBoundsException) {
            LOGGER.log(Level.SEVERE, "Wintap for emulator tests has an error.", lStringIndexOutOfBoundsException);
            lReturn = false;
        } catch (Exception Exception) {
            lReturn = false;
            LOGGER.log(Level.SEVERE, "JStat failed while starting the run", Exception);
            // something, maybe stat or something on the device couldve hanged
            // if a reboot plugin is available, see if reboot can help
            if (!lEmulator) {
                try {
                    if (RebootProxy.getInstance().Reboot()) {
                        iRebooted = true;
                    } else {
                        LOGGER.log(Level.SEVERE, "could not reboot. See previous errors.");
                    }
                } catch (Exception lException) {
                    LOGGER.log(Level.SEVERE, "could not reboot thru any plugins.", lException);
                }
            }
        } catch (Throwable lThrowable) {
            LOGGER.log(Level.SEVERE, lThrowable.getMessage(), lThrowable);
            lReturn = false;
        } finally {
            // Stop Test Driver
            stop();
        }
        return lReturn;
    }

    /**
     * Stops the Symbian Device (Hardware or Emulator).
     * 
     * This will also uninstall any remaing tasks in the Install Stack.
     */
    public boolean stop() {
        boolean lReturn = true;
        if (!iRebooted) {

            super.stop();

            // Uninstall any remaining tasks
            try {

                while (!TASK_SET.isEmpty()) {
                    ((ExecuteTransferSet) TASK_SET.pop().getTransferSet()).uninstall();
                }

            } catch (TimeLimitExceededException lTimeLimitExceededException) {
                LOGGER.log(Level.SEVERE, "Could not uninstall any remaining Tasks due to timeout.",
                        lTimeLimitExceededException);
                lReturn = false;
            }

            // Stop Symbian
            sSymbianDevice.stop();

        }
        return lReturn;
        // }
    }

    /**
     * 
     */
    private final DriverSwitch iSymbianSwitch = new DriverSwitch() {

        @Override
        public Object caseFlashROM(FlashROM object) {
            try {
                boolean lEmulator = Epoc.isTargetEmulator(CONFIG.getPreference(TDConfig.PLATFORM));
                if (!lEmulator) {
                    return new FlashROMTask(object);
                }
            } catch (ParseException lParseException) {
                LOGGER.log(Level.SEVERE, "Configuration error", lParseException);
            }
            return null;
        }

        @Override
        public Object caseCmdPC(final CmdPC aCmdPC) {
            if (aCmdPC.getPhase() == Phase.RUN || aCmdPC.getPhase() == Phase.BOTH) {
                return new CmdPCTask(aCmdPC);
            }

            return null;
        }

        @Override
        public Object caseCmdSymbian(final CmdSymbian aCmdSymbian) {
            return new CmdSymbianTask(aCmdSymbian);
        }

        @Override
        public Object caseTestExecuteScript(final TestExecuteScript aTestExecuteScript) {
            return new TEFTask(aTestExecuteScript);
        }

        @Override
        public Object caseRtest(Rtest aRtest) {
            return new RTest(aRtest);
        }

        @Override
        public Object caseTransfer(final Transfer aTransfer) {
            return new TransferTask(aTransfer);
        }

        public Object caseStartTrace(final StartTrace aStartTrace) {
            return new StartTraceTask(aStartTrace);
        }

        public Object caseStopTrace(final StopTrace aStopTrace) {
            return new StopTraceTask(aStopTrace);
        }

        @Override
        public Object caseTask(Task aTask) {
            return new IVisitor() {

                public Map<? extends Exception, ESeverity> execute(Task aTask, PreProcessor aSymbianDevice) {
                    Map<Exception, ESeverity> lExceptions = new HashMap<Exception, ESeverity>();
                    // The root directory to use for repositories
                    File lBaseDirectory = getBaseDirectory(aTask);
                    if (lBaseDirectory == null) {
                        return lExceptions;
                    }

                    // A transfer set used to create and transfer repositories
                    try {
                        aTask.setTransferSet(new ExecuteTransferSet(aTask.getName(), lBaseDirectory));
                    } catch (Exception lIOException) {
                        LOGGER.log(Level.WARNING, "Could not create new transfer.", lIOException);
                        lExceptions.put(lIOException, ESeverity.ERROR);
                    }

                    Map<Exception, ESeverity> uninstall = uninstall(aTask);
                    // Uninstall Previous Execute
                    lExceptions.putAll(uninstall);

                    Map<Exception, ESeverity> install = install(aTask);
                    // Install this task
                    lExceptions.putAll(install);

                    fireTaskFinishedEvent(new TaskFinishedEvent(aTask, false, false, lExceptions));

                    return lExceptions;
                }

            };
        }
    };

    /**
     * Uninstalls the previous tasks if necessary.
     * 
     * @param aTask
     *            The current tasks
     * @return <code>true</code> if no failures occurd during the
     *         installation, <code>false</code> otherwise
     */
    private Map<Exception, ESeverity> uninstall(final Task aTask) {
        LOGGER.entering(this.getClass().getName(), "uninstall");

        Map<Exception, ESeverity> lExceptions = new HashMap<Exception, ESeverity>();

        if (TASK_SET.isEmpty()) {
            TASK_SET.push(aTask);
            iPreviousLevel = aTask.getLevel();
            return lExceptions;

        }
        try {
            ExecuteTransferSet lExecuteTransferSet = null;
            if (!TASK_SET.isEmpty() && iPreviousLevel == aTask.getLevel()) {

                LOGGER.finer("Staying level in the task hierachy.");

                Task lTask = TASK_SET.pop();
                lExecuteTransferSet = (ExecuteTransferSet) lTask.getTransferSet();
                if (!lExecuteTransferSet.uninstall()) {
                    lExceptions.put(new Exception("Un-installing " + lExecuteTransferSet.getUid() + " failed."),
                            ESeverity.ERROR);
                }

            } else if (iPreviousLevel > aTask.getLevel()) {
                LOGGER.finer("Going down one level in the task hierachy.");

                Task lTask = TASK_SET.pop();
                iPreviousLevel = aTask.getLevel();
                while (aTask.eContainer() != lTask.eContainer()) {
                    lExecuteTransferSet = (ExecuteTransferSet) lTask.getTransferSet();
                    if (!lExecuteTransferSet.uninstall()) {
                        lExceptions.put(new Exception("Un-installing " + lExecuteTransferSet.getUid() + " failed."),
                                ESeverity.ERROR);
                    }
                    lTask = TASK_SET.pop();
                }
                lExecuteTransferSet = (ExecuteTransferSet) lTask.getTransferSet();
                if (!lExecuteTransferSet.uninstall()) {
                    lExceptions.put(new Exception("Un-installing " + lExecuteTransferSet.getUid() + " failed."),
                            ESeverity.ERROR);
                }
            }

        } catch (TimeLimitExceededException lTimeLimitExceededException) {

            LOGGER.log(Level.SEVERE, "Uninstall/deleting of repository failed due to timeout",
                    lTimeLimitExceededException);
            lExceptions.put(lTimeLimitExceededException, ESeverity.ERROR);

        } finally {
            iPreviousLevel = aTask.getLevel();
            TASK_SET.push(aTask);

        }

        return lExceptions;
    }

    private File iSisFile;

    /**
     * Installs the current task if necessary.
     * 
     * @param aTask
     *            The current task to install.
     * @param aExecuteTransferSet
     *            The transfer set relating to the current tasks.
     * @param aBase
     *            The base repository directory to install from.
     * @return <code>true</code> if no failures occurd during the
     *         installation, <code>false</code> otherwise
     * @throws ParseException
     *             If there was a configuration exception.
     */
    private Map<Exception, ESeverity> install(final Task aTask) {
        LOGGER.entering(this.getClass().getName(), "install");

        HashMap<File, File> lEmulatorHashBackup = null;
        Map<Exception, ESeverity> lExceptions = new HashMap<Exception, ESeverity>();
        TDConfig CONFIG = TDConfig.getInstance();
        String ltaskName = ((ExecuteTransferSet) aTask.getTransferSet()).getName();
        boolean lPlatSec = true;
        try {
            //lPlatSec = CONFIG.isPreference(TDConfig.PLATSEC) && !CONFIG.isPreference(TDConfig.SYS_BIN);
            lPlatSec = !CONFIG.isPreference(TDConfig.SYS_BIN);
        } catch (ParseException e) {
            LOGGER.log(Level.WARNING, "Could not get the configuration for PlatSec. Defaulting to ON");
        }

        try {

            // Install the SIS file or Repository
            if (lPlatSec) {
                // PlatSec ON

                File lBaseDirectory = getBaseDirectory(aTask);
                if (lBaseDirectory == null) {
                    return lExceptions;
                }

                File[] lFile = lBaseDirectory.listFiles(new FileFilter() {
                    public boolean accept(File lTestFile) {
                        if (lTestFile.getName().toLowerCase().startsWith("testdriver_") && lTestFile.getName()
                                .toLowerCase().endsWith(com.symbian.driver.core.environment.ILiterals.SIS)) {
                            return true;
                        }
                        return false;
                    }
                });

                if (lFile == null) {
                    LOGGER.fine("The repository is empty at: " + lBaseDirectory);
                } else if (lFile.length == 1) {

                    File lSisFile = lFile[0];

                    LOGGER.fine("Setting SIS File to: " + lSisFile.getCanonicalPath());

                    // ////////////////////////////////////////
                    //  EMULATOR  to delete: Moves the emulator files
                    // Replace with buildrom -> emulatorbuild
                    lEmulatorHashBackup = EmulatorPreProcessor.backupEmulator(lSisFile);

                    ((ExecuteTransferSet) aTask.getTransferSet()).installSis(lSisFile);

                } else if (lFile.length > 1) {
                    throw new IOException("There are too many SIS files at: " + ltaskName
                            + ". Please delete your repository and rebuild.");

                }

            } else {
                // PlatSec OFF
                LOGGER.fine("Installing Repository Directory with PlatSec Off");

                ((ExecuteTransferSet) aTask.getTransferSet()).installRepository();
            }

        } catch (IOException lIOException) {

            LOGGER.log(Level.SEVERE, "Installation/copying of repository " + ltaskName + " failed due IO Error",
                    lIOException);
            lExceptions.put(lIOException, ESeverity.ERROR);

        } catch (TimeLimitExceededException lTimeLimitExceededException) {

            LOGGER.log(Level.SEVERE, "Installation/copying of repository " + ltaskName + " failed due to time out.",
                    lTimeLimitExceededException);
            lExceptions.put(lTimeLimitExceededException, ESeverity.ERROR);

        } finally {
            EmulatorPreProcessor.restoreEmulator(lEmulatorHashBackup);
        }

        return lExceptions;
    }

    static File getBaseDirectory(Task aTask) {
        File lBaseDirectory = new File(".");
        try {
            lBaseDirectory = new File(TDConfig.getInstance().getPreferenceFile(TDConfig.REPOSITORY_ROOT),
                    ModelUtils.getBaseDirectory(aTask, Integer.MIN_VALUE));
        } catch (ParseException lParseException) {
            LOGGER.log(Level.WARNING, "Could not get repository directory.", lParseException);
        }

        return lBaseDirectory;
    }

}