Revision: 4618
          http://sourceforge.net/p/vexi/code/4618
Author:   mkpg2
Date:     2013-12-19 23:55:02 +0000 (Thu, 19 Dec 2013)
Log Message:
-----------
Launcher. Display console/log in the event of an error.

Modified Paths:
--------------
    trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Launcher.java
    trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/LauncherApplet.java
    trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/LauncherMain.java
    trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Splash.java
    
trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/util/StreamReader.java

Added Paths:
-----------
    trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Log.java

Removed Paths:
-------------
    trunk/org.vexi-launcher/Launcher.java
    trunk/org.vexi-launcher/LauncherApplet.java

Deleted: trunk/org.vexi-launcher/Launcher.java
===================================================================
--- trunk/org.vexi-launcher/Launcher.java       2013-12-19 22:33:44 UTC (rev 
4617)
+++ trunk/org.vexi-launcher/Launcher.java       2013-12-19 23:55:02 UTC (rev 
4618)
@@ -1,463 +0,0 @@
-package org.vexi.launcher;
-
-import java.applet.Applet;
-import java.awt.Color;
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import org.vexi.DotVexi;
-
-/**
- * @author m...@webenableit.co.uk
- * @contributor char...@webenableit.co.uk
- *
- * <p>The launcher is responsible for downloading the Vexi Core
- *    and the principle application components (.vexi files)
- *    and launching it as a separate process so that it can
- *    exist and survive outside of the restrictive environment
- *    that is imposed upon applets.</p>
- *    
- */
-abstract public class Launcher {
-
-       // REMARK although a signed applet doesn't have any known securities
-    // we restrict it to running from domains that we control because in
-    // the event that it is compromised we can update the copy on these 
-    // domains. In this way the fetching of the applet acts as the security
-    // check.
-    abstract public Color getTextColor();
-    abstract public Color getBorderColor();
-    abstract public Color getBarColor();
-    abstract public URL getSplashImageResource();
-    abstract public String[] getPermittedDomains();
-    abstract public Map getCerts(); 
-    abstract public String getVersion();
-    
-    ////////////////
-    // INIT
-    final LauncherApplet applet;
-    DotVexi dotvexi;
-    String fetchCount = "?";
-    int fetchIndex = 1;
-    public Launcher(LauncherApplet applet) {
-       this.applet = applet;
-       }       
-
-    static protected void logflush() {
-        System.err.flush();
-    }
-    
-    static protected void log(String s) {
-        System.err.println(s);
-    }
-    
-    
-    static private String getEnv(String name) {
-        try {
-            return System.getenv(name);
-        } catch(Throwable t) {
-            // REMARK - they deprecated this in 1.4, only to bring it back in 
1.5.
-            // By deprecated we mean it throws an error. So here we fall back 
to
-            // getting it from the commandline.
-            try {
-                String os = System.getProperty("os.name").toLowerCase();
-                Process p;
-                String cmd;
-                if (os.indexOf("windows 9") != -1 || os.indexOf("windows me") 
!= -1) {
-                    cmd = "command.com /c set";
-                } else if (os.indexOf("windows") > -1) {
-                    cmd = "cmd.exe /c set";
-                } else {
-                    cmd = "env";
-                }
-                p = Runtime.getRuntime().exec(cmd);
-                BufferedReader br = new BufferedReader(new 
InputStreamReader(p.getInputStream()));
-                String s;
-                while ((s = br.readLine()) != null) {
-                    if (s.startsWith(name + "=")) {
-                        return s.substring(name.length() + 1);
-                    }
-                }
-            } catch (Throwable t2) {
-                log("Encountered an exception during fallback discovery of: 
'"+name+"'");
-                t2.printStackTrace();
-            }
-            return null;    
-        }
-    }
-    
-    /** generates the basic command string to start java */
-    static private String findInJavaHome(String os_name, String javaHome) {
-        if (javaHome != null && !javaHome.equals("")) {
-            String r = javaHome + File.separatorChar + "bin" + 
File.separatorChar + "java";
-            if (os_name.indexOf("windows") != -1) {
-                r += ".exe";
-            }
-            if (new File(r).exists()) {
-                return r;
-            }
-        }
-        return null;
-    }
-    
-    /** searches for the JVM binary in the usual places 
-     * @throws Problem */
-    static private String findJvmBinary() throws Exception {
-        log("-- Locating the Java Binary --");
-        String jvmBinary = null;
-        String os_name = System.getProperty("os.name", "").toLowerCase();
-        
-        log("Trying Environment Variable 'VEXI_JRE'");
-        jvmBinary = findInJavaHome(os_name,getEnv("VEXI_JRE"));
-        if (jvmBinary != null) {
-            return jvmBinary;
-        }
-        
-        log("Trying Environment Variable 'JAVA_HOME'");
-        jvmBinary = findInJavaHome(os_name,getEnv("JAVA_HOME"));
-        if (jvmBinary != null) {
-            return jvmBinary;
-        }
-        
-        log("Trying System Property 'java.home'");
-        jvmBinary = findInJavaHome(os_name,System.getProperty("java.home"));
-        if (jvmBinary != null) {
-            return jvmBinary;
-        }
-        
-        // check PATH
-        log("Checking to see if java is on the PATH Environment Variable");
-        String path = getEnv("PATH");
-        if (path == null) {
-            path  = getEnv("Path");
-        }
-        if (path!=null) {
-            StringTokenizer st = new StringTokenizer(path, 
File.pathSeparatorChar + "");
-            while (st.hasMoreTokens()) {
-                String s = st.nextToken();
-                if (new File(s + File.separatorChar + "java").exists() || new 
File(s + File.separatorChar + "java.exe").exists() ) {
-                    jvmBinary = s + File.separatorChar + "java";
-                    if (os_name.indexOf("windows") != -1) {
-                        jvmBinary += ".exe";
-                    }
-                    return jvmBinary;
-                }
-            }
-        }
-
-        throw new Problem("Couldn't find a suitable JVM binary! See console 
log for details");
-    }
-
-    long lastDate = -1;
-    protected InputStream getInputStream(String url) throws IOException{
-        final URLConnection uc = connect(url);
-        InputStream is = uc.getInputStream();
-        int contentLength = uc.getContentLength();
-        lastDate = uc.getLastModified();
-        return progressInputStream(is, url, contentLength);
-    }
-
-    public void initDotVexi() {
-        dotvexi = new DotVexi(getCerts()) {
-            
-            protected void log(String s) { Launcher.log(s); }
-    
-            protected InputStream getInputStream(Object fountain, Object 
principal) throws IOException {
-                String url = (String)fountain;
-                return Launcher.this.getInputStream(url);
-            }
-            protected long getRemoteDate(Object fountain, Object principal) {
-                return lastDate;
-            }
-        };
-    }
-    
-    public void initSplash(){
-       Splash.init(getVersion(),getSplashImageResource(), getTextColor(), 
getBorderColor(), getBarColor());        
-    }
-
-    
-    private InputStream progressInputStream(InputStream is, final String 
displayname, final int contentLength ) {
-        final String left = "Downloading: "+displayname; 
-        final String right = fetchIndex+"/"+fetchCount;
-        
-        return new FilterInputStream(new BufferedInputStream(is)) {
-            int total = 0;
-            int percent = 0;
-            private void display() {
-                 double loaded = ((double)total) / ((double)contentLength);
-                 int newpercent = ((int)Math.ceil(loaded * 100));
-                 if (newpercent!=percent) {
-                    percent = newpercent;
-                    
-                    //log(percent + "%");
-                    Splash.update(left, right, (double)percent);
-                 }
-            }
-            
-            public int read() throws IOException {
-                int ret = super.read();
-                if (ret != -1) {
-                    total++;
-                }
-                display();
-                return ret;
-            }
-            public int read(byte[] buf, int off, int len) throws IOException {
-                int ret = super.read(buf, off, len);
-                if (ret != -1) {
-                    total += ret;
-                }
-                display();
-                return ret;
-            }
-        };
-    }
-
-    /** check if a url falls within the permitted domains
-     * @param url a string of an absolute url, must start with 'http://' or 
'file://'
-     * @return true iff url is permitted */
-    protected boolean checkUrl(String url) {
-        if (url.startsWith("file")) {
-            return true;
-        }
-        if (url.startsWith("http")) {
-            // remove the protocol
-            url = url.substring(url.indexOf("//")+2);
-            while (true) {
-                String[] permittedDomains = getPermittedDomains();
-                for (int i=0; i<permittedDomains.length; i++) {
-                    if (url.startsWith(permittedDomains[i])) {
-                        return true;
-                    }
-                }
-                // if we are a subdomain remove leading part and recheck
-                if (url.indexOf('.')==-1) {
-                    break;
-                }
-                url = url.substring(url.indexOf('.')+1);
-            }
-        }
-        return false;
-    }
-    
-    static private String join(String[] ss) {
-        String r = "";
-        for (int i=0; i<ss.length; i++) {
-            if (i>0) {
-                r += ",";
-            }
-            r += ss[i];
-        }
-        return r;
-    }
-    
-    /** fetches a file from the distribution site, writing it to the 
appropriate place */
-    public File fetch(String url) throws IOException {
-        File localfile = dotvexi.getLocalFile(url);
-        dotvexi.fetch(url, null, url, localfile);
-        fetchIndex++;
-        return localfile;
-    }
-    
-    /** attempts to create a local file for logging vexi output to */
-    protected File createLog(String logfile) throws IOException {
-        File dir = dotvexi.findSubDir("logs");
-        dir.mkdirs();
-        File f=null;
-        String fname = logfile;
-        for (int i=0; i<100; i++) {
-            f = new File(dir,fname);
-            if ((f.exists() && !f.delete())) {
-                fname = logfile+i;
-                continue; // file occupied!
-            }
-            if (!f.createNewFile()) {
-                break;
-            }
-            return f;
-        }
-        throw new RuntimeException("Could not create log file: " + 
f.getCanonicalPath());
-    }
-    
-
-    
-    static public class Problem extends Exception {
-        public Problem(String message) { super(message); }
-    }
-    
-    
-    
-    public void go(
-               String core, 
-               String mem, 
-               List<String> fetchVexis) {
-       //log("Codebase is "+url);
-       fetchCount = ""+(fetchVexis.size()+1);
-
-
-       String coreurl = core;
-       if (!coreurl.endsWith(".signed")) {
-               permitUnsignedCore(coreurl);
-       }
-       File corefile = fetch(coreurl);
-
-       List command = new ArrayList();
-       command.add(findJvmBinary());
-       if (mem!=null) {
-               command.add("-Xmx" + mem);
-       }
-       command.add("-jar");
-       command.add(corefile.getPath());
-
-       String logfile = getParameter("logfile");
-       if (logfile!=null) {
-               createLog(logfile);
-               command.add("-l");
-               command.add("logs/"+logfile);
-       }
-       command.add("-biscuitid");
-       command.add(DotVexi.urlUniqueName(codebase));
-
-
-       for (int i = 0; i<10000;i++) {
-               if (getParameter("option" + i) == null) {
-                       break;
-               }
-               command.add(getParameter("option" + i));
-       }
-
-
-       for (int i = 0; i<fetchVexis.size();i++) {
-               File f = fetch((String)fetchVexis.get(i));
-               command.add(f.getPath());
-       }
-
-
-       // REMARK - discovering os/architecture not relevant until 
-       // native builds are working again
-       /*
-            String os_name = System.getProperty("os.name", "").toLowerCase();
-            log("os.name == " + os_name);
-            Vector command = new Vector();
-            String arch = null;
-            if (os_name.indexOf("linux") != -1) {
-                arch = new BufferedReader(new 
InputStreamReader(Runtime.getRuntime().exec("/bin/uname 
-m").getInputStream())).readLine();
-                log("arch is " + arch);
-            }*/
-
-       spawn(command);
-    }
-    
-    /** spawns the Vexi core
-     * @param command contains the full command - including java */
-    private void spawn(List<String> command) throws IOException { 
-        File dir = dotvexi.getBaseDir();
-        String[] command_vec = command.toArray(new String[command.size()]);
-        log("in directory : " + dir.getCanonicalPath());
-        log("executing    : ");
-        for (int i=0; i<command_vec.length; i++) {
-            log("    \"" + command_vec[i] + "\"");
-        }
-
-        final Process p = Runtime.getRuntime().exec(command_vec,null,dir);
-        
-        new Thread(new Runnable() {
-            public void run() {
-                // catch output
-                StreamReader errorstream = new 
StreamReader(p.getErrorStream(), "ERROR", true);
-                StreamReader outputstream = new 
StreamReader(p.getInputStream(), "OUTPUT", false);
-                // kick off output streams
-                errorstream.start();
-                outputstream.start();
-                try {
-                    updateStatus("Vexi loaded");
-                    int exitValue = p.waitFor();
-                    if (exitValue != 0) {
-                        updateError("Vexi exited abnormally with error code 
'"+exitValue+"', see log output");
-                    } else {
-                        updateStatus("Vexi has finished running");
-                    }
-                } catch (Throwable t) {
-                    log("Error exiting... " + p.exitValue());
-                    t.printStackTrace();
-                }
-                log("Exiting...");
-                logflush();
-            }
-        }).start();
-    }
-
-
-    /**
-     * @author char...@webenableit.co.uk
-     *
-     * A very simple stream reader, copied from:
-     * http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
-     */
-    static class StreamReader extends Thread {
-        InputStream is;
-        String type;
-        
-        StreamReader(InputStream is, String type, boolean listenDisplay) {
-            this.is = is;
-            this.type = type;
-            this.listenDisplay = listenDisplay;
-        }
-        private boolean listenDisplay;
-        
-        public void run() {
-            try {
-                InputStreamReader isr = new InputStreamReader(is);
-                BufferedReader br = new BufferedReader(isr);
-                String line=null;
-                while ((line = br.readLine()) != null) {
-                    if (listenDisplay && line.contains("**display 
launched**")) {
-                        Splash.close();
-                    }
-                    log(type + ">" + line);
-                }
-            } catch (IOException ioe) {
-                ioe.printStackTrace();
-            }
-        }
-    }
-    
-    
-    ////////////////////
-    //// Utility
-    static private URLConnection connect(String url) throws IOException {
-        try {
-            URL u = new URL(url);
-            final URLConnection uc = u.openConnection();
-            uc.setUseCaches(false); // don't use the possibly short Java cache
-            uc.connect();
-            return uc;
-        } catch (NullPointerException npe) {
-            // WORKAROUND - sun libraries throw a NPE rather than
-            // a more informative exception.
-            throw new IOException("Invalid url: "+url);
-        }
-    }
-
-    //////////////
-    // Permission
-    void permitAlternativeURL(String url) throws Problem {
-        throw new Problem("Applet can not be run from unknown domain " + url + 
"\nPermitted domains: " + join(getPermittedDomains()));
-    }
-    void permitUnsignedCore(String file) throws Problem {
-        throw new Problem("Applet will not run unsigned core file: "+ file);
-    }
-}

Deleted: trunk/org.vexi-launcher/LauncherApplet.java
===================================================================
--- trunk/org.vexi-launcher/LauncherApplet.java 2013-12-19 22:33:44 UTC (rev 
4617)
+++ trunk/org.vexi-launcher/LauncherApplet.java 2013-12-19 23:55:02 UTC (rev 
4618)
@@ -1,153 +0,0 @@
-package org.vexi.launcher;
-
-import java.applet.Applet;
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Image;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Vector;
-
-import org.vexi.DotVexi;
-import org.vexi.launcher.Launcher.Problem;
-
-/**
- * @author m...@webenableit.co.uk
- * @contributor char...@webenableit.co.uk
- *
- * <p>The launcher is responsible for downloading the Vexi Core
- *    and the principle application components (.vexi files)
- *    and launching it as a separate process so that it can
- *    exist and survive outside of the restrictive environment
- *    that is imposed upon applets.</p>
- *    
- */
-abstract public class LauncherApplet extends Applet {
-       abstract protected Launcher createLauncher();
-    
-    ///////////////////////
-    // APPLET
-    ///////////////////////
-    
-       private Launcher launcher;
-       
-    /** applet entry point - this is where it all begins */
-    public final void init() {
-       launcher = createLauncher();
-       launcher.initSplash();
-       launcher.initDotVexi();
-        
-        // the rest is initialized outside of the restrictive applet sandbox
-        // as we need to download several files and start up a new process
-        // REMARK: this requires the applet to be signed, an unsigned applet
-        // will most likely fail very soon after this next thread is started
-        new Thread() {
-            public void run() {
-                java.security.AccessController.doPrivileged(new 
java.security.PrivilegedAction() {
-                    public Object run() {
-                        launcher.go();
-                        return null;
-                    }
-                });
-            }
-        }.start();
-
-    }
-    
-    void log(String s){ Launcher.log(s);}
-    
-    public void go() {
-       try{
-               log("Launcher Build : "+launcher.getVersion());
-
-               // Check codebase is permitted
-               String codebase = getCodeBase()+"";
-               updateStatus(""+codebase);
-               if (!checkUrl(codebase)) {
-                       permitAlternativeURL(codebase);
-               }
-               
-               String core = getParameter("core");
-            if (core==null) {
-                throw new Problem("Core property not set");
-            }
-            
-            List<String> fetchVexis = new ArrayList(10);
-            for (int i = 0; i<10000;i++) {
-                String fetch = getParameter("vexi" + i);
-                if (fetch == null) {
-                    break;
-                }
-                fetchVexis.add(fetch);
-            }
-            
-            go(core, fetchVexis);
-               
-       } catch (Problem e) {
-               updateError(e.getMessage());
-               log(e.getMessage());
-       } catch (Throwable e) {
-               updateError("Error; please check the Java console");
-               e.printStackTrace();
-       } finally {
-               Splash.close();
-       }        
-    }
-
-    
-    
-    final Font font = new Font("Sans-serif", Font.BOLD, 12);
-    final private Object statusLock = new Object();
-    private String statusText; 
-    private Color statusColor;
-    private Image backbuffer = null;
-    
-    protected void updateStatus(String statusText) { 
-       updateStatus(statusText, Color.black);
-    }    
-    protected void updateError(String statusText) { 
-       Launcher.log("Error: "+statusText);
-       updateStatus(statusText, Color.red); 
-    }
-    
-    void updateStatus(String statusText, Color statusColor) {
-        synchronized (statusLock) {
-            this.statusText = statusText;
-            this.statusColor = statusColor;
-        }
-        repaint();
-    }
-    
-    
-    public final void paint(Graphics g) { update(g); }
-    public final void update(Graphics g2) {
-        if (backbuffer == null || backbuffer.getWidth(null) != getSize().width 
|| backbuffer.getHeight(null) != getSize().height) {
-            backbuffer = createImage(getSize().width, getSize().height);
-        }
-        if (backbuffer == null) {
-            return;
-        }
-        Graphics2D g = (Graphics2D)backbuffer.getGraphics();
-        
-        Color color;
-        String text;
-        synchronized(statusLock) {
-            text = statusText;
-            color = statusColor;
-        }
-        
-        g.setColor(Color.white);
-        g.fillRect(0, 0, getSize().width, getSize().height);
-        
-        int centerOffset = (getSize().width-(int)font.getStringBounds(text, 
g.getFontRenderContext()).getWidth())/2;
-        g.setColor(color);
-        g.setFont(font);
-        g.drawString(text, centerOffset, 15);
-        
-        g2.setClip(0, 0, getSize().width, getSize().height);
-        g2.drawImage(backbuffer, 0, 0, null);
-    }
-}

Modified: trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Launcher.java
===================================================================
--- trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Launcher.java       
2013-12-19 22:33:44 UTC (rev 4617)
+++ trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Launcher.java       
2013-12-19 23:55:02 UTC (rev 4618)
@@ -32,13 +32,11 @@
  */
 abstract public class Launcher {
        public interface Context {
-               public void flush();
-               public void log(String msg);
-               public void warn(String msg);
-               public void error(String msg);
                public void updateStatus(String msg);
+               public void updateError(String msg);
                public String  getParameter(String s);
                public void check() throws Problem;
+               public void exited();
        }
 
     // REMARK although a signed applet doesn't have any known securities
@@ -56,25 +54,27 @@
     
     ////////////////
     // INIT
+    final public Log log;
     final protected Context context;
     DotVexi dotvexi;
     String fetchCount = "?";
     int fetchIndex = 1;
 
 
-    public Launcher(Context feedback) {
-               this.context = feedback;
+    public Launcher(Context context) {
+       this.log = new Log(context);
+               this.context = context;
        }
 
     protected void log(String s) {
-        context.log(s);
+        log.log(s);
     }
        
     public Map getCerts() {
         try {
                return loadCerts();
         } catch (Throwable e) {
-            context.error("Error: applet unable to load root certificates");
+            log.error("Error: applet unable to load root certificates");
             throw new Error(e);
         }
     }
@@ -180,6 +180,7 @@
     public InputStream getInputStream(String url) throws IOException{
         final URLConnection uc = connect(url);
         InputStream is = uc.getInputStream();
+        
         int contentLength = uc.getContentLength();
         lastDate = uc.getLastModified();
         return progressInputStream(is, url, contentLength);
@@ -188,7 +189,7 @@
     public void initDotVexi() {
         dotvexi = new DotVexi(getCerts()) {
             
-            protected void log(String s) { context.log(s); }
+            protected void log(String s) { log.log(s); }
     
             protected InputStream getInputStream(Object fountain, Object 
principal) throws IOException {
                 String url = (String)fountain;
@@ -202,7 +203,7 @@
     
     
     public void initSplash(){
-       Splash.init(context, getVersion(),getSplashImageResource(), 
getTextColor(), getBorderColor(), getBarColor());        
+       Splash.init(log, getVersion(),getSplashImageResource(), getTextColor(), 
getBorderColor(), getBarColor());        
     }
 
 
@@ -310,7 +311,7 @@
         throw new RuntimeException("Could not create log file: " + 
f.getCanonicalPath());
     }
     
-    public void go() {
+    public void go() throws Exception {
         try {
             log("Launcher Build : "+getVersion());
             
@@ -387,12 +388,6 @@
             }*/
             
             spawn(command);
-        } catch (Problem e) {
-            context.error(e.getMessage());
-            log(e.getMessage());
-        } catch (Throwable e) {
-               context.error("Error; please check the Java console");
-            e.printStackTrace();
         } finally {
             Splash.close();
         }
@@ -416,25 +411,26 @@
         new Thread(new Runnable() {
             public void run() {
                 // catch output
-                StreamReader errorstream = new StreamReader(context, 
p.getErrorStream(), "ERROR", true);
-                StreamReader outputstream = new StreamReader(context, 
p.getInputStream(), "OUTPUT", false);
+                StreamReader errorstream = new StreamReader(log, 
p.getErrorStream(), "ERROR", true);
+                StreamReader outputstream = new StreamReader(log, 
p.getInputStream(), "OUTPUT", false);
                 // kick off output streams
                 errorstream.start();
                 outputstream.start();
                 try {
-                       context.updateStatus("Vexi loaded");
+                       log.status("Vexi loaded");
                     int exitValue = p.waitFor();
                     if (exitValue != 0) {
-                       context.error("Vexi exited abnormally with error code 
'"+exitValue+"', see log output");
+                       log.error("Vexi exited abnormally with error code 
'"+exitValue+"', see log output");
                     } else {
-                       context.updateStatus("Vexi has finished running");
+                       log.status("Vexi has finished running");
+                        log.log("Exiting...");
+                       context.exited();
                     }
                 } catch (Throwable t) {
-                       context.error("Error exiting... " + p.exitValue());
-                    t.printStackTrace();
+                       log.error("Error exiting... " + p.exitValue());
+                    log.error(t);
+                    log.flush();
                 }
-                context.log("Exiting...");
-                context.flush();
             }
         }).start();
     }
@@ -444,7 +440,7 @@
     
     ////////////////////
     //// Utility
-    static private URLConnection connect(String url) throws IOException {
+    public URLConnection connect(String url) throws IOException {
         try {
             URL u = new URL(url);
             final URLConnection uc = u.openConnection();
@@ -455,7 +451,7 @@
             // WORKAROUND - sun libraries throw a NPE rather than
             // a more informative exception.
             throw new IOException("Invalid url: "+url);
-        }
+        } 
     }
 
     //////////////

Modified: 
trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/LauncherApplet.java
===================================================================
--- trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/LauncherApplet.java 
2013-12-19 22:33:44 UTC (rev 4617)
+++ trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/LauncherApplet.java 
2013-12-19 23:55:02 UTC (rev 4618)
@@ -13,36 +13,53 @@
 abstract public class LauncherApplet extends Applet implements Context{
     
        Launcher launcher;
+       Log log;
        
        abstract protected Launcher createLauncher();
        
 
     /** applet entry point - this is where it all begins */
     public final void init() {
-       launcher = createLauncher();
-       launcher.initSplash();
-        launcher.initDotVexi();
-        
-        // the rest is initialized outside of the restrictive applet sandbox
-        // as we need to download several files and start up a new process
-        // REMARK: this requires the applet to be signed, an unsigned applet
-        // will most likely fail very soon after this next thread is started
-        new Thread() {
-            public void run() {
-                java.security.AccessController.doPrivileged(new 
java.security.PrivilegedAction() {
-                    public Object run() {
-                        launcher.go();
-                        return null;
-                    }
-                });
-            }
-        }.start();
+       
+               launcher = createLauncher();
+               launcher.initSplash();
+               launcher.initDotVexi();
+               log = launcher.log;
 
+               // the rest is initialized outside of the restrictive applet 
sandbox
+               // as we need to download several files and start up a new 
process
+               // REMARK: this requires the applet to be signed, an unsigned 
applet
+               // will most likely fail very soon after this next thread is 
started
+               new Thread() {
+                       public void run() {
+                               java.security.AccessController.doPrivileged(new 
java.security.PrivilegedAction() {
+                                       public Object run() {
+                                               go();
+                                               return null;
+                                       }
+                               });
+                       }
+               }.start();
+
     }
+    
+    public void exited(){}
+    
+    public void go(){
+       try{
+               launcher.go();
+       } catch (Problem e) {
+               log.error(e.getMessage());
+       } catch (Throwable e) {
+               log.error("Unhandled exception");
+               log.error(e);
+       }       
+    }
+    
     public void check() throws Problem {
         
         String codebase = getCodeBase()+"";
-        updateStatus(""+codebase);
+        log.status(""+codebase);
         //log("Codebase is "+url);
 
         if (!launcher.checkUrl(codebase)) {
@@ -72,20 +89,7 @@
      * @param text
      *   message or error to display in the applet
      */
-    
-    public void log(String msg) {
-       System.err.println(msg);
-    }
-    public void flush() {
-       System.err.flush();
-    }
-    
-       public void warn(String msg) { log("[WARNING]: "+msg); }
-
-    public void error(String statusText) { 
-        log("[ERROR]: "+statusText);
-        updateStatus(statusText, Color.red); 
-    }
+    public void updateError(String statusText) { updateStatus(statusText, 
Color.red); }    
     public void updateStatus(String statusText) { updateStatus(statusText, 
Color.black); }    
     private void updateStatus(String statusText, Color statusColor) {
         synchronized (statusLock) {

Modified: 
trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/LauncherMain.java
===================================================================
--- trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/LauncherMain.java   
2013-12-19 22:33:44 UTC (rev 4617)
+++ trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/LauncherMain.java   
2013-12-19 23:55:02 UTC (rev 4618)
@@ -2,6 +2,9 @@
 
 import java.io.File;
 import java.io.InputStreamReader;
+import java.net.ConnectException;
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
@@ -16,20 +19,29 @@
  */
 abstract public class LauncherMain implements Context{
        
+
+
+
+       final Launcher launcher;
+       final Log log;
+       
        private Map<String,String> params;
-       private String application;
+       private String applicationUrl;
        private String hash;
-
-       abstract public Launcher getLauncher();
        
+       public LauncherMain() {
+               this.launcher = createLauncher();
+               this.log = launcher.log;
+       }
+       abstract public Launcher createLauncher();
        
        void init(String[] args){
                for(String s: args){
                        String[] k_v = s.split("=");
                        String k = k_v[0];
                        String v = k_v[1];
-                       if("application".equals(k)){
-                               this.application = v;
+                       if("application_url".equals(k)){
+                               this.applicationUrl = v;
                        }else if("hash".equals(k)){
                                this.hash = v;
                        }
@@ -37,49 +49,71 @@
        }
 
        public void run(String[] args) throws Exception{
-               getLauncher().initSplash();
-               
-               File confFile = new File("conf");
-               if(confFile.isFile()){
-                       String[] conf = 
IOUtil.fileToString(confFile).split("/n");
-                       init(conf);
-               }else{
-                       warn("conf file does not exist");
+               try{
+                       launcher.initSplash();
+                       
+                       File confFile = new File("conf");
+                       if(confFile.isFile()){
+                               String[] conf = 
IOUtil.fileToString(confFile).split("/n");
+                               init(conf);
+                       }else{
+                               log.warn("conf file does not exist");
+                       }
+                       
+                       init(args);
+                       if(applicationUrl==null){
+                               log.error("'application' not specified (in conf 
or args)");
+                               System.exit(1);
+                       }
+                       
+                       checkVersion();
+                       fetchArgs();
+                       launcher.initDotVexi();
+                       launcher.go();          
+        } catch (Problem e) {
+            log.error(e.getMessage());
+        } catch (Throwable e) {
+               log.error("Unexpected problem");
+            log.error(e);
                }
                
-               init(args);
-               if(application==null){
-                       error("'application' not specified (in conf or args)");
-                       System.exit(1);
-               }
-               
-               checkVersion();
-               fetchArgs();
-               getLauncher().initDotVexi();
-               getLauncher().go();
-
        }
        
        
-       String readString(String path) throws Exception{
-               return IOUtil.readerToString(new 
InputStreamReader(getLauncher().getInputStream(path), "UTF8"));
+       String readString(String url) throws Exception{
+               try{
+                       final URLConnection uc = launcher.connect(url);
+                       if(uc instanceof HttpURLConnection){
+                               HttpURLConnection huc = (HttpURLConnection)uc;
+                               
if(HttpURLConnection.HTTP_OK!=huc.getResponseCode()){
+                                       throw new Problem("Could not read 
"+url+"\nHttp Code '"+huc.getResponseCode()+"'");
+                               }
+                               String contentType = huc.getContentType();
+                               if(!contentType.contains("text/plain")){
+                                       throw new Problem("Could not read 
"+url+"\nInvalid content type '"+contentType+"'");
+                               }
+                       }
+               return IOUtil.readerToString(new 
InputStreamReader(uc.getInputStream(), "UTF8"));
+               }catch (ConnectException e) {
+               throw new Problem("Unable to connect: "+e.getMessage());
+        }
        }
        
        void checkVersion() throws Exception{
-               String hashes = readString(application+"/launcherversions");
+               String hashes = readString(applicationUrl+"/launcherversions");
                if(hash==null){
-                       warn("no version check");
+                       log.warn("no version check");
                }else{
                        for(String hash: hashes.split("\n")){
                                if(this.hash.equals(hash)){
                                        return;
                                }
                        }
-                       log("** Launcher incompatible, please download new 
version **");
-                       log("our hash: "+hash);
-                       log("allowed: ");
+                       log.error("** Launcher incompatible, please download 
new version **");
+                       log.log("our hash: "+hash);
+                       log.log("allowed: ");
                        for(String hash: hashes.split("\n")){
-                               log("   "+hash);
+                               log.log("   "+hash);
                        }
                        System.exit(0);
                }
@@ -87,7 +121,7 @@
        
        void fetchArgs() throws Exception{
                params = new LinkedHashMap();
-               String args = readString(application+"/launcherargs");
+               String args = readString(applicationUrl+"/launcher/args");
                String[] argArr = args.split("\n");
                for(String s: argArr){
                        if("".equals(s.trim())) continue;
@@ -96,18 +130,17 @@
                        if(k_v.length==2){
                                params.put(k_v[0], k_v[1]);
                        }else{
-                               warn("invalid arg: "+s);
+                               log.warn("invalid arg: "+s);
                        }
                }               
        }
 
-       public void flush() { System.err.flush(); }
-       public void log(String msg) { System.err.println(msg); }
-       public void warn(String msg) { log("[WARNING]: "+msg); }
-       public void error(String msg) { log("[ERROR]: "+msg); }
-       public void updateStatus(String msg) { log(msg); }
+       public void updateError(String msg) {}
+       public void updateStatus(String msg) {  }
 
        public String getParameter(String key) { return params.get(key); }
        
-       public void check() throws Problem {}   
+       public void check() throws Problem {}
+       
+    public void exited(){ System.exit(0); }
 }

Added: trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Log.java
===================================================================
--- trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Log.java            
                (rev 0)
+++ trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Log.java    
2013-12-19 23:55:02 UTC (rev 4618)
@@ -0,0 +1,89 @@
+package org.vexi.launcher;
+
+import java.awt.BorderLayout;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+import org.vexi.launcher.Launcher.Context;
+
+
+public class Log {
+       final Context context;
+       private List<String> log = new ArrayList();
+       private JTextArea text;
+       
+       Log(Context context){
+               this.context = context;
+       }
+       
+       public void flush(){
+               System.err.flush();
+       }
+       
+       public void status(String msg){
+               log(msg);
+               if(context!=null) context.updateStatus(msg);
+       }
+       
+       public void log(String msg){
+               if(text!=null){
+                       text.append(msg);
+                       text.append("\n");
+               }else{
+                       if(log.size()>1000){
+                               log.remove(0);
+                       }
+                       log.add(msg);
+               }
+               System.err.println(msg);
+       }
+       public void warn(String msg){ log("[WARNING] "+msg); }
+       public void error(String msg){ 
+               log("[ERROR] "+msg); 
+               if(context!=null) context.updateError(msg);
+               if(text==null){
+                       text = new JTextArea();
+               text.setLineWrap(true);
+               text.setWrapStyleWord(true);
+               for(String s: log){
+                       text.append(s);
+                       text.append("\n");
+               }
+               text.setBounds(5, 35, 385, 330);
+               JScrollPane scroll = new JScrollPane(text);
+               JPanel panel = new JPanel(null);           
+               panel.setLayout(new BorderLayout()); 
+               panel.add(scroll, BorderLayout.CENTER); 
+
+                       JFrame frame = new JFrame();
+               frame.setSize(400,400);
+               
+               frame.setLocation(0,0);
+               frame.setTitle("Launcher Log");           
+               frame.add(panel);
+               frame.setVisible(true);
+                       
+            frame.addWindowListener( new WindowAdapter() {
+                public void windowClosing(WindowEvent we) {
+                    context.exited();
+                }
+            } );
+               }       
+       }
+       public void error(Throwable e) {
+               StringWriter sw = new StringWriter();
+               PrintWriter pw = new PrintWriter(sw);
+               e.printStackTrace(pw);
+               pw.flush();
+               log(sw.toString());
+       }
+}
\ No newline at end of file


Property changes on: 
trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Log.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Splash.java
===================================================================
--- trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Splash.java 
2013-12-19 22:33:44 UTC (rev 4617)
+++ trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/Splash.java 
2013-12-19 23:55:02 UTC (rev 4618)
@@ -15,8 +15,6 @@
 import java.io.IOException;
 import java.net.URL;
 
-import org.vexi.launcher.Launcher.Context;
-
 /**
  * 
  * @author Mike Goodwin
@@ -31,24 +29,24 @@
     static private SplashWindow initFallback() {
         return new Fallback();
     }
-    static private SplashWindow initFast(Context context) {
+    static private SplashWindow initFast(Log log) {
         SplashScreen splash = SplashScreen.getSplashScreen();
         if (splash==null) {
-            context.warn("could not find fast splash screen, using old style");
+            log.warn("could not find fast splash screen, using old style");
             return initFallback();
         } else {
             return new Fast(splash); 
         }
     }
 
-    static public SplashWindow init(Context context, String version, URL 
splashImage, Color textcolor, Color bordercolor, Color barcolor) {
+    static public SplashWindow init(Log log, String version, URL splashImage, 
Color textcolor, Color bordercolor, Color barcolor) {
         Splash.version = version;
         Splash.textcolor = textcolor;
         Splash.bordercolor = bordercolor;
         Splash.barcolor = barcolor;
         try {
             Splash.class.getClassLoader().loadClass("java.awt.SplashScreen");
-            instance = initFast(context);
+            instance = initFast(log);
         } catch (ClassNotFoundException e) {
             instance = initFallback();
         }

Modified: 
trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/util/StreamReader.java
===================================================================
--- 
trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/util/StreamReader.java  
    2013-12-19 22:33:44 UTC (rev 4617)
+++ 
trunk/org.vexi-launcher/src/main/java/org/vexi/launcher/util/StreamReader.java  
    2013-12-19 23:55:02 UTC (rev 4618)
@@ -5,7 +5,7 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 
-import org.vexi.launcher.Launcher.Context;
+import org.vexi.launcher.Log;
 import org.vexi.launcher.Splash;
 
 /**
@@ -15,12 +15,12 @@
  * http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
  */
 public class StreamReader extends Thread {
-       final Context feedback;
+       final Log log;
     final InputStream is;
     final String type;
     
-    public StreamReader(Context feedback, InputStream is, String type, boolean 
listenDisplay) {
-       this.feedback = feedback;
+    public StreamReader(Log log, InputStream is, String type, boolean 
listenDisplay) {
+       this.log = log;
         this.is = is;
         this.type = type;
         this.listenDisplay = listenDisplay;
@@ -36,10 +36,10 @@
                 if (listenDisplay && line.contains("**display launched**")) {
                     Splash.close();
                 }
-                feedback.log(type + ">" + line);
+                log.log(type + ">" + line);
             }
         } catch (IOException ioe) {
-            ioe.printStackTrace();
+            log.error(ioe);
         }
     }
 }
\ No newline at end of file

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Vexi-svn mailing list
Vexi-svn@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vexi-svn

Reply via email to