webview javafx urlconnection

Controlador de protocolo personalizado JavaFX WebView



urlconnection (3)

Estoy tratando de escribir mi propio controlador de protocolo para una aplicación JavaFX que usa la vista web para acceder a un único sitio web. Lo que he hecho hasta ahora

Mi URLStreamHandlerFactory personalizada

public class MyURLStreamHandlerFactory implements URLStreamHandlerFactory { public URLStreamHandler createURLStreamHandler(String protocol) { System.out.println("Protocol: " + protocol); if (protocol.equalsIgnoreCase("http") || protocol.equalsIgnoreCase("https")) { return new MyURLStreamHandler(); } else { return new URLStreamHandler() { @Override protected URLConnection openConnection(URL u) throws IOException { return new URLConnection(u) { @Override public void connect() throws IOException { } }; } }; } } }

Mi URLStreamHandler personalizado

public class MyURLStreamHandler extends java.net.URLStreamHandler{ protected HttpURLConnection openConnection(URL u){ MyURLConnection q = new MyURLConnection(u); return q; } }

Mi HttpURLConnection personalizada

public class MyURLConnection extends HttpURLConnection { static int defaultPort = 443; InputStream in; OutputStream out; Socket s; publicMyURLConnection(URL url) { super(url); try { setRequestMethod("POST"); } catch (ProtocolException ex) { ex.printStackTrace(); } } public void setRequestProperty(String name, String value){ super.setRequestProperty(name, value); System.out.println("Namee: " + name); System.out.println("Value: " + value); } public String getRequestProperty(String name){ System.out.println("GET REQUEST: "); return super.getRequestProperty(name); } public OutputStream getOutputStream() throws IOException { OutputStream os = super.getOutputStream(); System.out.println("Output: " + os); return os; } public InputStream getInputStream() throws IOException { InputStream is = super.getInputStream(); System.out.println("INout stream: " + is); return is; } @Override public void connect() throws IOException { } @Override public void disconnect() { throw new UnsupportedOperationException("Not supported yet."); } @Override public boolean usingProxy() { throw new UnsupportedOperationException("Not supported yet."); }

Cuando ejecuto la aplicación, obtengo el siguiente error aunque parece establecer algunos encabezados

Jul 08, 2013 11:09:04 AM com.sun.webpane.webkit.network.URLLoader doRun WARNING: Unexpected error java.net.UnknownServiceException: protocol doesn''t support input at java.net.URLConnection.getInputStream(URLConnection.java:839) at qmed.QMedURLConnection.getInputStream(MyURLConnection.java:67) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468) at com.sun.webpane.webkit.network.URLLoader.receiveResponse(URLLoader.java:383) at com.sun.webpane.webkit.network.URLLoader.doRun(URLLoader.java:142) at com.sun.webpane.webkit.network.URLLoader.access$000(URLLoader.java:44) at com.sun.webpane.webkit.network.URLLoader$1.run(URLLoader.java:106) at com.sun.webpane.webkit.network.URLLoader$1.run(URLLoader.java:103) at java.security.AccessController.doPrivileged(Native Method) at com.sun.webpane.webkit.network.URLLoader.run(URLLoader.java:103) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724)

Todo lo que quiero hacer es recuperar la respuesta para una solicitud dada y leer sus datos binarios. Quiero que el protocolo se comporte exactamente de la misma manera que el predeterminado y solo verifique los datos binarios de una respuesta determinada. ¿Qué estoy haciendo mal?

La aplicación está haciendo todos los cortos de URLConnections. ¿Es correcto utilizar una HTTPURLConnection como mi clase URLConnection personalizada cuando el protocolo es http o https e iniciar un URLStreamHandler predeterminado cuando se usan otros protocolos como lo hago en MyURLStreamHandlerFactory? ¿Debo simplemente extender la clase URLConnection predeterminada en MYURLConnection para manejar todos los protocolos de la misma manera?

Cualquier ayuda sería muy apreciada, ya que este es un problema que amenaza el proyecto

Gracias


Al activar el Registro y seguimiento en el Panel de control de Java, su Consola Java imprimirá todos los intentos y las llamadas de red ejecutadas, incluidas las de WebView.

