@Override
    protected void createDestinationGroup(Composite parent) {
      UIPlugin plugin = UIPlugin.getInstance();
      Group destinationGroup = new Group(parent, SWT.NONE);
      GridLayout layout = new GridLayout();
      destinationGroup.setLayout(layout);
      destinationGroup.setLayoutData(
          new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
      destinationGroup.setText(plugin.getString("_UI_Forge_Credentials_label"));
      destinationGroup.setFont(parent.getFont());

      Font font = destinationGroup.getFont();

      Label loginLabel = new Label(destinationGroup, SWT.NONE);
      loginLabel.setText(plugin.getString("_UI_Login_label"));
      loginLabel.setFont(font);

      loginField = new Text(destinationGroup, SWT.BORDER | SWT.READ_ONLY);
      GridData data = new GridData(GridData.FILL_HORIZONTAL);
      data.widthHint = SIZING_TEXT_FIELD_WIDTH;
      loginField.setLayoutData(data);
      loginField.setFont(font);

      Label passwordLabel = new Label(destinationGroup, SWT.NONE);
      passwordLabel.setText(plugin.getString("_UI_Password_label"));
      passwordLabel.setFont(font);

      passwordField = new Text(destinationGroup, SWT.BORDER | SWT.PASSWORD);
      data = new GridData(GridData.FILL_HORIZONTAL);
      data.widthHint = SIZING_TEXT_FIELD_WIDTH;
      passwordField.setLayoutData(data);
      passwordField.setFont(font);
      passwordField.addListener(SWT.Modify, this);
    }
    @Override
    public boolean validateSourceGroup() {
      if (!super.validateSourceGroup()) return false;

      try {
        @SuppressWarnings("unchecked")
        List<IResource> whiteCheckedResources = getWhiteCheckedResources();
        UIPlugin plugin = UIPlugin.getInstance();
        String owner = null;
        Diagnostic diag = new Diagnostic();
        for (ExportSpec spec : getExportSpecs(whiteCheckedResources)) {
          try {
            Metadata md =
                getForge()
                    .createFromModuleDirectory(
                        spec.getModuleRoot(), false, spec.getFileFilter(), null, diag);
            if (md != null) {
              ModuleName name = md.getName();
              if (owner == null) owner = name.getOwner();
              else if (!owner.equals(name.getOwner())) {
                setErrorMessage(plugin.getString("_UI_MultipleModuleOwners"));
                return false;
              }
            }
          } catch (IOException e) {
          }
        }

        if (owner == null) {
          setErrorMessage(plugin.getString("_UI_NoModulesSelected"));
          return false;
        }
        if (!owner.equals(loginField.getText())) {
          // Owner changed
          validationChange = true;
          try {
            loginField.setText(owner);
            String password = null;
            if (saveInSecureStoreButton.getSelection()) password = loadSecurePassword(owner);
            if (password == null) password = "";
            passwordField.setText(password);
          } finally {
            validationChange = false;
          }
        }
        return true;
      } catch (CoreException e) {
        setErrorMessage(e.getMessage());
        return false;
      }
    }
    @Override
    protected void createOptionsGroupButtons(Group optionsGroup) {
      UIPlugin plugin = UIPlugin.getInstance();
      Font font = optionsGroup.getFont();
      saveInSecureStoreButton = new Button(optionsGroup, SWT.CHECK);
      saveInSecureStoreButton.setText(plugin.getString("_UI_SaveInSecureStorage_label"));
      saveInSecureStoreButton.addListener(SWT.Selection, this);
      saveInSecureStoreButton.setFont(font);

      dryRunButton = new Button(optionsGroup, SWT.CHECK);
      dryRunButton.setText(plugin.getString("_UI_DryRun_label"));
      dryRunButton.setFont(font);
      dryRunButton.setSelection(false);
    }
    @Override
    public boolean finish() {
      // about to invoke the operation so save our state
      saveWidgetValues();

      if (!saveDirtyEditors())
        // User clicked on cancel when being asked to save dirty editors.
        return false;

      final Injector injector =
          UIPlugin.getInstance()
              .createInjector(
                  new OAuthModule(
                      FORGE_CLIENT_ID,
                      FORGE_CLIENT_SECRET,
                      loginField.getText(),
                      passwordField.getText()));
      try {
        @SuppressWarnings("unchecked")
        List<IResource> whiteCheckedResources = getWhiteCheckedResources();
        File tmpDir = new File(System.getProperty("java.io.tmpdir"));
        File destinationDir = File.createTempFile("forge-", ".tarballs", tmpDir);
        destinationDir.delete();
        destinationDir.mkdir();
        ModuleExportToForgeOperation exportOp =
            new ModuleExportToForgeOperation(
                getExportSpecs(whiteCheckedResources),
                destinationDir,
                dryRunButton.getSelection()) {

              @Override
              protected Forge getForge() {
                return injector.getInstance(Forge.class);
              }

              @Override
              protected ForgeService getForgeService() {
                return injector.getInstance(ForgeService.class);
              }
            };
        boolean result = executeExport(exportOp);
        Diagnostic diag = exportOp.getDiagnostic();
        if (diag.getSeverity() == Diagnostic.ERROR) {
          Exception e = diag.getException();
          ErrorDialog.openError(
              getContainer().getShell(),
              DataTransferMessages.DataTransfer_exportProblems,
              null, // no special message
              UIPlugin.createStatus(IStatus.ERROR, diag.toString(), e));
        } else
          MessageDialog.openInformation(
              getContainer().getShell(),
              DataTransferMessages.DataTransfer_information,
              diag.toString());
        return result;
      } catch (CoreException e) {
        ErrorDialog.openError(
            getContainer().getShell(),
            DataTransferMessages.DataTransfer_exportProblems,
            null, // no special message
            e.getStatus());
      } catch (Exception e) {
        ErrorDialog.openError(
            getContainer().getShell(),
            DataTransferMessages.DataTransfer_exportProblems,
            null,
            UIPlugin.createStatus(IStatus.ERROR, e.getMessage(), e));
      }
      return false;
    }