/*******************************************************************************
* Copyright (c) 2015 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.foundation.ui.credentials;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.eclipse.equinox.security.storage.StorageException;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.jboss.tools.foundation.core.credentials.CredentialService;
import org.jboss.tools.foundation.core.credentials.ICredentialDomain;
import org.jboss.tools.foundation.ui.credentials.internal.NewCredentialUserDialog;
import org.jboss.tools.foundation.ui.internal.FoundationUIPlugin;
public class ChooseCredentialComponent {
protected ArrayList<ICredentialDomain> domainList;
protected ArrayList<ICredentialCompositeListener> listeners = new ArrayList<ICredentialCompositeListener>();
protected String initialUsername;
protected SelectionListener userComboListener, domainComboListener;
// Widgets
protected Combo domainCombo, userCombo;
protected Label domainLabel, usernameLabel;
protected Button addUser, editUser;
/**
* Draw the credential selection composite allowing all domains
*/
public ChooseCredentialComponent() {
this(null);
}
/**
* Draw the credential selection composite allowing selected domains,
* or, if null, all domains.
*
* @param parent The parent composite
* @param domains The selected domains, or null to mean all domains
*/
public ChooseCredentialComponent(String[] domains) {
this(domains, null);
}
/**
*
* @param parent
* @param domains
* @param selectedUsername
*/
public ChooseCredentialComponent(String[] domains, String selectedUsername) {
initialUsername = selectedUsername;
domainList = findDomains(domains);
}
public void create(Composite parent) {
createWidgets(parent);
addWidgetListeners();
refreshUserCombo(true);
}
protected void createWidgets(Composite parent) {
domainLabel = new Label(parent, SWT.NONE);
domainLabel.setText("Domain: ");
domainCombo = new Combo(parent, SWT.READ_ONLY);
domainCombo.setItems(findDomainNames(domainList));
domainCombo.select(0);
usernameLabel = new Label(parent, SWT.NONE);
usernameLabel.setText("Username: ");
userCombo = new Combo(parent, SWT.READ_ONLY);
Composite editAddParent = parent;
if( showEditButton()) {
editAddParent = new Composite(parent, SWT.NONE);
editAddParent.setLayout(new GridLayout(2, false));
editUser = new Button(editAddParent, SWT.PUSH);
editUser.setText("Edit...");
}
addUser = new Button(editAddParent, SWT.PUSH);
addUser.setText("Add...");
if( domainList.size() == 1 ) {
domainCombo.setEnabled(false);
}
}
protected void addWidgetListeners() {
// Adding listeners
domainComboListener = new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
refreshUserCombo();
}
};
domainCombo.addSelectionListener(domainComboListener);
userComboListener = new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
fireChanged();
}
};
userCombo.addSelectionListener(userComboListener);
addUser.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
addUserPressed();
}
});
if( editUser != null ) {
editUser.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
editUserPressed();
}
});
}
}
private void editUserPressed() {
NewCredentialUserDialog dialog = new NewCredentialUserDialog(
domainCombo.getShell(), CredentialService.getCredentialModel(), getDomain(), getUser());
if( dialog.open() == Window.OK) {
CredentialService.getCredentialModel().removeCredentials(getDomain(), getUser());
credentialDialogOkPressed(dialog);
}
}
private void addUserPressed() {
NewCredentialUserDialog dialog = new NewCredentialUserDialog(
domainCombo.getShell(),
CredentialService.getCredentialModel(), getDomain());
if( dialog.open() == Window.OK) {
credentialDialogOkPressed(dialog);
}
}
private void credentialDialogOkPressed(NewCredentialUserDialog dialog) {
ICredentialDomain cd = dialog.getDomain();
String name = dialog.getUser();
String pass = dialog.getPass();
if( dialog.isAlwaysPrompt()) {
CredentialService.getCredentialModel().addPromptedCredentials(cd, name);
} else {
CredentialService.getCredentialModel().addCredentials(cd, name, pass);
}
CredentialService.getCredentialModel().save();
refreshUserCombo(name, true);
}
private void refreshUserCombo() {
refreshUserCombo(false);
}
private void refreshUserCombo(boolean initial) {
if( initial ) {
refreshUserCombo(initialUsername, false);
} else {
refreshUserCombo(null, true);
}
}
private void refreshUserCombo(String user, boolean fire) {
ICredentialDomain d = getDomain();
if( d != null ) {
String[] userNames = d.getUsernames();
userCombo.setItems(userNames);
if( userNames.length > 0 ) {
if( user == null ) {
userCombo.select(0);
} else {
int ind = Arrays.asList(userNames).indexOf(user);
if( ind == -1 ) {
userCombo.select(0);
} else {
userCombo.select(ind);
}
}
}
}
if( fire )
fireChanged();
userCombo.getParent().layout(false, false);
userCombo.getParent().update();
}
protected void fireChanged() {
Iterator<ICredentialCompositeListener> it = listeners.iterator();
while(it.hasNext()) {
it.next().credentialsChanged();
}
}
protected boolean showEditButton() {
return true;
}
private String[] findDomainNames(List<ICredentialDomain> domains) {
ArrayList<String> ret = new ArrayList<String>();
Iterator<ICredentialDomain> it = domains.iterator();
while(it.hasNext()) {
String name = it.next().getName();
ret.add(name);
}
return (String[]) ret.toArray(new String[ret.size()]);
}
private ArrayList<ICredentialDomain> findDomains(String[] domains) {
ArrayList<ICredentialDomain> list = new ArrayList<ICredentialDomain>();
if( domains == null ) {
ICredentialDomain[] domainArr = CredentialService.getCredentialModel().getDomains();
list.addAll(Arrays.asList(domainArr));
} else {
for( int i = 0; i < domains.length; i++ ) {
ICredentialDomain domain = CredentialService.getCredentialModel().getDomain(domains[i]);
if( domain != null ) {
list.add(domain);
}
}
}
return list;
}
public void addCredentialListener(ICredentialCompositeListener listener) {
listeners.add(listener);
}
public void removeCredentialListener(ICredentialCompositeListener listener) {
listeners.remove(listener);
}
public ICredentialDomain getDomain() {
int ind = domainCombo.getSelectionIndex();
if( ind != -1 ) {
ICredentialDomain d = domainList.get(ind);
return d;
}
return null;
}
public String getUser() {
int userIndex = userCombo.getSelectionIndex();
return userIndex == -1 ? null : userCombo.getItem(userIndex);
}
public String getPassword() {
ICredentialDomain cd = getDomain();
if( cd != null ) {
try {
return cd.getPassword(getUser());
} catch(StorageException se) {
FoundationUIPlugin.pluginLog().logError(se);
}
}
return null;
}
public void setEnabled (boolean enabled) {
if( !enabled ) {
domainCombo.setEnabled(false);
userCombo.setEnabled(false);
} else {
domainCombo.setEnabled(domainList.size() != 1);
userCombo.setEnabled(true);
}
}
/**
* To be called only after create
* Lays out the widgets into a pre-existing grid layout with n columns
* @param columns
*/
public void gridLayout(int n) {
if( n == 2 ) {
// We're in a 2 column grid
GridData gd2 = new GridData();
gd2.widthHint = 200;
domainCombo.setLayoutData(gd2);
userCombo.setLayoutData(gd2);
GridData gd3 = new GridData();
gd3.horizontalSpan = 2;
addUser.setLayoutData(gd3);
} else if( n >= 3 ) {
// We're in a three column grid
GridData domainData = new GridData();
domainData.widthHint = 200;
domainData.horizontalSpan = n-1;
domainData.horizontalAlignment = SWT.FILL;
domainCombo.setLayoutData(domainData);
GridData userData = new GridData();
userData.widthHint = 200;
userData.horizontalSpan = n - 2;
userData.grabExcessHorizontalSpace = true;
userData.horizontalAlignment = SWT.FILL;
userCombo.setLayoutData(userData);
GridData gd3 = new GridData();
gd3.horizontalAlignment = SWT.FILL;
addUser.setLayoutData(gd3);
}
}
public Combo getUserCombo() {
return userCombo;
}
public Combo getDomainCombo() {
return domainCombo;
}
public SelectionListener getUserListener() {
return userComboListener;
}
public SelectionListener getDomainListener() {
return domainComboListener;
}
}