Move auth related widgets to CMS
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 28 Apr 2015 08:46:37 +0000 (08:46 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 28 Apr 2015 08:46:37 +0000 (08:46 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8080 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.cms/src/org/argeo/cms/widgets/auth/AbstractLoginDialog.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/widgets/auth/CompositeCallbackHandler.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/widgets/auth/DefaultLoginDialog.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java
org.argeo.security.ui/pom.xml
org.argeo.security.ui/src/org/argeo/security/ui/SecurityUiPlugin.java
org.argeo.security.ui/src/org/argeo/security/ui/auth/AbstractLoginDialog.java [deleted file]
org.argeo.security.ui/src/org/argeo/security/ui/auth/CompositeCallbackHandler.java [deleted file]
org.argeo.security.ui/src/org/argeo/security/ui/auth/DefaultLoginDialog.java [deleted file]

diff --git a/org.argeo.cms/src/org/argeo/cms/widgets/auth/AbstractLoginDialog.java b/org.argeo.cms/src/org/argeo/cms/widgets/auth/AbstractLoginDialog.java
new file mode 100644 (file)
index 0000000..a9ed1c7
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.widgets.auth;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.internal.kernel.Activator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.operation.ModalContext;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/** Base for login dialogs */
+public abstract class AbstractLoginDialog extends TrayDialog implements
+               CallbackHandler {
+       private static final long serialVersionUID = -8046708963512717709L;
+
+       private final static Log log = LogFactory.getLog(AbstractLoginDialog.class);
+
+       private Thread modalContextThread = null;
+       boolean processCallbacks = false;
+       boolean isCancelled = false;
+       Callback[] callbackArray;
+
+       protected final Callback[] getCallbacks() {
+               return this.callbackArray;
+       }
+
+       public abstract void internalHandle();
+
+       public boolean isCancelled() {
+               return isCancelled;
+       }
+
+       protected AbstractLoginDialog(Shell parentShell) {
+               super(parentShell);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth
+        * .callback.Callback[])
+        */
+       public void handle(final Callback[] callbacks) throws IOException {
+               // clean previous usage
+               if (processCallbacks) {
+                       // this handler was already used
+                       processCallbacks = false;
+               }
+
+               if (modalContextThread != null) {
+                       try {
+                               modalContextThread.join(1000);
+                       } catch (InterruptedException e) {
+                               // silent
+                       }
+                       modalContextThread = null;
+               }
+
+               // initialize
+               this.callbackArray = callbacks;
+               final Display display = Display.getDefault();
+               display.syncExec(new Runnable() {
+
+                       public void run() {
+                               isCancelled = false;
+                               setBlockOnOpen(false);
+                               open();
+
+                               final Button okButton = getButton(IDialogConstants.OK_ID);
+                               okButton.setText("Login");
+                               okButton.addSelectionListener(new SelectionListener() {
+                                       private static final long serialVersionUID = -200281625679096775L;
+
+                                       public void widgetSelected(final SelectionEvent event) {
+                                               processCallbacks = true;
+                                       }
+
+                                       public void widgetDefaultSelected(final SelectionEvent event) {
+                                               // nothing to do
+                                       }
+                               });
+                               final Button cancel = getButton(IDialogConstants.CANCEL_ID);
+                               cancel.addSelectionListener(new SelectionListener() {
+                                       private static final long serialVersionUID = -3826030278084915815L;
+
+                                       public void widgetSelected(final SelectionEvent event) {
+                                               isCancelled = true;
+                                               processCallbacks = true;
+                                       }
+
+                                       public void widgetDefaultSelected(final SelectionEvent event) {
+                                               // nothing to do
+                                       }
+                               });
+                       }
+               });
+               try {
+                       ModalContext.setAllowReadAndDispatch(true); // Works for now.
+                       ModalContext.run(new IRunnableWithProgress() {
+
+                               public void run(final IProgressMonitor monitor) {
+                                       modalContextThread = Thread.currentThread();
+                                       // Wait here until OK or cancel is pressed, then let it rip.
+                                       // The event
+                                       // listener
+                                       // is responsible for closing the dialog (in the
+                                       // loginSucceeded
+                                       // event).
+                                       while (!processCallbacks && (modalContextThread != null)
+                                                       && (modalContextThread == Thread.currentThread())
+                                                       && Activator.getBundleContext() != null) {
+                                               // Note: SecurityUiPlugin.getDefault() != null is false
+                                               // when the OSGi runtime is shut down
+                                               try {
+                                                       Thread.sleep(100);
+                                                       // if (display.isDisposed()) {
+                                                       // log.warn("Display is disposed, killing login dialog thread");
+                                                       // throw new ThreadDeath();
+                                                       // }
+                                               } catch (final Exception e) {
+                                                       // do nothing
+                                               }
+                                       }
+                                       processCallbacks = false;
+                                       // Call the adapter to handle the callbacks
+                                       if (!isCancelled())
+                                               internalHandle();
+                                       else
+                                               // clear callbacks are when cancelling
+                                               for (Callback callback : callbacks)
+                                                       if (callback instanceof PasswordCallback) {
+                                                               char[] arr = ((PasswordCallback) callback)
+                                                                               .getPassword();
+                                                               if (arr != null) {
+                                                                       Arrays.fill(arr, '*');
+                                                                       ((PasswordCallback) callback)
+                                                                                       .setPassword(null);
+                                                               }
+                                                       } else if (callback instanceof NameCallback)
+                                                               ((NameCallback) callback).setName(null);
+                               }
+                       }, true, new NullProgressMonitor(), Display.getDefault());
+               } catch (ThreadDeath e) {
+                       isCancelled = true;
+                       log.debug("Thread " + Thread.currentThread().getId() + " died");
+                       throw e;
+               } catch (Exception e) {
+                       isCancelled = true;
+                       IOException ioe = new IOException(
+                                       "Unexpected issue in login dialog, see root cause for more details");
+                       ioe.initCause(e);
+                       throw ioe;
+               } finally {
+                       // so that the modal thread dies
+                       processCallbacks = true;
+                       // try {
+                       // // wait for the modal context thread to gracefully exit
+                       // modalContextThread.join();
+                       // } catch (InterruptedException ie) {
+                       // // silent
+                       // }
+                       modalContextThread = null;
+               }
+       }
+
+       protected void configureShell(Shell shell) {
+               super.configureShell(shell);
+               shell.setText("Authentication");
+       }
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/widgets/auth/CompositeCallbackHandler.java b/org.argeo.cms/src/org/argeo/cms/widgets/auth/CompositeCallbackHandler.java
new file mode 100644 (file)
index 0000000..30f8308
--- /dev/null
@@ -0,0 +1,291 @@
+package org.argeo.cms.widgets.auth;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.argeo.util.LocaleCallback;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * A composite that can populate itself based on {@link Callback}s. It can be
+ * used directly as a {@link CallbackHandler} or be used by one by calling the
+ * {@link #createCallbackHandlers(Callback[])}.
+ * <p>
+ * Supported standard {@link Callback}s are:<br>
+ * <ul>
+ * <li>{@link PasswordCallback}</li>
+ * <li>{@link NameCallback}</li>
+ * <li>{@link TextOutputCallback}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Supported Argeo {@link Callback}s are:<br>
+ * <ul>
+ * <li>{@link LocaleCallback}</li>
+ * </ul>
+ * </p>
+ */
+public class CompositeCallbackHandler extends Composite implements
+               CallbackHandler {
+       private static final long serialVersionUID = -928223893722723777L;
+
+       private boolean wasUsedAlready = false;
+       private boolean isSubmitted = false;
+       private boolean isCanceled = false;
+
+       public CompositeCallbackHandler(Composite parent, int style) {
+               super(parent, style);
+       }
+
+       @Override
+       public synchronized void handle(final Callback[] callbacks)
+                       throws IOException, UnsupportedCallbackException {
+               // reset
+               if (wasUsedAlready && !isSubmitted() && !isCanceled()) {
+                       cancel();
+                       for (Control control : getChildren())
+                               control.dispose();
+                       isSubmitted = false;
+                       isCanceled = false;
+               }
+
+               for (Callback callback : callbacks)
+                       checkCallbackSupported(callback);
+               // create controls synchronously in the UI thread
+               getDisplay().syncExec(new Runnable() {
+
+                       @Override
+                       public void run() {
+                               createCallbackHandlers(callbacks);
+                       }
+               });
+
+               if (!wasUsedAlready)
+                       wasUsedAlready = true;
+
+               while (!isSubmitted() && !isCanceled()) {
+                       try {
+                               wait(1000l);
+                       } catch (InterruptedException e) {
+                               // silent
+                       }
+               }
+
+               cleanCallbacksAfterCancel(callbacks);
+       }
+
+       public void checkCallbackSupported(Callback callback)
+                       throws UnsupportedCallbackException {
+               if (callback instanceof TextOutputCallback
+                               || callback instanceof NameCallback
+                               || callback instanceof PasswordCallback
+                               || callback instanceof LocaleCallback) {
+                       return;
+               } else {
+                       throw new UnsupportedCallbackException(callback);
+               }
+       }
+
+       /**
+        * Set writable callbacks to null if the handle is canceled (check is done
+        * by the method)
+        */
+       public void cleanCallbacksAfterCancel(Callback[] callbacks) {
+               if (isCanceled()) {
+                       for (Callback callback : callbacks) {
+                               if (callback instanceof NameCallback) {
+                                       ((NameCallback) callback).setName(null);
+                               } else if (callback instanceof PasswordCallback) {
+                                       PasswordCallback pCallback = (PasswordCallback) callback;
+                                       char[] arr = pCallback.getPassword();
+                                       if (arr != null) {
+                                               Arrays.fill(arr, '*');
+                                               pCallback.setPassword(null);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       public void createCallbackHandlers(Callback[] callbacks) {
+               Composite composite = this;
+               for (int i = 0; i < callbacks.length; i++) {
+                       Callback callback = callbacks[i];
+                       if (callback instanceof TextOutputCallback) {
+                               createLabelTextoutputHandler(composite,
+                                               (TextOutputCallback) callback);
+                       } else if (callback instanceof NameCallback) {
+                               createNameHandler(composite, (NameCallback) callback);
+                       } else if (callback instanceof PasswordCallback) {
+                               createPasswordHandler(composite, (PasswordCallback) callback);
+                       } else if (callback instanceof LocaleCallback) {
+                               createLocaleHandler(composite, (LocaleCallback) callback);
+                       }
+               }
+       }
+
+       protected Text createNameHandler(Composite composite,
+                       final NameCallback callback) {
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getPrompt());
+               final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD
+                               | SWT.BORDER);
+               if (callback.getDefaultName() != null) {
+                       // set default value, if provided
+                       text.setText(callback.getDefaultName());
+                       callback.setName(callback.getDefaultName());
+               }
+               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               text.addModifyListener(new ModifyListener() {
+                       private static final long serialVersionUID = 7300032545287292973L;
+
+                       public void modifyText(ModifyEvent event) {
+                               callback.setName(text.getText());
+                       }
+               });
+               text.addSelectionListener(new SelectionListener() {
+                       private static final long serialVersionUID = 1820530045857665111L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                               submit();
+                       }
+               });
+
+               text.addKeyListener(new KeyListener() {
+                       private static final long serialVersionUID = -8698107785092095713L;
+
+                       @Override
+                       public void keyReleased(KeyEvent e) {
+                       }
+
+                       @Override
+                       public void keyPressed(KeyEvent e) {
+                       }
+               });
+               return text;
+       }
+
+       protected Text createPasswordHandler(Composite composite,
+                       final PasswordCallback callback) {
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getPrompt());
+               final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD
+                               | SWT.PASSWORD | SWT.BORDER);
+               passwordText
+                               .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               passwordText.addModifyListener(new ModifyListener() {
+                       private static final long serialVersionUID = -7099363995047686732L;
+
+                       public void modifyText(ModifyEvent event) {
+                               callback.setPassword(passwordText.getTextChars());
+                       }
+               });
+               passwordText.addSelectionListener(new SelectionListener() {
+                       private static final long serialVersionUID = 1820530045857665111L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                               submit();
+                       }
+               });
+               return passwordText;
+       }
+
+       protected Combo createLocaleHandler(Composite composite,
+                       final LocaleCallback callback) {
+               String[] labels = callback.getSupportedLocalesLabels();
+               if (labels.length == 0)
+                       return null;
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getPrompt());
+
+               final Combo combo = new Combo(composite, SWT.READ_ONLY);
+               combo.setItems(labels);
+               combo.select(callback.getDefaultIndex());
+               combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               combo.addSelectionListener(new SelectionListener() {
+                       private static final long serialVersionUID = 38678989091946277L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               callback.setSelectedIndex(combo.getSelectionIndex());
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                       }
+               });
+               return combo;
+       }
+
+       protected Label createLabelTextoutputHandler(Composite composite,
+                       final TextOutputCallback callback) {
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getMessage());
+               GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+               data.horizontalSpan = 2;
+               label.setLayoutData(data);
+               return label;
+               // TODO: find a way to pass this information
+               // int messageType = callback.getMessageType();
+               // int dialogMessageType = IMessageProvider.NONE;
+               // switch (messageType) {
+               // case TextOutputCallback.INFORMATION:
+               // dialogMessageType = IMessageProvider.INFORMATION;
+               // break;
+               // case TextOutputCallback.WARNING:
+               // dialogMessageType = IMessageProvider.WARNING;
+               // break;
+               // case TextOutputCallback.ERROR:
+               // dialogMessageType = IMessageProvider.ERROR;
+               // break;
+               // }
+               // setMessage(callback.getMessage(), dialogMessageType);
+       }
+
+       synchronized boolean isSubmitted() {
+               return isSubmitted;
+       }
+
+       synchronized boolean isCanceled() {
+               return isCanceled;
+       }
+
+       protected synchronized void submit() {
+               isSubmitted = true;
+               notifyAll();
+       }
+
+       protected synchronized void cancel() {
+               isCanceled = true;
+               notifyAll();
+       }
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/widgets/auth/DefaultLoginDialog.java b/org.argeo.cms/src/org/argeo/cms/widgets/auth/DefaultLoginDialog.java
new file mode 100644 (file)
index 0000000..b8de34b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.widgets.auth;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/** Default authentication dialog, to be used as {@link CallbackHandler}. */
+public class DefaultLoginDialog extends AbstractLoginDialog {
+       private static final long serialVersionUID = -8551827590693035734L;
+
+       public DefaultLoginDialog() {
+               this(Display.getCurrent().getActiveShell());
+       }
+
+       public DefaultLoginDialog(Shell parentShell) {
+               super(parentShell);
+       }
+
+       protected Point getInitialSize() {
+               return new Point(350, 180);
+       }
+
+       @Override
+       protected Control createContents(Composite parent) {
+               Control control = super.createContents(parent);
+               parent.pack();
+
+               // Move the dialog to the center of the top level shell.
+               Rectangle shellBounds;
+               if (Display.getCurrent().getActiveShell() != null) // RCP
+                       shellBounds = Display.getCurrent().getActiveShell().getBounds();
+               else
+                       shellBounds = Display.getCurrent().getBounds();// RAP
+               Point dialogSize = parent.getSize();
+               int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
+               int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
+               parent.setLocation(x, y);
+               return control;
+       }
+
+       protected Control createDialogArea(Composite parent) {
+               Composite dialogarea = (Composite) super.createDialogArea(parent);
+               CompositeCallbackHandler composite = new CompositeCallbackHandler(
+                               dialogarea, SWT.NONE);
+               composite.setLayout(new GridLayout(2, false));
+               composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               composite.createCallbackHandlers(getCallbacks());
+               return composite;
+       }
+
+       public void internalHandle() {
+       }
+}
index b79d60d261e469abde35663237dcf4cf5b3a7b47..3f0f6646998babee7df0bf9855cc01b68b8a2a5a 100644 (file)
@@ -22,16 +22,14 @@ import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.login.CredentialNotFoundException;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.ArgeoException;
 import org.argeo.cms.KernelHeader;
 import org.argeo.cms.auth.ArgeoLoginContext;
+import org.argeo.cms.widgets.auth.DefaultLoginDialog;
 import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
-import org.argeo.security.ui.auth.DefaultLoginDialog;
 import org.argeo.util.LocaleUtils;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.rap.rwt.RWT;
@@ -40,7 +38,6 @@ import org.eclipse.swt.widgets.Display;
 import org.eclipse.ui.PlatformUI;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
 
 /**
@@ -78,13 +75,13 @@ public class SecureEntryPoint implements EntryPoint {
                RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout);
 
                // Try to load security context thanks to the session processing filter
-//             HttpServletRequest httpRequest = RWT.getRequest();
-//             HttpSession httpSession = httpRequest.getSession();
-//             Object contextFromSessionObject = httpSession
-//                             .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
-//             if (contextFromSessionObject != null)
-//                     SecurityContextHolder
-//                                     .setContext((SecurityContext) contextFromSessionObject);
+               // HttpServletRequest httpRequest = RWT.getRequest();
+               // HttpSession httpSession = httpRequest.getSession();
+               // Object contextFromSessionObject = httpSession
+               // .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
+               // if (contextFromSessionObject != null)
+               // SecurityContextHolder
+               // .setContext((SecurityContext) contextFromSessionObject);
 
                final Display display = PlatformUI.createDisplay();
                Subject subject = new Subject();
@@ -106,9 +103,10 @@ public class SecureEntryPoint implements EntryPoint {
                                        throw new ArgeoException("Login succeeded but no auth");// fatal
 
                                // add security context to session
-//                             if (httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY) == null)
-//                                     httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY,
-//                                                     SecurityContextHolder.getContext());
+                               // if (httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY) ==
+                               // null)
+                               // httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY,
+                               // SecurityContextHolder.getContext());
 
                                // add thread locale to RWT session
                                if (log.isTraceEnabled())
index 9ca839e8f09678e87a06b26824ae2dd2b25bbfad..4c6cb5183fdcae9b62c87f389745c6093fb2ca0a 100644 (file)
        <name>Commons CMS Workbench</name>
        <packaging>jar</packaging>
        <dependencies>
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.cms</artifactId>
+                       <version>2.1.22-SNAPSHOT</version>
+               </dependency>
                <dependency>
                        <groupId>org.argeo.commons</groupId>
                        <artifactId>org.argeo.security.core</artifactId>
index a4190d69a620c89385aaae5107e923badf4a7e35..e5987938bad3d8ece9ebc63f7ee60d20b62055e1 100644 (file)
@@ -22,7 +22,7 @@ import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.UnsupportedCallbackException;
 
 import org.argeo.ArgeoException;
-import org.argeo.security.ui.auth.DefaultLoginDialog;
+import org.argeo.cms.widgets.auth.DefaultLoginDialog;
 import org.eclipse.swt.widgets.Display;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/auth/AbstractLoginDialog.java b/org.argeo.security.ui/src/org/argeo/security/ui/auth/AbstractLoginDialog.java
deleted file mode 100644 (file)
index 107697e..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.auth;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.security.ui.SecurityUiPlugin;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.dialogs.TrayDialog;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.operation.ModalContext;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-/** Base for login dialogs */
-public abstract class AbstractLoginDialog extends TrayDialog implements
-               CallbackHandler {
-       private static final long serialVersionUID = -8046708963512717709L;
-
-       private final static Log log = LogFactory.getLog(AbstractLoginDialog.class);
-
-       private Thread modalContextThread = null;
-       boolean processCallbacks = false;
-       boolean isCancelled = false;
-       Callback[] callbackArray;
-
-       protected final Callback[] getCallbacks() {
-               return this.callbackArray;
-       }
-
-       public abstract void internalHandle();
-
-       public boolean isCancelled() {
-               return isCancelled;
-       }
-
-       protected AbstractLoginDialog(Shell parentShell) {
-               super(parentShell);
-       }
-
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth
-        * .callback.Callback[])
-        */
-       public void handle(final Callback[] callbacks) throws IOException {
-               // clean previous usage
-               if (processCallbacks) {
-                       // this handler was already used
-                       processCallbacks = false;
-               }
-
-               if (modalContextThread != null) {
-                       try {
-                               modalContextThread.join(1000);
-                       } catch (InterruptedException e) {
-                               // silent
-                       }
-                       modalContextThread = null;
-               }
-
-               // initialize
-               this.callbackArray = callbacks;
-               final Display display = Display.getDefault();
-               display.syncExec(new Runnable() {
-
-                       public void run() {
-                               isCancelled = false;
-                               setBlockOnOpen(false);
-                               open();
-
-                               final Button okButton = getButton(IDialogConstants.OK_ID);
-                               okButton.setText("Login");
-                               okButton.addSelectionListener(new SelectionListener() {
-                                       private static final long serialVersionUID = -200281625679096775L;
-
-                                       public void widgetSelected(final SelectionEvent event) {
-                                               processCallbacks = true;
-                                       }
-
-                                       public void widgetDefaultSelected(final SelectionEvent event) {
-                                               // nothing to do
-                                       }
-                               });
-                               final Button cancel = getButton(IDialogConstants.CANCEL_ID);
-                               cancel.addSelectionListener(new SelectionListener() {
-                                       private static final long serialVersionUID = -3826030278084915815L;
-
-                                       public void widgetSelected(final SelectionEvent event) {
-                                               isCancelled = true;
-                                               processCallbacks = true;
-                                       }
-
-                                       public void widgetDefaultSelected(final SelectionEvent event) {
-                                               // nothing to do
-                                       }
-                               });
-                       }
-               });
-               try {
-                       ModalContext.setAllowReadAndDispatch(true); // Works for now.
-                       ModalContext.run(new IRunnableWithProgress() {
-
-                               public void run(final IProgressMonitor monitor) {
-                                       modalContextThread = Thread.currentThread();
-                                       // Wait here until OK or cancel is pressed, then let it rip.
-                                       // The event
-                                       // listener
-                                       // is responsible for closing the dialog (in the
-                                       // loginSucceeded
-                                       // event).
-                                       while (!processCallbacks && (modalContextThread != null)
-                                                       && (modalContextThread == Thread.currentThread())
-                                                       && SecurityUiPlugin.getBundleContext() != null) {
-                                               // Note: SecurityUiPlugin.getDefault() != null is false
-                                               // when the OSGi runtime is shut down
-                                               try {
-                                                       Thread.sleep(100);
-                                                       // if (display.isDisposed()) {
-                                                       // log.warn("Display is disposed, killing login dialog thread");
-                                                       // throw new ThreadDeath();
-                                                       // }
-                                               } catch (final Exception e) {
-                                                       // do nothing
-                                               }
-                                       }
-                                       processCallbacks = false;
-                                       // Call the adapter to handle the callbacks
-                                       if (!isCancelled())
-                                               internalHandle();
-                                       else
-                                               // clear callbacks are when cancelling
-                                               for (Callback callback : callbacks)
-                                                       if (callback instanceof PasswordCallback) {
-                                                               char[] arr = ((PasswordCallback) callback)
-                                                                               .getPassword();
-                                                               if (arr != null) {
-                                                                       Arrays.fill(arr, '*');
-                                                                       ((PasswordCallback) callback)
-                                                                                       .setPassword(null);
-                                                               }
-                                                       } else if (callback instanceof NameCallback)
-                                                               ((NameCallback) callback).setName(null);
-                               }
-                       }, true, new NullProgressMonitor(), Display.getDefault());
-               } catch (ThreadDeath e) {
-                       isCancelled = true;
-                       log.debug("Thread " + Thread.currentThread().getId() + " died");
-                       throw e;
-               } catch (Exception e) {
-                       isCancelled = true;
-                       IOException ioe = new IOException(
-                                       "Unexpected issue in login dialog, see root cause for more details");
-                       ioe.initCause(e);
-                       throw ioe;
-               } finally {
-                       // so that the modal thread dies
-                       processCallbacks = true;
-                       // try {
-                       // // wait for the modal context thread to gracefully exit
-                       // modalContextThread.join();
-                       // } catch (InterruptedException ie) {
-                       // // silent
-                       // }
-                       modalContextThread = null;
-               }
-       }
-
-       protected void configureShell(Shell shell) {
-               super.configureShell(shell);
-               shell.setText("Authentication");
-       }
-}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/auth/CompositeCallbackHandler.java b/org.argeo.security.ui/src/org/argeo/security/ui/auth/CompositeCallbackHandler.java
deleted file mode 100644 (file)
index a2fc831..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-package org.argeo.security.ui.auth;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.TextOutputCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.argeo.util.LocaleCallback;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-
-/**
- * A composite that can populate itself based on {@link Callback}s. It can be
- * used directly as a {@link CallbackHandler} or be used by one by calling the
- * {@link #createCallbackHandlers(Callback[])}.
- * <p>
- * Supported standard {@link Callback}s are:<br>
- * <ul>
- * <li>{@link PasswordCallback}</li>
- * <li>{@link NameCallback}</li>
- * <li>{@link TextOutputCallback}</li>
- * </ul>
- * </p>
- * <p>
- * Supported Argeo {@link Callback}s are:<br>
- * <ul>
- * <li>{@link LocaleCallback}</li>
- * </ul>
- * </p>
- */
-public class CompositeCallbackHandler extends Composite implements
-               CallbackHandler {
-       private static final long serialVersionUID = -928223893722723777L;
-
-       private boolean wasUsedAlready = false;
-       private boolean isSubmitted = false;
-       private boolean isCanceled = false;
-
-       public CompositeCallbackHandler(Composite parent, int style) {
-               super(parent, style);
-       }
-
-       @Override
-       public synchronized void handle(final Callback[] callbacks)
-                       throws IOException, UnsupportedCallbackException {
-               // reset
-               if (wasUsedAlready && !isSubmitted() && !isCanceled()) {
-                       cancel();
-                       for (Control control : getChildren())
-                               control.dispose();
-                       isSubmitted = false;
-                       isCanceled = false;
-               }
-
-               for (Callback callback : callbacks)
-                       checkCallbackSupported(callback);
-               // create controls synchronously in the UI thread
-               getDisplay().syncExec(new Runnable() {
-
-                       @Override
-                       public void run() {
-                               createCallbackHandlers(callbacks);
-                       }
-               });
-
-               if (!wasUsedAlready)
-                       wasUsedAlready = true;
-
-               while (!isSubmitted() && !isCanceled()) {
-                       try {
-                               wait(1000l);
-                       } catch (InterruptedException e) {
-                               // silent
-                       }
-               }
-
-               cleanCallbacksAfterCancel(callbacks);
-       }
-
-       public void checkCallbackSupported(Callback callback)
-                       throws UnsupportedCallbackException {
-               if (callback instanceof TextOutputCallback
-                               || callback instanceof NameCallback
-                               || callback instanceof PasswordCallback
-                               || callback instanceof LocaleCallback) {
-                       return;
-               } else {
-                       throw new UnsupportedCallbackException(callback);
-               }
-       }
-
-       /**
-        * Set writable callbacks to null if the handle is canceled (check is done
-        * by the method)
-        */
-       public void cleanCallbacksAfterCancel(Callback[] callbacks) {
-               if (isCanceled()) {
-                       for (Callback callback : callbacks) {
-                               if (callback instanceof NameCallback) {
-                                       ((NameCallback) callback).setName(null);
-                               } else if (callback instanceof PasswordCallback) {
-                                       PasswordCallback pCallback = (PasswordCallback) callback;
-                                       char[] arr = pCallback.getPassword();
-                                       if (arr != null) {
-                                               Arrays.fill(arr, '*');
-                                               pCallback.setPassword(null);
-                                       }
-                               }
-                       }
-               }
-       }
-
-       public void createCallbackHandlers(Callback[] callbacks) {
-               Composite composite = this;
-               for (int i = 0; i < callbacks.length; i++) {
-                       Callback callback = callbacks[i];
-                       if (callback instanceof TextOutputCallback) {
-                               createLabelTextoutputHandler(composite,
-                                               (TextOutputCallback) callback);
-                       } else if (callback instanceof NameCallback) {
-                               createNameHandler(composite, (NameCallback) callback);
-                       } else if (callback instanceof PasswordCallback) {
-                               createPasswordHandler(composite, (PasswordCallback) callback);
-                       } else if (callback instanceof LocaleCallback) {
-                               createLocaleHandler(composite, (LocaleCallback) callback);
-                       }
-               }
-       }
-
-       protected Text createNameHandler(Composite composite,
-                       final NameCallback callback) {
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getPrompt());
-               final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD
-                               | SWT.BORDER);
-               if (callback.getDefaultName() != null) {
-                       // set default value, if provided
-                       text.setText(callback.getDefaultName());
-                       callback.setName(callback.getDefaultName());
-               }
-               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               text.addModifyListener(new ModifyListener() {
-                       private static final long serialVersionUID = 7300032545287292973L;
-
-                       public void modifyText(ModifyEvent event) {
-                               callback.setName(text.getText());
-                       }
-               });
-               text.addSelectionListener(new SelectionListener() {
-                       private static final long serialVersionUID = 1820530045857665111L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                               submit();
-                       }
-               });
-
-               text.addKeyListener(new KeyListener() {
-                       private static final long serialVersionUID = -8698107785092095713L;
-
-                       @Override
-                       public void keyReleased(KeyEvent e) {
-                       }
-
-                       @Override
-                       public void keyPressed(KeyEvent e) {
-                       }
-               });
-               return text;
-       }
-
-       protected Text createPasswordHandler(Composite composite,
-                       final PasswordCallback callback) {
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getPrompt());
-               final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD
-                               | SWT.PASSWORD | SWT.BORDER);
-               passwordText
-                               .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               passwordText.addModifyListener(new ModifyListener() {
-                       private static final long serialVersionUID = -7099363995047686732L;
-
-                       public void modifyText(ModifyEvent event) {
-                               callback.setPassword(passwordText.getTextChars());
-                       }
-               });
-               passwordText.addSelectionListener(new SelectionListener() {
-                       private static final long serialVersionUID = 1820530045857665111L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                               submit();
-                       }
-               });
-               return passwordText;
-       }
-
-       protected Combo createLocaleHandler(Composite composite,
-                       final LocaleCallback callback) {
-               String[] labels = callback.getSupportedLocalesLabels();
-               if (labels.length == 0)
-                       return null;
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getPrompt());
-
-               final Combo combo = new Combo(composite, SWT.READ_ONLY);
-               combo.setItems(labels);
-               combo.select(callback.getDefaultIndex());
-               combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               combo.addSelectionListener(new SelectionListener() {
-                       private static final long serialVersionUID = 38678989091946277L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               callback.setSelectedIndex(combo.getSelectionIndex());
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                       }
-               });
-               return combo;
-       }
-
-       protected Label createLabelTextoutputHandler(Composite composite,
-                       final TextOutputCallback callback) {
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getMessage());
-               GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
-               data.horizontalSpan = 2;
-               label.setLayoutData(data);
-               return label;
-               // TODO: find a way to pass this information
-               // int messageType = callback.getMessageType();
-               // int dialogMessageType = IMessageProvider.NONE;
-               // switch (messageType) {
-               // case TextOutputCallback.INFORMATION:
-               // dialogMessageType = IMessageProvider.INFORMATION;
-               // break;
-               // case TextOutputCallback.WARNING:
-               // dialogMessageType = IMessageProvider.WARNING;
-               // break;
-               // case TextOutputCallback.ERROR:
-               // dialogMessageType = IMessageProvider.ERROR;
-               // break;
-               // }
-               // setMessage(callback.getMessage(), dialogMessageType);
-       }
-
-       synchronized boolean isSubmitted() {
-               return isSubmitted;
-       }
-
-       synchronized boolean isCanceled() {
-               return isCanceled;
-       }
-
-       protected synchronized void submit() {
-               isSubmitted = true;
-               notifyAll();
-       }
-
-       protected synchronized void cancel() {
-               isCanceled = true;
-               notifyAll();
-       }
-}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/auth/DefaultLoginDialog.java b/org.argeo.security.ui/src/org/argeo/security/ui/auth/DefaultLoginDialog.java
deleted file mode 100644 (file)
index 85f90bd..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.auth;
-
-import javax.security.auth.callback.CallbackHandler;
-
-import org.argeo.security.ui.SecurityUiPlugin;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-/** Default authentication dialog, to be used as {@link CallbackHandler}. */
-public class DefaultLoginDialog extends AbstractLoginDialog {
-       private static final long serialVersionUID = -8551827590693035734L;
-
-       public DefaultLoginDialog() {
-               this(SecurityUiPlugin.display.get().getActiveShell());
-       }
-
-       public DefaultLoginDialog(Shell parentShell) {
-               super(parentShell);
-       }
-
-       protected Point getInitialSize() {
-               return new Point(350, 180);
-       }
-
-       @Override
-       protected Control createContents(Composite parent) {
-               Control control = super.createContents(parent);
-               parent.pack();
-
-               // Move the dialog to the center of the top level shell.
-               Rectangle shellBounds;
-               if (Display.getCurrent().getActiveShell() != null) // RCP
-                       shellBounds = Display.getCurrent().getActiveShell().getBounds();
-               else
-                       shellBounds = Display.getCurrent().getBounds();// RAP
-               Point dialogSize = parent.getSize();
-               int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
-               int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
-               parent.setLocation(x, y);
-               return control;
-       }
-
-       protected Control createDialogArea(Composite parent) {
-               Composite dialogarea = (Composite) super.createDialogArea(parent);
-               CompositeCallbackHandler composite = new CompositeCallbackHandler(
-                               dialogarea, SWT.NONE);
-               composite.setLayout(new GridLayout(2, false));
-               composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               composite.createCallbackHandlers(getCallbacks());
-               return composite;
-       }
-
-       public void internalHandle() {
-       }
-}