baf9eb2cbdf3152d400f2201671b5d1f37b3e58b
[public/netxms.git] / src / java / netxms-eclipse / core / src / org / netxms / ui / eclipse / console / dialogs / LoginDialog.java
1 /**
2 * NetXMS - open source network management system
3 * Copyright (C) 2003-2009 Victor Kirhenshtein
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 package org.netxms.ui.eclipse.console.dialogs;
20
21 import java.security.cert.Certificate;
22 import java.security.cert.X509Certificate;
23 import java.util.Arrays;
24 import java.util.HashSet;
25 import org.eclipse.jface.dialogs.Dialog;
26 import org.eclipse.jface.dialogs.IDialogSettings;
27 import org.eclipse.jface.dialogs.MessageDialog;
28 import org.eclipse.jface.resource.ImageDescriptor;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.custom.StackLayout;
31 import org.eclipse.swt.events.DisposeEvent;
32 import org.eclipse.swt.events.DisposeListener;
33 import org.eclipse.swt.events.SelectionEvent;
34 import org.eclipse.swt.events.SelectionListener;
35 import org.eclipse.swt.graphics.Color;
36 import org.eclipse.swt.graphics.RGB;
37 import org.eclipse.swt.layout.GridData;
38 import org.eclipse.swt.layout.GridLayout;
39 import org.eclipse.swt.layout.RowLayout;
40 import org.eclipse.swt.widgets.Button;
41 import org.eclipse.swt.widgets.Combo;
42 import org.eclipse.swt.widgets.Composite;
43 import org.eclipse.swt.widgets.Control;
44 import org.eclipse.swt.widgets.Display;
45 import org.eclipse.swt.widgets.Event;
46 import org.eclipse.swt.widgets.Label;
47 import org.eclipse.swt.widgets.Listener;
48 import org.eclipse.swt.widgets.Monitor;
49 import org.eclipse.swt.widgets.Shell;
50 import org.eclipse.swt.widgets.Text;
51 import org.eclipse.ui.forms.widgets.Form;
52 import org.eclipse.ui.forms.widgets.FormToolkit;
53 import org.netxms.certificate.loader.exception.KeyStoreLoaderException;
54 import org.netxms.certificate.manager.CertificateManager;
55 import org.netxms.certificate.subject.Subject;
56 import org.netxms.certificate.subject.SubjectParser;
57 import org.netxms.ui.eclipse.console.Activator;
58 import org.netxms.ui.eclipse.console.AuthenticationMethod;
59 import org.netxms.ui.eclipse.console.BrandingManager;
60 import org.netxms.ui.eclipse.console.Messages;
61 import org.netxms.ui.eclipse.tools.WidgetHelper;
62 import org.netxms.ui.eclipse.widgets.LabeledText;
63 import static org.netxms.ui.eclipse.console.AuthenticationMethod.*;
64
65 /**
66 * Login dialog
67 */
68 public class LoginDialog extends Dialog implements SelectionListener
69 {
70 private FormToolkit toolkit;
71 private ImageDescriptor loginImage;
72 private Combo comboServer;
73 private LabeledText textLogin;
74 private Text textPassword;
75 private Combo comboCert;
76 private String password;
77 private Certificate cert;
78 private Color labelColor;
79 private final CertificateManager certMgr;
80 private AuthenticationMethod authenticationMethod;
81
82 /**
83 * @param parentShell
84 */
85 public LoginDialog(Shell parentShell, CertificateManager certMgr)
86 {
87 super(parentShell);
88
89 loginImage = BrandingManager.getInstance().getLoginTitleImage();
90 if (loginImage == null)
91 loginImage = Activator.getImageDescriptor("icons/login.png"); //$NON-NLS-1$
92
93 this.certMgr = certMgr;
94 authenticationMethod = AuthenticationMethod.AUTHENTICATION_NULL;
95 }
96
97 /*
98 * (non-Javadoc)
99 *
100 * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
101 */
102 @Override
103 protected void configureShell(Shell newShell)
104 {
105 super.configureShell(newShell);
106 String customTitle = BrandingManager.getInstance().getLoginTitle();
107 newShell.setText((customTitle != null) ? customTitle : Messages.LoginDialog_title); //$NON-NLS-1$
108
109 // Center dialog on screen
110 // We don't have main window at this moment, so use
111 // monitor data to determine right position
112 Monitor[] ma = newShell.getDisplay().getMonitors();
113 if (ma != null)
114 {
115 newShell.setLocation((ma[0].getClientArea().width - newShell.getSize().x) / 2,
116 (ma[0].getClientArea().height - newShell.getSize().y) / 2);
117 }
118 }
119
120 /*
121 * (non-Javadoc)
122 *
123 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
124 */
125 @Override
126 protected Control createDialogArea(Composite parent)
127 {
128 IDialogSettings settings = Activator.getDefault().getDialogSettings();
129
130 toolkit = new FormToolkit(parent.getDisplay());
131 Form dialogArea = toolkit.createForm(parent);
132 dialogArea.setLayoutData(new GridData(GridData.FILL_BOTH));
133 applyDialogFont(dialogArea);
134
135 GridLayout dialogLayout = new GridLayout();
136 dialogLayout.numColumns = 2;
137 dialogLayout.marginWidth = WidgetHelper.DIALOG_WIDTH_MARGIN;
138 dialogLayout.marginHeight = WidgetHelper.DIALOG_HEIGHT_MARGIN;
139 dialogLayout.horizontalSpacing = WidgetHelper.DIALOG_SPACING;
140 dialogArea.getBody().setLayout(dialogLayout);
141
142 RGB customColor = BrandingManager.getInstance().getLoginTitleColor();
143 labelColor = (customColor != null) ? new Color(dialogArea.getDisplay(), customColor) : new Color(dialogArea.getDisplay(), 36,
144 66, 90);
145 dialogArea.addDisposeListener(new DisposeListener() {
146 @Override
147 public void widgetDisposed(DisposeEvent e)
148 {
149 labelColor.dispose();
150 }
151 });
152
153 // Login image
154 Label label = new Label(dialogArea.getBody(), SWT.NONE);
155 label.setImage(loginImage.createImage());
156 label.addDisposeListener(new DisposeListener() {
157 @Override
158 public void widgetDisposed(DisposeEvent event)
159 {
160 ((Label)event.widget).getImage().dispose();
161 }
162 });
163 GridData gd = new GridData();
164 gd.horizontalAlignment = SWT.CENTER;
165 gd.verticalAlignment = SWT.CENTER;
166 gd.grabExcessVerticalSpace = true;
167 label.setLayoutData(gd);
168
169 Composite fields = toolkit.createComposite(dialogArea.getBody());
170 fields.setBackgroundMode(SWT.INHERIT_DEFAULT);
171 GridLayout fieldsLayout = new GridLayout();
172 fieldsLayout.verticalSpacing = WidgetHelper.DIALOG_SPACING;
173 fieldsLayout.marginHeight = 0;
174 fieldsLayout.marginWidth = 0;
175 fields.setLayout(fieldsLayout);
176 gd = new GridData();
177 gd.horizontalAlignment = SWT.FILL;
178 gd.grabExcessHorizontalSpace = true;
179 gd.verticalAlignment = SWT.TOP;
180 gd.grabExcessVerticalSpace = true;
181 fields.setLayoutData(gd);
182
183 gd = new GridData();
184 gd.horizontalAlignment = SWT.FILL;
185 gd.grabExcessHorizontalSpace = true;
186 comboServer = WidgetHelper.createLabeledCombo(fields, SWT.DROP_DOWN, Messages.LoginDialog_server, gd, toolkit);
187
188 textLogin = new LabeledText(fields, SWT.NONE, SWT.SINGLE | SWT.BORDER, toolkit);
189 textLogin.setLabel(Messages.LoginDialog_login);
190 gd = new GridData();
191 gd.horizontalAlignment = SWT.FILL;
192 gd.grabExcessHorizontalSpace = true;
193 gd.widthHint = WidgetHelper.getTextWidth(textLogin, "M") * 24;
194 textLogin.setLayoutData(gd);
195
196 // textPassword = new LabeledText(fields, SWT.NONE, SWT.SINGLE | SWT.BORDER | SWT.PASSWORD, toolkit);
197 // textPassword.setLabel(Messages.LoginDialog_password);
198 // gd = new GridData();
199 // gd.horizontalAlignment = SWT.FILL;
200 // gd.grabExcessHorizontalSpace = true;
201 // textPassword.setLayoutData(gd);
202
203 attachAuthenticationFields(settings, fields);
204
205 // Read field data
206 String[] items = settings.getArray("Connect.ServerHistory"); //$NON-NLS-1$
207 if (items != null)
208 comboServer.setItems(items);
209 String text = settings.get("Connect.Server"); //$NON-NLS-1$
210 if (text != null)
211 comboServer.setText(text);
212
213 text = settings.get("Connect.Login"); //$NON-NLS-1$
214 if (text != null)
215 textLogin.setText(text);
216
217 // Set initial focus
218 if (comboServer.getText().isEmpty())
219 comboServer.setFocus();
220 else if (textLogin.getText().isEmpty())
221 textLogin.setFocus();
222 else
223 textPassword.setFocus();
224
225 return dialogArea;
226 }
227
228 private void attachAuthenticationFields(final IDialogSettings settings, final Composite fields)
229 {
230 // Display display = Display.getCurrent();
231 //
232 // final Composite authComposite = new Composite(group, SWT.NONE);
233 // authComposite.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
234 // final GridLayout authCompositeLayout = new GridLayout(1, true);
235 // authComposite.setLayout(authCompositeLayout);
236 // authComposite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
237
238 // final Composite radios = new Composite(authComposite, SWT.NONE);
239 final Composite radios = new Composite(fields, SWT.NONE);
240 final RowLayout radiosLayout = new RowLayout(SWT.HORIZONTAL);
241 radiosLayout.justify = true;
242 radiosLayout.pack = false;
243
244 radios.setLayout(radiosLayout);
245 radios.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
246
247 toolkit.adapt(radios);
248
249 final Button passwdButton = new Button(radios, SWT.RADIO);
250 passwdButton.setText(Messages.LoginDialog_password);
251 passwdButton.setSelection(true);
252
253 final Button certButton = new Button(radios, SWT.RADIO);
254 certButton.setText("Certificate");
255 certButton.addSelectionListener(this);
256 // certButton.setEnabled(false);
257
258 attachAuthMethodComposite(fields, passwdButton, certButton);
259 }
260
261 private void attachAuthMethodComposite(final Composite fields, final Button passwdButton, final Button certButton)
262 {
263 final Composite authMethod = new Composite(fields, SWT.NONE);
264 final StackLayout authMethodLayout = new StackLayout();
265
266 authMethod.setLayout(authMethodLayout);
267 authMethod.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
268
269 toolkit.adapt(authMethod);
270
271 final Composite passwdField = attachPasswdField(authMethod);
272 final Composite certField = attachCertField(authMethod);
273
274 authMethodLayout.topControl = passwdButton.getSelection() ? passwdField : certField;
275
276 final Listener radioButtonListener = new Listener() {
277 @Override
278 public void handleEvent(Event event)
279 {
280 StackLayout layout = (StackLayout)authMethod.getLayout();
281
282 if (passwdButton.getSelection())
283 {
284 layout.topControl = passwdField;
285 authenticationMethod = AUTHENTICATION_PASSWORD;
286 }
287 else
288 {
289 layout.topControl = certField;
290 authenticationMethod = AUTHENTICATION_CERTIFICATE;
291 }
292 authMethod.layout();
293 }
294 };
295
296 passwdButton.addListener(SWT.Selection, radioButtonListener);
297 certButton.addListener(SWT.Selection, radioButtonListener);
298 }
299
300 private Composite attachPasswdField(final Composite authMethod)
301 {
302 final Composite passwdField = new Composite(authMethod, SWT.NONE);
303
304 final GridLayout layout = new GridLayout();
305 layout.verticalSpacing = GridData.CENTER;
306 layout.horizontalSpacing = 0;
307 layout.marginTop = 0;
308 layout.marginBottom = 0;
309 layout.marginWidth = 0;
310 layout.marginHeight = 0;
311
312 passwdField.setLayout(layout);
313 passwdField.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
314
315 final Label label = new Label(passwdField, SWT.NONE);
316 label.setText(Messages.LoginDialog_password); //$NON-NLS-1$
317 textPassword = new Text(passwdField, SWT.SINGLE | SWT.BORDER | SWT.PASSWORD);
318 // textPassword = new LabeledText(passwdField, SWT.SINGLE | SWT.PASSWORD | SWT.BORDER);
319 textPassword.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
320 // textPassword = new LabeledText(authMethod, SWT.NONE, SWT.SINGLE | SWT.BORDER | SWT.PASSWORD, toolkit);
321 // textPassword.setLabel(Messages.LoginDialog_password);
322 // textPassword.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
323
324 // gd = new GridData();
325 // gd.horizontalAlignment = SWT.FILL;
326 // gd.grabExcessHorizontalSpace = true;
327 // textPassword.setLayoutData(gd);
328
329 toolkit.adapt(passwdField);
330
331 return passwdField;
332 }
333
334 private Composite attachCertField(final Composite authMethod)
335 {
336 final Composite certField = new Composite(authMethod, SWT.NONE);
337
338 final GridLayout layout = new GridLayout();
339 layout.verticalSpacing = GridData.CENTER;
340 layout.horizontalSpacing = 0;
341 layout.marginTop = 0;
342 layout.marginBottom = 0;
343 layout.marginWidth = 0;
344 layout.marginHeight = 0;
345
346 certField.setLayout(layout);
347 certField.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
348
349 final Label label = new Label(certField, SWT.NONE);
350 label.setText("Certificate");
351
352 comboCert = new Combo(certField, SWT.DROP_DOWN | SWT.READ_ONLY);
353 comboCert.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
354 comboCert.addSelectionListener(this);
355
356 // GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
357 // final Combo comboCert = WidgetHelper.createLabeledCombo(authMethod, (SWT.DROP_DOWN | SWT.READ_ONLY), "Certificate", gd,
358 // toolkit);
359 // comboCert.setItems(new String[] { "A", "B", "C" });
360
361 toolkit.adapt(certField);
362
363 return certField;
364 }
365
366 /*
367 * (non-Javadoc)
368 *
369 * @see org.eclipse.jface.dialogs.Dialog#okPressed()
370 */
371 @Override
372 protected void okPressed()
373 {
374 IDialogSettings settings = Activator.getDefault().getDialogSettings();
375
376 HashSet<String> items = new HashSet<String>();
377 items.addAll(Arrays.asList(comboServer.getItems()));
378 items.add(comboServer.getText());
379
380 settings.put("Connect.Server", comboServer.getText()); //$NON-NLS-1$
381 settings.put("Connect.ServerHistory", items.toArray(new String[items.size()])); //$NON-NLS-1$
382 settings.put("Connect.Login", textLogin.getText()); //$NON-NLS-1$
383
384 if (authenticationMethod == AUTHENTICATION_PASSWORD)
385 {
386 password = textPassword.getText();
387 }
388
389 super.okPressed();
390 }
391
392 /**
393 * @return the password
394 */
395 public String getPassword()
396 {
397 return password;
398 }
399
400 @Override
401 public void widgetSelected(SelectionEvent e)
402 {
403 Object source = e.getSource();
404 // System.out.println(source);
405 if (source.toString().equals("Button {Certificate}"))
406 {
407 Button certButton = (Button)source;
408
409 if (!certButton.getSelection())
410 return;
411
412 if (!fillCertCombo())
413 certButton.setSelection(false);
414 }
415 else if (source.toString().startsWith("Combo {"))
416 {
417 selectCert();
418 }
419
420 }
421
422 private void selectCert()
423 {
424 int index = comboCert.getSelectionIndex() - 1;
425 if (index >= 0)
426 {
427 cert = certMgr.getCerts()[index];
428 authenticationMethod = AuthenticationMethod.AUTHENTICATION_CERTIFICATE;
429 }
430 }
431
432 private boolean fillCertCombo()
433 {
434 if (comboCert.getItemCount() != 0)
435 return true;
436
437 try
438 {
439 if (certMgr.hasNoCertificates())
440 {
441 certMgr.load();
442 }
443 }
444 catch(KeyStoreLoaderException ksle)
445 {
446 Shell shell = Display.getCurrent().getActiveShell();
447 MessageDialog.openError(shell, "Whoops!", "The password you provided appears to be wrong.");
448 return false;
449 }
450
451 Certificate[] certs = certMgr.getCerts();
452 String[] subjectStrings = new String[certs.length];
453
454 for(int i = 0; i < certs.length; i++)
455 {
456 X509Certificate x509 = (X509Certificate)certs[i];
457 String subjString = x509.getSubjectDN().toString();
458
459 Subject subj = SubjectParser.parseSubject(subjString);
460
461 subjectStrings[i] = String.format("%s (%s, %s, %s)", subj.getCommonName(), subj.getOrganization(), subj.getState(),
462 subj.getCountry());
463 }
464
465 if (subjectStrings.length != 0)
466 {
467 comboCert.setItems(subjectStrings);
468 comboCert.add("+", 0);
469 comboCert.select(0);
470
471 return true;
472 }
473
474 return false;
475 }
476
477 @Override
478 public void widgetDefaultSelected(SelectionEvent e)
479 {
480 // Don't do anything
481 }
482
483 public AuthenticationMethod getAuthenticationMethod()
484 {
485 return authenticationMethod;
486 }
487
488 public Certificate getCertificate()
489 {
490 return cert;
491 }
492 }