/*
* 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 2006-2009 Sun Microsystems, Inc.
* Portions Copyright 2013-2014 ForgeRock AS.
*/
package org.opends.quicksetup.webstart;
import org.forgerock.i18n.LocalizableMessage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import javax.jnlp.DownloadService;
import javax.jnlp.DownloadServiceListener;
import javax.jnlp.ServiceManager;
import javax.jnlp.UnavailableServiceException;
import org.opends.quicksetup.ApplicationException;
import org.opends.quicksetup.Installation;
import org.opends.quicksetup.ReturnCode;
import org.opends.quicksetup.util.Utils;
import org.opends.server.util.SetupUtils;
import static org.opends.quicksetup.util.Utils.*;
import static org.opends.messages.QuickSetupMessages.*;
/**
* This class is used to download the files that have been marked as lazy
* in the QuickSetup.jnlp file.
*
* The global idea is to force the user to download just one jar file
* (quicksetup.jar) to display the Web Start installer dialog. Then QuickSetup
* will call this class and it will download the jar files. Until this class is
* not finished the WebStartInstaller will be on the
* ProgressStep.DOWNLOADING step.
*/
public class WebStartDownloader implements DownloadServiceListener {
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
private ApplicationException ex;
private boolean isFinished;
private int downloadPercentage = 0;
private int currentPercMin = 0;
private int currentPercMax = 0;
private int currentValidatingPercent = 0;
private int currentUpgradingPercent = 0;
private Status status = Status.DOWNLOADING;
private LocalizableMessage summary = null;
/**
* This enumeration contains the different Status on which
* the downloading process of the jars can be.
*
*/
public enum Status
{
/**
* Downloading a jar file.
*/
DOWNLOADING,
/**
* Validating a jar file.
*/
VALIDATING,
/**
* Upgrading a jar file.
*/
UPGRADING
}
/**
* Creates a default instance.
*/
public WebStartDownloader() {
this.summary = INFO_DOWNLOADING.get();
}
/**
* Starts the downloading of the jar files. If forceDownload is set to
* true the files will be re-downloaded even if they already
* are on cache.
*
* This method does not block the thread that calls it.
*
* @param forceDownload used to ignore the case and force download.
*/
public void start(final boolean forceDownload)
{
isFinished = false;
Thread t = new Thread(new Runnable()
{
public void run()
{
try
{
startDownload(forceDownload);
} catch (ApplicationException ex)
{
WebStartDownloader.this.ex = ex;
} catch (MalformedURLException mfe)
{
// This is a bug
ex =
new ApplicationException(ReturnCode.BUG,
getThrowableMsg(INFO_BUG_MSG.get(),mfe), mfe);
} catch (IOException ioe)
{
StringBuilder buf = new StringBuilder();
String[] jars = getJarUrls();
for (int i = 0; i < jars.length; i++)
{
if (i != 0)
{
buf.append(",");
}
buf.append(jars[i]);
}
ex =
new ApplicationException(
ReturnCode.DOWNLOAD_ERROR,
getThrowableMsg(
INFO_DOWNLOADING_ERROR.get(buf.toString()), ioe), ioe);
} catch (Throwable t)
{
// This is a bug
ex =
new ApplicationException(ReturnCode.BUG,
getThrowableMsg(INFO_BUG_MSG.get(), t), t);
}
}
});
t.start();
}
/**
* Gets a summary message of the downloader's current progress.
* @return String for showing the user progress
*/
public LocalizableMessage getSummary() {
return this.summary;
}
/**
* Sets a summary message of the downloader's current progress.
* @param summary String for showing the user progress
*/
public void setSummary(LocalizableMessage summary) {
this.summary = summary;
}
/**
* Returns true if the install is finished and
* false otherwise.
* @return true if the install is finished and
* false otherwise.
*/
public boolean isFinished()
{
return isFinished;
}
/**
* Returns the Status of the current download process.
* @return the current status of the download process.
*/
public Status getStatus()
{
return status;
}
/**
* Returns the current download percentage.
* @return the current download percentage.
*/
public int getDownloadPercentage()
{
return downloadPercentage;
}
/**
* Returns the completed percentage for the file being currently validated.
* @return the completed percentage for the file being currently validated.
*/
public int getCurrentValidatingPercentage()
{
return currentValidatingPercent;
}
/**
* Returns the completed percentage for the file being currently upgraded.
* @return the completed percentage for the file being currently upgraded.
*/
public int getCurrentUpgradingPercentage()
{
return currentUpgradingPercent;
}
/**
* Starts synchronously the downloading on this thread. The thread calling
* this method will be blocked. If forceDownload is set to
* true the files will be re-downloaded even if they already
* are on cache.
* @param forceDownload used to ignore the case and force download.
* @throws MalformedURLException if there is an error with the URLs that we
* get from the property SetupUtils.LAZY_JAR_URLS
* @throws IOException if a network problem occurs.
* @throws ApplicationException if the download service is not available.
*/
private void startDownload(boolean forceDownload)
throws IOException, ApplicationException
{
DownloadService ds;
try
{
ds =
(DownloadService) ServiceManager.lookup(Utils.JNLP_SERVICE_NAME);
} catch (UnavailableServiceException e)
{
logger.error(LocalizableMessage.raw("Could not find service: "+
Utils.JNLP_SERVICE_NAME, e));
String setupFile;
if (Utils.isWindows())
{
setupFile = Installation.WINDOWS_SETUP_FILE_NAME;
}
else
{
setupFile = Installation.UNIX_SETUP_FILE_NAME;
}
throw new ApplicationException(
ReturnCode.DOWNLOAD_ERROR,
getThrowableMsg(INFO_DOWNLOADING_ERROR_NO_SERVICE_FOUND.get(
Utils.JNLP_SERVICE_NAME, setupFile),
e), e);
}
String[] urls = getJarUrls();
String[] versions = getJarVersions();
/*
* Calculate the percentages that correspond to each file.
* TODO ideally this should be done dynamically, but as this is just
* to provide progress, updating this information from time to time can
* be enough and does not complexify the build process.
*/
int[] percentageMax = new int[urls.length];
int[] ratios = new int[urls.length];
int totalRatios = 0;
for (int i=0; inull if no exception occurred.
* @return the ApplicationException that has occurred during the download or
* null if no exception occurred.
*/
public ApplicationException getException()
{
return ex;
}
/**
* {@inheritDoc}
*/
public void downloadFailed(URL url, String version)
{
ex =
new ApplicationException(
ReturnCode.DOWNLOAD_ERROR,
INFO_DOWNLOADING_ERROR.get(url.toString()), null);
}
/**
* {@inheritDoc}
*/
public void progress(URL url, String version, long readSoFar, long total,
int overallPercent)
{
if (overallPercent >= 0)
{
downloadPercentage = getPercentage(overallPercent);
}
status = Status.DOWNLOADING;
}
/**
* {@inheritDoc}
*/
public void upgradingArchive(URL url, String version, int patchPercent,
int overallPercent)
{
currentUpgradingPercent = overallPercent;
status = Status.UPGRADING;
}
/**
* {@inheritDoc}
*/
public void validating(URL url, String version, long entry, long total,
int overallPercent)
{
if (total > 0)
{
currentValidatingPercent = (int)((100 * entry) / total);
}
else {
currentValidatingPercent = 0;
}
status = Status.VALIDATING;
}
/**
* Returns the jar files in a String[] from the System properties.
* @return the jar files from the System properties.
*/
private String[] getJarUrls()
{
String jars = System.getProperty(SetupUtils.LAZY_JAR_URLS);
return jars.split(" ");
}
/**
* Returns the downloaded percentage based on how much of the current jar file
* has been downloaded.
* @param currentJarRatio the download ratio of the jar file that is being
* currently downloaded.
* @return the downloaded percentage based on how much of the current jar file
* has been downloaded.
*/
private int getPercentage(int currentJarRatio)
{
return currentPercMin
+ (currentJarRatio * (currentPercMax - currentPercMin) / 100);
}
/**
* Returns the java jar versions in a String[]. Currently just returns some
* null strings.
* @return the java jar versions in a String[].
*/
private String[] getJarVersions()
{
return new String[getJarUrls().length];
}
}