2 * HTML via Java(tm) Language Bindings
3 * Copyright (C) 2013 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. apidesign.org
13 * designates this particular file as subject to the
14 * "Classpath" exception as provided by apidesign.org
15 * in the License file that accompanied this code.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. Look for COPYING file in the top folder.
19 * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
21 package org.apidesign.html.wstyrus;
23 import java.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.io.Reader;
30 import java.net.URISyntaxException;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.logging.Level;
34 import java.util.logging.Logger;
35 import org.glassfish.grizzly.PortRange;
36 import org.glassfish.grizzly.http.server.HttpHandler;
37 import org.glassfish.grizzly.http.server.HttpServer;
38 import org.glassfish.grizzly.http.server.NetworkListener;
39 import org.glassfish.grizzly.http.server.Request;
40 import org.glassfish.grizzly.http.server.Response;
41 import org.glassfish.grizzly.http.server.ServerConfiguration;
42 import org.glassfish.grizzly.websockets.WebSocket;
43 import org.glassfish.grizzly.websockets.WebSocketAddOn;
44 import org.glassfish.grizzly.websockets.WebSocketApplication;
45 import org.glassfish.grizzly.websockets.WebSocketEngine;
49 * @author Jaroslav Tulach <jtulach@netbeans.org>
51 final class TyrusDynamicHTTP extends HttpHandler {
52 private static int resourcesCount;
53 private static List<Resource> resources;
54 private static ServerConfiguration conf;
55 private static HttpServer server;
57 private TyrusDynamicHTTP() {
60 static URI initServer() throws Exception {
61 server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
62 final WebSocketAddOn addon = new WebSocketAddOn();
63 for (NetworkListener listener : server.getListeners()) {
64 listener.registerAddOn(addon);
66 resources = new ArrayList<Resource>();
68 conf = server.getServerConfiguration();
69 final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
71 conf.addHttpHandler(dh, "/");
75 return pageURL("http", server, "/test.html");
79 public void service(Request request, Response response) throws Exception {
80 if ("/test.html".equals(request.getRequestURI())) {
81 response.setContentType("text/html");
82 final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
83 copyStream(is, response.getOutputStream(), null);
86 if ("/dynamic".equals(request.getRequestURI())) {
87 String mimeType = request.getParameter("mimeType");
88 List<String> params = new ArrayList<String>();
89 boolean webSocket = false;
90 for (int i = 0;; i++) {
91 String p = request.getParameter("param" + i);
95 if ("protocol:ws".equals(p)) {
101 final String cnt = request.getParameter("content");
102 String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
103 ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
105 final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
107 url = registerWebSocket(res);
109 url = registerResource(res);
111 response.getWriter().write(url.toString());
112 response.getWriter().write("\n");
116 for (Resource r : resources) {
117 if (r.httpPath.equals(request.getRequestURI())) {
118 response.setContentType(r.httpType);
119 r.httpContent.reset();
120 String[] params = null;
121 if (r.parameters.length != 0) {
122 params = new String[r.parameters.length];
123 for (int i = 0; i < r.parameters.length; i++) {
124 params[i] = request.getParameter(r.parameters[i]);
125 if (params[i] == null) {
126 if ("http.method".equals(r.parameters[i])) {
127 params[i] = request.getMethod().toString();
128 } else if ("http.requestBody".equals(r.parameters[i])) {
129 Reader rdr = request.getReader();
130 StringBuilder sb = new StringBuilder();
136 sb.append((char) ch);
138 params[i] = sb.toString();
141 if (params[i] == null) {
147 copyStream(r.httpContent, response.getOutputStream(), null, params);
152 private URI registerWebSocket(Resource r) {
153 WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
154 return pageURL("ws", server, r.httpPath);
157 private URI registerResource(Resource r) {
158 if (!resources.contains(r)) {
160 conf.addHttpHandler(this, r.httpPath);
162 return pageURL("http", server, r.httpPath);
165 private static URI pageURL(String proto, HttpServer server, final String page) {
166 NetworkListener listener = server.getListeners().iterator().next();
167 int port = listener.getPort();
169 return new URI(proto + "://localhost:" + port + page);
170 } catch (URISyntaxException ex) {
171 throw new IllegalStateException(ex);
175 static final class Resource {
177 final InputStream httpContent;
178 final String httpType;
179 final String httpPath;
180 final String[] parameters;
182 Resource(InputStream httpContent, String httpType, String httpPath,
183 String[] parameters) {
184 httpContent.mark(Integer.MAX_VALUE);
185 this.httpContent = httpContent;
186 this.httpType = httpType;
187 this.httpPath = httpPath;
188 this.parameters = parameters;
192 static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
198 if (ch == '$' && params.length > 0) {
199 int cnt = is.read() - '0';
200 if (baseURL != null && cnt == 'U' - '0') {
201 os.write(baseURL.getBytes("UTF-8"));
203 if (cnt >= 0 && cnt < params.length) {
204 os.write(params[cnt].getBytes("UTF-8"));
216 private static class WS extends WebSocketApplication {
217 private final Resource r;
219 private WS(Resource r) {
224 public void onMessage(WebSocket socket, String text) {
226 r.httpContent.reset();
227 ByteArrayOutputStream out = new ByteArrayOutputStream();
228 copyStream(r.httpContent, out, null, text);
229 String s = new String(out.toByteArray(), "UTF-8");
231 } catch (IOException ex) {
232 LOG.log(Level.WARNING, null, ex);
235 private static final Logger LOG = Logger.getLogger(WS.class.getName());