@Override
  public void launch(ISelection selection, String mode) {
    if (!(selection instanceof IStructuredSelection)) {
      return;
    }

    Object s = ((IStructuredSelection) selection).getFirstElement();
    if (!(s instanceof IAdaptable)) {
      return;
    }

    IResource r = (IResource) ((IAdaptable) s).getAdapter(IResource.class);
    if (r == null) {
      return;
    }

    IProject project = r.getProject();
    if (project == null) {
      return;
    }

    // verify that this is a non library Android project
    ProjectState state = Sdk.getProjectState(project);
    if (state == null || state.isLibrary()) {
      return;
    }

    // verify that this project has C/C++ nature
    if (!CoreModel.hasCCNature(project) && !CoreModel.hasCNature(project)) {
      AndmoreAndroidPlugin.printErrorToConsole(
          project,
          String.format(
              "Selected project (%s) does not have C/C++ nature. "
                  + "To add native support, right click on the project, "
                  + "Android Tools -> Add Native Support",
              project.getName()));
      return;
    }

    debugProject(project, mode);
  }
  private void debugProject(IProject project, String mode) {
    // obtain existing native debug config for project
    ILaunchConfiguration config =
        AndroidLaunchController.getLaunchConfig(project, NdkGdbLaunchDelegate.LAUNCH_TYPE_ID);
    if (config == null) {
      return;
    }

    // Set the ndk gdb specific launch attributes in the config (if
    // necessary)
    if (!hasNdkAttributes(config)) {
      try {
        config = setNdkDefaults(config, project);
      } catch (CoreException e) {
        AndmoreAndroidPlugin.printErrorToConsole(
            project, "Unable to create launch configuration for project.");
        return;
      }
    }

    // launch
    DebugUITools.launch(config, mode);
  }
  private static List<IClasspathEntry> convertJarsToClasspathEntries(
      final IProject iProject, Set<File> jarFiles) {
    List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>(jarFiles.size());

    // and process the jar files list, but first sanitize it to remove dups.
    JarListSanitizer sanitizer =
        new JarListSanitizer(
            iProject.getFolder(SdkConstants.FD_OUTPUT).getLocation().toFile(),
            new AndroidPrintStream(iProject, null /*prefix*/, AndmoreAndroidPlugin.getOutStream()));

    String errorMessage = null;

    try {
      List<File> sanitizedList = sanitizer.sanitize(jarFiles);

      for (File jarFile : sanitizedList) {
        if (jarFile instanceof CPEFile) {
          CPEFile cpeFile = (CPEFile) jarFile;
          IClasspathEntry e = cpeFile.getClasspathEntry();

          entries.add(
              JavaCore.newLibraryEntry(
                  e.getPath(),
                  e.getSourceAttachmentPath(),
                  e.getSourceAttachmentRootPath(),
                  e.getAccessRules(),
                  e.getExtraAttributes(),
                  true /*isExported*/));
        } else {
          String jarPath = jarFile.getAbsolutePath();

          IPath sourceAttachmentPath = null;
          IClasspathAttribute javaDocAttribute = null;

          File jarProperties = new File(jarPath + DOT_PROPERTIES);
          if (jarProperties.isFile()) {
            Properties p = new Properties();
            InputStream is = null;
            try {
              p.load(is = new FileInputStream(jarProperties));

              String value = p.getProperty(ATTR_SRC);
              if (value != null) {
                File srcPath = getFile(jarFile, value);

                if (srcPath.exists()) {
                  sourceAttachmentPath = new Path(srcPath.getAbsolutePath());
                }
              }

              value = p.getProperty(ATTR_DOC);
              if (value != null) {
                File docPath = getFile(jarFile, value);
                if (docPath.exists()) {
                  try {
                    javaDocAttribute =
                        JavaCore.newClasspathAttribute(
                            IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME,
                            docPath.toURI().toURL().toString());
                  } catch (MalformedURLException e) {
                    AndmoreAndroidPlugin.log(
                        e,
                        "Failed to process 'doc' attribute for %s",
                        jarProperties.getAbsolutePath());
                  }
                }
              }

            } catch (FileNotFoundException e) {
              // shouldn't happen since we check upfront
            } catch (IOException e) {
              AndmoreAndroidPlugin.log(e, "Failed to read %s", jarProperties.getAbsolutePath());
            } finally {
              if (is != null) {
                try {
                  is.close();
                } catch (IOException e) {
                  // ignore
                }
              }
            }
          }

          if (javaDocAttribute != null) {
            entries.add(
                JavaCore.newLibraryEntry(
                    new Path(jarPath),
                    sourceAttachmentPath,
                    null /*sourceAttachmentRootPath*/,
                    new IAccessRule[0],
                    new IClasspathAttribute[] {javaDocAttribute},
                    true /*isExported*/));
          } else {
            entries.add(
                JavaCore.newLibraryEntry(
                    new Path(jarPath),
                    sourceAttachmentPath,
                    null /*sourceAttachmentRootPath*/,
                    true /*isExported*/));
          }
        }
      }
    } catch (DifferentLibException e) {
      errorMessage = e.getMessage();
      AndmoreAndroidPlugin.printErrorToConsole(iProject, (Object[]) e.getDetails());
    } catch (Sha1Exception e) {
      errorMessage = e.getMessage();
    }

    processError(
        iProject,
        errorMessage,
        AndmoreAndroidConstants.MARKER_DEPENDENCY,
        true /*outputToConsole*/);

    return entries;
  }