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