com.nokia.cdt.internal.debug.launch.NokiaAbstractLaunchDelegate.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.cdt.internal.debug.launch.NokiaAbstractLaunchDelegate.java

Source

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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.nokia.cdt.internal.debug.launch;

import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.launch.AbstractCLaunchDelegate;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;

import com.freescale.cdt.debug.cw.core.cdi.Session;
import com.nokia.carbide.cdt.builder.builder.CarbideCPPBuilder;
import com.nokia.cdt.debug.common.internal.source.lookup.SourceMappingUtils;
import com.nokia.cdt.debug.cw.symbian.ui.executables.ExecutableTargeted;
import com.nokia.cdt.internal.debug.launch.ui.ExecutablesTab;

public abstract class NokiaAbstractLaunchDelegate extends AbstractCLaunchDelegate {

    /**
     * [comment_20070318] This is my local (not perfect but fine in practice)
     * solution to prevent user from launching the same LC again. See Bug 3548.
     * 
     * Better solution is change
     * org.eclipse.debug.internal.core.LaunchConfiguration.launch()
     * 
     * but we don't want to modify platform code. .............03/18/07
     */
    static private List<ILaunchConfiguration> m_beingLaunched = Collections
            .synchronizedList(new LinkedList<ILaunchConfiguration>());

    public boolean isBeingLaunched(ILaunchConfiguration lc) {
        if (lc instanceof ILaunchConfigurationWorkingCopy)
            lc = ((ILaunchConfigurationWorkingCopy) lc).getOriginal();

        if (!m_beingLaunched.contains(lc))
            return false;
        else {
            String cfgName = lc.getName();
            String format = LaunchMessages.getString("NokiaAbstractLaunchDelegate.LaunchUnderway"); //$NON-NLS-1$
            String msg = MessageFormat.format(format, new Object[] { cfgName });
            showMessage(LaunchMessages.getString("CarbideCPPLaunchDelegate.DebuggerName"), msg); //$NON-NLS-1$

            return true;
        }
    }

    public void addBeingLaunched(ILaunchConfiguration lc) {
        if (lc instanceof ILaunchConfigurationWorkingCopy)
            lc = ((ILaunchConfigurationWorkingCopy) lc).getOriginal();

        m_beingLaunched.add(lc);
    }

    public void removeBeingLaunched(ILaunchConfiguration lc) {
        if (lc instanceof ILaunchConfigurationWorkingCopy)
            lc = ((ILaunchConfigurationWorkingCopy) lc).getOriginal();

        m_beingLaunched.remove(lc);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#buildForLaunch(org.eclipse.debug.core.ILaunchConfiguration,
     *      java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
     */
    @Override
    public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor)
            throws CoreException {

        /*
         * This override is just for preventing user from launching the same LC
         * twice. See my comment [comment_20070318] in this file.
         */
        if (isBeingLaunched(configuration))
            return false;

        try {
            addBeingLaunched(configuration);

            return super.buildForLaunch(configuration, mode, monitor);

        } finally {
            removeBeingLaunched(configuration);
        }
    }

    protected String getPluginID() {
        return LaunchPlugin.getUniqueIdentifier();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.debug.core.model.ILaunchConfigurationDelegate2#preLaunchCheck(org.eclipse.debug.core.ILaunchConfiguration,
     *      java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
     */
    public boolean preLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor)
            throws CoreException {

        // Prevent launching the same LC again. See my comment
        // [comment_20070318] in this file.
        if (isBeingLaunched(configuration))
            return false;

        try {
            addBeingLaunched(configuration);

            // Don't go on if a session (from another LC) is being started or
            // stopped.
            synchronized (Session.sessionStartStopMutex()) {
            }

            if (monitor.isCanceled())
                return false;

            // If a debug session is already running for the given launch
            // configuration, don't allow user to start another session.
            //
            if (Session.preLaunchCheckForExistingTarget(configuration, new SubProgressMonitor(monitor, 0))) {
                // Pop up a dialog telling user.
                String cfgName = configuration.getName();
                showMessage(LaunchMessages.getString("CarbideCPPLaunchDelegate.DebuggerName"), //$NON-NLS-1$
                        LaunchMessages.getString("CarbideCPPLaunchDelegate.DebugUnderway") + //$NON-NLS-1$
                                "\t\"" + cfgName + "\""); //$NON-NLS-1$ //$NON-NLS-2$

                return false;
            }

            return super.preLaunchCheck(configuration, mode, monitor);
        } finally {
            removeBeingLaunched(configuration);
        }
    }

