package org.nightlabs.jfire.auth.ui.editor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Collections;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.ViewerSorter;
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.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.statushandlers.StatusManager;
import org.nightlabs.base.ui.editor.ToolBarSectionPart;
import org.nightlabs.base.ui.entity.editor.EntityEditorUtil;
import org.nightlabs.base.ui.table.AbstractTableComposite;
import org.nightlabs.base.ui.util.RCPUtil;
import org.nightlabs.jfire.auth.ui.JFireAuthUIPlugin;
import org.nightlabs.jfire.auth.ui.UserManagementSystemActiveJDOTable;
import org.nightlabs.jfire.auth.ui.UserManagementSystemTable;
import org.nightlabs.jfire.auth.ui.UserManagementSystemUIMappingRegistry;
import org.nightlabs.jfire.base.JFireEjb3Factory;
import org.nightlabs.jfire.security.GlobalSecurityReflector;
import org.nightlabs.jfire.security.UserSecurityGroup;
import org.nightlabs.jfire.security.integration.UserManagementSystem;
import org.nightlabs.jfire.security.integration.UserManagementSystemManagerRemote;
import org.nightlabs.jfire.security.integration.UserManagementSystemSyncEvent;
import org.nightlabs.jfire.security.integration.UserManagementSystemType;
import org.nightlabs.jfire.security.integration.UserSecurityGroupSyncConfig;
import org.nightlabs.jfire.security.integration.UserSecurityGroupSyncConfigContainer;
import org.nightlabs.util.CollectionUtil;
/**
* Section of {@link UserSecurityGroupEditorSyncConfigPage} for editing generic options:
* select {@link UserManagementSystem}, configure if synchronization should be performed for selected {@link UserManagementSystem}
* (via {@link UserSecurityGroupSyncConfig}), run synchronization manually for this {@link UserSecurityGroup} and selected {@link UserManagementSystem}s.
*
* Does not work directly with edited {@link UserSecurityGroup} or {@link UserSecurityGroupSyncConfigContainer} instances
* but with {@link UserSecurityGroupSyncConfigGenericModel} which wraps around and performs model specific actions.
*
* @author Denis Dudnik <deniska.dudnik[at]gmail{dot}com>
*
*/
public class UserSecurityGroupSyncConfigGenericSection extends ToolBarSectionPart {
/**
* Set to <code>true</code> while automatic refreshing of UI elements
* happens. Some listeners are enabled at this time.
*/
private boolean refreshing = false;
private UserSecurityGroupSyncConfigGenericModel model;
private UserManagementSystemTable userManagementSystemTable;
public UserSecurityGroupSyncConfigGenericSection(IFormPage page, Composite parent) {
super(page, parent, ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.TITLE_BAR, "Synchronize to");
createContents(getSection(), page.getEditor().getToolkit());
}
/**
* {@inheritDoc}
*/
@Override
public boolean setFormInput(Object input) {
this.model = new UserSecurityGroupSyncConfigGenericModel((UserSecurityGroupSyncConfigContainer) input);
return super.setFormInput(input);
}
/**
* {@inheritDoc}
*/
@Override
public void refresh() {
refreshing = true;
try{
if (model != null){
userManagementSystemTable.setInput(model.getAllRelatedUserManagementSystems());
}
}finally{
refreshing = false;
}
super.refresh();
}
/**
* Adds given {@link ISelectionChangedListener} to underlying {@link UserManagementSystemActiveJDOTable}
*
* @param listener Can't be <code>null</code>, {@link IllegalArgumentException} will be thrown in this case
*/
public void addSelectionChangedListener(ISelectionChangedListener listener){
if (listener == null){
throw new IllegalArgumentException("ISelectionChangedListener can't be null!");
}
userManagementSystemTable.addSelectionChangedListener(listener);
}
/**
* Removes given {@link ISelectionChangedListener} from underlying {@link UserManagementSystemActiveJDOTable}
*
* @param listener Can't be <code>null</code>, {@link IllegalArgumentException} will be thrown in this case
*/
public void removeSelectionChangedListener(ISelectionChangedListener listener){
if (listener == null){
throw new IllegalArgumentException("ISelectionChangedListener can't be null!");
}
userManagementSystemTable.removeSelectionChangedListener(listener);
}
/**
* Get {@link UserSecurityGroupSyncConfig}s by selected {@link UserManagementSystem}s
*
* @return a {@link Collection} of {@link UserSecurityGroupSyncConfig}s which correspond to selected {@link UserManagementSystem}s
*/
public Collection<UserSecurityGroupSyncConfig<?, ?>> getSelectedSyncConfigs(){
if (!userManagementSystemTable.isDisposed()){
return model.getSyncConfigsForUserManagementSystems(userManagementSystemTable.getSelectedElements());
}
return Collections.emptyList();
}
private void createContents(Section section, FormToolkit toolkit){
section.setExpanded(true);
section.setLayout(new GridLayout());
section.setLayoutData(new GridData(GridData.FILL_BOTH));
Composite parent = EntityEditorUtil.createCompositeClient(toolkit, section, 1);
GridLayout parentLayout = (GridLayout) parent.getLayout();
parentLayout.verticalSpacing = 10;
parentLayout.marginTop = 10;
parentLayout.marginRight = 20;
GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
gd.heightHint = 200;
parent.setLayoutData(gd);
Composite wrapper = toolkit.createComposite(parent, SWT.NONE);
GridLayout gLayout = new GridLayout(5, false);
gLayout.verticalSpacing = 10;
gLayout.horizontalSpacing = 10;
gLayout.marginWidth = 0;
gLayout.marginHeight = 0;
wrapper.setLayout(gLayout);
gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
gd.minimumWidth = 600;
gd.widthHint = 600;
wrapper.setLayoutData(gd);
Button addSystemButton = toolkit.createButton(wrapper, "Add...", SWT.PUSH);
addSystemButton.setToolTipText("Open selector with available UserManagementSystems to be added for sync configuration");
gd = new GridData();
gd.widthHint = 100;
addSystemButton.setLayoutData(gd);
addSystemButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
SelectUserManagementSystemDialog dialog = new SelectUserManagementSystemDialog(getSection().getShell(), null);
if (Window.OK == dialog.open()){
if (model != null){
Collection<UserManagementSystem> selectedElements = dialog.getSelectedElements();
UserManagementSystem firstAdded = null;
for (UserManagementSystem userManagementSystem : selectedElements) {
if (!model.syncConfigExistsForUserManagementSystem(userManagementSystem)){
@SuppressWarnings("unchecked")
IUserSecurityGroupSyncConfigDelegate delegate = UserManagementSystemUIMappingRegistry.sharedInstance().getUserGroupSyncConfigDelegate(
(Class<? extends UserManagementSystemType<?>>) userManagementSystem.getType().getClass());
if (delegate != null
&& model.addSyncConfig(delegate.createSyncConfig(model.getSyncConfigsContainer(), userManagementSystem))
&& firstAdded == null){
firstAdded = userManagementSystem;
}
}
}
if (!refreshing) {
markDirty();
refresh();
if (firstAdded != null){
userManagementSystemTable.setSelectedElements(CollectionUtil.createArrayList(firstAdded));
}
}
}
}
}
});
final Button removeSystemButton = toolkit.createButton(wrapper, "Remove", SWT.PUSH);
removeSystemButton.setToolTipText("Remove selected UserManagementSystem(s) from this list, so synchronization of this group is no longer configured for them");
gd = new GridData();
gd.widthHint = 100;
removeSystemButton.setLayoutData(gd);
removeSystemButton.setEnabled(false);
removeSystemButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
if (model != null){
Collection<UserManagementSystem> selectedElements = userManagementSystemTable.getSelectedElements();
model.removeSyncConfigsForUserManagementSystems(selectedElements);
if (!refreshing) {
markDirty();
refresh();
}
}
}
});
final Button editSystemButton = toolkit.createButton(wrapper, "Open editor...", SWT.PUSH);
editSystemButton.setToolTipText("Open editor(s) for selected UserManagementSystem(s)");
gd = new GridData();
gd.widthHint = 100;
editSystemButton.setLayoutData(gd);
editSystemButton.setEnabled(false);
editSystemButton.addSelectionListener(new SelectionAdapter() {
@SuppressWarnings("unchecked")
@Override
public void widgetSelected(SelectionEvent event) {
Collection<UserManagementSystem> selectedElements = userManagementSystemTable.getSelectedElements();
Throwable lastThrowable = null;
for (UserManagementSystem userManagementSystem : selectedElements) {
if (userManagementSystem != null){
try {
RCPUtil.openEditor(
new UserManagementSystemEditorInput(
userManagementSystem.getUserManagementSystemObjectID(),
(Class<? extends UserManagementSystemType<?>>) userManagementSystem.getType().getClass()),
UserManagementSystemEditor.EDITOR_ID);
} catch (PartInitException e) {
lastThrowable = e;
StatusManager.getManager().handle(
new Status(Status.ERROR, JFireAuthUIPlugin.PLUGIN_ID, e.getMessage(), e),
StatusManager.LOG);
}
}
}
if (lastThrowable != null){
StatusManager.getManager().handle(
new Status(
Status.ERROR, JFireAuthUIPlugin.PLUGIN_ID,
"Exception(s) occured while opening editors for UserManagementSystems! See log for details, last one was: " + lastThrowable.getMessage(), lastThrowable),
StatusManager.SHOW);
}
}
});
final Button editSyncEnabledButton = toolkit.createButton(wrapper, "sync enabled?", SWT.CHECK);
editSyncEnabledButton.setToolTipText("Enable/disable synchronization of this UserSecurityGroup to/from selected UserManagementSystem(s)");
gd = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END);
editSyncEnabledButton.setLayoutData(gd);
editSyncEnabledButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
if (model != null){
Collection<UserManagementSystem> selectedElements = userManagementSystemTable.getSelectedElements();
model.setSyncEnabledForUserManagementSystems(selectedElements, editSyncEnabledButton.getSelection());
updateSyncEnabledCheckBoxButton(editSyncEnabledButton, selectedElements);
if (!refreshing) {
markDirty();
}
}
}
});
final Button startSyncButton = toolkit.createButton(wrapper, "Sync to all", SWT.PUSH);
startSyncButton.setToolTipText("Performs synchronization for this UserSecurityGroup to/from selected UserManagementSystem(s) or all if non selected, sync should be enabled");
gd = new GridData();
gd.widthHint = 100;
startSyncButton.setLayoutData(gd);
startSyncButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
if (model == null){
return;
}
final Collection<UserManagementSystem> systemsToSync = userManagementSystemTable.getSelectedElements();
if (systemsToSync.isEmpty()){
systemsToSync.addAll(userManagementSystemTable.getElements());
}
ProgressMonitorDialog progressMonitorDialog = new ProgressMonitorDialog(getSection().getShell());
progressMonitorDialog.setOpenOnRun(true);
progressMonitorDialog.setCancelable(true);
try {
progressMonitorDialog.run(true, true, new IRunnableWithProgress() {
@SuppressWarnings("unchecked")
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
monitor.beginTask(
"Synchronizing this User security group with user management system(s)...", systemsToSync.size());
try{
Throwable lastThrowable = null;
for (UserManagementSystem userManagementSystem : systemsToSync){
if (monitor.isCanceled()){
break;
}
if (!model.syncConfigExistsForUserManagementSystem(userManagementSystem)
|| !model.getSyncConfigForUserManagementSystem(userManagementSystem).isSyncEnabled()){
continue;
}
try {
Class<? extends UserManagementSystemType<?>> umsTypeClass = (Class<? extends UserManagementSystemType<?>>) userManagementSystem.getType().getClass();
IUserSecurityGroupSyncConfigDelegate delegate = UserManagementSystemUIMappingRegistry.sharedInstance().getUserGroupSyncConfigDelegate(umsTypeClass);
if (delegate == null){
StatusManager.getManager().handle(
new Status(
Status.ERROR, JFireAuthUIPlugin.PLUGIN_ID,
"Can't proceed with synchronization because IUserSecurityGroupSyncConfigDelegate is null for " + umsTypeClass.getName()),
StatusManager.LOG);
continue;
}
UserManagementSystemManagerRemote remoteBean = JFireEjb3Factory.getRemoteBean(
UserManagementSystemManagerRemote.class, GlobalSecurityReflector.sharedInstance().getInitialContextProperties());
UserManagementSystemSyncEvent syncEvent = delegate.createSyncEvent(
model.getSyncConfigForUserManagementSystem(userManagementSystem), userManagementSystem.isLeading());
remoteBean.runLDAPServerSynchronization(
userManagementSystem.getUserManagementSystemObjectID(), syncEvent);
} catch (Exception e) {
lastThrowable = e;
StatusManager.getManager().handle(
new Status(
Status.ERROR, JFireAuthUIPlugin.PLUGIN_ID, lastThrowable.getMessage(), lastThrowable),
StatusManager.LOG);
} finally {
monitor.worked(1);
}
}
if (lastThrowable != null){
throw new InvocationTargetException(lastThrowable);
}
}finally{
monitor.done();
}
}
});
} catch (InvocationTargetException e) {
Throwable lastThrowable = e.getTargetException();
StatusManager.getManager().handle(
new Status(
Status.ERROR, JFireAuthUIPlugin.PLUGIN_ID,
"Exception(s) occured while running synchronization! See log for details, last one was: " + lastThrowable.getMessage(), lastThrowable),
StatusManager.SHOW);
} catch (InterruptedException e) {
StatusManager.getManager().handle(
new Status(
Status.WARNING, JFireAuthUIPlugin.PLUGIN_ID,
e.getMessage(), e),
StatusManager.SHOW);
}
}
});
userManagementSystemTable = new UserManagementSystemTable(wrapper, AbstractTableComposite.DEFAULT_STYLE_SINGLE);
userManagementSystemTable.setLinesVisible(false);
userManagementSystemTable.setHeaderVisible(true);
userManagementSystemTable.getTableViewer().setSorter(new ViewerSorter());
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 5;
gd.heightHint = 300;
gd.minimumHeight = 200;
userManagementSystemTable.setLayoutData(gd);
userManagementSystemTable.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
Collection<UserManagementSystem> selectedElements = userManagementSystemTable.getSelectedElements();
boolean isEmpty = selectedElements.isEmpty();
removeSystemButton.setEnabled(!isEmpty);
editSystemButton.setEnabled(!isEmpty);
startSyncButton.setText(isEmpty ? "Sync to all" : "Sync to selected");
updateSyncEnabledCheckBoxButton(editSyncEnabledButton, selectedElements);
}
});
}
private void updateSyncEnabledCheckBoxButton(Button editSyncEnabledButton, Collection<UserManagementSystem> selectedElements){
if (model != null){
boolean syncEnabledAll = true;
boolean syncDisabledAll = true;
for (UserManagementSystem userManagementSystem : selectedElements) {
UserSecurityGroupSyncConfig<?, ?> syncConfig = model.getSyncConfigForUserManagementSystem(userManagementSystem);
if (syncConfig.isSyncEnabled()){
syncDisabledAll = false;
}else{
syncEnabledAll = false;
}
}
editSyncEnabledButton.setSelection(syncEnabledAll || (!syncEnabledAll && !syncDisabledAll));
editSyncEnabledButton.setGrayed(!syncEnabledAll && !syncDisabledAll);
}
}
}