001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2009-2010 Sun Microsystems, Inc.
015 * Portions Copyright 2011-2016 ForgeRock AS.
016 */
017
018package org.opends.guitools.controlpanel.ui;
019
020import java.awt.Component;
021import java.awt.GridBagConstraints;
022import java.awt.event.ActionEvent;
023import java.awt.event.ActionListener;
024import java.io.File;
025import java.io.IOException;
026import java.net.URI;
027import java.security.cert.X509Certificate;
028import java.util.ArrayList;
029import java.util.Iterator;
030import java.util.LinkedHashSet;
031
032import javax.naming.NamingEnumeration;
033import javax.naming.NamingException;
034import javax.naming.directory.SearchControls;
035import javax.naming.directory.SearchResult;
036import javax.naming.ldap.InitialLdapContext;
037import javax.swing.Box;
038import javax.swing.DefaultComboBoxModel;
039import javax.swing.JComboBox;
040import javax.swing.JEditorPane;
041import javax.swing.JLabel;
042import javax.swing.JPasswordField;
043import javax.swing.JTextField;
044import javax.swing.SwingUtilities;
045
046import org.forgerock.i18n.LocalizableMessage;
047import org.forgerock.i18n.slf4j.LocalizedLogger;
048import org.opends.admin.ads.ServerDescriptor;
049import org.opends.admin.ads.util.ApplicationTrustManager;
050import org.opends.admin.ads.util.ConnectionUtils;
051import org.opends.guitools.controlpanel.ControlPanelArgumentParser;
052import org.opends.guitools.controlpanel.datamodel.ConfigReadException;
053import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
054import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
055import org.opends.guitools.controlpanel.task.OnlineUpdateException;
056import org.opends.guitools.controlpanel.util.BackgroundTask;
057import org.opends.guitools.controlpanel.util.Utilities;
058import org.opends.quicksetup.Installation;
059import org.opends.quicksetup.UserData;
060import org.opends.quicksetup.UserDataCertificateException;
061import org.opends.quicksetup.ui.CertificateDialog;
062import org.opends.quicksetup.util.UIKeyStore;
063import org.opends.quicksetup.util.Utils;
064import org.opends.server.monitors.VersionMonitorProvider;
065import org.forgerock.opendj.ldap.DN;
066import org.opends.server.types.OpenDsException;
067import org.opends.server.util.DynamicConstants;
068import org.opends.server.util.StaticUtils;
069
070import static com.forgerock.opendj.cli.Utils.*;
071
072import static org.opends.admin.ads.util.ConnectionUtils.*;
073import static org.opends.guitools.controlpanel.util.Utilities.*;
074import static org.opends.messages.AdminToolMessages.*;
075import static org.opends.messages.QuickSetupMessages.*;
076import static org.opends.server.monitors.VersionMonitorProvider.*;
077
078/**
079 * The panel that appears when the user is asked to provide authentication.
080 */
081public class LocalOrRemotePanel extends StatusGenericPanel
082{
083
084  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
085  private static final long serialVersionUID = 5051556513294844797L;
086
087  private JComboBox combo;
088  private JLabel portLabel;
089  private JTextField hostName;
090  private JTextField port;
091  private JPasswordField pwd;
092  private JTextField dn;
093  private JLabel pwdLabel;
094  private JLabel dnLabel;
095  private String usedUrl;
096  private JLabel localInstallLabel;
097  private JEditorPane localInstall;
098  private JLabel localNotRunning;
099  private boolean isLocalServerRunning;
100  private boolean callOKWhenVisible;
101
102  /** Default constructor. */
103  public LocalOrRemotePanel()
104  {
105    super();
106    createLayout();
107  }
108
109  /** {@inheritDoc} */
110  @Override
111  public LocalizableMessage getTitle()
112  {
113    return INFO_CTRL_PANEL_LOCAL_OR_REMOTE_PANEL_TITLE.get();
114  }
115
116  /** {@inheritDoc} */
117  @Override
118  public GenericDialog.ButtonType getButtonType()
119  {
120    return GenericDialog.ButtonType.OK_CANCEL;
121  }
122
123  /**
124   * Returns the displayed host name.
125   * @return the displayed host name.
126   */
127  public String getHostName()
128  {
129    return hostName.getText();
130  }
131
132  /**
133   * Returns the displayed administration port.
134   * @return the displayed administration port.
135   */
136  public int getPort()
137  {
138    try
139    {
140      return Integer.valueOf(this.port.getText().trim());
141    }
142    catch (Exception ignored)
143    {
144      return -1;
145    }
146  }
147
148  /**
149   * Returns the displayed bind DN.
150   * @return the displayed bind DN.
151   */
152  public String getBindDN()
153  {
154    return dn.getText();
155  }
156
157  /**
158   * Returns the displayed password.
159   * @return the displayed password.
160   */
161  public char[] getBindPassword()
162  {
163    return pwd.getPassword();
164  }
165
166  /**
167   * Returns whether the panel displays the remote or the local server.
168   * @return whether the panel displays the remote or the local server.
169   */
170  public boolean isRemote()
171  {
172    int index = combo.getSelectedIndex();
173    return index == 1;
174  }
175
176  /**
177   * Sets the displayed host name.
178   * @param hostName the host name.
179   */
180  public void setHostName(String hostName)
181  {
182    this.hostName.setText(hostName);
183  }
184
185  /**
186   * Sets the displayed administration port.
187   * @param port the displayed administration port.
188   */
189  public void setPort(int port)
190  {
191    this.port.setText(String.valueOf(port));
192  }
193
194  /**
195   * Sets the displayed bind DN.
196   * @param bindDN the displayed bind DN.
197   */
198  public void setBindDN(String bindDN)
199  {
200    this.dn.setText(bindDN);
201  }
202
203  /**
204   * Sets the displayed password.
205   * @param pwd the password.
206   */
207  public void setBindPassword(char[] pwd)
208  {
209    this.pwd.setText(new String(pwd));
210  }
211
212  /**
213   * Sets whether the panel should display the remote or the local server.
214   * @param remote whether the panel should display the remote or the local
215   * server.
216   */
217  public void setRemote(boolean remote)
218  {
219    int index = remote ? 1 : 0;
220    combo.setSelectedIndex(index);
221    updateComponentState();
222  }
223
224  /**
225   * Method to be called when we want the panel to call automatically okClicked
226   * method when the panel is made visible.
227   * @param callOKWhenVisible whether okClicked must be called automatically
228   * when the panel is made visible or not.
229   */
230  public void setCallOKWhenVisible(boolean callOKWhenVisible)
231  {
232    this.callOKWhenVisible = callOKWhenVisible;
233  }
234
235  /**
236   * Returns whether okClicked must be called automatically when the panel is
237   * made visible or not.
238   * @return whether okClicked must be called automatically when the panel is
239   * made visible or not.
240   */
241  public boolean isCallOKWhenVisible()
242  {
243    return callOKWhenVisible;
244  }
245
246  /**
247   * Creates the layout of the panel (but the contents are not populated here).
248   */
249  private void createLayout()
250  {
251    GridBagConstraints gbc = new GridBagConstraints();
252
253    gbc.anchor = GridBagConstraints.WEST;
254    gbc.gridx = 0;
255    gbc.gridy = 0;
256
257    gbc.weightx = 0.0;
258    gbc.weighty = 0.0;
259    String localServerInstallPath;
260    File instancePath = Installation.getLocal().getInstanceDirectory();
261    try
262    {
263      localServerInstallPath = instancePath.getCanonicalPath();
264    }
265    catch (IOException ioe)
266    {
267      localServerInstallPath = instancePath.getAbsolutePath();
268    }
269    combo = Utilities.createComboBox();
270    combo.setModel(new DefaultComboBoxModel(
271        new Object[] {INFO_CTRL_PANEL_LOCAL_SERVER.get(),
272            INFO_CTRL_PANEL_REMOTE_SERVER.get()}));
273    combo.setSelectedIndex(0);
274    gbc.gridwidth = 2;
275    JLabel l = Utilities.createDefaultLabel(
276        INFO_CTRL_PANEL_LOCAL_OR_REMOTE.get());
277    add(l, gbc);
278    gbc.gridwidth = 1;
279    gbc.insets.top = 10;
280    gbc.gridy ++;
281    add(combo, gbc);
282    l.setLabelFor(combo);
283    gbc.gridx = 1;
284
285    localNotRunning = Utilities.createDefaultLabel();
286    Utilities.setWarningLabel(localNotRunning,
287        INFO_CTRL_PANEL_LOCAL_SERVER_NOT_RUNNING.get());
288    gbc.insets.left = 10;
289    add(localNotRunning, gbc);
290    localNotRunning.setFocusable(true);
291    hostName = Utilities.createMediumTextField();
292    hostName.setText(UserData.getDefaultHostName());
293    hostName.setToolTipText(
294        INFO_CTRL_PANEL_REMOTE_SERVER_TOOLTIP.get().toString());
295    add(hostName, gbc);
296    gbc.insets.top = 10;
297    gbc.gridy ++;
298    gbc.insets.left = 0;
299    gbc.weightx = 0.0;
300    gbc.insets.right = 0;
301    gbc.gridx = 0;
302
303    ActionListener actionListener = new ActionListener()
304    {
305      @Override
306      public void actionPerformed(ActionEvent ev)
307      {
308        updateComponentState();
309      }
310    };
311    combo.addActionListener(actionListener);
312
313    gbc.gridx = 0;
314    gbc.gridwidth = 1;
315
316
317    localInstallLabel = Utilities.createPrimaryLabel(
318        INFO_CTRL_PANEL_INSTANCE_PATH_LABEL.get());
319    gbc.insets.left = 0;
320    add(localInstallLabel, gbc);
321    gbc.gridx = 1;
322    gbc.insets.left = 10;
323    gbc.fill = GridBagConstraints.HORIZONTAL;
324    gbc.weightx = 0.1;
325    localInstall = Utilities.makeHtmlPane(localServerInstallPath,
326        ColorAndFontConstants.defaultFont);
327    add(localInstall, gbc);
328    localInstallLabel.setLabelFor(localInstall);
329    gbc.gridx ++;
330    gbc.weightx = 1.0;
331    gbc.insets.left = 0;
332    add(Box.createHorizontalGlue(), gbc);
333
334    gbc.gridy ++;
335    gbc.insets.top = 10;
336    gbc.insets.left = 0;
337    gbc.gridx = 0;
338    gbc.weightx = 0.0;
339    portLabel = Utilities.createPrimaryLabel(
340        INFO_CTRL_PANEL_ADMINISTRATION_PORT.get());
341    add(portLabel, gbc);
342    gbc.gridx = 1;
343    gbc.insets.left = 10;
344    port = Utilities.createMediumTextField();
345    port.setText(String.valueOf(
346        ControlPanelArgumentParser.getDefaultAdministrationPort()));
347    gbc.weightx = 1.0;
348    gbc.fill = GridBagConstraints.HORIZONTAL;
349    add(port, gbc);
350    portLabel.setLabelFor(port);
351
352    gbc.gridy ++;
353    gbc.gridx = 0;
354    gbc.weightx = 0.0;
355    gbc.fill = GridBagConstraints.NONE;
356    gbc.insets.left = 0;
357    dnLabel = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_BIND_DN_LABEL.get());
358    add(dnLabel, gbc);
359    gbc.insets.left = 10;
360    gbc.gridx = 1;
361    dn = Utilities.createTextField(
362        ControlPanelArgumentParser.getDefaultBindDN(), 20);
363    gbc.weightx = 1.0;
364    gbc.fill = GridBagConstraints.HORIZONTAL;
365    gbc.insets.left = 10;
366    add(dn, gbc);
367    dnLabel.setLabelFor(dn);
368    gbc.insets.top = 10;
369    gbc.insets.left = 0;
370
371    gbc.gridx = 0;
372    gbc.gridy ++;
373    gbc.weightx = 0.0;
374    gbc.fill = GridBagConstraints.NONE;
375    pwdLabel = Utilities.createPrimaryLabel(
376        INFO_CTRL_PANEL_BIND_PASSWORD_LABEL.get());
377    gbc.insets.left = 0;
378    add(pwdLabel, gbc);
379    gbc.insets.left = 10;
380    gbc.gridx = 1;
381    pwd = Utilities.createPasswordField();
382    gbc.weightx = 1.0;
383    gbc.fill = GridBagConstraints.HORIZONTAL;
384    add(pwd, gbc);
385    pwdLabel.setLabelFor(pwd);
386
387    addBottomGlue(gbc);
388  }
389
390  /** {@inheritDoc} */
391  @Override
392  public Component getPreferredFocusComponent()
393  {
394    if (pwd.isVisible())
395    {
396      return pwd;
397    }
398    return combo;
399  }
400
401  /** {@inheritDoc} */
402  @Override
403  public void configurationChanged(ConfigurationChangeEvent ev)
404  {
405  }
406
407  /** {@inheritDoc} */
408  @Override
409  public void toBeDisplayed(boolean visible)
410  {
411    super.toBeDisplayed(visible);
412    if (visible)
413    {
414      // Do it outside the event thread if the panel requires it.
415      BackgroundTask<Void> worker = new BackgroundTask<Void>()
416      {
417        @Override
418        public Void processBackgroundTask() throws Throwable
419        {
420          StaticUtils.sleep(200);
421          File instancePath = Installation.getLocal().getInstanceDirectory();
422          isLocalServerRunning = Utilities.isServerRunning(instancePath);
423          return null;
424        }
425
426
427        @Override
428        public void backgroundTaskCompleted(Void returnValue,
429            Throwable t)
430        {
431          updateComponentState();
432          displayMainPanel();
433          Component comp = getPreferredFocusComponent();
434          if (comp != null)
435          {
436            comp.requestFocusInWindow();
437          }
438          if (isCallOKWhenVisible())
439          {
440            okClicked();
441          }
442        }
443      };
444      displayMessage(INFO_CTRL_PANEL_LOADING_PANEL_SUMMARY.get());
445      worker.startBackgroundTask();
446      if (!isCallOKWhenVisible())
447      {
448        pwd.setText("");
449      }
450    }
451  }
452
453  /** {@inheritDoc} */
454  @Override
455  public void okClicked()
456  {
457    setPrimaryValid(portLabel);
458    setPrimaryValid(dnLabel);
459    setPrimaryValid(pwdLabel);
460    final LinkedHashSet<LocalizableMessage> errors = new LinkedHashSet<>();
461
462    boolean dnInvalid = false;
463    boolean pwdInvalid = false;
464
465    final boolean isLocal = combo.getSelectedIndex() == 0;
466
467    boolean doChecks = !isLocal || isLocalServerRunning;
468    if (doChecks)
469    {
470      if ("".equals(dn.getText().trim()))
471      {
472        dnInvalid = true;
473        errors.add(INFO_EMPTY_DIRECTORY_MANAGER_DN.get());
474      }
475      else if (!isDN(dn.getText()))
476      {
477        dnInvalid = true;
478        errors.add(INFO_NOT_A_DIRECTORY_MANAGER_DN.get());
479      }
480
481      if (pwd.getPassword().length == 0)
482      {
483        pwdInvalid = true;
484        errors.add(INFO_EMPTY_PWD.get());
485      }
486      if (dnInvalid)
487      {
488        setPrimaryInvalid(dnLabel);
489      }
490
491      if (pwdInvalid)
492      {
493        setPrimaryInvalid(pwdLabel);
494      }
495
496      if (!isLocal)
497      {
498        if ("".equals(hostName.getText().trim()))
499        {
500          errors.add(INFO_EMPTY_REMOTE_HOST_NAME.get());
501        }
502
503        try
504        {
505          int p = Integer.parseInt(port.getText());
506          if (p <= 0 || p > 65535)
507          {
508            errors.add(INFO_INVALID_REMOTE_SERVER_PORT.get(0, 65535));
509          }
510        }
511        catch (Throwable t)
512        {
513          errors.add(INFO_INVALID_REMOTE_SERVER_PORT.get(0, 65535));
514        }
515      }
516    }
517
518    if (errors.isEmpty())
519    {
520      setEnabledOK(false);
521      displayMessage(INFO_CTRL_PANEL_VERIFYING_AUTHENTICATION_SUMMARY.get());
522
523      BackgroundTask<InitialLdapContext> worker =
524        new BackgroundTask<InitialLdapContext>()
525      {
526        /** {@inheritDoc} */
527        @Override
528        public InitialLdapContext processBackgroundTask() throws Throwable
529        {
530          getInfo().stopPooling();
531          if (isLocal)
532          {
533            // At least load the local information.
534            SwingUtilities.invokeLater(new Runnable()
535            {
536              @Override
537              public void run()
538              {
539                displayMessage(
540                    INFO_CTRL_PANEL_READING_CONFIGURATION_SUMMARY.get());
541              }
542            });
543            if (getInfo().isLocal() != isLocal)
544            {
545              closeInfoConnections();
546            }
547            getInfo().setIsLocal(isLocal);
548            getInfo().regenerateDescriptor();
549            if (!isLocalServerRunning)
550            {
551              return null;
552            }
553          }
554          InitialLdapContext ctx = null;
555          try
556          {
557            if (isLocal)
558            {
559              usedUrl = getInfo().getAdminConnectorURL();
560              ctx = Utilities.getAdminDirContext(getInfo(), dn.getText(),
561                  String.valueOf(pwd.getPassword()));
562            }
563            else
564            {
565              usedUrl = ConnectionUtils.getLDAPUrl(hostName.getText().trim(),
566                  Integer.valueOf(port.getText().trim()), true);
567              ctx = createLdapsContext(usedUrl, dn.getText(),
568                  String.valueOf(pwd.getPassword()),
569                  getInfo().getConnectTimeout(), null,
570                  getInfo().getTrustManager(), null);
571              checkVersion(ctx);
572            }
573
574            StaticUtils.sleep(500);
575            SwingUtilities.invokeLater(new Runnable()
576            {
577              @Override
578              public void run()
579              {
580                displayMessage(INFO_CTRL_PANEL_READING_CONFIGURATION_SUMMARY.get());
581              }
582            });
583            closeInfoConnections();
584            getInfo().setIsLocal(isLocal);
585            getInfo().setDirContext(ctx);
586            getInfo().setUserDataDirContext(null);
587            getInfo().regenerateDescriptor();
588            return ctx;
589          } catch (Throwable t)
590          {
591            StaticUtils.close(ctx);
592            throw t;
593          }
594        }
595
596        /** {@inheritDoc} */
597        @Override
598        public void backgroundTaskCompleted(InitialLdapContext ctx,
599            Throwable throwable)
600        {
601          boolean handleCertificateException = false;
602          boolean localServerErrorConnecting = false;
603
604          if (throwable != null)
605          {
606            logger.info(LocalizableMessage.raw("Error connecting: " + throwable, throwable));
607
608            if (isVersionException(throwable))
609            {
610              errors.add(((OpenDsException)throwable).getMessageObject());
611            }
612            else if (isCertificateException(throwable))
613            {
614              ApplicationTrustManager.Cause cause =
615                getInfo().getTrustManager().getLastRefusedCause();
616
617              logger.info(LocalizableMessage.raw("Certificate exception cause: "+cause));
618              UserDataCertificateException.Type excType = null;
619              if (cause == ApplicationTrustManager.Cause.NOT_TRUSTED)
620              {
621                excType = UserDataCertificateException.Type.NOT_TRUSTED;
622              }
623              else if (cause ==
624                ApplicationTrustManager.Cause.HOST_NAME_MISMATCH)
625              {
626                excType = UserDataCertificateException.Type.HOST_NAME_MISMATCH;
627              }
628              else
629              {
630                LocalizableMessage msg = getThrowableMsg(
631                    INFO_ERROR_CONNECTING_TO_LOCAL.get(), throwable);
632                errors.add(msg);
633              }
634
635              if (excType != null)
636              {
637                String h;
638                int p;
639                try
640                {
641                  URI uri = new URI(usedUrl);
642                  h = uri.getHost();
643                  p = uri.getPort();
644                }
645                catch (Throwable t)
646                {
647                  logger.warn(LocalizableMessage.raw(
648                      "Error parsing ldap url of ldap url.", t));
649                  h = INFO_NOT_AVAILABLE_LABEL.get().toString();
650                  p = -1;
651                }
652                UserDataCertificateException udce =
653                  new UserDataCertificateException(null,
654                      INFO_CERTIFICATE_EXCEPTION.get(h, p),
655                      throwable, h, p,
656                      getInfo().getTrustManager().getLastRefusedChain(),
657                      getInfo().getTrustManager().getLastRefusedAuthType(),
658                      excType);
659
660                handleCertificateException(udce);
661                handleCertificateException = true;
662              }
663            }
664            else if (throwable instanceof NamingException)
665            {
666              boolean found = false;
667              String providedDn = dn.getText();
668              if (isLocal)
669              {
670                Iterator<DN> it = getInfo().getServerDescriptor().
671                getAdministrativeUsers().iterator();
672                while (it.hasNext() && !found)
673                {
674                  found = Utils.areDnsEqual(providedDn, it.next().toString());
675                }
676                if (!found)
677                {
678                  errors.add(INFO_NOT_A_DIRECTORY_MANAGER_IN_CONFIG.get());
679                }
680                else
681                {
682                  errors.add(Utils.getMessageForException(
683                      (NamingException)throwable));
684                }
685                localServerErrorConnecting = true;
686              }
687              else
688              {
689                String hostPort = ServerDescriptor.getServerRepresentation(
690                    hostName.getText().trim(),
691                    Integer.valueOf(port.getText().trim()));
692                NamingException ne = (NamingException)throwable;
693                errors.add(getMessageForException(ne, hostPort));
694                setPrimaryInvalid(portLabel);
695              }
696              setPrimaryInvalid(dnLabel);
697              setPrimaryInvalid(pwdLabel);
698            }
699            else if (throwable instanceof ConfigReadException)
700            {
701              logger.warn(LocalizableMessage.raw(
702                  "Error reading configuration: "+throwable, throwable));
703              errors.add(((ConfigReadException)throwable).getMessageObject());
704            }
705            else
706            {
707              // This is a bug
708              logger.error(LocalizableMessage.raw(
709                  "Unexpected error: "+throwable, throwable));
710              errors.add(getThrowableMsg(INFO_BUG_MSG.get(), throwable));
711            }
712          }
713          displayMainPanel();
714          setEnabledOK(true);
715          if (!errors.isEmpty())
716          {
717            if (!localServerErrorConnecting)
718            {
719              displayErrorDialog(errors);
720            }
721            else
722            {
723              ArrayList<String> stringErrors = new ArrayList<>();
724              for (LocalizableMessage err : errors)
725              {
726                stringErrors.add(err.toString());
727              }
728              String msg = Utilities.getStringFromCollection(stringErrors,
729                  "<br>");
730              if (displayConfirmationDialog(
731                  INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
732                  INFO_CTRL_PANEL_ERROR_CONNECTING_TO_LOCAL.get(msg)))
733              {
734                Utilities.getParentDialog(
735                    LocalOrRemotePanel.this).setVisible(false);
736              }
737            }
738            pwd.setSelectionStart(0);
739            pwd.setSelectionEnd(pwd.getPassword().length);
740            pwd.requestFocusInWindow();
741          }
742          else if (!handleCertificateException)
743          {
744            Utilities.getParentDialog(
745                LocalOrRemotePanel.this).setVisible(false);
746          }
747
748          if (!handleCertificateException)
749          {
750            startPooling();
751          }
752        }
753      };
754      worker.startBackgroundTask();
755    }
756    else
757    {
758      displayErrorDialog(errors);
759      if (dnInvalid)
760      {
761        dn.setSelectionStart(0);
762        dn.setSelectionEnd(dn.getText().length());
763        dn.requestFocusInWindow();
764      }
765      if (pwdInvalid)
766      {
767        pwd.setSelectionStart(0);
768        pwd.setSelectionEnd(pwd.getPassword().length);
769        pwd.requestFocusInWindow();
770      }
771    }
772  }
773
774  /** {@inheritDoc} */
775  @Override
776  public void cancelClicked()
777  {
778    setPrimaryValid(dnLabel);
779    setPrimaryValid(pwdLabel);
780    setPrimaryValid(portLabel);
781    pwd.setText(null);
782    super.cancelClicked();
783  }
784
785  /**
786   * Displays a dialog asking the user to accept a certificate if the user
787   * accepts it, we update the trust manager and simulate a click on "OK" to
788   * re-check the authentication.
789   * This method assumes that we are being called from the event thread.
790   */
791  private void handleCertificateException(UserDataCertificateException ce)
792  {
793    CertificateDialog dlg = new CertificateDialog(null, ce);
794    dlg.pack();
795    Utilities.centerGoldenMean(dlg, Utilities.getParentDialog(this));
796    dlg.setVisible(true);
797    if (dlg.getUserAnswer() !=
798      CertificateDialog.ReturnType.NOT_ACCEPTED)
799    {
800      X509Certificate[] chain = ce.getChain();
801      String authType = ce.getAuthType();
802      String host = ce.getHost();
803
804      if (chain != null && authType != null && host != null)
805      {
806        logger.info(LocalizableMessage.raw("Accepting certificate presented by host "+host));
807        getInfo().getTrustManager().acceptCertificate(chain, authType, host);
808        /* Simulate a click on the OK by calling in the okClicked method. */
809        SwingUtilities.invokeLater(new Runnable()
810        {
811          @Override
812          public void run()
813          {
814            okClicked();
815          }
816        });
817      }
818      else
819      {
820        if (chain == null)
821        {
822          logger.warn(LocalizableMessage.raw(
823              "The chain is null for the UserDataCertificateException"));
824        }
825        if (authType == null)
826        {
827          logger.warn(LocalizableMessage.raw(
828              "The auth type is null for the UserDataCertificateException"));
829        }
830        if (host == null)
831        {
832          logger.warn(LocalizableMessage.raw(
833              "The host is null for the UserDataCertificateException"));
834        }
835      }
836    }
837    if (dlg.getUserAnswer() ==
838      CertificateDialog.ReturnType.ACCEPTED_PERMANENTLY)
839    {
840      X509Certificate[] chain = ce.getChain();
841      if (chain != null)
842      {
843        try
844        {
845          UIKeyStore.acceptCertificate(chain);
846        }
847        catch (Throwable t)
848        {
849          logger.warn(LocalizableMessage.raw("Error accepting certificate: "+t, t));
850        }
851      }
852    }
853  }
854
855  private void updateComponentState()
856  {
857    boolean isLocal = combo.getSelectedIndex() == 0;
858    hostName.setVisible(!isLocal);
859    port.setVisible(!isLocal);
860    portLabel.setVisible(!isLocal);
861    localInstall.setVisible(isLocal);
862    localInstallLabel.setVisible(isLocal);
863
864    boolean displayAuthentication = !isLocal || isLocalServerRunning;
865    dn.setVisible(displayAuthentication);
866    dnLabel.setVisible(displayAuthentication);
867    pwd.setVisible(displayAuthentication);
868    pwdLabel.setVisible(displayAuthentication);
869
870    localNotRunning.setVisible(isLocal && !isLocalServerRunning);
871  }
872
873  private void startPooling()
874  {
875    // The server descriptor has been already retrieved.
876    // startPooling tries to retrieve immediately the server descriptor, so
877    // sleep the pooling period before calling it.
878    Thread t = new Thread(new Runnable()
879    {
880      @Override
881      public void run()
882      {
883        StaticUtils.sleep(getInfo().getPoolingPeriod());
884        getInfo().startPooling();
885      }
886    });
887    t.start();
888  }
889
890  private void checkVersion(InitialLdapContext ctx) throws OpenDsException
891  {
892    LocalizableMessage msg = null;
893    try
894    {
895      // Search for the version on the remote server.
896      SearchControls searchControls = new SearchControls();
897      searchControls.setSearchScope(
898      SearchControls.OBJECT_SCOPE);
899      searchControls.setReturningAttributes(
900      new String[] {
901          VersionMonitorProvider.ATTR_PRODUCT_NAME,
902          VersionMonitorProvider.ATTR_MAJOR_VERSION,
903          VersionMonitorProvider.ATTR_POINT_VERSION,
904          VersionMonitorProvider.ATTR_MINOR_VERSION
905          });
906      NamingEnumeration<SearchResult> en =
907        ctx.search("cn=Version,cn=monitor", "objectclass=*", searchControls);
908      SearchResult sr = null;
909      try
910      {
911        while (en.hasMore())
912        {
913          sr = en.next();
914        }
915      }
916      finally
917      {
918        en.close();
919      }
920
921      CustomSearchResult csr = new CustomSearchResult(sr, "cn=Version,cn=monitor");
922
923      String hostName = ConnectionUtils.getHostName(ctx);
924
925      String productName = String.valueOf(getFirstValueAsString(csr, ATTR_PRODUCT_NAME));
926      String major = String.valueOf(getFirstValueAsString(csr, ATTR_MAJOR_VERSION));
927      String point = String.valueOf(getFirstValueAsString(csr, ATTR_POINT_VERSION));
928      String minor = String.valueOf(getFirstValueAsString(csr, ATTR_MINOR_VERSION));
929      // Be strict, control panel is only compatible with exactly the same version
930      if (!productName.equalsIgnoreCase(DynamicConstants.PRODUCT_NAME))
931      {
932        msg = ERR_NOT_SAME_PRODUCT_IN_REMOTE_SERVER_NOT_FOUND.get(hostName,
933            productName, DynamicConstants.PRODUCT_NAME);
934      }
935      else if (!String.valueOf(DynamicConstants.MAJOR_VERSION).equals(major)
936          || !String.valueOf(DynamicConstants.MINOR_VERSION).equals(minor)
937          || !String.valueOf(DynamicConstants.POINT_VERSION).equals(point))
938      {
939        msg = ERR_INCOMPATIBLE_VERSION_IN_REMOTE_SERVER.get(hostName,
940            major, minor, point, DynamicConstants.MAJOR_VERSION,
941            DynamicConstants.MINOR_VERSION, DynamicConstants.POINT_VERSION);
942      }
943    }
944    catch (Throwable t)
945    {
946      msg = ERR_VERSION_IN_REMOTE_SERVER_NOT_FOUND.get();
947    }
948    if (msg != null)
949    {
950      throw new OnlineUpdateException(msg, null);
951    }
952  }
953
954  private boolean isVersionException(Throwable t)
955  {
956    if (t instanceof OpenDsException)
957    {
958      OpenDsException oe = (OpenDsException)t;
959      if (oe.getMessageObject() != null)
960      {
961        LocalizableMessage msg = oe.getMessageObject();
962        if (StaticUtils.hasDescriptor(msg, ERR_INCOMPATIBLE_VERSION_IN_REMOTE_SERVER) ||
963            StaticUtils.hasDescriptor(msg, ERR_VERSION_IN_REMOTE_SERVER_NOT_FOUND) ||
964            StaticUtils.hasDescriptor(msg, ERR_NOT_SAME_PRODUCT_IN_REMOTE_SERVER_NOT_FOUND))
965        {
966          return true;
967        }
968      }
969    }
970    return false;
971  }
972
973  private void closeInfoConnections()
974  {
975    StaticUtils.close(getInfo().getDirContext(), getInfo().getUserDataDirContext());
976  }
977}