1 package snow.updater; 2 3 import java.util.jar.*; 4 import java.io.*; 5 import java.util.zip.GZIPInputStream ; 6 import javax.swing.JFrame ; 7 import javax.swing.JOptionPane ; 8 import java.util.*; 9 import snow.utils.ProcessUtils; 10 import java.util.zip.ZipEntry ; 11 import java.util.zip.ZipFile ; 12 import snow.utils.SysUtils; 13 import java.io.InputStream ; 14 import java.io.FileOutputStream ; 15 import snow.utils.gui.ProgressModalDialog; 16 import snow.utils.storage.FileUtils; 17 import java.net.*; 18 import java.io.File ; 21 22 26 public final class Updater 27 { 28 29 public Updater() 30 { 31 } 32 33 35 public static boolean isWebStartMode(String jarName) 36 { 37 try{ 38 File tf = getJarCurrentlyRunning(jarName); 41 if(tf==null) return true; 42 } 43 catch(Exception e) { 44 } 45 46 return false; 47 } 48 49 public static boolean isNewVersionAvailable(String jarName, String url) throws Exception 50 { 51 if(shutdownHook!=null) 52 { 53 throw new Exception ("An update is already pending, please close the application."); 54 } 55 56 File tf = getJarCurrentlyRunning(jarName); 57 if(tf==null) return false; 59 long[] dl = getDateAndSizeOnServer(new URL(url)); 60 if(dl[0]-tf.lastModified() > 1000*3600) 61 { 62 return true; 63 } 64 65 return false; 66 } 67 68 private static Thread shutdownHook = null; 69 70 71 public static void updateAndLaunchReplacerTask(String jarName, String url) throws Exception 72 { 73 if(shutdownHook!=null) 74 { 75 throw new Exception ("An update is already pending, please close the application."); 76 } 77 final File tf = getJarCurrentlyRunning(jarName); 78 if(tf==null) throw new Exception ("Cannot update: there is no "+jarName+" in the classpath"); 79 80 ProgressModalDialog pmd = new ProgressModalDialog((JFrame ) null, "Downloading the new jar", true, false); 81 final File tempDest = new File (tf.getAbsolutePath()+".new"); 83 if(url.toLowerCase().endsWith(".pack.gz")) 84 { 85 final File tempDestGZ = new File (tf.getAbsolutePath()+".new.pack.gz"); 86 tempDestGZ.deleteOnExit(); 87 downloadFromServer(new URL(url), tempDestGZ, pmd); 88 89 pmd.setProgressComment("Unpack200 to "+tempDest.getName()); 90 replaceJarWithPack200Decompressed(tempDest, tempDestGZ); 91 } 92 else 93 { 94 downloadFromServer(new URL(url), tempDest, pmd); 95 } 96 pmd.closeDialog(); 97 98 99 extractReplacer(tf); 100 101 Runtime.getRuntime().addShutdownHook(shutdownHook = new Thread () 104 { 105 @Override public void run() 106 { 107 File javaExe = new File (System.getProperty("java.home")+"/bin/java"+(SysUtils.is_Windows_OS()?".exe":"")); 108 109 ProcessBuilder pb = new ProcessBuilder (javaExe.getAbsolutePath(), 110 "JarNewVersionReplacer", 111 tf.getAbsolutePath(), tempDest.getAbsolutePath() ); 114 try{ 115 pb.start(); 116 }catch(Exception e){ e.printStackTrace(); } 117 } 118 }); 119 120 JOptionPane.showMessageDialog(null, 121 "The new version has been succesfully downloaded." 122 +"\nAnother JVM has been started that will replace" 123 +"\n "+tf 124 +"\nwith the new version when you close this application.", 125 "Download successful", JOptionPane.INFORMATION_MESSAGE); 126 127 129 130 } 131 132 private static void extractReplacer(File f) throws Exception 133 { 134 ZipFile zf = new ZipFile (f); 135 try{ 136 ZipEntry ze = zf.getEntry("JarNewVersionReplacer.class"); 137 if(ze==null) throw new Exception ("JarNewVersionReplacer entry not found in jar file "+f); 138 File dest = new File (f.getParentFile(), "JarNewVersionReplacer.class"); 139 FileUtils.writeToFile( zf.getInputStream(ze), dest); 140 } 141 catch(Exception e) { 142 throw e; 143 } 144 finally{ 145 FileUtils.closeIgnoringExceptions(zf); 146 } 147 } 148 149 150 151 155 public static File getJarCurrentlyRunning(String name) { 157 String cps = System.getProperty("java.class.path",""); 158 String [] cp = cps.split(";"); 160 for(String cpi : cp) 161 { 162 cpi = cpi.trim(); 163 164 if(cpi.toLowerCase().endsWith(name)) 165 { 166 if(cpi.equalsIgnoreCase(name)) 167 { 168 File fi = new File (System.getProperty("user.dir", ""), cpi); 170 if(fi.exists()) return fi; 171 } 172 File fi = new File (cpi); 173 if(fi.exists()) return fi; 174 } 175 } 176 return null; 178 } 179 180 public static long[] getDateAndSizeOnServer(URL url) throws Exception 181 { 182 HttpURLConnection con = (HttpURLConnection) url.openConnection(); 183 long date = con.getLastModified(); 184 long size = con.getContentLength(); 185 con.disconnect(); 186 if(date<1 || size<1) throw new Exception ("No connection to "+url); 187 return new long[]{ date, size }; 188 } 189 190 private static void downloadFromServer(URL url, File dest, ProgressModalDialog pmd) throws Exception 191 { 192 HttpURLConnection con = (HttpURLConnection) url.openConnection(); 193 con.setDoOutput(false); 194 long date = con.getLastModified(); 195 long size = con.getContentLength(); 196 long start = System.currentTimeMillis(); 197 pmd.setProgressComment("Downloading "+url+", "+FileUtils.formatSize(size)+""); 198 pmd.start(); 199 writeToFile(con.getInputStream(), dest,pmd,size); 200 if(date>0) 201 { 202 dest.setLastModified(date); 203 } 204 double speed = 8.0*size /(System.currentTimeMillis()-start); System.out.println("Downloaded "+url+" at "+speed+" kBit/s"); 206 con.disconnect(); 207 } 208 209 211 public static void writeToFile(InputStream is, File file, ProgressModalDialog pmd, long totSize) throws Exception 212 { 213 if(totSize==0) totSize=500000; 215 File parent = file.getParentFile(); 216 if(parent!=null && !parent.exists()) 217 { 218 parent.mkdirs(); 219 } 220 221 FileOutputStream fos = null; 222 try 223 { 224 fos = new FileOutputStream (file); 225 byte[] buf = new byte[256]; 226 long totRead = 0; 227 int read = -1; 228 while((read=is.read(buf))!=-1) 229 { 230 if(pmd.wasCancelled()) throw new Exception ("Download cancelled"); 231 232 fos.write( buf,0,read); 233 totRead+=read; 234 235 pmd.setProgressValue((int)(totRead*90.0/totSize),""); 236 237 } 238 } 239 catch(Exception e) 240 { 241 throw e; 242 } 243 finally 244 { 245 FileUtils.closeIgnoringExceptions( fos ); 246 FileUtils.closeIgnoringExceptions( is ); 247 } 248 } 249 250 @SuppressWarnings ("unchecked") 251 private static void replaceJarWithPack200Decompressed(File jarFile, File pack200GzFile) throws Exception 252 { 253 File tmpDest = File.createTempFile("jar_"+jarFile.getName(), null); 254 tmpDest.deleteOnExit(); 255 FileOutputStream fostream = null; 256 JarOutputStream jostream = null; 257 FileInputStream fis = null; 258 259 try 260 { 261 fostream = new FileOutputStream (tmpDest); 262 jostream = new JarOutputStream(fostream); 263 264 Pack200.Unpacker unpacker = Pack200.newUnpacker(); 265 Map p = unpacker.properties(); 266 p.put(Pack200.Unpacker.DEFLATE_HINT, Pack200.Unpacker.TRUE); 267 268 fis = new FileInputStream(pack200GzFile); 269 GZIPInputStream gis = new GZIPInputStream (fis); 270 271 unpacker.unpack(gis, jostream); 272 273 jostream.close(); 275 fis.close(); 276 277 if(jarFile.exists()) 279 { 280 if(!jarFile.delete()) 281 { 282 throw new Exception ("Cannot delete "+jarFile); 283 } 284 } 285 286 287 288 } 289 catch(Exception e) 290 { 291 throw e; 292 } 293 finally 294 { 295 FileUtils.closeIgnoringExceptions( fis ); 296 FileUtils.closeIgnoringExceptions( fostream ); 297 } 298 299 long lm = tmpDest.lastModified(); 300 tmpDest.renameTo(jarFile); 301 jarFile.setLastModified(lm); 303 304 305 } 306 307 public static void main(String [] arguments) 308 { 309 new File ("C:/proj/tide/published/snowmail.sn.funpic.de/tide/tide.jar"). 310 setLastModified(1000200030000l); 311 } 312 313 314 } | Popular Tags |