Use the new netbeans.inspect property to connect to the IDE
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 15 Sep 2013 18:24:48 +0200
changeset 12831d0e583ac981
parent 1282 8d29792a09c6
child 1284 3fc5a6900ecf
Use the new netbeans.inspect property to connect to the IDE
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXInspect.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/WebDebug.java
     1.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java	Thu Sep 12 14:15:47 2013 +0200
     1.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java	Sun Sep 15 18:24:48 2013 +0200
     1.3 @@ -45,7 +45,7 @@
     1.4      private final ToggleGroup resizeGroup = new ToggleGroup();
     1.5      private final ComboBox<String> comboZoom = new ComboBox<String>();
     1.6      
     1.7 -    BrowserToolbar(WebView webView, Pane container, boolean useFirebug, final WebDebug webDebug) {
     1.8 +    BrowserToolbar(WebView webView, Pane container, boolean useFirebug) {
     1.9          this.webView = webView;
    1.10          this.container = container;
    1.11          
    1.12 @@ -104,19 +104,6 @@
    1.13              });
    1.14              getItems().add(firebug);
    1.15          }
    1.16 -        
    1.17 -        if (webDebug != null) {
    1.18 -            final ToggleButton btnSelMode = new ToggleButton(null, new ImageView(
    1.19 -                    new Image(BrowserToolbar.class.getResourceAsStream("selectionMode.png"))));
    1.20 -            btnSelMode.setTooltip(new Tooltip("Toggle selection mode"));
    1.21 -            btnSelMode.selectedProperty().addListener(new InvalidationListener() {
    1.22 -                @Override
    1.23 -                public void invalidated(Observable o) {
    1.24 -                    toggleSelectionMode(webDebug, btnSelMode.isSelected());
    1.25 -                }
    1.26 -            });
    1.27 -            getItems().add(btnSelMode);
    1.28 -        }
    1.29      }
    1.30  
    1.31      private String zoom( String zoomFactor ) {
    1.32 @@ -181,11 +168,6 @@
    1.33          webView.autosize();
    1.34      }
    1.35  
    1.36 -    private void toggleSelectionMode(WebDebug dbg, boolean selMode) {
    1.37 -        // "inspect"
    1.38 -        dbg.call("{\"message\":\"selection_mode\",\"selectionMode\":" + selMode + "}");
    1.39 -    }
    1.40 -    
    1.41      final void toggleFireBug(boolean enable) {
    1.42          WebEngine eng = webView.getEngine();
    1.43          Object installed = eng.executeScript("window.Firebug");
     2.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java	Thu Sep 12 14:15:47 2013 +0200
     2.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java	Sun Sep 15 18:24:48 2013 +0200
     2.3 @@ -55,8 +55,9 @@
     2.4      @Override
     2.5      public void start(Stage primaryStage) throws Exception {
     2.6          WebView view = new WebView();
     2.7 -        final String nbUserDir = this.getParameters().getNamed().get("userdir"); // NOI18N
     2.8 -        WebController wc = new WebController(view, nbUserDir, getParameters().getUnnamed());
     2.9 +        WebController wc = new WebController(view, getParameters().getUnnamed());
    2.10 +        
    2.11 +        FXInspect.initialize(view.getEngine());
    2.12  
    2.13          final VBox vbox = new VBox();
    2.14          vbox.setAlignment( Pos.CENTER );
    2.15 @@ -73,7 +74,7 @@
    2.16          final boolean showToolbar = "true".equals(this.getParameters().getNamed().get("toolbar")); // NOI18N
    2.17          final boolean useFirebug = "true".equals(this.getParameters().getNamed().get("firebug")); // NOI18N
    2.18          if (showToolbar) {
    2.19 -            final ToolBar toolbar = new BrowserToolbar(view, vbox, useFirebug, wc.dbg);
    2.20 +            final ToolBar toolbar = new BrowserToolbar(view, vbox, useFirebug);
    2.21              root.setTop( toolbar );
    2.22          }
    2.23          root.setCenter(hbox);
    2.24 @@ -90,12 +91,9 @@
    2.25       */
    2.26      private static class WebController {
    2.27          private final JVMBridge bridge;
    2.28 -        private final WebDebug dbg;
    2.29 -        private final String ud;
    2.30  
    2.31 -        public WebController(WebView view, String ud, List<String> params) {
    2.32 +        public WebController(WebView view, List<String> params) {
    2.33              this.bridge = new JVMBridge(view.getEngine());
    2.34 -            this.ud = ud;
    2.35              LOG.log(Level.INFO, "Initializing WebView with {0}", params);
    2.36              final WebEngine eng = view.getEngine();
    2.37              try {
    2.38 @@ -138,15 +136,6 @@
    2.39                      dialogStage.showAndWait();
    2.40                  }
    2.41              });
    2.42 -            WebDebug wd = null;
    2.43 -            try {
    2.44 -                if (ud != null) {
    2.45 -                    wd = WebDebug.create(eng.impl_getDebugger(), ud);
    2.46 -                }
    2.47 -            } catch (Exception ex) {
    2.48 -                LOG.log(Level.WARNING, null, ex);
    2.49 -            }
    2.50 -            this.dbg = wd;
    2.51          }
    2.52  
    2.53          boolean initBck2Brwsr(WebEngine webEngine) {
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXInspect.java	Sun Sep 15 18:24:48 2013 +0200
     3.3 @@ -0,0 +1,112 @@
     3.4 +/**
     3.5 + * Back 2 Browser Bytecode Translator
     3.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program. Look for COPYING file in the top folder.
    3.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    3.20 + */
    3.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
    3.22 +
    3.23 +import com.sun.javafx.scene.web.Debugger;
    3.24 +import java.io.IOException;
    3.25 +import java.io.ObjectInputStream;
    3.26 +import java.io.ObjectOutputStream;
    3.27 +import java.net.InetAddress;
    3.28 +import java.net.Socket;
    3.29 +import java.nio.charset.StandardCharsets;
    3.30 +import java.util.logging.Level;
    3.31 +import java.util.logging.Logger;
    3.32 +import javafx.application.Platform;
    3.33 +import javafx.scene.web.WebEngine;
    3.34 +import javafx.util.Callback;
    3.35 +import org.openide.util.Exceptions;
    3.36 +
    3.37 +/**
    3.38 + *
    3.39 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.40 + */
    3.41 +final class FXInspect implements Runnable {
    3.42 +    private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
    3.43 +    
    3.44 +    
    3.45 +    private final WebEngine engine;
    3.46 +    private final ObjectInputStream input;
    3.47 +    
    3.48 +    private FXInspect(WebEngine engine, int port) throws IOException {
    3.49 +        this.engine = engine;
    3.50 +        
    3.51 +        Socket socket = new Socket(InetAddress.getByName(null), port);
    3.52 +        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
    3.53 +        this.input = new ObjectInputStream(socket.getInputStream());
    3.54 +        initializeDebugger(output);
    3.55 +    }
    3.56 +    
    3.57 +    static boolean initialize(WebEngine engine) {
    3.58 +        final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
    3.59 +        if (inspectPort != -1) {
    3.60 +            try {
    3.61 +                FXInspect inspector = new FXInspect(engine, inspectPort);
    3.62 +                Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
    3.63 +                t.start();
    3.64 +                return true;
    3.65 +            } catch (IOException ex) {
    3.66 +                LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
    3.67 +            }
    3.68 +        }
    3.69 +        return false;
    3.70 +    }
    3.71 +    
    3.72 +    private void initializeDebugger(final ObjectOutputStream output) {
    3.73 +        Platform.runLater(new Runnable() {
    3.74 +            @Override
    3.75 +            public void run() {
    3.76 +                Debugger debugger = engine.impl_getDebugger();
    3.77 +                debugger.setEnabled(true);
    3.78 +                debugger.setMessageCallback(new Callback<String,Void>() {
    3.79 +                    @Override
    3.80 +                    public Void call(String message) {
    3.81 +                        try {
    3.82 +                            byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
    3.83 +                            output.writeInt(bytes.length);
    3.84 +                            output.write(bytes);
    3.85 +                            output.flush();
    3.86 +                        } catch (IOException ioex) {
    3.87 +                            ioex.printStackTrace();
    3.88 +                        }
    3.89 +                        return null;
    3.90 +                    }
    3.91 +                });
    3.92 +            }
    3.93 +        });
    3.94 +    }
    3.95 +
    3.96 +    @Override
    3.97 +    public void run() {
    3.98 +        try {
    3.99 +            while (true) {
   3.100 +                int length = input.readInt();
   3.101 +                byte[] bytes = new byte[length];
   3.102 +                input.readFully(bytes);
   3.103 +                final String message = new String(bytes, StandardCharsets.UTF_8);
   3.104 +                Platform.runLater(new Runnable() {
   3.105 +                    @Override
   3.106 +                    public void run() {
   3.107 +                        engine.impl_getDebugger().sendMessage(message);
   3.108 +                    }
   3.109 +                });
   3.110 +            }
   3.111 +        } catch (IOException ioex) {
   3.112 +            ioex.printStackTrace();
   3.113 +        }
   3.114 +    }
   3.115 +}
     4.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/WebDebug.java	Thu Sep 12 14:15:47 2013 +0200
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,189 +0,0 @@
     4.4 -/**
     4.5 - * Back 2 Browser Bytecode Translator
     4.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.7 - *
     4.8 - * This program is free software: you can redistribute it and/or modify
     4.9 - * it under the terms of the GNU General Public License as published by
    4.10 - * the Free Software Foundation, version 2 of the License.
    4.11 - *
    4.12 - * This program is distributed in the hope that it will be useful,
    4.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 - * GNU General Public License for more details.
    4.16 - *
    4.17 - * You should have received a copy of the GNU General Public License
    4.18 - * along with this program. Look for COPYING file in the top folder.
    4.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
    4.20 - */
    4.21 -package org.apidesign.bck2brwsr.launcher.fximpl;
    4.22 -
    4.23 -import com.sun.javafx.scene.web.Debugger;
    4.24 -import java.io.File;
    4.25 -import java.io.IOException;
    4.26 -import java.io.InputStream;
    4.27 -import java.io.InterruptedIOException;
    4.28 -import java.io.OutputStream;
    4.29 -import java.io.UnsupportedEncodingException;
    4.30 -import java.lang.reflect.Method;
    4.31 -import java.util.concurrent.ArrayBlockingQueue;
    4.32 -import java.util.concurrent.Executors;
    4.33 -import java.util.concurrent.TimeUnit;
    4.34 -import java.util.concurrent.atomic.AtomicReference;
    4.35 -import java.util.logging.Level;
    4.36 -import java.util.logging.Logger;
    4.37 -import javafx.application.Platform;
    4.38 -import javafx.util.Callback;
    4.39 -
    4.40 -/** Simulates WebKit protocol over WebSockets.
    4.41 - *
    4.42 - * @author Jaroslav Tulach
    4.43 - */
    4.44 -abstract class WebDebug extends OutputStream 
    4.45 -implements Callback<String, Void>, Runnable {
    4.46 -    private static final Logger LOG = Logger.getLogger(WebDebug.class.getName());
    4.47 -
    4.48 -    private final Debugger debug;
    4.49 -    private final StringBuilder cmd = new StringBuilder();
    4.50 -    private final ToDbgInputStream toDbg;
    4.51 -    private final String ud;
    4.52 -    
    4.53 -    WebDebug(Debugger debug, String ud) throws Exception {
    4.54 -        this.debug = debug;
    4.55 -        this.ud = ud;
    4.56 -        toDbg = new ToDbgInputStream();
    4.57 -        debug.setEnabled(true);
    4.58 -        debug.setMessageCallback(this);
    4.59 -    }
    4.60 -    
    4.61 -    static WebDebug create(Debugger debug, String ud) throws Exception {
    4.62 -        WebDebug web = new WebDebug(debug, ud) {};
    4.63 -        
    4.64 -        Executors.newFixedThreadPool(1).execute(web);
    4.65 -        
    4.66 -        return web;
    4.67 -    }
    4.68 -
    4.69 -    @Override
    4.70 -    public void run() {
    4.71 -        try {
    4.72 -            String p = System.getProperty("startpage.file");
    4.73 -            File f;
    4.74 -            if (p != null && (f = new File(p)).exists()) {
    4.75 -                String[] args = {"--livehtml", f.getAbsolutePath()};
    4.76 -                File dir = f.getParentFile();
    4.77 -                cliHandler(args, toDbg, this, System.err, dir);
    4.78 -            }
    4.79 -        } catch (Exception ex) {
    4.80 -            LOG.log(Level.SEVERE, null, ex);
    4.81 -        }
    4.82 -    }
    4.83 -
    4.84 -    @Override
    4.85 -    public void close() {
    4.86 -        try {
    4.87 -            toDbg.close();
    4.88 -        } catch (IOException ex) {
    4.89 -            LOG.log(Level.SEVERE, null, ex);
    4.90 -        }
    4.91 -    }
    4.92 -
    4.93 -    @Override
    4.94 -    public Void call(String p) {
    4.95 -        assert p.indexOf('\n') == -1 : "No new line: " + p;
    4.96 -        LOG.log(Level.INFO, "toDbgr: {0}", p);
    4.97 -        toDbg.pushMsg(p);
    4.98 -        return null;
    4.99 -    }
   4.100 -
   4.101 -    @Override
   4.102 -    public void write(int b) throws IOException {
   4.103 -        if (b == '\n') {
   4.104 -            final String msg = cmd.toString();
   4.105 -            Platform.runLater(new Runnable() {
   4.106 -                @Override
   4.107 -                public void run() {
   4.108 -                    LOG.log(Level.INFO, "toView: {0}", msg);
   4.109 -                    debug.sendMessage(msg);
   4.110 -                }
   4.111 -            });
   4.112 -            cmd.setLength(0);
   4.113 -        } else {
   4.114 -            if (cmd.length() > 100000) {
   4.115 -                LOG.log(Level.WARNING, "Too big:\n{0}", cmd);
   4.116 -            }
   4.117 -            cmd.append((char)b);
   4.118 -        }
   4.119 -    }   
   4.120 -
   4.121 -    private void cliHandler(
   4.122 -        String[] args, InputStream is, OutputStream os, OutputStream err, File dir
   4.123 -    ) {
   4.124 -        try {
   4.125 -            Class<?> main = Class.forName("org.netbeans.MainImpl");
   4.126 -            Method m = main.getDeclaredMethod("execute", String[].class, InputStream.class, 
   4.127 -                OutputStream.class, OutputStream.class, AtomicReference.class
   4.128 -            );
   4.129 -            m.setAccessible(true);
   4.130 -            System.setProperty("netbeans.user", ud);
   4.131 -            int ret = (Integer)m.invoke(null, args, is, os, err, null);
   4.132 -            LOG.log(Level.INFO, "Return value: {0}", ret);
   4.133 -        } catch (Exception ex) {
   4.134 -            LOG.log(Level.SEVERE, null, ex);
   4.135 -        } finally {
   4.136 -            LOG.info("Communication is over");
   4.137 -        }
   4.138 -        
   4.139 -    }
   4.140 -
   4.141 -    private class ToDbgInputStream extends InputStream {
   4.142 -        private byte[] current;
   4.143 -        private int currentPos;
   4.144 -        private final ArrayBlockingQueue<byte[]> pending = new ArrayBlockingQueue<byte[]>(64);
   4.145 -
   4.146 -        public ToDbgInputStream() {
   4.147 -        }
   4.148 -
   4.149 -        @Override
   4.150 -        public int read() throws IOException {
   4.151 -            return read(null, 0, 1);
   4.152 -        }
   4.153 -        
   4.154 -        @Override
   4.155 -        public int read(byte[] arr, int offset, int len) throws IOException {
   4.156 -            if (current == null || current.length <= currentPos) {
   4.157 -                for (;;) {
   4.158 -                    WebDebug.this.flush();
   4.159 -                    try {
   4.160 -                        current = pending.poll(5, TimeUnit.MILLISECONDS);
   4.161 -                        if (current == null) {
   4.162 -                            return 0;
   4.163 -                        }
   4.164 -                        break;
   4.165 -                    } catch (InterruptedException ex) {
   4.166 -                        throw (InterruptedIOException)new InterruptedIOException().initCause(ex);
   4.167 -                    }
   4.168 -                }
   4.169 -                LOG.info("Will return: " + new String(current));
   4.170 -                currentPos = 0;
   4.171 -            }
   4.172 -            int cnt = 0;
   4.173 -            while (len-- > 0 && currentPos < current.length) {
   4.174 -                final byte nextByte = current[currentPos++];
   4.175 -                if (arr == null) {
   4.176 -                    return nextByte;
   4.177 -                }
   4.178 -                arr[offset + cnt++] = nextByte;
   4.179 -            }
   4.180 -            LOG.log(Level.INFO, "read returns: {0}", new String(arr, offset, cnt));
   4.181 -            return cnt;
   4.182 -        }
   4.183 -
   4.184 -        private void pushMsg(String p) {
   4.185 -            try {
   4.186 -                pending.offer((p + '\n').getBytes("UTF-8"));
   4.187 -            } catch (UnsupportedEncodingException ex) {
   4.188 -                throw new IllegalStateException(ex);
   4.189 -            }
   4.190 -        }
   4.191 -    }
   4.192 -}