org.eclipse.mylyn.internal.gerrit.ui.GerritRepositoryLocationUi.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.internal.gerrit.ui.GerritRepositoryLocationUi.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Tasktop Technologies and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.internal.gerrit.ui;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.mylyn.commons.net.Policy;
import org.eclipse.mylyn.commons.net.UnsupportedRequestException;
import org.eclipse.mylyn.commons.workbench.WorkbenchUtil;
import org.eclipse.mylyn.commons.workbench.browser.WebBrowserDialog;
import org.eclipse.mylyn.internal.gerrit.core.GerritConnector;
import org.eclipse.mylyn.internal.gerrit.core.client.IOpenIdLocation;
import org.eclipse.mylyn.internal.gerrit.core.client.OpenIdAuthenticationRequest;
import org.eclipse.mylyn.internal.gerrit.core.client.OpenIdAuthenticationResponse;
import org.eclipse.mylyn.internal.tasks.ui.TaskRepositoryLocationUi;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationAdapter;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;

/**
 * @author Steffen Pingel
 */
public class GerritRepositoryLocationUi extends TaskRepositoryLocationUi implements IOpenIdLocation {

    private static Object lock = new Object();

    private static volatile int version = 1;

    public GerritRepositoryLocationUi(TaskRepository taskRepository) {
        super(taskRepository);
    }

    @Override
    public String getProviderUrl() {
        if (Boolean.parseBoolean(taskRepository.getProperty(GerritConnector.KEY_REPOSITORY_OPEN_ID_ENABLED))) {
            return taskRepository.getProperty(GerritConnector.KEY_REPOSITORY_OPEN_ID_PROVIDER);
        }
        return null;
    }

    @Override
    public OpenIdAuthenticationResponse requestAuthentication(OpenIdAuthenticationRequest request,
            IProgressMonitor monitor) throws UnsupportedRequestException {
        if (Policy.isBackgroundMonitor(monitor)) {
            throw new UnsupportedRequestException();
        }

        final String repositoryUrl = taskRepository.getUrl();

        int currentVersion = version;
        // synchronize on a static lock to ensure that only one password dialog is displayed at a time
        synchronized (lock) {
            // check if the credentials changed while the thread was waiting for the lock
            if (currentVersion != version) {
                // another password prompt was shown, exit to try again
                return null;
            }

            return showAuthenticationDialog(repositoryUrl, request);
        }
    }

    private OpenIdAuthenticationResponse showAuthenticationDialog(final String repositoryUrl,
            final OpenIdAuthenticationRequest request) {
        final StringBuilder sb = new StringBuilder();
        try {
            for (Map.Entry<String, String> entry : request.getProviderArgs().entrySet()) {
                if (sb.length() > 0) {
                    sb.append("&"); //$NON-NLS-1$
                }
                sb.append(URLEncoder.encode(entry.getKey(), "UTF-8")); //$NON-NLS-1$
                sb.append("="); //$NON-NLS-1$
                sb.append(URLEncoder.encode(entry.getValue(), "UTF-8")); //$NON-NLS-1$
            }
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        final AtomicReference<OpenIdAuthenticationResponse> result = new AtomicReference<OpenIdAuthenticationResponse>();
        Display.getDefault().syncExec(new Runnable() {
            @Override
            public void run() {
                final WebBrowserDialog dialog = new WebBrowserDialog(WorkbenchUtil.getShell(), "Login", null,
                        "Login to OpenID Provider", MessageDialog.NONE,
                        new String[] { IDialogConstants.CANCEL_LABEL }, 0) {
                    @Override
                    protected Point getInitialSize() {
                        return new Point(780, 580);
                    }
                };
                dialog.create();

                dialog.getBrowser().addLocationListener(new LocationAdapter() {
                    @Override
                    public void changing(LocationEvent event) {
                        if (event.location != null && event.location.startsWith(request.getReturnUrl())) {
                            result.set(new OpenIdAuthenticationResponse(event.location, null));
                        }
                        // alternatively check cookies since IE does not notify listeners of redirects 
                        String value = Browser.getCookie(request.getCookie(), request.getCookieUrl());
                        if (value != null) {
                            result.set(new OpenIdAuthenticationResponse(event.location, value));
                        }
                        if (result.get() != null) {
                            event.doit = false;
                            // delay execution to avoid IE crash
                            dialog.getBrowser().getDisplay().asyncExec(new Runnable() {
                                @Override
                                public void run() {
                                    if (dialog.getShell() != null && !dialog.getShell().isDisposed()) {
                                        dialog.close();
                                    }
                                }
                            });
                        }
                    }
                });

                // navigate to login page
                dialog.getBrowser().setUrl(request.getRequestUrl() + "?" + sb.toString());
                dialog.open();
            }
        });
        return result.get();
    }
}