/* * 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]; } }