Using dynamic grizzly http server to let @OnReceive tests succeed classloader
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 24 Jun 2013 16:51:38 +0200
branchclassloader
changeset 148669d777afc3a
parent 147 2f6a718b2631
child 149 8b1e8f243bc9
Using dynamic grizzly http server to let @OnReceive tests succeed
boot/src/main/java/net/java/html/boot/BrowserBuilder.java
ko-fx/pom.xml
ko-fx/src/test/java/org/apidesign/html/kofx/DynamicHTTP.java
ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java
     1.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Mon Jun 24 16:51:33 2013 +0200
     1.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Mon Jun 24 16:51:38 2013 +0200
     1.3 @@ -21,6 +21,7 @@
     1.4  package net.java.html.boot;
     1.5  
     1.6  import java.io.IOException;
     1.7 +import java.net.MalformedURLException;
     1.8  import java.net.URL;
     1.9  import java.util.Collection;
    1.10  import java.util.Enumeration;
    1.11 @@ -61,9 +62,22 @@
    1.12          }
    1.13          
    1.14          FImpl impl = new FImpl(clazz.getClassLoader());
    1.15 -        URL url = clazz.getResource(resource);
    1.16 +        URL url = null;
    1.17 +        MalformedURLException mal = null;
    1.18 +        try {
    1.19 +            url = new URL(resource);
    1.20 +        } catch (MalformedURLException ex) {
    1.21 +            mal = ex;
    1.22 +        }
    1.23          if (url == null) {
    1.24 -            throw new IllegalStateException("Can't find resouce: " + resource + " relative to " + clazz);
    1.25 +            url = clazz.getResource(resource);
    1.26 +        }
    1.27 +        if (url == null) {
    1.28 +            IllegalStateException ise = new IllegalStateException("Can't find resouce: " + resource + " relative to " + clazz);
    1.29 +            if (mal != null) {
    1.30 +                ise.initCause(mal);
    1.31 +            }
    1.32 +            throw ise;
    1.33          }
    1.34  
    1.35          for (Fn.Presenter dfnr : ServiceLoader.load(Fn.Presenter.class)) {
     2.1 --- a/ko-fx/pom.xml	Mon Jun 24 16:51:33 2013 +0200
     2.2 +++ b/ko-fx/pom.xml	Mon Jun 24 16:51:38 2013 +0200
     2.3 @@ -73,5 +73,11 @@
     2.4        <version>${project.version}</version>
     2.5        <scope>test</scope>
     2.6      </dependency>
     2.7 +    <dependency>
     2.8 +      <groupId>org.glassfish.grizzly</groupId>
     2.9 +      <artifactId>grizzly-http-server</artifactId>
    2.10 +      <version>2.3.3</version>
    2.11 +      <scope>test</scope>
    2.12 +    </dependency>
    2.13    </dependencies>
    2.14  </project>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/ko-fx/src/test/java/org/apidesign/html/kofx/DynamicHTTP.java	Mon Jun 24 16:51:38 2013 +0200
     3.3 @@ -0,0 +1,190 @@
     3.4 +/**
     3.5 + * HTML via Java(tm) Language Bindings
     3.6 + * Copyright (C) 2013 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. apidesign.org
    3.16 + * designates this particular file as subject to the
    3.17 + * "Classpath" exception as provided by apidesign.org
    3.18 + * in the License file that accompanied this code.
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License
    3.21 + * along with this program. Look for COPYING file in the top folder.
    3.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    3.23 + */
    3.24 +package org.apidesign.html.kofx;
    3.25 +
    3.26 +import java.io.ByteArrayInputStream;
    3.27 +import java.io.IOException;
    3.28 +import java.io.InputStream;
    3.29 +import java.io.OutputStream;
    3.30 +import java.io.Reader;
    3.31 +import java.net.URI;
    3.32 +import java.net.URISyntaxException;
    3.33 +import java.util.ArrayList;
    3.34 +import java.util.List;
    3.35 +import org.glassfish.grizzly.PortRange;
    3.36 +import org.glassfish.grizzly.http.server.HttpHandler;
    3.37 +import org.glassfish.grizzly.http.server.HttpServer;
    3.38 +import org.glassfish.grizzly.http.server.NetworkListener;
    3.39 +import org.glassfish.grizzly.http.server.Request;
    3.40 +import org.glassfish.grizzly.http.server.Response;
    3.41 +import org.glassfish.grizzly.http.server.ServerConfiguration;
    3.42 +import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
    3.43 +
    3.44 +/**
    3.45 + *
    3.46 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.47 + */
    3.48 +final class DynamicHTTP extends HttpHandler {
    3.49 +    private static int resourcesCount;
    3.50 +    private static List<Resource> resources;
    3.51 +    private static ServerConfiguration conf;
    3.52 +    private static HttpServer server;
    3.53 +    
    3.54 +    private DynamicHTTP() {
    3.55 +    }
    3.56 +    
    3.57 +    static URI initServer() throws Exception {
    3.58 +        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
    3.59 +        resources = new ArrayList<Resource>();
    3.60 +
    3.61 +        conf = server.getServerConfiguration();
    3.62 +        final DynamicHTTP dh = new DynamicHTTP();
    3.63 +
    3.64 +        conf.addHttpHandler(dh, "/");
    3.65 +        
    3.66 +        server.start();
    3.67 +
    3.68 +        return pageURL(server, "/test.html");
    3.69 +    }
    3.70 +    
    3.71 +    @Override
    3.72 +    public void service(Request request, Response response) throws Exception {
    3.73 +        if ("/test.html".equals(request.getRequestURI())) {
    3.74 +            response.setContentType("text/html");
    3.75 +            final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
    3.76 +            copyStream(is, response.getOutputStream(), null);
    3.77 +            return;
    3.78 +        }
    3.79 +        if ("/dynamic".equals(request.getRequestURI())) {
    3.80 +            String mimeType = request.getParameter("mimeType");
    3.81 +            List<String> params = new ArrayList<String>();
    3.82 +            for (int i = 0;; i++) {
    3.83 +                String p = request.getParameter("param" + i);
    3.84 +                if (p == null) {
    3.85 +                    break;
    3.86 +                }
    3.87 +                params.add(p);
    3.88 +            }
    3.89 +            final String cnt = request.getParameter("content");
    3.90 +            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
    3.91 +            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
    3.92 +            URI url = registerResource(new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()])));
    3.93 +            response.getWriter().write(url.toString());
    3.94 +            response.getWriter().write("\n");
    3.95 +            return;
    3.96 +        }
    3.97 +
    3.98 +        for (Resource r : resources) {
    3.99 +            if (r.httpPath.equals(request.getRequestURI())) {
   3.100 +                response.setContentType(r.httpType);
   3.101 +                r.httpContent.reset();
   3.102 +                String[] params = null;
   3.103 +                if (r.parameters.length != 0) {
   3.104 +                    params = new String[r.parameters.length];
   3.105 +                    for (int i = 0; i < r.parameters.length; i++) {
   3.106 +                        params[i] = request.getParameter(r.parameters[i]);
   3.107 +                        if (params[i] == null) {
   3.108 +                            if ("http.method".equals(r.parameters[i])) {
   3.109 +                                params[i] = request.getMethod().toString();
   3.110 +                            } else if ("http.requestBody".equals(r.parameters[i])) {
   3.111 +                                Reader rdr = request.getReader();
   3.112 +                                StringBuilder sb = new StringBuilder();
   3.113 +                                for (;;) {
   3.114 +                                    int ch = rdr.read();
   3.115 +                                    if (ch == -1) {
   3.116 +                                        break;
   3.117 +                                    }
   3.118 +                                    sb.append((char) ch);
   3.119 +                                }
   3.120 +                                params[i] = sb.toString();
   3.121 +                            }
   3.122 +                        }
   3.123 +                        if (params[i] == null) {
   3.124 +                            params[i] = "null";
   3.125 +                        }
   3.126 +                    }
   3.127 +                }
   3.128 +
   3.129 +                copyStream(r.httpContent, response.getOutputStream(), null, params);
   3.130 +            }
   3.131 +        }
   3.132 +    }
   3.133 +
   3.134 +    private URI registerResource(Resource r) {
   3.135 +        if (!resources.contains(r)) {
   3.136 +            resources.add(r);
   3.137 +            conf.addHttpHandler(this, r.httpPath);
   3.138 +        }
   3.139 +        return pageURL(server, r.httpPath);
   3.140 +    }
   3.141 +    
   3.142 +    private static URI pageURL(HttpServer server, final String page) {
   3.143 +        NetworkListener listener = server.getListeners().iterator().next();
   3.144 +        int port = listener.getPort();
   3.145 +        try {
   3.146 +            return new URI("http://localhost:" + port + page);
   3.147 +        } catch (URISyntaxException ex) {
   3.148 +            throw new IllegalStateException(ex);
   3.149 +        }
   3.150 +    }
   3.151 +    
   3.152 +    static final class Resource {
   3.153 +
   3.154 +        final InputStream httpContent;
   3.155 +        final String httpType;
   3.156 +        final String httpPath;
   3.157 +        final String[] parameters;
   3.158 +
   3.159 +        Resource(InputStream httpContent, String httpType, String httpPath,
   3.160 +            String[] parameters) {
   3.161 +            httpContent.mark(Integer.MAX_VALUE);
   3.162 +            this.httpContent = httpContent;
   3.163 +            this.httpType = httpType;
   3.164 +            this.httpPath = httpPath;
   3.165 +            this.parameters = parameters;
   3.166 +        }
   3.167 +    }
   3.168 +
   3.169 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
   3.170 +        for (;;) {
   3.171 +            int ch = is.read();
   3.172 +            if (ch == -1) {
   3.173 +                break;
   3.174 +            }
   3.175 +            if (ch == '$' && params.length > 0) {
   3.176 +                int cnt = is.read() - '0';
   3.177 +                if (baseURL != null && cnt == 'U' - '0') {
   3.178 +                    os.write(baseURL.getBytes("UTF-8"));
   3.179 +                } else {
   3.180 +                    if (cnt >= 0 && cnt < params.length) {
   3.181 +                        os.write(params[cnt].getBytes("UTF-8"));
   3.182 +                    } else {
   3.183 +                        os.write('$');
   3.184 +                        os.write(cnt + '0');
   3.185 +                    }
   3.186 +                }
   3.187 +            } else {
   3.188 +                os.write(ch);
   3.189 +            }
   3.190 +        }
   3.191 +    }
   3.192 +    
   3.193 +}
     4.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java	Mon Jun 24 16:51:33 2013 +0200
     4.2 +++ b/ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java	Mon Jun 24 16:51:38 2013 +0200
     4.3 @@ -23,10 +23,8 @@
     4.4  import java.io.BufferedReader;
     4.5  import java.io.IOException;
     4.6  import java.io.InputStreamReader;
     4.7 -import java.io.PrintWriter;
     4.8  import java.lang.annotation.Annotation;
     4.9  import java.lang.reflect.Method;
    4.10 -import java.net.HttpURLConnection;
    4.11  import java.net.URI;
    4.12  import java.net.URISyntaxException;
    4.13  import java.net.URL;
    4.14 @@ -48,8 +46,6 @@
    4.15  import org.openide.util.lookup.ServiceProvider;
    4.16  import org.testng.annotations.Factory;
    4.17  import static org.testng.Assert.*;
    4.18 -import org.testng.ITest;
    4.19 -import org.testng.annotations.Test;
    4.20  
    4.21  /**
    4.22   *
    4.23 @@ -59,7 +55,7 @@
    4.24  public final class KnockoutFXTest extends KnockoutTCK {
    4.25      public KnockoutFXTest() {
    4.26      }
    4.27 -
    4.28 +    
    4.29      @Factory public static Object[] compatibilityTests() throws Exception {
    4.30          Class[] arr = testClasses();
    4.31          ClassLoader l = KnockoutFXTest.class.getClassLoader();
    4.32 @@ -84,8 +80,10 @@
    4.33          }
    4.34          R r = new R();
    4.35          
    4.36 +        URI uri = DynamicHTTP.initServer();
    4.37 +        
    4.38          final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
    4.39 -            loadPage("test.html").
    4.40 +            loadPage(uri.toString()).
    4.41              onClassReady(r.browserClass).
    4.42              onLoad(r);
    4.43          Executors.newSingleThreadExecutor().submit(new Runnable() {