Puede ver todas las llamadas HTTP y HTTPS y su código de retorno + datos de cookies. También puede ver otras conexiones de protocolo, pero probablemente no los datos enviados sobre ellos.

Esto se aplica a Applets en un navegador. Si necesita esto en un contexto diferente, tal vez haya una forma de activar las mismas opciones pasando parámetros de línea de comando.


Esto no está directamente relacionado con la pregunta formulada, pero podría hacer que la pregunta en sí sea obsoleta.

Con Java SE 6 Update 10, los applets de Java admiten el acceso a recursos en cualquier dominio y puerto que esté configurado correctamente con crossdomain.xml .

Con esto, la razón para registrar su propio protocolo puede quedar obsoleta, ya que puede acceder a todos los recursos que necesita.

Otra idea es: si está intentando crear un tipo de sniffer de red, ¿por qué no utilizar directamente un programa de analizador / sniffer de red diseñado para esa tarea?


Puede ser que lo único que te falta es un setDoInput(true) o anular getDoInput() y devolver verdadero (eso es lo que hice).

Si eso no ayuda a verificar mi solución de trabajo:

MyURLStreamHandlerFactory:

import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; public class MyURLStreamHandlerFactory implements URLStreamHandlerFactory { public URLStreamHandler createURLStreamHandler(String protocol) { if (protocol.equals("myapp")) { return new MyURLHandler(); } return null; } }

Registrar fábrica:

URL.setURLStreamHandlerFactory(new MyURLStreamHandlerFactory());

MyURLHandler:

import java.io.IOException; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; public class MyURLHandler extends URLStreamHandler { @Override protected URLConnection openConnection(URL url) throws IOException { return new MyURLConnection(url); } }

MyURLConnection:

import java.io.*; import java.net.SocketTimeoutException; import java.net.URL; import java.net.URLConnection; /** * Register a protocol handler for URLs like this: <code>myapp:///pics/sland.gif</code><br> */ public class MyURLConnection extends URLConnection { private byte[] data; @Override public void connect() throws IOException { if (connected) { return; } loadImage(); connected = true; } public String getHeaderField(String name) { if ("Content-Type".equalsIgnoreCase(name)) { return getContentType(); } else if ("Content-Length".equalsIgnoreCase(name)) { return "" + getContentLength(); } return null; } public String getContentType() { String fileName = getURL().getFile(); String ext = fileName.substring(fileName.lastIndexOf(''.'')); return "image/" + ext; // TODO: switch based on file-type } public int getContentLength() { return data.length; } public long getContentLengthLong() { return data.length; } public boolean getDoInput() { return true; } public InputStream getInputStream() throws IOException { connect(); return new ByteArrayInputStream(data); } private void loadImage() throws IOException { if (data != null) { return; } try { int timeout = this.getConnectTimeout(); long start = System.currentTimeMillis(); URL url = getURL(); String imgPath = url.toExternalForm(); imgPath = imgPath.startsWith("myapp://") ? imgPath.substring("myapp://".length()) : imgPath.substring("myapp:".length()); // attention: triple ''/'' is reduced to a single ''/'' // this is my own asynchronous image implementation // instead of this part (including the following loop) you could do your own (synchronous) loading logic MyImage img = MyApp.getImage(imgPath); do { if (img.isFailed()) { throw new IOException("Could not load image: " + getURL()); } else if (!img.hasData()) { long now = System.currentTimeMillis(); if (now - start > timeout) { throw new SocketTimeoutException(); } Thread.sleep(100); } } while (!img.hasData()); data = img.getData(); } catch (InterruptedException e) { e.printStackTrace(); } } public OutputStream getOutputStream() throws IOException { // this might be unnecessary - the whole method can probably be omitted for our purposes return new ByteArrayOutputStream(); } public java.security.Permission getPermission() throws IOException { return null; // we need no permissions to access this URL } }

Algunas partes de MyURLConnection pueden no ser necesarias para que funcione, pero así funciona para mí.

Uso en JavaFX WebView:

<img src="myapp:///pics/image.png"/>

Nota sobre permisos:

Usé un applet con AllPermissions para mi prueba con el código anterior.

En Sandbox -Applet esto no funcionará, ya que setFactory permiso setFactory .