jasenautoupdater.java

来自「spam source codejasen-0.9jASEN - java An」· Java 代码 · 共 664 行 · 第 1/2 页

JAVA
664
字号
/*
 * @(#)JasenAutoUpdater.java	5/01/2005
 *
 * Copyright (c) 2005 jASEN.org
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in
 *      the documentation and/or other materials provided with the distribution.
 *
 *   3. The names of the authors may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 *   4. Any modification or additions to the software must be contributed back
 *      to the project.
 *
 *   5. Any investigation or reverse engineering of source code or binary to
 *      enable emails to bypass the filters, and hence inflict spam and or viruses
 *      onto users who use or do not use jASEN could subject the perpetrator to
 *      criminal and or civil liability.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JASEN.ORG,
 * OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
package org.jasen.update;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.Vector;
import java.util.zip.ZipFile;

import org.apache.log4j.Logger;
import org.jasen.JasenScanner;
import org.jasen.interfaces.AutoUpdateExecutor;
import org.jasen.io.ByteArrayReader;
import org.jasen.thread.StoppableThread;
import org.jasen.util.FileUtils;
import org.jasen.util.IOUtils;
import org.jasen.util.WebUtils;
import org.xml.sax.SAXException;

/**
 * <p>
 * The auto updater is a thread which continuously runs and at regular intervals checks the update site for engine updates.
 * </p>
 * <p>
 * If new updates are found, they are downloaded and upon successful download the engine is signalled to
 * block any further scan requests until the updates have been loaded.
 * </p>
 * @author Jason Polites
 */
public final class JasenAutoUpdater extends StoppableThread {

    static final Logger logger = Logger.getLogger(JasenAutoUpdater.class);

    public static final String UPDATE_PATH = "updates/";
    public static final String UPDATE_LIB_PATH = UPDATE_PATH + "lib/";
    public static final String PARCEL_CACHE = UPDATE_PATH + "jasen-update.dat_DO_NOT_DELETE";

    private JasenAutoUpdateManager manager;

    private long lastUpdateTime = -1L;

    private JasenAutoUpdateParcelDigester digester;

    private volatile boolean running = false;
    private volatile boolean neverStart = false;
    private volatile boolean stopped = false;
    private volatile boolean forcedUpdate = false;
    private volatile boolean idle = true;

    /**
     *
     */
    public JasenAutoUpdater(JasenAutoUpdateManager manager) {
        super();
        this.manager = manager;
    }

    /**
     * @param name
     */
    public JasenAutoUpdater(JasenAutoUpdateManager manager, String name) {
        super(name);
        this.manager = manager;
    }

    public void run() {

        logger.debug("AutoUpdater starting...");

        if(!neverStart) {

            running = true;

            long nextUpdateTime;
            long currentTime;

            digester = new JasenAutoUpdateParcelDigester();
            digester.init();

            // Make sure we have an update path
            File updatePath = new File(UPDATE_PATH);
            updatePath.mkdirs();

            while(running && !neverStart) {

                logger.debug("AutoUpdater running");

                idle = false;

                synchronized(this) {

                    logger.debug("AutoUpdater in check cycle");

    	            currentTime = System.currentTimeMillis();

    	            if(forcedUpdate) {
    	                forcedUpdate = false;
    	                lastUpdateTime = currentTime;
    	                checkForUpdates();
    	            }
    	            else if(lastUpdateTime == -1 && manager.getConfiguration().isCheckOnStartup()) {
    	                lastUpdateTime = currentTime;
    	                checkForUpdates();
    	            }
    	            else if(lastUpdateTime != -1) {
    	                nextUpdateTime = lastUpdateTime + (manager.getConfiguration().getFrequency() * 60000L); // milliseconds

    	                if(nextUpdateTime <= currentTime) {
    	                    lastUpdateTime = currentTime;
    	                    checkForUpdates();
    	                }
    	            }
    	            else
    	            {
    	                lastUpdateTime = currentTime;
    	            }

    	            logger.debug("Auto updater is running");

    	            // Wait for timeout or stop signal
    	            if(running) {
    	                try {
    	                    idle = true;
    	                    logger.debug("AutoUpdater waiting for notification");
    	                    wait(manager.getConfiguration().getFrequency() * 60000L);
    	                    logger.debug("AutoUpdater stopped waiting");
    	                    idle = false;
    	                }
    	                catch (InterruptedException ignore) {}
    	            }
    	        }
            }
        }

        logger.debug("AutoUpdater stopped");

        stopped = true;

        // Make sure nobody is waiting for us to stop
        synchronized(this) {
            notifyAll();
        }
    }

