net.sourceforge.sqlexplorer.dbproduct.ConnectionJob.java Source code

Java tutorial

Introduction

Here is the source code for net.sourceforge.sqlexplorer.dbproduct.ConnectionJob.java

Source

/*
 * Copyright (C) 2007 SQL Explorer Development Team
 * http://sourceforge.net/projects/eclipsesql
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package net.sourceforge.sqlexplorer.dbproduct;

import java.sql.SQLException;

import net.sourceforge.sqlexplorer.Messages;
import net.sourceforge.sqlexplorer.connections.SessionEstablishedListener;
import net.sourceforge.sqlexplorer.dialogs.PasswordConnDlg;
import net.sourceforge.sqlexplorer.plugin.SQLExplorerPlugin;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;

/**
 * Establishes a connection in the background and notifies a listener when complete; takes
 * care of prompting the user for new username/password credentials if the login fails etc
 * @author John Spackman
 */
public class ConnectionJob extends Job {

    // The Alias to connect
    private Alias alias;

    // The User we're trying to log in
    private User user;

    // The callback to give the new session to
    private SessionEstablishedListener listener;

    // Whether to ask for the password on the first pass, instead of trying a saved one
    private boolean requirePassword;

    // True if the password dialog was cancelled
    private boolean cancelled;

    /**
     * Constructor
     * @param alias Alias to connect
     * @param user User to establish a connection for (can be null, but if provided user.getAlias() must match alias)
     * @param listener Callback listener
     * @param requirePassword Whether to always prompt the user for a password, even if one is already known
     */
    public ConnectionJob(Alias alias, User user, SessionEstablishedListener listener, boolean requirePassword) {
        super(Messages.getString("Progress.Connection.Title") + " " + alias.getName() + '/'
                + ((user != null) ? user.getUserName() : "?"));
        this.alias = alias;
        this.user = user;
        if (user != null && user.getAlias() != alias)
            throw new RuntimeException("Invalid User - users alias must match the alias provided");
        this.listener = listener;
        this.requirePassword = user == null || requirePassword;
        if (alias.hasNoUserName())
            requirePassword = false;
    }

    /**
     * Constructor; asks for a password on the first attempt only if the alias.isAutoLogin() is false
     * @param alias Alias to connect
     * @param user User to establish a connection for
     * @param listener Callback listener
     */
    public ConnectionJob(Alias alias, User user, SessionEstablishedListener listener) {
        this(alias, user, listener, !alias.isAutoLogon());
    }

    /**
     * Constructor; logs in a brand new user
     * @param alias Alias to connect
     * @param listener Callback listener
     */
    public ConnectionJob(Alias alias, SessionEstablishedListener listener) {
        this(alias, null, listener, true);
    }

    @Override
    protected IStatus run(IProgressMonitor monitor) {
        boolean firstPass = true;

        while (!monitor.isCanceled() && user != null && !cancelled) {
            Session session = null;
            Exception exception = null;

            // Try to login
            try {
                if (!firstPass || !requirePassword)
                    session = user.createSession();
                if (session != null) {
                    if (!user.hasAuthenticated()) {
                        SQLConnection connection = null;
                        try {
                            connection = session.grabConnection();
                        } catch (SQLException e) {
                            user.releaseSession(session);
                            session = null;
                            throw e;
                        } finally {
                            if (connection != null)
                                session.releaseConnection(connection);
                        }
                    }
                    if (listener != null)
                        listener.sessionEstablished(session);
                    return new Status(IStatus.OK, getClass().getName(), IStatus.OK,
                            Messages.getString("Progress.Connection.Success"), null);
                }
            } catch (SQLException e) {
                exception = e;
            }
            if (monitor.isCanceled())
                break;

            // Prompt for username and password
            promptForPassword(exception != null ? exception.getMessage() : null);

            // Always need to prompt for the password after the first pass
            firstPass = false;
        }

        // Can't do it
        if (listener != null)
            listener.cannotEstablishSession(user);
        return new Status(IStatus.CANCEL, getClass().getName(), IStatus.CANCEL,
                Messages.getString("Progress.Connection.Cancelled"), null);
    }

    /**
     * Prompts the user for a new username/password to attempt login with; if the dialog is
     * cancelled then this.user is set to null.
     * @param message
     */
    private void promptForPassword(final String message) {
        final Shell shell = SQLExplorerPlugin.getDefault().getSite().getShell();

        // Switch to the UI thread to run the password dialog, but run it synchronously so we
        //   wait for it to complete
        shell.getDisplay().syncExec(new Runnable() {
            public void run() {
                if (message != null) {
                    String title = Messages.getString("Progress.Connection.Title") + ' ' + alias.getName();
                    if (user != null && !alias.hasNoUserName())
                        title += '/' + user.getUserName();
                    if (alias.hasNoUserName()) {
                        MessageDialog dlg = new MessageDialog(shell, title, null,
                                Messages.getString("Progress.Connection.ErrorMessage_Part1") + "\n\n" + message,
                                MessageDialog.ERROR, new String[] { IDialogConstants.OK_LABEL }, 0);
                        dlg.open();
                        cancelled = true;
                        return;
                    } else {
                        MessageDialog dlg = new MessageDialog(shell, title, null,
                                Messages.getString("Progress.Connection.ErrorMessage_Part1") + "\n\n" + message
                                        + "\n\n" + Messages.getString("Progress.Connection.ErrorMessage_Part2"),
                                MessageDialog.ERROR,
                                new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL }, 0);
                        boolean retry = dlg.open() == 0;
                        if (!retry) {
                            cancelled = true;
                            return;
                        }
                    }
                }

                Shell shell = Display.getCurrent().getActiveShell();
                PasswordConnDlg dlg = new PasswordConnDlg(shell, user.getAlias(), user);
                if (dlg.open() != Window.OK) {
                    cancelled = true;
                    return;
                }

                // Create a new user and add it to the alias
                User userTmp = new User(dlg.getUserName(), dlg.getPassword());
                userTmp.setAutoCommit(dlg.getAutoCommit());
                userTmp.setCommitOnClose(dlg.getCommitOnClose());
                user = alias.addUser(userTmp);
            }
        });
    }

    /**
     * Establishes a connection in the background
     * @param alias Alias to connect
     * @param user User to establish a connection for
     * @param listener Callback listener
     */
    public static void createSession(Alias alias, User user, SessionEstablishedListener listener) {
        createSession(alias, user, listener, false);
    }

    /**
     * Establishes a connection in the background for a brand new set of user credentials
     * @param alias Alias to connect
     * @param user User to establish a connection for
     * @param listener Callback listener
     */
    public static void createSession(Alias alias, SessionEstablishedListener listener) {
        createSession(alias, null, listener, false);
    }

    /**
     * Establishes a connection in the background
     * @param alias Alias to connect
     * @param user User to establish a connection for
     * @param listener Callback listener
     * @param requirePassword Whether to always prompt the user for a password, even if one is already known
     */
    public static void createSession(Alias alias, User user, SessionEstablishedListener listener,
            boolean requirePassword) {
        final ConnectionJob bgJob = new ConnectionJob(alias, user, listener, requirePassword);
        final IWorkbenchSite site = SQLExplorerPlugin.getDefault().getSite();

        site.getShell().getDisplay().syncExec(new Runnable() {
            public void run() {
                IWorkbenchSiteProgressService siteps = (IWorkbenchSiteProgressService) site
                        .getAdapter(IWorkbenchSiteProgressService.class);
                siteps.showInDialog(site.getShell(), bgJob);
                bgJob.schedule();
            }
        });
    }
}