All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.updater.AbstractApplicationUpdaterAction Maven / Gradle / Ivy

package org.nuiton.updater;

/*
 * #%L
 * Nuiton Application Updater
 * $Id: AbstractApplicationUpdaterAction.java 2588 2013-07-20 14:25:42Z tchemit $
 * $HeadURL: https://nuiton.org/svn/nuiton-updater/tags/nuiton-updater-3.0-alpha-2/src/main/java/org/nuiton/updater/AbstractApplicationUpdaterAction.java $
 * %%
 * 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
 * .
 * #L%
 */

import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemManager;
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.config.ApplicationConfig;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Abstract updater action.
 *
 * @author tchemit 
 * @since 2.6.12
 */
public abstract class AbstractApplicationUpdaterAction implements Runnable {

    /** Logger. */
    private static final Log log =
            LogFactory.getLog(AbstractApplicationUpdaterAction.class);

    public static final String HTTP_PROXY = "http_proxy";

    public static final String URL_KEY = "url";

    public static final String AUTHENTICATION_KEY = "auth";

    public static final String VERSION_KEY = "version";

    protected ApplicationConfig config;

    protected String vfsPropertiesUrl;

    protected File currentDir;

    public AbstractApplicationUpdaterAction(ApplicationConfig config,
                                            String vfsPropertiesUrl,
                                            File currentDir) {
        this.config = config;
        this.vfsPropertiesUrl = vfsPropertiesUrl;
        this.currentDir = currentDir;
    }

    protected Map getVersions(ApplicationConfig releaseConfig,
                                                       boolean allVersion,
                                                       File destDir) {
        List appNames = getApplicationName(releaseConfig);
        Map appVersions = getCurrentVersion(appNames, currentDir);

        log.debug("application current version: " + appVersions);

        // recherche des applications a mettre a jour
        Map appToUpdate = new HashMap();
        for (String app : appNames) {
            String currentVersion = appVersions.get(app);
            String newVersion = releaseConfig.getOption(app + ApplicationUpdater.SEPARATOR_KEY + VERSION_KEY);
            boolean greater = VersionUtil.greaterThan(newVersion, currentVersion);
            log.debug(String.format("for %s Current(%s) < newVersion(%s) ? %s",
                                    app, currentVersion, newVersion, greater));
            boolean add = allVersion || greater;
            if (add) {
                String urlString = releaseConfig.getOption(
                        app + ApplicationUpdater.SEPARATOR_KEY + URL_KEY);
                boolean needAuthentication = releaseConfig.getOptionAsBoolean(
                        app + ApplicationUpdater.SEPARATOR_KEY + AUTHENTICATION_KEY);

                if (allVersion && !greater) {
                    newVersion = null;
                }
                appToUpdate.put(app, new ApplicationInfo(
                        app, currentVersion, newVersion, urlString, destDir, needAuthentication));
            }
        }
        return appToUpdate;
    }

    /**
     * Converti le path en URL vfs2. Path doit etre une URL, mais pour les fichiers
     * au lieu d'etre absolue ils peuvent etre relatif, un traitement special
     * est donc fait pour ce cas. Cela est necessaire pour facilement faire
     * des tests unitaires independant de la machine ou il sont fait
     *
     * @param path
     * @return
     */
    protected String toVfsURL(String path) {
        String result = path;
        Pattern p = Pattern.compile("(.*?file:)([^/][^!]*)(.*)");
        Matcher m = p.matcher(path);
        if (m.matches()) {
            String filepath = m.group(2);
            File f = new File(filepath);
            result = path.replaceAll(
                    "(.*?file:)([^/][^!]*)(.*)",
                    "$1" + f.getAbsolutePath() + "$3");
        }
        return result;
    }

    /**
     * Return config prepared for os and arch
     *
     * @return
     * @throws Exception
     */
    protected ApplicationConfig getUpdaterConfig(FileSystemOptions vfsConfig,
                                                 String vfsPropertiesUrl) throws Exception {
        String osName = StringUtils.lowerCase(config.getOsName());
        String osArch = StringUtils.lowerCase(config.getOsArch());
        // take only first part for osName (windows 2000 or windows 2003 -> windows)
        osName = StringUtils.substringBefore(osName, " ");

        if (log.isDebugEnabled()) {
            log.debug(String.format("Try to load properties from '%s'", vfsPropertiesUrl));
        }

        Properties prop = new Properties();

        FileSystemManager fsManager = VFS.getManager();
        FileObject properties = fsManager.resolveFile(toVfsURL(vfsPropertiesUrl), vfsConfig);
        try {
            InputStream in = new BufferedInputStream(properties.getContent().getInputStream());
            prop.load(in);
        } finally {
            try {
                properties.close();
            } catch (Exception doNothing) {
                log.debug("Can't close vfs file", doNothing);
            }
        }

        if (log.isDebugEnabled()) {
            log.debug(String.format(
                    "Properties loaded from '%s'\n%s",
                    vfsPropertiesUrl, prop));
        }

        // load config with new properties as default
        ApplicationConfig result = new ApplicationConfig(prop);
        // don't parse. We want only prop in applicationConfig
        result = result.getSubConfig(
                ApplicationUpdater.class.getSimpleName() + ApplicationUpdater.SEPARATOR_KEY);

        result = result.getSubConfig(osName + ApplicationUpdater.SEPARATOR_KEY);
        result = result.getSubConfig(osArch + ApplicationUpdater.SEPARATOR_KEY);
        return result;
    }

    /**
     * Recupere le proxy http a utiliser pour les connexions reseaux
     *
     * @param config
     * @return
     */
    protected FileSystemOptions getVFSConfig(ApplicationConfig config) {
        FileSystemOptions result = new FileSystemOptions();
        String proxyHost = config.getOption(HTTP_PROXY);
        try {
            proxyHost = StringUtils.substringAfter(proxyHost, "://");
            if (StringUtils.isNotBlank(proxyHost)) {
                String hostname = StringUtils.substringBefore(proxyHost, ":");
                String port = StringUtils.substringAfter(proxyHost, ":");
                if (StringUtils.isNumeric(port)) {

                    int portNumber = Integer.parseInt(port);

                    HttpFileSystemConfigBuilder.getInstance().setProxyHost(result, hostname);
                    HttpFileSystemConfigBuilder.getInstance().setProxyPort(result, portNumber);
                } else {
                    log.warn(String.format("Invalide proxy port number '%s', not used proxy", port));
                }
            }
        } catch (Exception eee) {
            log.warn(String.format("Can't use proxy '%s'", proxyHost), eee);
        }
        return result;
    }

    /**
     * Recherche pour chaque application la version courante
     *
     * @param apps la liste des applications a rechercher
     * @return
     */
    protected Map getCurrentVersion(List apps, File dir) {
        Map result = Maps.newTreeMap();
        for (String app : apps) {
            File applicationDirectory = new File(dir, app);
            String version = ApplicationUpdater.loadVersionFile(
                    app,
                    applicationDirectory);
            result.put(app, version);
        }
        return result;
    }

    /**
     * Retourne la liste des noms d'application se trouvant dans la
     * configuration
     *
     * @param config
     * @return
     */
    protected List getApplicationName(ApplicationConfig config) {
        Pattern p = Pattern.compile("([^.]+)\\.version");
        List result = new LinkedList();
        for (String v : config.getFlatOptions().stringPropertyNames()) {
            Matcher match = p.matcher(v);
            if (match.matches()) {
                result.add(match.group(1));
            } else if (StringUtils.endsWith(v, ".version")) {
                log.debug(String.format("value is not valid application version '%s'", v));
            }
        }
        return result;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy