@Override
  public boolean performFinish() {
    // save the properties
    ProjectHelper.saveStringProperty(mProject, PROPERTY_KEYSTORE, mKeystore);
    ProjectHelper.saveStringProperty(mProject, PROPERTY_ALIAS, mKeyAlias);
    ProjectHelper.saveStringProperty(
        mProject, PROPERTY_DESTINATION, mDestinationFile.getAbsolutePath());

    // run the export in an UI runnable.
    IWorkbench workbench = PlatformUI.getWorkbench();
    final boolean[] result = new boolean[1];
    try {
      workbench
          .getProgressService()
          .busyCursorWhile(
              new IRunnableWithProgress() {
                /**
                 * Run the export.
                 *
                 * @throws InvocationTargetException
                 * @throws InterruptedException
                 */
                @Override
                public void run(IProgressMonitor monitor)
                    throws InvocationTargetException, InterruptedException {
                  try {
                    result[0] = doExport(monitor);
                  } finally {
                    monitor.done();
                  }
                }
              });
    } catch (InvocationTargetException e) {
      return false;
    } catch (InterruptedException e) {
      return false;
    }

    return result[0];
  }
  private void buildErrorUi(IProject project) {
    // Show description the first time
    setErrorMessage(null);
    setMessage(null);
    setPageComplete(true);
    mHasMessage = false;

    // composite parent for the warning/error
    GridLayout gl = null;
    mErrorComposite = new Composite(mTopComposite, SWT.NONE);
    mErrorComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    gl = new GridLayout(2, false);
    gl.marginHeight = gl.marginWidth = 0;
    gl.verticalSpacing *= 3; // more spacing than normal.
    mErrorComposite.setLayout(gl);

    if (project == null) {
      setErrorMessage("Select project to export.");
      mHasMessage = true;
    } else {
      try {
        if (project.hasNature(AndroidConstants.NATURE) == false) {
          addError(mErrorComposite, "Project is not an Android project.");
        } else {
          // check for errors
          if (ProjectHelper.hasError(project, true)) {
            addError(mErrorComposite, "Project has compilation error(s)");
          }

          // check the project output
          IFolder outputIFolder = BaseProjectHelper.getOutputFolder(project);
          if (outputIFolder != null) {
            String outputOsPath = outputIFolder.getLocation().toOSString();
            String apkFilePath =
                outputOsPath
                    + File.separator
                    + project.getName()
                    + AndroidConstants.DOT_ANDROID_PACKAGE;

            File f = new File(apkFilePath);
            if (f.isFile() == false) {
              addError(
                  mErrorComposite,
                  String.format(
                      "%1$s/%2$s/%1$s%3$s does not exists!",
                      project.getName(),
                      outputIFolder.getName(),
                      AndroidConstants.DOT_ANDROID_PACKAGE));
            }
          } else {
            addError(mErrorComposite, "Unable to get the output folder of the project!");
          }

          // project is an android project, we check the debuggable attribute.
          AndroidManifestParser manifestParser =
              AndroidManifestParser.parse(
                  BaseProjectHelper.getJavaProject(project),
                  null /* errorListener */,
                  true /* gatherData */,
                  false /* markErrors */);

          Boolean debuggable = manifestParser.getDebuggable();

          if (debuggable != null && debuggable == Boolean.TRUE) {
            addWarning(
                mErrorComposite,
                "The manifest 'debuggable' attribute is set to true.\nYou should set it to false for applications that you release to the public.");
          }

          // check for mapview stuff
        }
      } catch (CoreException e) {
        // unable to access nature
        addError(mErrorComposite, "Unable to get project nature");
      }
    }

    if (mHasMessage == false) {
      Label label = new Label(mErrorComposite, SWT.NONE);
      GridData gd = new GridData(GridData.FILL_HORIZONTAL);
      gd.horizontalSpan = 2;
      label.setLayoutData(gd);
      label.setText("No errors found. Click Next.");
    }

    mTopComposite.layout();
  }