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 + -
显示快捷键?