2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
6 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7 * Other names may be trademarks of their respective owners.
9 * The contents of this file are subject to the terms of either the GNU
10 * General Public License Version 2 only ("GPL") or the Common
11 * Development and Distribution License("CDDL") (collectively, the
12 * "License"). You may not use this file except in compliance with the
13 * License. You can obtain a copy of the License at
14 * http://www.netbeans.org/cddl-gplv2.html
15 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16 * specific language governing permissions and limitations under the
17 * License. When distributing the software, include this License Header
18 * Notice in each file and include the License file at
19 * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
20 * particular file as subject to the "Classpath" exception as provided
21 * by Oracle in the GPL Version 2 section of the License file that
22 * accompanied this code. If applicable, add the following below the
23 * License Header, with the fields enclosed by brackets [] replaced by
24 * your own identifying information:
25 * "Portions Copyrighted [year] [name of copyright owner]"
29 * The Original Software is NetBeans. The Initial Developer of the Original
30 * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
32 * If you wish your version of this file to be governed by only the CDDL
33 * or only the GPL Version 2, indicate your decision by adding
34 * "[Contributor] elects to include this software in this distribution
35 * under the [CDDL or GPL Version 2] license." If you do not indicate a
36 * single choice of license, a recipient has the option to distribute
37 * your version of this file under either the CDDL, the GPL Version 2 or
38 * to extend the choice of license to its licensees as provided above.
39 * However, if you add GPL Version 2 code and therefore, elected the GPL
40 * Version 2 license, then the option applies only if the new code is
41 * made subject to such option by the copyright holder.
43 package org.netbeans.html.wstyrus;
45 import java.io.ByteArrayInputStream;
46 import java.io.ByteArrayOutputStream;
47 import java.io.IOException;
48 import java.io.InputStream;
49 import java.io.OutputStream;
50 import java.io.Reader;
52 import java.net.URISyntaxException;
53 import java.util.ArrayList;
54 import java.util.List;
55 import java.util.logging.Level;
56 import java.util.logging.Logger;
57 import org.glassfish.grizzly.PortRange;
58 import org.glassfish.grizzly.http.server.HttpHandler;
59 import org.glassfish.grizzly.http.server.HttpServer;
60 import org.glassfish.grizzly.http.server.NetworkListener;
61 import org.glassfish.grizzly.http.server.Request;
62 import org.glassfish.grizzly.http.server.Response;
63 import org.glassfish.grizzly.http.server.ServerConfiguration;
64 import org.glassfish.grizzly.websockets.WebSocket;
65 import org.glassfish.grizzly.websockets.WebSocketAddOn;
66 import org.glassfish.grizzly.websockets.WebSocketApplication;
67 import org.glassfish.grizzly.websockets.WebSocketEngine;
71 * @author Jaroslav Tulach <jtulach@netbeans.org>
73 final class TyrusDynamicHTTP extends HttpHandler {
74 private static int resourcesCount;
75 private static List<Resource> resources;
76 private static ServerConfiguration conf;
77 private static HttpServer server;
79 private TyrusDynamicHTTP() {
82 static URI initServer() throws Exception {
83 server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
84 final WebSocketAddOn addon = new WebSocketAddOn();
85 for (NetworkListener listener : server.getListeners()) {
86 listener.registerAddOn(addon);
88 resources = new ArrayList<Resource>();
90 conf = server.getServerConfiguration();
91 final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
93 conf.addHttpHandler(dh, "/");
97 return pageURL("http", server, "/test.html");
101 public void service(Request request, Response response) throws Exception {
102 if ("/test.html".equals(request.getRequestURI())) {
103 response.setContentType("text/html");
104 final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
105 copyStream(is, response.getOutputStream(), null);
108 if ("/dynamic".equals(request.getRequestURI())) {
109 String mimeType = request.getParameter("mimeType");
110 List<String> params = new ArrayList<String>();
111 boolean webSocket = false;
112 for (int i = 0;; i++) {
113 String p = request.getParameter("param" + i);
117 if ("protocol:ws".equals(p)) {
123 final String cnt = request.getParameter("content");
124 String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
125 ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
127 final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
129 url = registerWebSocket(res);
131 url = registerResource(res);
133 response.getWriter().write(url.toString());
134 response.getWriter().write("\n");
138 for (Resource r : resources) {
139 if (r.httpPath.equals(request.getRequestURI())) {
140 response.setContentType(r.httpType);
141 r.httpContent.reset();
142 String[] params = null;
143 if (r.parameters.length != 0) {
144 params = new String[r.parameters.length];
145 for (int i = 0; i < r.parameters.length; i++) {
146 params[i] = request.getParameter(r.parameters[i]);
147 if (params[i] == null) {
148 if ("http.method".equals(r.parameters[i])) {
149 params[i] = request.getMethod().toString();
150 } else if ("http.requestBody".equals(r.parameters[i])) {
151 Reader rdr = request.getReader();
152 StringBuilder sb = new StringBuilder();
158 sb.append((char) ch);
160 params[i] = sb.toString();
163 if (params[i] == null) {
169 copyStream(r.httpContent, response.getOutputStream(), null, params);
174 private URI registerWebSocket(Resource r) {
175 WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
176 return pageURL("ws", server, r.httpPath);
179 private URI registerResource(Resource r) {
180 if (!resources.contains(r)) {
182 conf.addHttpHandler(this, r.httpPath);
184 return pageURL("http", server, r.httpPath);
187 private static URI pageURL(String proto, HttpServer server, final String page) {
188 NetworkListener listener = server.getListeners().iterator().next();
189 int port = listener.getPort();
191 return new URI(proto + "://localhost:" + port + page);
192 } catch (URISyntaxException ex) {
193 throw new IllegalStateException(ex);
197 static final class Resource {
199 final InputStream httpContent;
200 final String httpType;
201 final String httpPath;
202 final String[] parameters;
204 Resource(InputStream httpContent, String httpType, String httpPath,
205 String[] parameters) {
206 httpContent.mark(Integer.MAX_VALUE);
207 this.httpContent = httpContent;
208 this.httpType = httpType;
209 this.httpPath = httpPath;
210 this.parameters = parameters;
214 static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
220 if (ch == '$' && params.length > 0) {
221 int cnt = is.read() - '0';
222 if (baseURL != null && cnt == 'U' - '0') {
223 os.write(baseURL.getBytes("UTF-8"));
225 if (cnt >= 0 && cnt < params.length) {
226 os.write(params[cnt].getBytes("UTF-8"));
238 private static class WS extends WebSocketApplication {
239 private final Resource r;
241 private WS(Resource r) {
246 public void onMessage(WebSocket socket, String text) {
248 r.httpContent.reset();
249 ByteArrayOutputStream out = new ByteArrayOutputStream();
250 copyStream(r.httpContent, out, null, text);
251 String s = new String(out.toByteArray(), "UTF-8");
253 } catch (IOException ex) {
254 LOG.log(Level.WARNING, null, ex);
257 private static final Logger LOG = Logger.getLogger(WS.class.getName());