/*
* 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
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* 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
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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
*
*
* Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.quicksetup.webstart;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.jnlp.DownloadService;
import javax.jnlp.DownloadServiceListener;
import javax.jnlp.ServiceManager;
import javax.jnlp.UnavailableServiceException;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.ApplicationException;
import org.opends.quicksetup.util.Utils;
/**
* 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,
JnlpProperties {
/**
* Returns the name of the zip file name that contains all the installation.
* @return the name of the zip file name that contains all the installation.
*/
static public String getZipFileName()
{
// Passed as a java option in the JNLP file
return System.getProperty(ZIP_FILE_NAME);
}
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 String summary = null;
/**
* This enumeration contains the different Status on which
* the dowloading 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 = getMsg("downloading");
}
/**
* 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 (MalformedURLException mfe)
{
// This is a bug
ex =
new ApplicationException(ApplicationException.Type.BUG,
getExceptionMsg(
"bug-msg", 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]);
}
String[] arg =
{ buf.toString() };
ex =
new ApplicationException(ApplicationException.Type.DOWNLOAD_ERROR,
getExceptionMsg("downloading-error", arg, ioe), ioe);
} catch (Throwable t)
{
// This is a bug
ex =
new ApplicationException(ApplicationException.Type.BUG,
getExceptionMsg(
"bug-msg", t), t);
}
}
});
t.start();
}
/**
* Gets a summary message of the downloader's current progress.
* @return String for showing the user progress
*/
public String 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(String 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 URL that we
* get from the JnlpProperties.
* @throws IOException if a network problem occurs.
*/
private void startDownload(boolean forceDownload)
throws IOException
{
DownloadService ds;
try
{
ds =
(DownloadService) ServiceManager.lookup(
"javax.jnlp.DownloadService");
} catch (UnavailableServiceException e)
{
ds = null;
}
if (ds != null)
{
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(ApplicationException.Type.DOWNLOAD_ERROR,
getMsg("downloading-error", new String[] { 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(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];
}
/* Some commodity methods to get localized messages */
private String getExceptionMsg(String key, Throwable t)
{
return getExceptionMsg(key, null, t);
}
private String getExceptionMsg(String key, String[] args, Throwable t)
{
return Utils.getThrowableMsg(ResourceProvider.getInstance(), key, args, t);
}
private String getMsg(String key, String[] args)
{
return ResourceProvider.getInstance().getMsg(key, args);
}
private String getMsg(String key)
{
return ResourceProvider.getInstance().getMsg(key);
}
}