/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2008-2010 Sun Microsystems, Inc. * Portions Copyright 2012-2015 ForgeRock AS. */ package org.opends.quicksetup.ui; import org.opends.quicksetup.util.UIKeyStore; import org.opends.quicksetup.Application; import org.opends.quicksetup.ButtonName; import org.opends.quicksetup.UserData; import org.opends.quicksetup.UserDataCertificateException; import org.opends.quicksetup.UserDataException; import org.opends.quicksetup.WizardStep; import org.forgerock.i18n.LocalizableMessage; import static org.opends.messages.QuickSetupMessages.*; import javax.swing.*; import java.awt.event.WindowEvent; import java.security.cert.X509Certificate; import java.util.LinkedHashSet; import java.util.Set; import org.forgerock.i18n.slf4j.LocalizedLogger; /** * This class represents an application with a wizard GUI that can be run in the * context of QuickSetup. Examples of applications might be 'installer', * and 'uninstaller'. */ public abstract class GuiApplication extends Application { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** The currently displayed wizard step. */ private WizardStep displayedStep; /** The QuickSetupDialog in control. */ private QuickSetupDialog qs; private String[] args = {}; /** * Constructs an instance of an application. Subclasses * of this application must have a default constructor. */ public GuiApplication() { this.displayedStep = getFirstWizardStep(); } /** * Gets the frame title of the GUI application that will be used * in some operating systems. * @return internationalized String representing the frame title */ public abstract LocalizableMessage getFrameTitle(); /** * Returns the initial wizard step. * @return Step representing the first step to show in the wizard */ public abstract WizardStep getFirstWizardStep(); /** * Called by the quicksetup controller when the user advances to * a new step in the wizard. Applications are expected to manipulate * the QuickSetupDialog to reflect the current step. * * @param step Step indicating the new current step * @param userData UserData representing the data specified by the user * @param dlg QuickSetupDialog hosting the wizard */ public void setDisplayedWizardStep(WizardStep step, UserData userData, QuickSetupDialog dlg) { this.displayedStep = step; // First call the panels to do the required updates on their layout dlg.setDisplayedStep(step, userData); setWizardDialogState(dlg, userData, step); } /** * Called when the user advances to new step in the wizard. Applications * are expected to manipulate the QuickSetupDialog to reflect the current * step. * @param dlg QuickSetupDialog hosting the wizard * @param userData UserData representing the data specified by the user * @param step Step indicating the new current step */ public abstract void setWizardDialogState(QuickSetupDialog dlg, UserData userData, WizardStep step); /** * Returns the tab formatted. * @return the tab formatted. */ protected LocalizableMessage getTab() { return formatter.getTab(); } /** * Called by the controller when the window is closing. The application * can take application specific actions here. * @param dlg QuickSetupDialog that will be closing * @param evt The event from the Window indicating closing */ public abstract void windowClosing(QuickSetupDialog dlg, WindowEvent evt); /** * This method is called when we detected that there is something installed * we inform of this to the user and the user wants to proceed with the * installation destroying the contents of the data and the configuration * in the current installation. */ public void forceToDisplay() { // This is really only appropriate for Installer. // The default implementation is to do nothing. // The Installer application overrides this with // whatever it needs. } /** * Called before the application cancels its operation, giving the * user a chance to confirm the cancellation action. * @param qs QuickSetup that can be used for confirming * @return boolean where true indicates that the user answered * affirmatively to the cancelation confirmation */ public boolean confirmCancel(QuickSetup qs) { return qs.displayConfirmation( INFO_CONFIRM_CANCEL_PROMPT.get(), INFO_CONFIRM_CANCEL_TITLE.get()); } /** * Get the name of the button that will receive initial focus. * @return ButtonName of the button to receive initial focus */ public abstract ButtonName getInitialFocusButtonName(); /** * Creates the main panel for the wizard dialog. * @param dlg QuickSetupDialog used * @return JPanel frame panel */ public JPanel createFramePanel(QuickSetupDialog dlg) { return new FramePanel(dlg.getStepsPanel(), dlg.getCurrentStepPanel(), dlg.getButtonsPanel()); } /** * Returns the set of wizard steps used in this application's wizard. * @return Set of Step objects representing wizard steps */ public abstract Set<? extends WizardStep> getWizardSteps(); /** * Creates a wizard panel given a specific step. * @param step for which a panel representation should be created * @return QuickSetupStepPanel for representing the <code>step</code> */ public abstract QuickSetupStepPanel createWizardStepPanel(WizardStep step); /** * Gets the next step in the wizard given a current step. * @param step Step the current step * @return Step the next step */ public abstract WizardStep getNextWizardStep(WizardStep step); /** * Gets the previous step in the wizard given a current step. * @param step Step the current step * @return Step the previous step */ public abstract WizardStep getPreviousWizardStep(WizardStep step); /** * Gets the finished step in the wizard. * @return Step the finished step */ public abstract WizardStep getFinishedStep(); /** * Gets the currently displayed wizard step. * @return WizardStep being displayed. */ public WizardStep getCurrentWizardStep() { return displayedStep; } /** * Indicates whether the provided <code>step</code> is a sub step or not. * @param step WizardStep for which the return value indicates whether * or not is a sub step. * @return boolean where true indicates the provided <code>step</code> is a * substep. */ public boolean isSubStep(WizardStep step) { return false; } /** * Indicates whether the provided <code>step</code> is visible or not * depending on the contents of the UserData object that is provided. * @param step WizardStep for which the return value indicates whether * or not is visible. * @param userData the UserData to be used to determine if the step is * visible or not. * @return boolean where true indicates the provided <code>step</code> is * visible. */ public boolean isVisible(WizardStep step, UserData userData) { return true; } /** * Indicates whether the provided <code>step</code> is visible or not * depending on the contents of the QuickSetup object that is provided. * @param step WizardStep for which the return value indicates whether * or not is visible. * @param qs the QuickSetup to be used to determine if the step is * visible or not. * @return boolean where true indicates the provided <code>step</code> is * visible. */ public boolean isVisible(WizardStep step, QuickSetup qs) { return true; } /** * Returns the list of all the steps in an ordered manner. This is required * because in the case of an application with substeps the user of the other * interfaces is not enough. This is a default implementation that uses * the getNextWizardStep method to calculate the list that work for * applications with no substeps. * @return a list containing ALL the steps (including substeps) in an ordered * manner. */ public LinkedHashSet<WizardStep> getOrderedSteps() { LinkedHashSet<WizardStep> orderedSteps = new LinkedHashSet<>(); WizardStep step = getFirstWizardStep(); orderedSteps.add(step); while (null != (step = getNextWizardStep(step))) { orderedSteps.add(step); } return orderedSteps; } /** * Indicates whether or not the user is allowed to return to a previous * step from <code>step</code>. * @param step WizardStep for which the the return value indicates whether * or not the user can return to a previous step * @return boolean where true indicates the user can return to a previous * step from <code>step</code> */ public boolean canGoBack(WizardStep step) { return !getFirstWizardStep().equals(step); } /** * Indicates whether or not the user is allowed to move to a new * step from <code>step</code>. * @param step WizardStep for which the the return value indicates whether * or not the user can move to a new step * @return boolean where true indicates the user can move to a new * step from <code>step</code> */ public boolean canGoForward(WizardStep step) { return !step.isProgressStep() && getNextWizardStep(step) != null; } /** * Indicates whether or not the user is allowed to finish the wizard from * <code>step</code>. * @param step WizardStep for which the the return value indicates whether * or not the user can finish the wizard * @return boolean where true indicates the user can finish the wizard */ public abstract boolean canFinish(WizardStep step); /** * Called when the user has clicked the 'previous' button. * @param cStep WizardStep at which the user clicked the previous button * @param qs QuickSetup controller */ public abstract void previousClicked(WizardStep cStep, QuickSetup qs); /** * Called when the user has clicked the 'finish' button. * @param cStep WizardStep at which the user clicked the previous button * @param qs QuickSetup controller * @return boolean that the application uses to indicate the the * application should be launched. If false, the application is * responsible for updating the user data for the final screen and * launching the application if this is the desired behavior. */ public abstract boolean finishClicked(final WizardStep cStep, final QuickSetup qs); /** * Called when the user has clicked the 'next' button. * @param cStep WizardStep at which the user clicked the next button * @param qs QuickSetup controller */ public abstract void nextClicked(WizardStep cStep, QuickSetup qs); /** * Called when the user has clicked the 'close' button. * @param cStep WizardStep at which the user clicked the close button * @param qs QuickSetup controller */ public void closeClicked(WizardStep cStep, QuickSetup qs) { qs.quit(); } /** * Called when the user has clicked the 'quit' button. * @param step WizardStep at which the user clicked the quit button * @param qs QuickSetup controller */ public void quitClicked(WizardStep step, QuickSetup qs) { qs.quit(); } /** * Called whenever this application should update its user data from * values found in QuickSetup. * @param cStep current wizard step * @param qs QuickSetup controller * @throws org.opends.quicksetup.UserDataException if there is a problem with * the data */ public abstract void updateUserData(WizardStep cStep, QuickSetup qs) throws UserDataException; /** * Gets the key for the close button's tool tip text. * @return String key of the text in the resource bundle */ public LocalizableMessage getCloseButtonToolTip() { return INFO_CLOSE_BUTTON_TOOLTIP.get(); } /** * Gets the key for the quit button's tool tip text. * @return String key of the text in the resource bundle */ public LocalizableMessage getQuitButtonToolTip() { return INFO_QUIT_BUTTON_INSTALL_TOOLTIP.get(); } /** * Gets the key for the finish button's tool tip text. * @return String key of the text in the resource bundle */ public LocalizableMessage getFinishButtonToolTip() { return INFO_FINISH_BUTTON_TOOLTIP.get(); } /** * Gets the key for the finish button's label. * @return String key of the text in the resource bundle */ public LocalizableMessage getFinishButtonLabel() { return INFO_FINISH_BUTTON_LABEL.get(); } /** * Indicates whether the finish button must be placed on the left (close to * "Next" button) or on the right (close to "Quit" button). * @return <CODE>true</CODE> if the finish button must be placed on the left * and <CODE>false</CODE> otherwise. */ public boolean finishOnLeft() { return true; } /** * Updates the list of certificates accepted by the user in the trust manager * based on the information stored in the UserDataCertificateException we got * when trying to connect in secure mode. * @param ce the UserDataCertificateException that contains the information to * be used. * @param acceptPermanently whether the certificate must be accepted * permanently or not. */ protected void acceptCertificateForException(UserDataCertificateException ce, boolean acceptPermanently) { X509Certificate[] chain = ce.getChain(); String authType = ce.getAuthType(); String host = ce.getHost(); if (chain != null && authType != null && host != null) { logger.info(LocalizableMessage.raw("Accepting certificate presented by host "+host)); getTrustManager().acceptCertificate(chain, authType, host); } else { if (chain == null) { logger.warn(LocalizableMessage.raw( "The chain is null for the UserDataCertificateException")); } if (authType == null) { logger.warn(LocalizableMessage.raw( "The auth type is null for the UserDataCertificateException")); } if (host == null) { logger.warn(LocalizableMessage.raw( "The host is null for the UserDataCertificateException")); } } if (acceptPermanently && chain != null) { try { UIKeyStore.acceptCertificate(chain); } catch (Throwable t) { logger.warn(LocalizableMessage.raw("Error accepting certificate: "+t, t)); } } } /** * Gets the amount of addition pixels added to the height * of the tallest panel in order to size the wizard for * asthetic reasons. * @return int height to add */ public int getExtraDialogHeight() { return 0; } /** * Sets the QuickSetupDialog driving this application. * @param dialog QuickSetupDialog driving this application */ public void setQuickSetupDialog(QuickSetupDialog dialog) { this.qs = dialog; } /** * Sets the arguments passed in the command-line to launch the application. * @param args the arguments passed in the command-line to launch the * application. */ public void setUserArguments(String[] args) { this.args = args; } /** * Returns the arguments passed in the command-line to launch the application. * @return the arguments passed in the command-line to launch the application. */ public String[] getUserArguments() { return args; } }