package com.sijobe.spc.updater; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Vector; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * Downloads and checks the specified XML manifest file. See the parseManifest() * file for more information regarding the format of the XML file. * * @author simo_415 * @version 1.1 */ public class CheckVersion extends Thread { public static final String MANIFEST = "http://bit.ly/spccheckupdate"; private UpdateCallback callback; private List<ModVersion> projects; private String mcversion; public CheckVersion(ModVersion project[], String mcver, UpdateCallback callback) { this.callback = callback; this.projects = (List<ModVersion>)Arrays.asList(project); this.mcversion = mcver; } /** * Runs an update check verifying that the project is up-to-date * * @see java.lang.Thread#run() */ public void run() { // download file File f = downloadFile(MANIFEST); if (f == null || !f.exists()) { return; } // parse xml Vector<HashMap<String,Object>> update = parseManifest(f); // check if update required using "business" logic Vector<HashMap<String,Object>> required = new Vector<HashMap<String,Object>>(); SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (HashMap<String,Object> h : update) { boolean checkversion = true; String version = (String)h.get("version"); if (version == null) checkversion = false; boolean checkdate = true; String datetime = (String)h.get("datetime"); if (datetime == null) checkdate = false; for (ModVersion svi : projects) { //System.out.println("'" + datetime + "' - " + version + " '" + svi.getLastUpdate() + "' - " + svi.getVersion()); // Checks if manifest version number is greater - if so adds to required boolean add = false; if (checkversion && svi.getVersion() != null) { //System.out.println(version + ".compareTo(" + svi.getVersion() + ") = " + version.compareTo(svi.getVersion())); if (version.compareTo(svi.getVersion()) > 0) { add = true; } } // Checks if manifest last update is great - if so adds to required if (!add && checkdate && svi.getLastUpdate() != null) { long updatemanifest = 0; try { Date updateman = dateformat.parse(datetime); updatemanifest= updateman.getTime(); } catch (ParseException e) { //e.printStackTrace(); } //System.out.println(updatemanifest + " > " + svi.getLastUpdate().getTime() + " = " + (updatemanifest > svi.getLastUpdate().getTime())); if (updatemanifest > svi.getLastUpdate().getTime()) { add = true; } } // Check that current version of MC will run updated mod if (add) { if (mcversion == null || mcversion.equalsIgnoreCase("")) { required.add(h); } else { for (String pver : (List<String>)h.get("minecraft")) { if (pver.equalsIgnoreCase(mcversion)) { required.add(h); } } } } } } // delete file try { f.delete(); } catch (Exception e) {} // callback specified method if (callback != null) { try { callback.updateCallback(required); } catch (Exception e) { e.printStackTrace(); } } } /** * Parses the supplied V1.0 manifest file. Manifest should be in the following format: * * <update version="1.0"> * <project name="NAME OF PROJECT"> * <version>VERSION OF PROJECT</version> * <datetime>DATE AND TIME OF RELEASE IN YYYY-MM-DD HH:MM:SS format</datetime> * <minecraft> * <supportedversion>MCVERSION1</supportedversion> * <supportedversion>MCVERSION2</supportedversion> * <supportedversion>MCVERSION3</supportedversion> * </minecraft> * <website>WEBSITE OF PROJECT</website> * <download>DIRECT DOWNLOAD OF PROJECT</download> * </project> * </update> * * @param manifest - The manifest file to process * @return A vector containing the loaded XML manifest file */ public Vector<HashMap<String,Object>> parseManifest(File manifest) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); Vector<HashMap<String,Object>> ps = null; try { DocumentBuilder db = dbf.newDocumentBuilder(); Document d = db.parse(manifest); Element e = d.getDocumentElement(); if (e.getAttribute("version").compareTo("1.0") > 0) { System.out.println("Warning: checking for the update may fail. New version of manifest file detected"); } NodeList nl = e.getElementsByTagName("project"); ps = new Vector<HashMap<String,Object>>(); if(nl != null && nl.getLength() > 0) { for(int i = 0 ; i < nl.getLength();i++) { Element el = (Element)nl.item(i); for (ModVersion spc : projects) { if (spc.getName() != null && el.getAttribute("name").equalsIgnoreCase(spc.getName())) { HashMap<String,Object> h = getProject(el); h.put("name",spc.getName()); ps.add(h); } } } } } catch(Exception e) { e.printStackTrace(); return null; } return ps; } /** * Gets the project associated with the element * @param project - The project to convert from XML from HashMap * @return The HashMap equivalent of the XML data */ private HashMap<String,Object> getProject(Element project) { HashMap<String,Object> h = new HashMap<String, Object>(); h.put("version", getValue(project,"version")); h.put("datetime", getValue(project,"datetime")); h.put("website", getValue(project,"website")); h.put("download", getValue(project,"download")); h.put("message", getValue(project,"message")); NodeList minecraft = project.getElementsByTagName("minecraft"); Vector<String> v = new Vector<String>(); for (int i = 0; i < minecraft.getLength(); i++) { v.add(getValue((Element)minecraft.item(i),"supportedversion")); } h.put("minecraft", v); return h; } /** * Gets the value of the specified element * @param e Element to get the values from * @param tag The tag to grab the value from * @return The value of the specified tag in the specified element */ private String getValue(Element e, String tag) { String s = null; NodeList n = e.getElementsByTagName(tag); if(n != null && n.getLength() > 0) { s = ((Element)n.item(0)).getTextContent(); //System.out.println(n.item(0).getNodeName() + " - " + s); } return s; } /** * Will download the file specified by the URL * @param rawurl - The HTTP URL to download from * @return The file object which was downloaded - the object will not exist (null) if it was unsuccessful */ public File downloadFile(String rawurl) { File temp = null; InputStream is = null; FileOutputStream fos = null; try { URL url = new URL(rawurl); url.openConnection(); is = url.openStream(); temp = File.createTempFile("spcupdate",System.currentTimeMillis() + ""); fos = new FileOutputStream(temp); byte[] buffer = new byte[1024]; int bytes = 0; while ((bytes = is.read(buffer)) > 0) { fos.write(buffer, 0, bytes); //buffer = new byte[1024]; } } catch (Exception e) { e.printStackTrace(); try { temp.delete(); } catch (Exception e2) {} temp = null; } finally { try { fos.close(); } catch (Exception e) {} try { is.close(); } catch (Exception e) {} } return temp; } }