    private boolean checkForUpdates() {

        logger.debug("Checking for updates...");

        // Look for the update parcel
        // Because this is small, just write it to a String
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        JasenAutoUpdateParcel parcel = null;
        JasenAutoUpdateParcel oldParcel = null;
        URL parcelUrl;

        boolean updated = false;
        boolean updateRequired = false;

        try {
            parcelUrl = prepareItemURL(manager.getConfiguration().getUpdateURL(), manager.getConfiguration().getParcel());

            WebUtils.get(parcelUrl, bout, manager.getConfiguration().getReadBuffer(),manager.getConfiguration().getReadTimeout());

            // Use the digester to parse the file
            ByteArrayReader reader = new ByteArrayReader(bout.toByteArray());
            parcel = (JasenAutoUpdateParcel)digester.parse(reader);

            // Check the current parcel against the last recorded parcel
            oldParcel = loadLastParcel();

            if(oldParcel == null || (oldParcel.getUpdateDate() == null || !oldParcel.getUpdateDate().equals(parcel.getUpdateDate()))) {
                // We are ok to update...
                updateRequired = true;

                // Notify the manager
                logger.debug("Updates are required, notifying the manager");

                manager.notifyUpdateRequired(parcel);

                update(parcel);

                // And record the update
                saveCurrentParcel(parcel);

                updated = true;
            }
            else
            {
                logger.debug("No updates required");
            }
        }
        catch (IOException e) {
            
            if(e instanceof FileNotFoundException) {
                logger.debug("No updates available");
            }
            else
            {
                manager.getErrorHandler().handleException(e);
            }
        }
        catch (SAXException e) {
            manager.getErrorHandler().handleException(e);
        }
        catch (ClassNotFoundException e) {
            manager.getErrorHandler().handleException(e);
        }
        finally {
            // Notify completed
            //if(updateRequired) {
            logger.debug("Updates completed, notifying the manager");

                // Create a report
                JasenAutoUpdateReport report = new JasenAutoUpdateReport();
                report.setUpdated(updated);
                report.setUpdateParcel(parcel);

                if(parcel != null && parcel.getWebUpdateRequired() != null) {
                    report.setWebUpdateRequired(new Boolean(parcel.getWebUpdateRequired()).booleanValue());
                    report.setWebUpdateUrl(parcel.getWebUpdateUrl());
                }

                report.setEngineRestart(updated);

                manager.notifyUpdateComplete(report);
                
                logger.debug("Manager notified");
            //}
        }

        return updated;
    }

    private void update(JasenAutoUpdateParcel parcel) throws IOException {

        logger.debug("Updates found, downloading...");

        URL updateUrl = prepareItemURL(manager.getConfiguration().getUpdateURL(), parcel.getArchiveName());

        // This time, pipe to a file
        File update = new File(UPDATE_PATH + parcel.getArchiveName());
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(update);
            WebUtils.get(updateUrl, out, manager.getConfiguration().getReadBuffer(),manager.getConfiguration().getReadTimeout(), manager);
        }
        finally {
            if(out != null) {
                try {
                    out.close();
                } catch (Exception ignore) {}
            }
        }

        // Now, the update should be a zip file
        ZipFile zip = null;
        Vector tmpFiles = null;
        InputStream zin = null;
        OutputStream fout = null;

        try {
            zip = new ZipFile(update);

            // We want to simply extract each file defined in the parcel and write it to the relevant path
            if(parcel.getFiles() != null) {
                JasenAutoUpdateFile updateFile = null;
                Iterator i = parcel.getFiles().iterator();


                File outFile = null;
                File tmpFile = null;
                Vector oldFiles = null;

                while(i.hasNext()) {
                    updateFile = (JasenAutoUpdateFile)i.next();

                    try {
                        outFile = new File(updateFile.getJasenPath());

                        // If this file already exists, rename it until we are done
                        if(outFile.exists()) {
                            if(oldFiles == null) {
                                oldFiles = new Vector();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?