    public static IProject getProject(ILaunchConfiguration configuration) {
        String projectName = null;
        try {
            projectName = getProjectName(configuration);
        } catch (CoreException e) {
        }
        if (projectName != null) {
            projectName = projectName.trim();
            if (projectName.length() > 0) {
                IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
                return project;
            }
        }
        return null;
    }

    protected void doAdditionalSessionSetup(Session session) {
        session.setExecutableTargetedCallback(new ExecutableTargeted());
    }

    protected ILaunchConfiguration synchronizeWithProjectAccessPaths(ICProject project, ILaunchConfiguration config)
            throws CoreException {
        ILaunchConfigurationWorkingCopy workingCopy = config.getWorkingCopy();
        SourceMappingUtils.addSourceMappingToLaunch(workingCopy);
        return workingCopy.doSave();
    }

    /**
     * Returns list of executables that need to be targeted for debugging other
     * than the main executable which is always targeted. This list includes the
     * binaries imported into the project as well as all the executables built
     * as part of the inf file.
     * 
     * @return
     * @throws CModelException
     */
    protected IPath[] getOtherExecutables(ICProject project, IPath exePath, ILaunchConfiguration config,
            IProgressMonitor monitor) throws CModelException {
        List<IPath> targetedBinaries = new ArrayList<IPath>();

        try {
            targetedBinaries.addAll(ExecutablesTab.getExecutablesToTarget(config, monitor));

            // remove the main exe if it exists
            if (targetedBinaries.contains(exePath)) {
                targetedBinaries.remove(exePath);
            }
        } catch (CoreException e) {
        }

        return (IPath[]) targetedBinaries.toArray(new IPath[targetedBinaries.size()]);
    }

    /**
     * Search binary files in the project for those that need be debugged (aside
     * from the binary built by the project) for this debug session.
     * 
     * @return
     * @throws CModelException
     */
    protected List<IPath> getImportedExecutables(ICProject project, IPath exePath) throws CModelException {

        // Target imported executables in the project
        ArrayList<IPath> importedBinaries = new ArrayList<IPath>();
        if (projectMayHaveImportedExecutables(project)) {
            IBinary[] binaries = project.getBinaryContainer().getBinaries();
            for (int i = 0; i < binaries.length; i++) {
                IBinary binary = binaries[i];
                // only look at binaries with the correct cpu type (e.g. "arm",
                // "x86")
                if (binary.getCPU().toLowerCase().contains(getCPUString())) {
                    IPath binaryPath = binary.getResource().getLocation();

                    /*
                     * Weed out other binaries that has the same base file name as
                     * the main target. That is pretty common when the project has
                     * build configs for different SDKs, say, S60_3 ARMV5, S60_3
                     * GCCE, UIQ21 GCC. E.g. a Blackflag project may contain several
                     * versions of "blackflag.exe" from different build configs.
                     * Targeting all those would cause problems in DE, say, when
                     * setting a breakpoint during debug, DE would try to duplicate
                     * the break in all other "blackflag.exe", resulting various
                     * problems. ..... 08/30/06
                     */
                    if (binaryPath.lastSegment().equals(exePath.lastSegment()))
                        continue;

                    if (!binary.getPath().lastSegment().startsWith(".") && !binaryPath.equals(exePath)) { //$NON-NLS-1$
                        importedBinaries.add(binaryPath);
                    }
                }
            }
        }
        return importedBinaries;
    }

    private boolean projectMayHaveImportedExecutables(ICProject project) {
        try {
            IResource[] members = project.getProject().members();
            for (int i = 0; i < members.length; i++) {
                if (members[i].isLinked())
                    return true;
            }
        } catch (CoreException e) {
        }

        return false;
    }

    protected String getTargetLabel(String processName) {
        String format = "{0} (Launched {1})"; //$NON-NLS-1$
        String timestamp = DateFormat.getInstance().format(new Date(System.currentTimeMillis()));
        return MessageFormat.format(format, new Object[] { processName, timestamp });
    }

    protected String getCPUString() {
        // default. May be overridden.
        return "arm"; //$NON-NLS-1$
    }

    protected void showMessage(final String title, final String msg) {
        // Pop up a dialog telling user.
        Display display = Display.getCurrent();
        if (display == null) {
            display = Display.getDefault();
        }

        display.syncExec(new Runnable() {
            public void run() {
                MessageDialog.openWarning(CUIPlugin.getActiveWorkbenchShell(), title, msg);
            }
        });
    }

    @Override
    protected boolean existsErrors(IProject proj) throws CoreException {
        return CarbideCPPBuilder.projectHasBuildErrors(proj);
    }
}