r2528 - trunk/nuiton-updater/src/main/java/org/nuiton/util/updater
Author: tchemit Date: 2013-03-13 00:03:34 +0100 (Wed, 13 Mar 2013) New Revision: 2528 Url: http://nuiton.org/projects/nuiton-utils/repository/revisions/2528 Log: fixes #2547: Add a progression model when downloading the update fixes #2590: Improve download api Added: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/DownloadMonitor.java trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateInvalidArchiveLayoutException.java trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateNotFoundException.java Modified: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/ApplicationInfo.java trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/ApplicationUpdater.java Modified: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/ApplicationInfo.java =================================================================== --- trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/ApplicationInfo.java 2013-03-12 16:07:04 UTC (rev 2527) +++ trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/ApplicationInfo.java 2013-03-12 23:03:34 UTC (rev 2528) @@ -25,6 +25,7 @@ */ import java.io.File; +import java.io.Serializable; /** * TODO @@ -33,8 +34,10 @@ * @author tchemit <chemit@codelutin.com> * @since 2.7 */ -public class ApplicationInfo { +public class ApplicationInfo implements Serializable { + private static final long serialVersionUID = 1L; + public String name; public String oldVersion; Modified: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/ApplicationUpdater.java =================================================================== --- trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/ApplicationUpdater.java 2013-03-12 16:07:04 UTC (rev 2527) +++ trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/ApplicationUpdater.java 2013-03-12 23:03:34 UTC (rev 2528) @@ -25,6 +25,7 @@ */ import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -35,14 +36,15 @@ import org.apache.commons.vfs2.FileSystemOptions; import org.apache.commons.vfs2.VFS; import org.apache.commons.vfs2.provider.http.HttpFileSystemConfigBuilder; +import org.nuiton.util.VersionUtil; import org.nuiton.util.config.ApplicationConfig; import org.nuiton.util.config.ArgumentsParserException; -import org.nuiton.util.VersionUtil; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -134,18 +136,20 @@ final static private String SEPARATOR_KEY = "."; - public static final String HTTP_PROXY = "http_proxy"; + public static final String HTTP_PROXY = "http_proxy"; - public static final String URL_KEY = "url"; + public static final String URL_KEY = "url"; - public static final String AUTHENTICATION_KEY = "auth"; + public static final String AUTHENTICATION_KEY = "auth"; - public static final String VERSION_KEY = "version"; + public static final String VERSION_KEY = "version"; - public static final String VERSION_FILE = "version.appup"; + public static final String VERSION_FILE = "version.appup"; protected ApplicationConfig config; + protected DownloadMonitor downloadMonitor; + /** Utilise le fichier de configuration par defaut: ApplicationUpdater.properties */ public ApplicationUpdater() { this(null); @@ -170,6 +174,9 @@ this.config = config; } + public void setDownloadMonitor(DownloadMonitor downloadMonitor) { + this.downloadMonitor = downloadMonitor; + } /** * @param url url where properties file is downloadable. This properties @@ -184,7 +191,7 @@ File destDir, boolean async, ApplicationUpdaterCallback callback) { - Updater up = new Updater(config, url, currentDir, destDir, callback); + Updater up = new Updater(config, url, currentDir, destDir, downloadMonitor, callback); if (async) { Thread thread = new Thread(up, ApplicationUpdater.class.getSimpleName()); thread.start(); @@ -193,6 +200,11 @@ } } + public static void createVersionFile(File dir, String version) throws IOException { + File versionFile = new File(dir, VERSION_FILE); + FileUtils.writeStringToFile(versionFile, version); + } + /** * La classe ou le travail est reellement fait, peut-etre appeler dans * un thread si necessaire. @@ -209,15 +221,19 @@ protected ApplicationUpdaterCallback callback; + protected DownloadMonitor downloadMonitor; + public Updater(ApplicationConfig config, String vfsPropertiesUrl, File currentDir, File destDir, + DownloadMonitor downloadMonitor, ApplicationUpdaterCallback callback) { this.config = config; this.vfsPropertiesUrl = vfsPropertiesUrl; this.currentDir = currentDir; this.destDir = destDir; + this.downloadMonitor = downloadMonitor; this.callback = callback; } @@ -228,6 +244,7 @@ * <p/> * Si callback existe envoi les messages necessaire */ + @Override public void run() { try { FileSystemOptions vfsConfig = getVFSConfig(config); @@ -282,7 +299,6 @@ log.debug("Can't clean directory", doNothing); } - log.warn(String.format( "Can't update application '%s' with url '%s'", app, info.url)); @@ -311,10 +327,11 @@ * nommera au final "monApp/Readme.txt" * * @param vfsConfig le proxy a utiliser pour la connexion a l'url - * @param info information sur l'application a mettre a jour + * @param info information sur l'application a mettre a jour * @throws Exception */ - protected void doUpdate(FileSystemOptions vfsConfig, ApplicationInfo info) throws Exception { + protected void doUpdate(FileSystemOptions vfsConfig, + ApplicationInfo info) throws Exception { if (info.destDir != null) { File dest = new File(info.destDir, info.name); String url = toVfsURL(info.url); @@ -325,11 +342,22 @@ if (callback != null) { callback.startUpdate(info); } - deepCopy(vfsConfig, url, dest.getAbsolutePath()); + // le type de l'archive contenant la mise à jour + String archiveType = url.substring(0, url.indexOf(':')); + + // recuperation de l'archive en locale (dans /tmp) + File archive = downloadUpdate(vfsConfig, info, url.substring(archiveType.length() + 1)); + + // extraction depuis l'archive téléchargée de l'unique répertoire vers la destination + explodeUpdate(vfsConfig, + info, + archiveType, + archive, + dest); + // ajout du fichier de version - File versionFile = new File(dest, VERSION_FILE); - FileUtils.writeStringToFile(versionFile, info.newVersion); + createVersionFile(dest, info.newVersion); log.info(String.format( "Application '%s' is uptodate with version '%s' in '%s'", info.name, info.newVersion, info.destDir)); @@ -339,6 +367,94 @@ } /** + * Télécharge une archive dans un fichier temporaraire. + * <p/> + * Si l'archive a plus d'un repertoire root, une exception est levee + * + * @param info + * @param srcPath source path de la forme vfs2 ex:"zip:http://www.nuiton.org/attachments/download/830/nuiton-utils-2.6.5-deps.zip" + * @throws FileSystemException + */ + protected File downloadUpdate(FileSystemOptions vfsConfig, + ApplicationInfo info, + String srcPath) throws IOException { + File result = new File(FileUtils.getTempDirectory(), srcPath); + + FileSystemManager fsManager = VFS.getManager(); + FileObject source = fsManager.resolveFile(srcPath, vfsConfig); + + if (!source.exists()) { + throw new UpdateNotFoundException(info); + } + FileObject target = fsManager.toFileObject(result); + InputStream input = source.getContent().getInputStream(); + try { + OutputStream output = target.getContent().getOutputStream(); + try { + long inputSize = source.getContent().getSize(); + if (downloadMonitor != null) { + downloadMonitor.setSize(inputSize); + } + long count = 0; + int n; + byte[] buffer = new byte[1024]; + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + if (downloadMonitor != null) { + downloadMonitor.setCurrent(count); + } + } + output.close(); + } finally { + + IOUtils.closeQuietly(output); + } + input.close(); + } finally { + IOUtils.closeQuietly(input); + } + return result; + } + + /** + * Recopie le contenu du répertoire de l'archive dans le + * répertoire {@code target}. + * <p/> + * Si le répertoire cible existe déjà, il sera alors vidé. + * <p/> + * Si l'archive ne contient pas exactement un répertoire alors une exception est levée + * + * @param archiveType le type de l'archive + * @param source l'archive à décompresser + * @param target le répertoire cible + * @throws FileSystemException + * @throws UpdateInvalidArchiveLayoutException + * si l'archive n'a pas le bon format + */ + protected void explodeUpdate(FileSystemOptions vfsConfig, + ApplicationInfo info, + String archiveType, + File source, + File target) throws FileSystemException, UpdateInvalidArchiveLayoutException { + + FileSystemManager fsManager = VFS.getManager(); + FileObject sourceObject = fsManager.resolveFile(archiveType + ":" + source.getAbsolutePath(), vfsConfig); + + FileObject[] children = sourceObject.getChildren(); + if (children.length != 1) { + throw new UpdateInvalidArchiveLayoutException(info, source); + } + // clean target + FileObject targetObject = fsManager.toFileObject(target); + targetObject.delete(new AllFileSelector()); + + //copy to it the archive only directory + FileObject child = children[0]; + targetObject.copyFrom(child, new AllFileSelector()); + } + + /** * Recupere le contenu du repertoire de l'archive pour le mettre dans targetPath * si targetPath existait deja, il est supprime au prealable. * <p/> @@ -347,7 +463,9 @@ * @param srcPath source path de la forme vfs2 ex:"zip:http://www.nuiton.org/attachments/download/830/nuiton-utils-2.6.5-deps.zip" * @param targetPath le path destination * @throws FileSystemException + * @deprecated since 2.6.11, no more used */ + @Deprecated protected void deepCopy(FileSystemOptions vfsConfig, String srcPath, String targetPath) throws FileSystemException { Added: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/DownloadMonitor.java =================================================================== --- trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/DownloadMonitor.java (rev 0) +++ trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/DownloadMonitor.java 2013-03-12 23:03:34 UTC (rev 2528) @@ -0,0 +1,38 @@ +package org.nuiton.util.updater; + +/* + * #%L + * Nuiton Utils :: Nuiton Updater + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/** + * Pour monitorer la progression d'un téléchargement. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.11 + */ +public interface DownloadMonitor { + + void setSize(long size); + + void setCurrent(long current); +} Property changes on: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/DownloadMonitor.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateInvalidArchiveLayoutException.java =================================================================== --- trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateInvalidArchiveLayoutException.java (rev 0) +++ trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateInvalidArchiveLayoutException.java 2013-03-12 23:03:34 UTC (rev 2528) @@ -0,0 +1,56 @@ +package org.nuiton.util.updater; + +/* + * #%L + * Nuiton Utils :: Nuiton Updater + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import java.io.File; + +/** + * Exception leve lorsque l'archive d'une mise à jour ne respecte pas le bon + * format (à savoir contenir un uniquement répertoire). + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.11 + */ +public class UpdateInvalidArchiveLayoutException extends Exception { + + private static final long serialVersionUID = 1L; + + + protected final ApplicationInfo info; + protected final File archiveFile; + + public UpdateInvalidArchiveLayoutException(ApplicationInfo info, File archiveFile) { + this.info= info; + this.archiveFile = archiveFile; + } + + public ApplicationInfo getInfo() { + return info; + } + + public File getArchiveFile() { + return archiveFile; + } +} Property changes on: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateInvalidArchiveLayoutException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateNotFoundException.java =================================================================== --- trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateNotFoundException.java (rev 0) +++ trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateNotFoundException.java 2013-03-12 23:03:34 UTC (rev 2528) @@ -0,0 +1,48 @@ +package org.nuiton.util.updater; + +/* + * #%L + * Nuiton Utils :: Nuiton Updater + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import java.io.IOException; + +/** + * When an update is not found. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.11 + */ +public class UpdateNotFoundException extends IOException { + + private static final long serialVersionUID = 1L; + + protected ApplicationInfo info; + + public UpdateNotFoundException(ApplicationInfo info) { + this.info = info; + } + + public ApplicationInfo getInfo() { + return info; + } +} Property changes on: trunk/nuiton-updater/src/main/java/org/nuiton/util/updater/UpdateNotFoundException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native
participants (1)
-
tchemit@users.nuiton.org