package org.gnu.amSpacks.user; import java.io.*; import java.net.*; import java.lang.reflect.*; import javax.swing.*; import java.util.zip.*; /** This class must be present as part of your package. * Your installation must contain the folder "bin". * In this folder, it must have the executable .jar * archive with this class inside. Then you can * easily call this class from any other class, stored in * the same archive. */ public class Update { /** Main demonstrates how to start the update. This the main class * in demo.jar . * */ public static void main(String[] args) { try { Update autoupdater = new Update(); URL[] servers = new URL[] { /** The locations, where the main configuration file can be found. */ new URL("http://mypage.bluewin.ch/audrius/updates.xml"), new URL("http://jsight.sourceforge.net/updates.xml"), new URL("http://bioinformatics.org/jSight/updates.xml"), }; autoupdater.setUpdateFrom(servers); autoupdater.proceed(); } catch (MalformedURLException ex) { assert false:"Should never happen."; } }; /* The rest of the code does not require your attention */ private URL[] updateFrom = null; /** Starts the update process. */ public void proceed() { if (updateFrom==null) throw new Error("Set the server list by calling setUpdataFrom(URL[] list)"); try { File f = getBinFolder(); File dir = getApplicationFolder(); File autoUpdateJar = new File(f, "autoupdate.jar"); jarLoader loader = new jarLoader(autoUpdateJar.getAbsolutePath()); Class c = loader.findClass("org.gnu.amSpacks.AutoUpdate"); File target = dir; Method m = c.getMethod("update", new Class[] { updateFrom.getClass(), File.class }); m.invoke(null, new Object[] { updateFrom, target }); } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(null, "Sorry, unable to update. Please\n"+ "download the new version manually.\n"+ "See Help|About for the download address.", "Error", JOptionPane.ERROR_MESSAGE); } } private String getMainJar() { return file(getClass().getResource("Update.class")); }; private File getBinFolder() throws Exception { File f = new File(getMainJar()); if (!f.exists()) throw new Exception("Unable to loacate the main jar file"); return f.getParentFile(); } private File getApplicationFolder() throws Exception { File d = getBinFolder(); if (!d.getName().equals("bin")) throw new Exception("The main parent file must be located in a folder 'bin'"); return d.getParentFile(); } private static String file(URL _u) { URL u = _u; String up = u.toExternalForm(); String uab=null; boolean jar = up.indexOf(".jar!")>0 || up.startsWith("jar:"); if (jar) // this is a jar file, go to root. { try { u = new URL(u,"/"); uab = u.getFile(); if (uab.endsWith("!/")) { uab=uab.substring(0, uab.length()-2); } } catch (Exception exc) { exc.printStackTrace(); }; } else // folder { uab = up; } // delete the file: prefix: // do not include, but delete also a subsequent char, '/' if (uab.startsWith("file:")) { uab = uab.substring("file:".length()+1); }; String path = uab; File library = new File(path); /* FIX: folder names with spaces. if (!library.exists()) { library = new File("/"+path); }; */ if (!library.exists()) { try { library = new File("/" + URLDecoder.decode(path, "UTF-8")); } catch (UnsupportedEncodingException ex) { library = new File("/" + path, "UTF-8"); } }; // if not jar, move two folders up: if (!jar) { library = library.getParentFile().getParentFile().getParentFile(); }; if (!library.exists()) { System.out.println("PANIC: no library "+library.getAbsolutePath()+" as from "+_u.toExternalForm()); }; return library.getAbsolutePath(); }; private void setUpdateFrom(URL[] updateFrom) { this.updateFrom = updateFrom; } private class jarLoader extends ClassLoader { final String jar; final String subJar; private String getJar() { return jar; }; private jarLoader(String _jar, String _subJar) { super(getSystemClassLoader()); jar = _jar; subJar = _subJar; }; private jarLoader(String _jar) { super(getSystemClassLoader()); jar = _jar; subJar = null; }; public Class findClass(String name) throws ClassNotFoundException { try { byte[] b; if (subJar!=null) b = loadClassData(jar, subJar, name); else b = loadClassData(jar, name); return defineClass(name, b, 0, b.length); } catch (Exception exc) { //exc.printStackTrace(); throw new ClassNotFoundException("Cannot load "+name); } } protected byte[] loadClassData(String jar, String name) throws ClassNotFoundException, IOException { name = name.replace('.','/')+".class"; //System.out.println("loading "+name+" directly from "+jar); ZipInputStream zw; ZipEntry ze; zw = new ZipInputStream( new BufferedInputStream( new FileInputStream(jar) ) ); ze = zw.getNextEntry(); while (ze!=null && !ze.getName().endsWith(name)) { //System.out.println(ze.getName()); ze = zw.getNextEntry(); }; if (ze==null) throw new ClassNotFoundException(name+" not found in "+jar); return readContent(zw); }; /** Load class from jar of subJar in that jar. Jar and subJar names must not be * identical. */ protected byte[] loadClassData(String jar, String subJar, String name) throws Exception { if (subJar==null) return loadClassData(jar, name); if (!subJar.startsWith("/")) subJar = "/"+subJar; name = name.replace('.','/')+".class"; //System.out.println("loading "+name+" from "+jar+" : "+subJar); ZipInputStream zw; ZipEntry ze; if (jar.endsWith(subJar)) { //System.out.println("Direct library specified."); zw = new ZipInputStream( new BufferedInputStream( new FileInputStream(jar) ) ); } else { //System.out.println("Looking for "+subJar+" inside archive."); ZipInputStream zi = new ZipInputStream( new BufferedInputStream( new FileInputStream(jar) ) ); ze = zi.getNextEntry(); while (ze!=null && !ze.getName().endsWith(subJar)) { ze = zi.getNextEntry(); }; if (ze==null) throw new ClassNotFoundException(subJar+" not found in "+jar); zw = new ZipInputStream(zi); }; System.out.println(subJar+" found and opened."); ze = zw.getNextEntry(); while (ze!=null && !ze.getName().endsWith(name)) { //System.out.println(ze.getName()); ze = zw.getNextEntry(); }; if (ze==null) throw new ClassNotFoundException(name+" not found in "+jar+"/"+subJar); return readContent(zw); } private ZipInputStream getJarInputStream() throws Exception { if (subJar==null) return new ZipInputStream( new BufferedInputStream( new FileInputStream(jar) ) ); //System.out.println("loading "+name+" from "+jar+" : "+subJar); ZipEntry ze; if (jar.endsWith(subJar)) { return new ZipInputStream( new BufferedInputStream( new FileInputStream(jar) ) ); } else { //System.out.println("Looking for "+subJar+" inside archive."); ZipInputStream zi = new ZipInputStream( new BufferedInputStream( new FileInputStream(jar) ) ); ze = zi.getNextEntry(); while (ze!=null && !ze.getName().endsWith(subJar)) { ze = zi.getNextEntry(); }; if (ze==null) throw new ClassNotFoundException(subJar+" not found in "+jar); return new ZipInputStream(zi); } } private byte[] readContent(InputStream zw) throws IOException { ByteArrayOutputStream bu = new ByteArrayOutputStream(2000); int x; while ( (x = zw.read())!=-1) bu.write(x); return bu.toByteArray(); }; public String toString() { return "jarLoader "+jar+" - "+subJar; } public InputStream getResourceAsStream(String name) { try { ZipInputStream zw; ZipEntry ze; zw = new ZipInputStream( new BufferedInputStream( new FileInputStream(jar) ) ); ze = zw.getNextEntry(); while (ze!=null && !ze.getName().endsWith(name)) { ze = zw.getNextEntry(); }; if (ze==null) { return super.getResourceAsStream(name); }; return zw; } catch (Exception exc) { exc.printStackTrace(); exc.printStackTrace(); return super.getResourceAsStream(name); } }; private InputStream getResourceAsStreamExclusive(String name) { try { ZipInputStream zw; ZipEntry ze; zw = new ZipInputStream( new BufferedInputStream( new FileInputStream(jar) ) ); ze = zw.getNextEntry(); while (ze!=null && !ze.getName().endsWith(name)) { ze = zw.getNextEntry(); }; if (ze==null) return null; return zw; } catch (Exception exc) { exc.printStackTrace(); return null; } }; public URL getResource(String name) { try { if (getResourceAsStream(name)!=null) return new URL("jar:file:/"+jar+"!/"+name); } catch (Exception exc) { }; return super.getResource(name); } } }