/*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2016 ForgeRock AS.
*/
package org.opends.quicksetup.ui;
import org.opends.quicksetup.event.ButtonActionListener;
import org.opends.quicksetup.event.ProgressUpdateListener;
import org.opends.quicksetup.event.ButtonEvent;
import org.opends.quicksetup.event.ProgressUpdateEvent;
import org.opends.quicksetup.*;
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.quicksetup.util.HtmlProgressMessageFormatter;
import org.opends.quicksetup.util.BackgroundTask;
import org.opends.server.util.SetupUtils;
import static org.opends.quicksetup.util.Utils.*;
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.i18n.LocalizableMessage;
import static org.opends.messages.QuickSetupMessages.*;
import static com.forgerock.opendj.util.OperatingSystem.isMacOS;
import static com.forgerock.opendj.cli.Utils.getThrowableMsg;
import javax.swing.*;
import java.awt.Cursor;
import java.util.ArrayList;
import java.util.List;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import java.util.logging.Handler;
import java.util.Map;
/**
* This class is responsible for doing the following:
*
*
*
Check whether we are installing or uninstalling.
*
Performs all the checks and validation of the data provided by the user
* during the setup.
*
It will launch also the installation once the user clicks on 'Finish' if
* we are installing the product.
*
*/
public class QuickSetup implements ButtonActionListener, ProgressUpdateListener
{
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
private GuiApplication application;
private CurrentInstallStatus installStatus;
private WizardStep currentStep;
private QuickSetupDialog dialog;
private LocalizableMessageBuilder progressDetails = new LocalizableMessageBuilder();
private ProgressDescriptor lastDescriptor;
private ProgressDescriptor lastDisplayedDescriptor;
private ProgressDescriptor descriptorToDisplay;
/** Update period of the dialogs. */
private static final int UPDATE_PERIOD = 500;
/** The full pathname of the MacOS X LaunchServices OPEN(1) helper. */
private static final String MAC_APPLICATIONS_OPENER = "/usr/bin/open";
/**
* This method creates the install/uninstall dialogs and to check the current
* install status. This method must be called outside the event thread because
* it can perform long operations which can make the user think that the UI is
* blocked.
*
* @param tempLogFile
* temporary log file where messages will be logged.
* @param args
* for the moment this parameter is not used but we keep it in order
* to (in case of need) pass parameters through the command line.
*/
public void initialize(final TempLogFile tempLogFile, String[] args)
{
ProgressMessageFormatter formatter = new HtmlProgressMessageFormatter();
installStatus = new CurrentInstallStatus();
application = Application.create();
application.setProgressMessageFormatter(formatter);
application.setCurrentInstallStatus(installStatus);
application.setTempLogFile(tempLogFile);
if (args != null)
{
application.setUserArguments(args);
}
else
{
application.setUserArguments(new String[] {});
}
try
{
initLookAndFeel();
}
catch (Throwable t)
{
// This is likely a bug.
t.printStackTrace();
}
/* In the calls to setCurrentStep the dialog will be created */
setCurrentStep(application.getFirstWizardStep());
}
/**
* This method displays the setup dialog.
* This method must be called from the event thread.
*/
public void display()
{
getDialog().packAndShow();
}
/**
* ButtonActionListener implementation. It assumes that we are called in the
* event thread.
*
* @param ev
* the ButtonEvent we receive.
*/
public void buttonActionPerformed(ButtonEvent ev)
{
switch (ev.getButtonName())
{
case NEXT:
nextClicked();
break;
case CLOSE:
closeClicked();
break;
case FINISH:
finishClicked();
break;
case QUIT:
quitClicked();
break;
case CONTINUE_INSTALL:
continueInstallClicked();
break;
case PREVIOUS:
previousClicked();
break;
case LAUNCH_STATUS_PANEL:
launchStatusPanelClicked();
break;
case INPUT_PANEL_BUTTON:
inputPanelButtonClicked();
break;
default:
throw new IllegalArgumentException("Unknown button name: " + ev.getButtonName());
}
}
/**
* ProgressUpdateListener implementation. Here we take the ProgressUpdateEvent
* and create a ProgressDescriptor that will be used to update the progress
* dialog.
*
* @param ev
* the ProgressUpdateEvent we receive.
* @see #runDisplayUpdater()
*/
public void progressUpdate(ProgressUpdateEvent ev)
{
synchronized (this)
{
ProgressDescriptor desc = createProgressDescriptor(ev);
boolean isLastDescriptor = desc.getProgressStep().isLast();
if (isLastDescriptor)
{
lastDescriptor = desc;
}
descriptorToDisplay = desc;
}
}
/**
* This method is used to update the progress dialog.
*
* We are receiving notifications from the installer and uninstaller (this
* class is a ProgressListener). However if we lots of notifications updating
* the progress panel every time we get a progress update can result of a lot
* of flickering. So the idea here is to have a minimal time between 2 updates
* of the progress dialog (specified by UPDATE_PERIOD).
*
* @see #progressUpdate(org.opends.quicksetup.event.ProgressUpdateEvent)
*/
private void runDisplayUpdater()
{
boolean doPool = true;
while (doPool)
{
try
{
Thread.sleep(UPDATE_PERIOD);
}
catch (Exception ex) {}
synchronized (this)
{
final ProgressDescriptor desc = descriptorToDisplay;
if (desc != null)
{
if (desc != lastDisplayedDescriptor)
{
lastDisplayedDescriptor = desc;
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
if (application.isFinished() && !getCurrentStep().isFinishedStep())
{
setCurrentStep(application.getFinishedStep());
}
getDialog().displayProgress(desc);
}
});
}
doPool = desc != lastDescriptor;
}
}
}
}
/** Method called when user clicks 'Next' button of the wizard. */
private void nextClicked()
{
final WizardStep cStep = getCurrentStep();
application.nextClicked(cStep, this);
BackgroundTask> worker = new NextClickedBackgroundTask(cStep);
getDialog().workerStarted();
worker.startBackgroundTask();
}
private void updateUserData(final WizardStep cStep)
{
BackgroundTask> worker = new BackgroundTask