]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/widgets/auth/AbstractLoginDialog.java
Return private path if call is authenticated.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / widgets / auth / AbstractLoginDialog.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.cms.widgets.auth;
17
18 import java.io.IOException;
19 import java.util.Arrays;
20
21 import javax.security.auth.callback.Callback;
22 import javax.security.auth.callback.CallbackHandler;
23 import javax.security.auth.callback.NameCallback;
24 import javax.security.auth.callback.PasswordCallback;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.argeo.cms.internal.kernel.Activator;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.NullProgressMonitor;
31 import org.eclipse.jface.dialogs.IDialogConstants;
32 import org.eclipse.jface.dialogs.TrayDialog;
33 import org.eclipse.jface.operation.IRunnableWithProgress;
34 import org.eclipse.jface.operation.ModalContext;
35 import org.eclipse.swt.events.SelectionEvent;
36 import org.eclipse.swt.events.SelectionListener;
37 import org.eclipse.swt.widgets.Button;
38 import org.eclipse.swt.widgets.Display;
39 import org.eclipse.swt.widgets.Shell;
40
41 /** Base for login dialogs */
42 public abstract class AbstractLoginDialog extends TrayDialog implements
43 CallbackHandler {
44 private static final long serialVersionUID = -8046708963512717709L;
45
46 private final static Log log = LogFactory.getLog(AbstractLoginDialog.class);
47
48 private Thread modalContextThread = null;
49 boolean processCallbacks = false;
50 boolean isCancelled = false;
51 Callback[] callbackArray;
52
53 protected final Callback[] getCallbacks() {
54 return this.callbackArray;
55 }
56
57 public abstract void internalHandle();
58
59 public boolean isCancelled() {
60 return isCancelled;
61 }
62
63 protected AbstractLoginDialog(Shell parentShell) {
64 super(parentShell);
65 }
66
67 /*
68 * (non-Javadoc)
69 *
70 * @see
71 * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth
72 * .callback.Callback[])
73 */
74 public void handle(final Callback[] callbacks) throws IOException {
75 // clean previous usage
76 if (processCallbacks) {
77 // this handler was already used
78 processCallbacks = false;
79 }
80
81 if (modalContextThread != null) {
82 try {
83 modalContextThread.join(1000);
84 } catch (InterruptedException e) {
85 // silent
86 }
87 modalContextThread = null;
88 }
89
90 // initialize
91 this.callbackArray = callbacks;
92 final Display display = Display.getDefault();
93 display.syncExec(new Runnable() {
94
95 public void run() {
96 isCancelled = false;
97 setBlockOnOpen(false);
98 open();
99
100 final Button okButton = getButton(IDialogConstants.OK_ID);
101 okButton.setText("Login");
102 okButton.addSelectionListener(new SelectionListener() {
103 private static final long serialVersionUID = -200281625679096775L;
104
105 public void widgetSelected(final SelectionEvent event) {
106 processCallbacks = true;
107 }
108
109 public void widgetDefaultSelected(final SelectionEvent event) {
110 // nothing to do
111 }
112 });
113 final Button cancel = getButton(IDialogConstants.CANCEL_ID);
114 cancel.addSelectionListener(new SelectionListener() {
115 private static final long serialVersionUID = -3826030278084915815L;
116
117 public void widgetSelected(final SelectionEvent event) {
118 isCancelled = true;
119 processCallbacks = true;
120 }
121
122 public void widgetDefaultSelected(final SelectionEvent event) {
123 // nothing to do
124 }
125 });
126 }
127 });
128 try {
129 ModalContext.setAllowReadAndDispatch(true); // Works for now.
130 ModalContext.run(new IRunnableWithProgress() {
131
132 public void run(final IProgressMonitor monitor) {
133 modalContextThread = Thread.currentThread();
134 // Wait here until OK or cancel is pressed, then let it rip.
135 // The event
136 // listener
137 // is responsible for closing the dialog (in the
138 // loginSucceeded
139 // event).
140 while (!processCallbacks && (modalContextThread != null)
141 && (modalContextThread == Thread.currentThread())
142 && Activator.getBundleContext() != null) {
143 // Note: SecurityUiPlugin.getDefault() != null is false
144 // when the OSGi runtime is shut down
145 try {
146 Thread.sleep(100);
147 // if (display.isDisposed()) {
148 // log.warn("Display is disposed, killing login dialog thread");
149 // throw new ThreadDeath();
150 // }
151 } catch (final Exception e) {
152 // do nothing
153 }
154 }
155 processCallbacks = false;
156 // Call the adapter to handle the callbacks
157 if (!isCancelled())
158 internalHandle();
159 else
160 // clear callbacks are when cancelling
161 for (Callback callback : callbacks)
162 if (callback instanceof PasswordCallback) {
163 char[] arr = ((PasswordCallback) callback)
164 .getPassword();
165 if (arr != null) {
166 Arrays.fill(arr, '*');
167 ((PasswordCallback) callback)
168 .setPassword(null);
169 }
170 } else if (callback instanceof NameCallback)
171 ((NameCallback) callback).setName(null);
172 }
173 }, true, new NullProgressMonitor(), Display.getDefault());
174 } catch (ThreadDeath e) {
175 isCancelled = true;
176 log.debug("Thread " + Thread.currentThread().getId() + " died");
177 throw e;
178 } catch (Exception e) {
179 isCancelled = true;
180 IOException ioe = new IOException(
181 "Unexpected issue in login dialog, see root cause for more details");
182 ioe.initCause(e);
183 throw ioe;
184 } finally {
185 // so that the modal thread dies
186 processCallbacks = true;
187 // try {
188 // // wait for the modal context thread to gracefully exit
189 // modalContextThread.join();
190 // } catch (InterruptedException ie) {
191 // // silent
192 // }
193 modalContextThread = null;
194 }
195 }
196
197 protected void configureShell(Shell shell) {
198 super.configureShell(shell);
199 shell.setText("Authentication");
200 }
201 }