package org.nightlabs.jfire.auth.ui.ldap.tree; import javax.security.auth.login.LoginException; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.nightlabs.base.ui.layout.WeightedTableLayout; import org.nightlabs.base.ui.resource.SharedImages; import org.nightlabs.base.ui.resource.SharedImages.ImageDimension; import org.nightlabs.base.ui.resource.SharedImages.ImageFormat; import org.nightlabs.base.ui.table.TableLabelProvider; import org.nightlabs.base.ui.tree.AbstractTreeComposite; import org.nightlabs.base.ui.tree.TreeContentProvider; import org.nightlabs.base.ui.util.RCPUtil; import org.nightlabs.jfire.auth.ui.ldap.LDAPEntrySelectorComposite.BindCredentials; import org.nightlabs.jfire.auth.ui.ldap.LdapUIPlugin; import org.nightlabs.jfire.auth.ui.ldap.resource.Messages; import org.nightlabs.jfire.auth.ui.ldap.tree.LDAPTreeEntry.LDAPTreeEntryLoadCallback; import org.nightlabs.jfire.base.security.integration.ldap.attributes.LDAPAttributeSet; import org.nightlabs.jfire.base.security.integration.ldap.connection.ILDAPConnectionParamsProvider; import org.nightlabs.util.CollectionUtil; /** * Tree of LDAP entries. Either {@link ILDAPConnectionParamsProvider} or root {@link LDAPTreeEntry} objects should * be passed as input for this tree when calling {@link #setInput(Object)}. In case root {@link LDAPTreeEntry} objects are set * they SHOULD have {@link ILDAPConnectionParamsProvider} set to each of them. * * {@link LDAPTree} handles load entry events and shows {@link LDAPBindCredentialsDialog} in case attemted LDAP directory has no * anonymous access. Actual communication with LDAP directory happens inside {@link LDAPTreeEntry} class. * * @author Denis Dudnik <deniska.dudnik[at]gmail{dot}com> * */ public class LDAPTree extends AbstractTreeComposite<LDAPTreeEntry> implements LDAPTreeEntryLoadCallback{ /** * Credentials for binding against LDAP directory. */ private BindCredentials bindCredentials; /** * {@inheritDoc} */ public LDAPTree(Composite parent) { super(parent); } /** * {@inheritDoc} */ public LDAPTree(Composite parent, int style) { super(parent, style); } /** * {@inheritDoc} */ public LDAPTree(Composite parent, boolean init) { super(parent, init); } /** * {@inheritDoc} */ public LDAPTree(Composite parent, int style, boolean setLayoutData, boolean init, boolean headerVisible) { super(parent, style, setLayoutData, init, headerVisible); } /** * {@inheritDoc} */ public LDAPTree(Composite parent, int style, boolean setLayoutData, boolean init, boolean headerVisible, boolean sortColumns) { super(parent, style, setLayoutData, init, headerVisible, sortColumns); } /** * {@inheritDoc} */ @Override public void setTreeProvider(TreeViewer treeViewer) { treeViewer.setContentProvider(new LDAPTreeContentProvider()); treeViewer.setLabelProvider(new LDAPTreeLabelProvider()); } /** * {@inheritDoc} */ @Override public void createTreeColumns(Tree tree) { new TreeColumn(tree, SWT.LEFT).setText(Messages.getString("org.nightlabs.jfire.auth.ui.ldap.tree.LDAPTree.treeColumnLDAPEntries")); //$NON-NLS-1$ tree.setLayout(new WeightedTableLayout(new int[]{100})); } /** * {@inheritDoc} */ @Override public void treeEntryLoaded(final LDAPTreeEntry loadedEntry) { if (!isDisposed()){ getDisplay().asyncExec(new Runnable() { @Override public void run() { if (getInput() instanceof ILDAPConnectionParamsProvider){ setInput(loadedEntry.getChildren(null)); }else{ refresh(loadedEntry, true); } } }); } } /** * {@inheritDoc} */ @Override public void hadleTreeEntryLoadError(Throwable cause) { if (cause instanceof LoginException){ if (!isDisposed()){ getDisplay().asyncExec(new Runnable() { @Override public void run() { // showing dialog for entering bind login/password LDAPBindCredentialsDialog dlg = new LDAPBindCredentialsDialog(RCPUtil.getActiveShell(), null); if (Window.OK == dlg.open()){ final String login = dlg.getLogin(); final String password = dlg.getPassword(); bindCredentials = new BindCredentials() { @Override public String getPassword() { return password; } @Override public String getLogin() { return login; } }; refresh(); } } }); } }else{ throw new RuntimeException(cause); } } /** * Set {@link BindCredentials} to be used when binding against LDAP directory. If not set and LDAP directory does not allow * anonymous access than simple dialog {@link LDAPBindCredentialsDialog} will be shown when tree content provider will try to load data. * * @param bindCredentials */ public void setBindCredentials(BindCredentials bindCredentials) { this.bindCredentials = bindCredentials; } private static final String OBJECT_CLASS_ATTRIBUTE = "objectClass"; //$NON-NLS-1$ class LDAPTreeContentProvider extends TreeContentProvider{ private ILDAPConnectionParamsProvider ldapConnectionParamsProvider; private LDAPTreeEntry[] rootEntries; @Override public Object[] getChildren(final Object parentElement) { if (parentElement instanceof LDAPTreeEntry){ LDAPTreeEntry[] children = ((LDAPTreeEntry) parentElement).getChildren(bindCredentials, LDAPTree.this); if (children != null){ return children; } return new String[]{Messages.getString("org.nightlabs.jfire.auth.ui.ldap.tree.LDAPTree.loadingText")}; //$NON-NLS-1$ } return super.getChildren(parentElement); } public boolean hasChildren(Object element) { return true; } @Override public Object[] getElements(Object obj) { if (rootEntries == null){ LDAPTreeEntry rootTreeEntry = new LDAPTreeEntry("", new String[]{OBJECT_CLASS_ATTRIBUTE}); //$NON-NLS-1$ rootTreeEntry.setLdapConnectionParamsProvider(ldapConnectionParamsProvider); return getChildren(rootTreeEntry); }else{ return rootEntries; } } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (newInput instanceof ILDAPConnectionParamsProvider){ this.ldapConnectionParamsProvider = (ILDAPConnectionParamsProvider) newInput; }else if (newInput instanceof LDAPTreeEntry[]){ this.rootEntries = (LDAPTreeEntry[]) newInput; }else{ super.inputChanged(viewer, oldInput, newInput); } } } class LDAPTreeLabelProvider extends TableLabelProvider{ private static final String POSIXACCOUNT = "posixAccount"; //$NON-NLS-1$ private static final String PERSON = "person"; //$NON-NLS-1$ private static final String ORGANIZATIONALUNIT = "organizationalUnit"; //$NON-NLS-1$ private static final String ORGANIZATION = "organization"; //$NON-NLS-1$ private static final String GROUP_OF_NAMES = "groupOfNames"; //$NON-NLS-1$ private static final String GROUP_OF_UNIQUE_NAMES = "groupOfUniqueNames"; //$NON-NLS-1$ @Override public String getColumnText(Object obj, int i) { if (obj instanceof String){ return (String) obj; }else if (obj instanceof LDAPTreeEntry){ return ((LDAPTreeEntry) obj).getName(); } return ""; //$NON-NLS-1$ } @Override public Image getColumnImage(Object element, int columnIndex) { if (element instanceof LDAPTreeEntry){ return getImageForEntry((LDAPTreeEntry) element); } return super.getColumnImage(element, columnIndex); } @Override public Image getImage(Object element) { if (element instanceof LDAPTreeEntry){ return getImageForEntry((LDAPTreeEntry) element); } return super.getImage(element); } private Image getImageForEntry(LDAPTreeEntry entry){ if (!"".equals(entry.getName()) && entry.hasAttributesLoaded()){ //$NON-NLS-1$ try { LDAPAttributeSet attributes = entry.getAttributes(bindCredentials); if (attributes.containsAnyAttributeValue(OBJECT_CLASS_ATTRIBUTE, CollectionUtil.createHashSet(ORGANIZATIONALUNIT, ORGANIZATION))){ return SharedImages.getSharedImage( LdapUIPlugin.sharedInstance(), LDAPTree.class, "treeNodeOrg", ImageDimension._16x16.toString(), ImageFormat.png //$NON-NLS-1$ ); }else if (attributes.containsAnyAttributeValue(OBJECT_CLASS_ATTRIBUTE, CollectionUtil.createHashSet(PERSON, POSIXACCOUNT))){ return SharedImages.getSharedImage( LdapUIPlugin.sharedInstance(), LDAPTree.class, "treeNodeUser", ImageDimension._16x16.toString(), ImageFormat.png //$NON-NLS-1$ ); }else if (attributes.containsAnyAttributeValue(OBJECT_CLASS_ATTRIBUTE, CollectionUtil.createHashSet(GROUP_OF_NAMES, GROUP_OF_UNIQUE_NAMES))){ return SharedImages.getSharedImage( LdapUIPlugin.sharedInstance(), LDAPTree.class, "treeNodeUserGroup", ImageDimension._16x16.toString(), ImageFormat.png //$NON-NLS-1$ ); } } catch (Exception e) { // do nothing, just show default image } } return SharedImages.getSharedImage( LdapUIPlugin.sharedInstance(), LDAPTree.class, "treeNode", ImageDimension._16x16.toString(), ImageFormat.png //$NON-NLS-1$ ); } } }