2013-07-08 3 views
4

Я пытаюсь написать собственный обработчик протокола для приложения JavaFX, которое использует веб-просмотр для доступа к одному веб-сайту. То, что я сделал до сих порПользовательский обработчик протокола JavaFX WebView

Мой заказ URLStreamHandlerFactory

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 { 
         } 
        }; 
       } 
      }; 
     } 
    } 
} 

Мой заказ URLStreamHandler

public class MyURLStreamHandler extends java.net.URLStreamHandler{ 

    protected HttpURLConnection openConnection(URL u){ 
     MyURLConnection q = new MyURLConnection(u); 
     return q; 
    }  
} 

Мой заказ HttpURLConnection

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."); 
    } 

При запуске приложения я получаю следующее сообщение об ошибке althouhg кажется, что некоторые заголовки

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) 

Все, что я хочу сделать, это получить ответ назад для данного запроса и прочитать его двоичные данные. Я хочу, чтобы протокол вел себя точно так же, как и по умолчанию, и проверял только двоичные данные данного респондента. Что я делаю не так?

Приложение делает все шорты URLConnections. Правильно ли использовать HTTPURLConnection в качестве моего настраиваемого класса URLConnection, когда протокол является http или https, и запускать URL-адрес URLStreamHandler по умолчанию, когда используются другие протоколы, как я делаю в MyURLStreamHandlerFactory? Должен ли я просто расширить класс URLConnection по умолчанию в MYURLConnection, чтобы обрабатывать все протоколы одинаково?

Любая помощь будет высоко ценится, как это проект угрожающим проблема

Спасибо

ответ

3

Это может быть все, что вам не хватает является setDoInput(true) или переопределить getDoInput() и возвращает истину (это то, что я сделал) ,

Если это не поможет проверить мое рабочее решение:

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; 
    } 

} 

Регистрация Фабрика:

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 
    } 

} 

Некоторые части MyURLConnection не могут быть необходимы для того, чтобы работать, но, как это работает для меня.

Использование в JavaFX WebView:

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

Примечание о разрешениях:

Я использовал апплет с AllPermissions для моего теста с вышеприведенным кодом.

В Песочница -В дополнение это не будет работать, так как отсутствует разрешение setFactory.

+0

Отличный ответ. Пока я нашел его ближайшим к моим потребностям. Но я хочу захватить все протоколы. HTTP, HTTPS, file: // так же, как мы можем видеть все запросы в консоли разработчика. –

+0

Что вы пытаетесь достичь с этим? Возможно, инструмент сетевого анализатора/анализатора сделает то, что вы хотите. –

+0

Еще одна вещь, которая может помочь, - использовать FirebugLite: '' - вставьте этот код в вашу страницу WebView, и вы можете отлаживать страницу в WebView. К сожалению, FBLite не имеет сетевой вкладки. –

-1

Это не связано непосредственно с вопросом, но может сделать сам вопрос устаревшим.

С Java SE 6 Обновление 10 Поддержка Java-апплетов для доступа к ресурсам в любом домене и порту, который правильно настроен с crossdomain.xml.

С учетом этого причина регистрации собственного протокола может стать устаревшей, поскольку вы можете получить доступ ко всем имеющимся ресурсам.

Другая идея: если вы пытаетесь создать своего рода сетевой сниффер, почему бы не использовать программу сетевого анализатора/анализатора, предназначенную для такой задачи?

-2

При активации ведения журнала и трассировки на панели управления Java ваша Java-консоль будет печатать все попытки и выполнять сетевые вызовы, в том числе и из WebView.

Вы можете просмотреть все HTTP & HTTPS-вызовы и их данные с возвратом-кодом + файлы cookie. Вы также можете увидеть другие подключения к протоколу, но, вероятно, не передавать никаких данных.

Это относится к апплетам в браузере. Если вам это нужно в другом контексте, возможно, есть способ активировать одни и те же параметры, передав параметры командной строки.