/* * Software Name : ATK * * Copyright (C) 2007 - 2012 France Télécom * * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. * * ------------------------------------------------------------------ * File Name : FileResolver.java * * Created : 01/03/2007 * Author(s) : Nicolas MOTEAU */ package com.orange.atk.atkUI.corecli.utils; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import com.orange.atk.atkUI.corecli.Alert; /** * This class allow to retrieve a file by its path, whatever it has to be * downloaded or not. It handles a cache of downloaded files to prevent * downloading twice the same file * * @author Nicolas MOTEAU * @since JDK5.0 */ public class FileResolver { /** the temporary directory to store downloaded files */ private File tempDir = null; /** the maximum time to wait for connexion (in ms) */ private int httpMaxConTime = 0; /** the maximum time to wait for download (in ms) */ private int httpMaxDwnTime = 0; /** the maximun attempts for download */ private int httpMaxAttempts = 0; /** * A map used to prevent downloading twice the same file (same URI). Since * it is static, it is shared among all FileResolvers (provided it is loaded * by the same classloader!) * */ private static Map<String, File> downloadedFiles = new HashMap<String, File>(); /** * Build a new FileResolver with the given options * * @param tempDir * the temporary directory to store downloaded files. * @param httpMaxConTime * the maximum time to wait for connexion (in ms) * @param httpMaxDwnTime * the maximum time to wait for download (in ms) * @param proxySet * wether the proxy have to be set or net * @param proxyHost * the name of the proxy * @param proxyPort * the proxy port to use */ public FileResolver(File tempDir, int httpMaxConTime, int httpMaxDwnTime, int httpMaxAttempts, boolean proxySet, String proxyHost, String proxyPort) { this.tempDir = tempDir; if (!this.tempDir.isDirectory()) { Alert.raise(null, "Unable to find temporary directory '" + tempDir + "'"); } this.httpMaxConTime = httpMaxConTime; this.httpMaxDwnTime = httpMaxDwnTime; this.httpMaxAttempts = httpMaxAttempts; if (proxySet) { // configure proxy for http System.getProperties().put("http.proxyHost", proxyHost); System.getProperties().put("http.proxyPort", proxyPort); } } public File getFile(String uri, String prefix, String ext, String login, String password, String userAgent, File tempDir) { File file = null; if (uri.startsWith("http:")) { // distant file // first look for the file in cache file = downloadedFiles.get(uri); if (file == null) { // build the base name and extention to give to the file try { file = File.createTempFile(prefix, ext, tempDir); } catch (IOException e) { Logger.getLogger(this.getClass()).error(e); } if (file != null) { String fileName = file.getName(); int lastDotIndex = fileName.lastIndexOf('.'); String baseFileName = fileName.substring(0, lastDotIndex); Logger.getLogger(this.getClass()) .info("downloading file at '" + uri + "' to '" + file.getAbsolutePath() + "'"); file = httpDownload(uri, tempDir, baseFileName, ext, login, password, userAgent); Logger.getLogger(this.getClass()).info( "download ok to '" + file.getAbsolutePath() + "'"); // add it in cache downloadedFiles.put(uri, file); } } } else { // local file file = new File(uri); if (!file.exists()) { file = null; Alert.raise(null, "Unable to find file '" + uri + "'"); } } return file; } /** * Retrieves a file located at the given URI. It the file is distant, it * will be downloaded and put in cache. * * @param uri * location of the file to retrieve. * @param fileName * the name to give to the downloaded file (may be null). * @param login * login to use to download the file. * @param password * to use to download the file. * @param userAgent * to use to download the file. * @return the file or null if there is no file at the given uri. * @throws Alert * if the file cannot be found. */ public File getFile(String uri, String prefix, String ext, String login, String password, String userAgent) { return getFile(uri, prefix, ext, login, password, userAgent, tempDir); } /** * Download the file located at the given URL, and write it to the given * target local directory. Return a File object on that file. Exit if there * is any problem while downloading, or to store the downloaded file. * * @param location * the URL of the file to fetch. * @param targetDir * the directory where to save the downloaded file. * @param baseName * the base name used to build the file name. * @param ext * the extention of the file name * @param login * login to use to download the file. * @param password * to use to download the file. * @param userAgent * to use to download the file. * @return the downloaded file. * @throws Alert * if a problem occurs during download. */ private File httpDownload(String location, File targetDir, String baseName, String ext, String login, String password, String userAgent) throws Alert { Downloader downloader = null; DownloadMonitor downloadMonitor = null; int attemptsDone = 0; // build a valid name to give to the file base on given baseName and ext String targetFileName = baseName; if (!ext.startsWith(".")) { targetFileName += "."; } targetFileName += ext; File target = new File(targetDir, targetFileName); int i = 1; while (target.exists()) { targetFileName = "" + i + baseName; if (!ext.startsWith(".")) { targetFileName += "."; } targetFileName += ext; target = new File(targetDir, targetFileName); i++; } target.deleteOnExit(); // launch a download thread for that file, providing it with // a monitor to keep an eye on the status of the operation. boolean done = false; // used to implement a strategy à la windows : in case of failure, // timeout is double for each retry (until maxAttempts reached). int httpConTimeOut = httpMaxConTime; int httpDwnTime = httpMaxDwnTime; while (!done && (attemptsDone < httpMaxAttempts)) { downloadMonitor = new DownloadMonitor(); downloader = new Downloader(location, target, httpConTimeOut/* httpMaxConTime */, httpDwnTime/* httpMaxDwnTime */, downloadMonitor); if (login != null && password != null && login.length() != 0) { downloader.setLogin(login); downloader.setPassword(password); } if ((userAgent != null) && (userAgent.trim().length() > 0)) { downloader.setUserAgent(userAgent); } downloader.start(); downloadMonitor.waitForEnd(); int status = downloadMonitor.getDownloadStatus(); if (status == DownloadMonitor.DLOAD_SUCCESS) { done = true; attemptsDone++; } else { if (status == DownloadMonitor.DLOAD_TIMEOUT_C) { httpConTimeOut = httpConTimeOut * 2; Logger.getLogger(this.getClass()).warn("Connexion timeout increased"); attemptsDone++; } else if (status == DownloadMonitor.DLOAD_TIMEOUT_T) { httpDwnTime = httpDwnTime * 2; Logger.getLogger(this.getClass()).warn("Download timeout increased"); attemptsDone++; } else if (status == DownloadMonitor.DLOAD_FAILED) { attemptsDone++; } else if (status == DownloadMonitor.DLOAD_FAILED_NO_NEW_ATTEMPT) { attemptsDone = httpMaxAttempts; } // in all cases: downloader.stopAsap(); } } if (!done) { Alert.raise(null, downloader.getErrorMessage()); } return target; } }