2 * Back 2 Browser Bytecode Translator
3 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. Look for COPYING file in the top folder.
16 * If not, see http://opensource.org/licenses/GPL-2.0.
18 package org.apidesign.bck2brwsr.launcher.fximpl;
20 import com.sun.javafx.scene.web.Debugger;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.InterruptedIOException;
25 import java.io.OutputStream;
26 import java.io.UnsupportedEncodingException;
27 import java.lang.reflect.Method;
28 import java.util.concurrent.ArrayBlockingQueue;
29 import java.util.concurrent.Executors;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.atomic.AtomicReference;
32 import java.util.logging.Level;
33 import java.util.logging.Logger;
34 import javafx.application.Platform;
35 import javafx.util.Callback;
37 /** Simulates WebKit protocol over WebSockets.
39 * @author Jaroslav Tulach
41 abstract class WebDebug extends OutputStream
42 implements Callback<String, Void>, Runnable {
43 private static final Logger LOG = Logger.getLogger(WebDebug.class.getName());
45 private final Debugger debug;
46 private final StringBuilder cmd = new StringBuilder();
47 private final ToDbgInputStream toDbg;
48 private final String ud;
50 WebDebug(Debugger debug, String ud) throws Exception {
53 toDbg = new ToDbgInputStream();
54 debug.setEnabled(true);
55 debug.setMessageCallback(this);
58 static WebDebug create(Debugger debug, String ud) throws Exception {
59 WebDebug web = new WebDebug(debug, ud) {};
61 Executors.newFixedThreadPool(1).execute(web);
69 String p = "/home/jarda/src/bck2brwsr/html~demo/twitter/src/main/resources/org/apidesign/html/demo/twitter/index.html";
71 String[] args = {"--livehtml", f.getAbsolutePath()};
72 File dir = f.getParentFile();
73 cliHandler(args, toDbg, this, System.err, dir);
74 } catch (Exception ex) {
75 LOG.log(Level.SEVERE, null, ex);
83 } catch (IOException ex) {
84 LOG.log(Level.SEVERE, null, ex);
89 public Void call(String p) {
90 assert p.indexOf('\n') == -1 : "No new line: " + p;
91 LOG.log(Level.INFO, "toDbgr: {0}", p);
97 public void write(int b) throws IOException {
99 final String msg = cmd.toString();
100 Platform.runLater(new Runnable() {
103 LOG.log(Level.INFO, "toView: {0}", msg);
104 debug.sendMessage(msg);
109 if (cmd.length() > 100000) {
110 LOG.log(Level.WARNING, "Too big:\n{0}", cmd);
116 private void cliHandler(
117 String[] args, InputStream is, OutputStream os, OutputStream err, File dir
120 Class<?> main = Class.forName("org.netbeans.MainImpl");
121 Method m = main.getDeclaredMethod("execute", String[].class, InputStream.class,
122 OutputStream.class, OutputStream.class, AtomicReference.class
124 m.setAccessible(true);
125 System.setProperty("netbeans.user", ud);
126 int ret = (Integer)m.invoke(null, args, is, os, err, null);
127 LOG.log(Level.INFO, "Return value: {0}", ret);
128 } catch (Exception ex) {
129 LOG.log(Level.SEVERE, null, ex);
131 LOG.info("Communication is over");
136 private class ToDbgInputStream extends InputStream {
137 private byte[] current;
138 private int currentPos;
139 private final ArrayBlockingQueue<byte[]> pending = new ArrayBlockingQueue<byte[]>(64);
141 public ToDbgInputStream() {
145 public int read() throws IOException {
146 return read(null, 0, 1);
150 public int read(byte[] arr, int offset, int len) throws IOException {
151 if (current == null || current.length <= currentPos) {
153 WebDebug.this.flush();
155 current = pending.poll(100, TimeUnit.MILLISECONDS);
156 if (current == null) {
160 } catch (InterruptedException ex) {
161 throw (InterruptedIOException)new InterruptedIOException().initCause(ex);
164 LOG.info("Will return: " + new String(current));
168 while (len-- > 0 && currentPos < current.length) {
169 final byte nextByte = current[currentPos++];
173 arr[offset + cnt++] = nextByte;
175 LOG.log(Level.INFO, "read returns: {0}", new String(arr, offset, cnt));
179 private void pushMsg(String p) {
181 pending.offer((p + '\n').getBytes("UTF-8"));
182 } catch (UnsupportedEncodingException ex) {
183 throw new IllegalStateException(ex);