/** * Copyright 2012-2013 Maciej Jaworski, Mariusz Kapcia, Paweł Kędzia, Mateusz Kubuszok * * <p>Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at</p> * * <p>http://www.apache.org/licenses/LICENSE-2.0</p> * * <p>Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.</p> */ package com.autoupdater.client.download; import static com.autoupdater.client.download.ConnectionConfiguration.DOWNLOAD_DIRECTORY; import static com.autoupdater.client.environment.AvailabilityFilter.filterUpdateSelection; import static java.io.File.separator; import static net.jsdpu.logger.Logger.getLogger; import java.io.IOException; import java.net.HttpURLConnection; import java.util.SortedSet; import java.util.TreeSet; import net.jsdpu.logger.Logger; import com.autoupdater.client.download.aggregated.services.BugsInfoAggregatedDownloadService; import com.autoupdater.client.download.aggregated.services.ChangelogInfoAggregatedDownloadService; import com.autoupdater.client.download.aggregated.services.FileAggregatedDownloadService; import com.autoupdater.client.download.aggregated.services.PackagesInfoAggregatedDownloadService; import com.autoupdater.client.download.aggregated.services.UpdateInfoAggregatedDownloadService; import com.autoupdater.client.download.connections.ConnectionFactory; import com.autoupdater.client.download.services.BugsInfoDownloadService; import com.autoupdater.client.download.services.ChangelogInfoDownloadService; import com.autoupdater.client.download.services.FileDownloadService; import com.autoupdater.client.download.services.PackagesInfoDownloadService; import com.autoupdater.client.download.services.UpdateInfoDownloadService; import com.autoupdater.client.environment.EnvironmentData; import com.autoupdater.client.environment.ProgramSettingsNotFoundException; import com.autoupdater.client.environment.settings.ProgramSettings; import com.autoupdater.client.models.Models; import com.autoupdater.client.models.Package; import com.autoupdater.client.models.Program; import com.autoupdater.client.models.Update; /** * Factory that creates AggregatedDownloadServices for a Client with * EnvironmentData as source of information. * * <p> * Services are returned ready to run. Their states can be observed through * AggregatedNotifiers. When aggregated service state change to PROCESSED, all * of its services is finished - either as PROCESSED, FAILED or CANCELLED. * </p> * * <p> * It is possible to try to obtain aggregated result. If all services finished * successfully it will be returned. Otherwise DownloadResultException will be * thrown. * </p> * * <p> * If some services failed and some finished successfully, it is still possible * to manually iterate over the services and obtain those results. * </p> * * @see EnvironmentData * @see com.autoupdater.client.download.aggregated.services.PackagesInfoAggregatedDownloadService * @see com.autoupdater.client.download.aggregated.services.UpdateInfoAggregatedDownloadService * @see com.autoupdater.client.download.aggregated.services.ChangelogInfoAggregatedDownloadService * @see com.autoupdater.client.download.aggregated.services.FileAggregatedDownloadService */ public class DownloadServiceFactory { private static final Logger logger = getLogger(DownloadServiceFactory.class); private final EnvironmentData environmentData; private final ConnectionFactory connectionFactory; /** * Creates factory which spawns services that download several * documents/files at once. * * @param environmentData * environment data */ public DownloadServiceFactory(EnvironmentData environmentData) { this(environmentData, new ConnectionFactory(environmentData.getClientSettings())); } /** * Creates factory which spawns services that download several * documents/files at once. * * @param environmentData * environment data * @param connectionFactory * factory that creates connections for services */ public DownloadServiceFactory(EnvironmentData environmentData, ConnectionFactory connectionFactory) { logger.debug("Initiated DownloadServiceFactory"); this.environmentData = environmentData; this.connectionFactory = connectionFactory; } /** * Creates aggregated service used for downloading all packages available on * servers. * * <p> * Example of use: * * <pre> * PackagesInfoAggregatedDownloadService aggregatedService = client * .createPackagesInfoAggregatedDownloadService(); * * aggregatedService.start(); * aggregatedService.joinThread(); * * SortedSet<Program> availableOnServer = aggregatedService.getResult(); * </pre> * * </p> * * @return aggregates service ready to run * @throws IOException * thrown when IO error occurs while creating connection */ public PackagesInfoAggregatedDownloadService createPackagesInfoAggregatedDownloadService() throws IOException { logger.debug("Creates PackagesInfoAggregatedDownloadService"); PackagesInfoAggregatedDownloadService aggregatedService = new PackagesInfoAggregatedDownloadService(); for (ProgramSettings programSettings : environmentData.getProgramsSettingsForEachServer()) { HttpURLConnection connection = connectionFactory.getPerProgramConnectionFactory( programSettings).createPackagesInfoConnection(); PackagesInfoDownloadService service = new PackagesInfoDownloadService(connection); aggregatedService.addService(service, programSettings); } aggregatedService.setInstalledPrograms(environmentData.getInstallationsData()); return aggregatedService; } /** * Creates aggregated service used for downloading all update information * for selected packages. * * <p> * Example of use: * * <pre> * UpdateInfoAggregatedDownloadService aggregatedService = client * .createUpdateInfoAggregatedDownloadService(selectedPackages); * * aggregatedService.start(); * aggregatedService.joinThread(); * * aggregatedService.getResult(); * // Updates will be put inside their respective instances of Package * </pre> * * </p> * * @param selectedPackages * packages for which update information should be downloaded * @return aggregates service ready to run * @throws IOException * thrown when connection cannot be created * @throws ProgramSettingsNotFoundException * thrown when ProgramSettings of some program cannot be found */ public UpdateInfoAggregatedDownloadService createUpdateInfoAggregatedDownloadService( SortedSet<Package> selectedPackages) throws IOException, ProgramSettingsNotFoundException { logger.debug("Creates UpdateInfoAggregatedDownloadService"); UpdateInfoAggregatedDownloadService aggregatedService = new UpdateInfoAggregatedDownloadService(); for (Package _package : selectedPackages) { ProgramSettings programSettings = environmentData .findProgramSettingsForPackage(_package); HttpURLConnection connection = connectionFactory.getPerProgramConnectionFactory( programSettings).createUpdateInfoConnection(_package.getID()); UpdateInfoDownloadService service = new UpdateInfoDownloadService(connection); aggregatedService.addService(service, _package); } return aggregatedService; } /** * Creates aggregated service used for downloading all changelogs for * selected packages. * * <p> * Example of use: * * <pre> * ChangelogInfoAggregatedDownloadService aggregatedService = client * .createChangelogInfoAggregatedDownloadService(selectedPackages); * * aggregatedService.start(); * aggregatedService.joinThread(); * * aggregatedService.getResult(); * // Changelogs will be put inside their respective instances of Package * </pre> * * </p> * * @param selectedPackages * packages for which changelogs should be downloaded * @return aggregates service ready to run * @throws IOException * thrown when connection cannot be created * @throws ProgramSettingsNotFoundException * thrown when ProgramSettings of some program cannot be found */ public ChangelogInfoAggregatedDownloadService createChangelogInfoAggregatedDownloadService( SortedSet<Package> selectedPackages) throws ProgramSettingsNotFoundException, IOException { logger.debug("Creates ChangelogInfoAggregatedDownloadService"); ChangelogInfoAggregatedDownloadService aggregatedService = new ChangelogInfoAggregatedDownloadService(); for (Package _package : selectedPackages) { ProgramSettings programSettings = environmentData .findProgramSettingsForPackage(_package); HttpURLConnection connection = connectionFactory.getPerProgramConnectionFactory( programSettings).createChangelogInfoConnection(_package.getID()); ChangelogInfoDownloadService service = new ChangelogInfoDownloadService(connection); aggregatedService.addService(service, _package); } return aggregatedService; } /** * Creates aggregated service used for downloading all bugs for selected * programs. * * <p> * Example of use: * * <pre> * BugsInfoAggregatedDownloadService aggregatedService = client * .createBugsInfoAggregatedDownloadService(selectedPrograms); * * aggregatedService.start(); * aggregatedService.joinThread(); * * aggregatedService.getResult(); * // Bugs will be put inside their respective instances of Program * </pre> * * </p> * * @param selectedPrograms * packages for which bugs sets should be downloaded * @return aggregates service ready to run * @throws IOException * thrown when connection cannot be created * @throws ProgramSettingsNotFoundException * thrown when ProgramSettings of some program cannot be found */ public BugsInfoAggregatedDownloadService createBugsInfoAggregatedDownloadService( SortedSet<Program> selectedPrograms) throws ProgramSettingsNotFoundException, IOException { logger.debug("Creates BugsInfoAggregatedDownloadService"); BugsInfoAggregatedDownloadService aggregatedService = new BugsInfoAggregatedDownloadService(); for (Program program : selectedPrograms) { ProgramSettings programSettings = environmentData .findProgramSettingsForProgram(program); HttpURLConnection connection = connectionFactory.getPerProgramConnectionFactory( programSettings).createBugsInfoConnection(program.getName()); BugsInfoDownloadService service = new BugsInfoDownloadService(connection); aggregatedService.addService(service, program); } return aggregatedService; } /** * Creates aggregated service used for downloading all update files for * selected updates. * * <p> * Example of use: * * <pre> * FileAggregatedDownloadService aggregatedService = client * .createFileAggregatedDownloadService(selectedPrograms); * * aggregatedService.start(); * aggregatedService.joinThread(); * * aggregatedService.getResult(); * // Files will be put inside their respective instances of Update * </pre> * * </p> * * @param requestedUpdates * updates for which files should be downloaded * @return aggregates service ready to run * @throws IOException * thrown when connection cannot be created * @throws ProgramSettingsNotFoundException * thrown when ProgramSettings of some program cannot be found */ public FileAggregatedDownloadService createFileAggregatedDownloadService( SortedSet<Update> requestedUpdates) throws ProgramSettingsNotFoundException, IOException { logger.debug("Creates FileAggregatedDownloadService"); FileAggregatedDownloadService aggregatedService = new FileAggregatedDownloadService(); SortedSet<Update> downloadedUpdates = (SortedSet<Update>) Models.addAll( new TreeSet<Update>(), filterUpdateSelection(requestedUpdates), Models.EComparisionType.LOCAL_TO_SERVER); for (Update update : downloadedUpdates) { ProgramSettings programSettings = environmentData.findProgramSettingsForUpdate(update); String downloadDestinationPath = DOWNLOAD_DIRECTORY + separator + programSettings.getServerAddress().hashCode() + separator + update.getID(); HttpURLConnection connection = connectionFactory.getPerProgramConnectionFactory( programSettings).createFileConnection(update.getID()); FileDownloadService service = new FileDownloadService(connection, downloadDestinationPath); aggregatedService.addService(service, update); } aggregatedService.setAllUpdates(requestedUpdates); return aggregatedService; } }