You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ay...@apache.org on 2014/03/10 16:50:39 UTC
[1/2] refactor websocket (CXF-5339) into a seprate transport component
Repository: cxf
Updated Branches:
refs/heads/master c9c443054 -> 8fe4fc13a
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocket.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocket.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocket.java
new file mode 100644
index 0000000..92c6525
--- /dev/null
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocket.java
@@ -0,0 +1,1111 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.websocket.jetty;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.helpers.CastUtils;
+import org.eclipse.jetty.websocket.WebSocket;
+
+class JettyWebSocket implements WebSocket.OnBinaryMessage, WebSocket.OnTextMessage {
+ private static final Logger LOG = LogUtils.getL7dLogger(JettyWebSocket.class);
+ private static final String CRLF = "\r\n";
+
+ private static final String URI_KEY = "$uri";
+ private static final String METHOD_KEY = "$method";
+ private static final String SC_KEY = "$sc";
+ private static final String SM_KEY = "$sm";
+ private static final String FLUSHED_KEY = "$flushed";
+
+ private JettyWebSocketManager manager;
+ private ServletContext servletContext;
+ private Connection webSocketConnection;
+ private Map<String, Object> requestProperties;
+ private String protocol;
+
+ public JettyWebSocket(JettyWebSocketManager manager, HttpServletRequest request, String protocol) {
+ this.manager = manager;
+ this.protocol = protocol;
+ this.requestProperties = readProperties(request);
+ }
+
+ private Map<String, Object> readProperties(HttpServletRequest request) {
+ Map<String, Object> properties = new HashMap<String, Object>();
+ properties.put("servletPath", request.getServletPath());
+ properties.put("requestURI", request.getRequestURI());
+ properties.put("requestURL", request.getRequestURL().toString());
+ properties.put("contextPath", request.getContextPath());
+ properties.put("servletPath", request.getServletPath());
+ properties.put("pathInfo", request.getPathInfo());
+ properties.put("pathTranslated", request.getPathTranslated());
+ properties.put("protocol", request.getProtocol());
+ properties.put("scheme", request.getScheme());
+ // some additional ones
+ properties.put("localAddr", request.getLocalAddr());
+ properties.put("localName", request.getLocalName());
+ properties.put("localPort", request.getLocalPort());
+ properties.put("locale", request.getLocale());
+ properties.put("locales", request.getLocales());
+ properties.put("remoteHost", request.getRemoteHost());
+ properties.put("remoteAddr", request.getRemoteAddr());
+ properties.put("serverName", request.getServerName());
+ properties.put("secure", request.isSecure());
+ properties.put("authType", request.getAuthType());
+ properties.put("dispatcherType", request.getDispatcherType());
+
+ return properties;
+ }
+
+ @Override
+ public void onClose(int closeCode, String message) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "onClose({0}, {1})", new Object[]{closeCode, message});
+ }
+ this.webSocketConnection = null;
+ }
+
+ @Override
+ public void onOpen(Connection connection) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "onOpen({0}))", connection);
+ }
+ this.webSocketConnection = connection;
+ }
+
+ @Override
+ public void onMessage(String data) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "onMessage({0})", data);
+ }
+ try {
+ byte[] bdata = data.getBytes("utf-8");
+ HttpServletRequest request = createServletRequest(bdata, 0, bdata.length);
+ HttpServletResponse response = createServletResponse();
+ if (manager != null) {
+ manager.service(request, response);
+ }
+ } catch (Exception e) {
+ LOG.log(Level.WARNING, "Failed to invoke service", e);
+ }
+ }
+
+ @Override
+ public void onMessage(byte[] data, int offset, int length) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "onMessage({0}, {1}, {2})", new Object[]{data, offset, length});
+ }
+ try {
+ HttpServletRequest request = createServletRequest(data, offset, length);
+ HttpServletResponse response = createServletResponse();
+ if (manager != null) {
+ manager.service(request, response);
+ }
+ } catch (Exception e) {
+ LOG.log(Level.WARNING, "Failed to invoke service", e);
+ }
+ }
+
+ private <T> T getRequestProperty(String name, Class<T> cls) {
+ return getValue(requestProperties, name, cls);
+ }
+
+ private WebSocketVirtualServletRequest createServletRequest(byte[] data, int offset, int length)
+ throws IOException {
+ return new WebSocketVirtualServletRequest(servletContext, this, new ByteArrayInputStream(data, offset, length));
+ }
+
+ private WebSocketVirtualServletResponse createServletResponse() throws IOException {
+ return new WebSocketVirtualServletResponse(this);
+ }
+
+ /**
+ * Writes to the underlining socket.
+ *
+ * @param data
+ * @param offset
+ * @param length
+ */
+ void write(byte[] data, int offset, int length) throws IOException {
+ LOG.log(Level.INFO, "write(byte[], offset, length)");
+ webSocketConnection.sendMessage(data, offset, length);
+ }
+
+ private static byte[] buildResponse(Map<String, String> headers, byte[] data, int offset, int length) {
+ StringBuilder sb = new StringBuilder();
+ String v = headers.get(SC_KEY);
+ sb.append(v == null ? "200" : v).append(CRLF);
+ v = headers.get("Content-Type");
+ if (v != null) {
+ sb.append("Content-Type: ").append(v).append(CRLF);
+ }
+ sb.append(CRLF);
+
+ byte[] hb = sb.toString().getBytes();
+ byte[] longdata = new byte[hb.length + length];
+ System.arraycopy(hb, 0, longdata, 0, hb.length);
+ if (data != null && length > 0) {
+ System.arraycopy(data, offset, longdata, hb.length, length);
+ }
+ return longdata;
+ }
+
+ private static byte[] buildResponse(byte[] data, int offset, int length) {
+ byte[] longdata = new byte[length + 2];
+ longdata[0] = 0x0d;
+ longdata[1] = 0x0a;
+ System.arraycopy(data, offset, longdata, 2, length);
+ return longdata;
+ }
+
+ ServletOutputStream getServletOutputStream(final Map<String, String> headers) {
+ LOG.log(Level.INFO, "getServletOutputStream()");
+ return new ServletOutputStream() {
+
+ @Override
+ public void write(int b) throws IOException {
+ byte[] data = new byte[1];
+ data[0] = (byte)b;
+ write(data, 0, 1);
+ }
+
+ @Override
+ public void write(byte[] data, int offset, int length) throws IOException {
+ if (headers.get(FLUSHED_KEY) == null) {
+ data = buildResponse(headers, data, offset, length);
+ headers.put(FLUSHED_KEY, "true");
+ } else {
+ data = buildResponse(data, offset, length);
+ }
+ webSocketConnection.sendMessage(data, 0, data.length);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (headers.get(FLUSHED_KEY) == null) {
+ byte[] data = buildResponse(headers, null, 0, 0);
+ webSocketConnection.sendMessage(data, 0, data.length);
+ headers.put(FLUSHED_KEY, "true");
+ }
+ super.close();
+ }
+
+ };
+ }
+
+ OutputStream getOutputStream(final Map<String, String> headers) {
+ LOG.log(Level.INFO, "getOutputStream()");
+ return new OutputStream() {
+
+ @Override
+ public void write(int b) throws IOException {
+ byte[] data = new byte[1];
+ data[0] = (byte)b;
+ write(data, 0, 1);
+ }
+
+ @Override
+ public void write(byte[] data, int offset, int length) throws IOException {
+ if (headers.get(FLUSHED_KEY) == null) {
+ data = buildResponse(headers, data, offset, length);
+ headers.put(FLUSHED_KEY, "true");
+ } else {
+ data = buildResponse(data, offset, length);
+ }
+ webSocketConnection.sendMessage(data, 0, data.length);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (headers.get(FLUSHED_KEY) == null) {
+ byte[] data = buildResponse(headers, null, 0, 0);
+ webSocketConnection.sendMessage(data, 0, data.length);
+ headers.put(FLUSHED_KEY, "true");
+ }
+ super.close();
+ }
+ };
+
+ }
+
+ String getProtocol() {
+ return protocol;
+ }
+
+ //
+ static class WebSocketVirtualServletRequest implements HttpServletRequest {
+ private ServletContext context;
+ private JettyWebSocket websocket;
+ private InputStream in;
+ private Map<String, String> requestHeaders;
+ private Map<String, Object> attributes;
+
+ public WebSocketVirtualServletRequest(ServletContext context, JettyWebSocket websocket, InputStream in)
+ throws IOException {
+ this.context = context;
+ this.websocket = websocket;
+ this.in = in;
+
+ this.requestHeaders = readHeaders(in);
+ String path = requestHeaders.get(URI_KEY);
+ String origin = websocket.getRequestProperty("requestURI", String.class);
+ if (!path.startsWith(origin)) {
+ //REVISIT for now, log it here and reject the request later.
+ LOG.log(Level.WARNING, "invalid path: {0} not within {1}", new Object[]{path, origin});
+ }
+ this.attributes = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER);
+ }
+
+ @Override
+ public AsyncContext getAsyncContext() {
+ return null;
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "getAttribute({0})", name);
+ }
+ return attributes.get(name);
+ }
+
+ @Override
+ public Enumeration<String> getAttributeNames() {
+ LOG.log(Level.INFO, "getAttributeNames()");
+ return Collections.enumeration(attributes.keySet());
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getCharacterEncoding()");
+ return null;
+ }
+
+ @Override
+ public int getContentLength() {
+ LOG.log(Level.INFO, "getContentLength()");
+ return 0;
+ }
+
+ @Override
+ public String getContentType() {
+ LOG.log(Level.INFO, "getContentType()");
+ return requestHeaders.get("Content-Type");
+ }
+
+ @Override
+ public DispatcherType getDispatcherType() {
+ LOG.log(Level.INFO, "getDispatcherType()");
+ return websocket.getRequestProperty("dispatcherType", DispatcherType.class);
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ return new ServletInputStream() {
+ @Override
+ public int read() throws IOException {
+ return in.read();
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return in.read(b, off, len);
+ }
+ };
+ }
+
+ @Override
+ public String getLocalAddr() {
+ LOG.log(Level.INFO, "getLocalAddr()");
+ return websocket.getRequestProperty("localAddr", String.class);
+ }
+
+ @Override
+ public String getLocalName() {
+ LOG.log(Level.INFO, "getLocalName()");
+ return websocket.getRequestProperty("localName", String.class);
+ }
+
+ @Override
+ public int getLocalPort() {
+ LOG.log(Level.INFO, "getLocalPort()");
+ return websocket.getRequestProperty("localPort", int.class);
+ }
+
+ @Override
+ public Locale getLocale() {
+ LOG.log(Level.INFO, "getLocale()");
+ return websocket.getRequestProperty("locale", Locale.class);
+ }
+
+ @Override
+ public Enumeration<Locale> getLocales() {
+ LOG.log(Level.INFO, "getLocales()");
+ return CastUtils.cast(websocket.getRequestProperty("locales", Enumeration.class));
+ }
+
+ @Override
+ public String getParameter(String name) {
+ // TODO Auto-generated method stub
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "getParameter({0})", name);
+ }
+ return null;
+ }
+
+ @Override
+ public Map<String, String[]> getParameterMap() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getParameterMap()");
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getParameterNames() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getParameterNames()");
+ return null;
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+ // TODO Auto-generated method stub
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "getParameterValues({0})", name);
+ }
+ return null;
+ }
+
+ @Override
+ public String getProtocol() {
+ LOG.log(Level.INFO, "getProtocol");
+ return websocket.getRequestProperty("protocol", String.class);
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ LOG.log(Level.INFO, "getReader");
+ return new BufferedReader(new InputStreamReader(in, "utf-8"));
+ }
+
+ @Override
+ public String getRealPath(String path) {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getRealPath");
+ return null;
+ }
+
+ @Override
+ public String getRemoteAddr() {
+ LOG.log(Level.INFO, "getRemoteAddr");
+ return websocket.getRequestProperty("remoteAddr", String.class);
+ }
+
+ @Override
+ public String getRemoteHost() {
+ LOG.log(Level.INFO, "getRemoteHost");
+ return websocket.getRequestProperty("remoteHost", String.class);
+ }
+
+ @Override
+ public int getRemotePort() {
+ LOG.log(Level.INFO, "getRemotePort");
+ return websocket.getRequestProperty("remotePort", int.class);
+ }
+
+ @Override
+ public RequestDispatcher getRequestDispatcher(String path) {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getRequestDispatcher");
+ return null;
+ }
+
+ @Override
+ public String getScheme() {
+ LOG.log(Level.INFO, "getScheme");
+ return websocket.getRequestProperty("scheme", String.class);
+ }
+
+ @Override
+ public String getServerName() {
+ return websocket.getRequestProperty("serverName", String.class);
+ }
+
+ @Override
+ public int getServerPort() {
+ LOG.log(Level.INFO, "getServerPort");
+ return websocket.getRequestProperty("serverPoart", int.class);
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ LOG.log(Level.INFO, "getServletContext");
+ return context;
+ }
+
+ @Override
+ public boolean isAsyncStarted() {
+ LOG.log(Level.INFO, "isAsyncStarted");
+ return false;
+ }
+
+ @Override
+ public boolean isAsyncSupported() {
+ LOG.log(Level.INFO, "isAsyncSupported");
+ return false;
+ }
+
+ @Override
+ public boolean isSecure() {
+ LOG.log(Level.INFO, "isSecure");
+ return websocket.getRequestProperty("secure", boolean.class);
+ }
+
+ @Override
+ public void removeAttribute(String name) {
+ LOG.log(Level.INFO, "removeAttribute");
+ attributes.remove(name);
+ }
+
+ @Override
+ public void setAttribute(String name, Object o) {
+ LOG.log(Level.INFO, "setAttribute");
+ attributes.put(name, o);
+ }
+
+ @Override
+ public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
+ LOG.log(Level.INFO, "setCharacterEncoding");
+ // ignore as we stick to utf-8.
+ }
+
+ @Override
+ public AsyncContext startAsync() {
+ LOG.log(Level.INFO, "startAsync");
+ return null;
+ }
+
+ @Override
+ public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "startAsync");
+ return null;
+ }
+
+ @Override
+ public boolean authenticate(HttpServletResponse servletResponse) throws IOException, ServletException {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "authenticate");
+ return false;
+ }
+
+ @Override
+ public String getAuthType() {
+ LOG.log(Level.INFO, "getAuthType");
+ return websocket.getRequestProperty("authType", String.class);
+ }
+
+ @Override
+ public String getContextPath() {
+ LOG.log(Level.INFO, "getContextPath");
+ return websocket.getRequestProperty("contextPath", String.class);
+ }
+
+ @Override
+ public Cookie[] getCookies() {
+ LOG.log(Level.INFO, "getCookies");
+ return null;
+ }
+
+ @Override
+ public long getDateHeader(String name) {
+ LOG.log(Level.INFO, "getDateHeader");
+ return 0;
+ }
+
+ @Override
+ public String getHeader(String name) {
+ LOG.log(Level.INFO, "getHeader");
+ return requestHeaders.get(name);
+ }
+
+ @Override
+ public Enumeration<String> getHeaderNames() {
+ LOG.log(Level.INFO, "getHeaderNames");
+ return Collections.enumeration(requestHeaders.keySet());
+ }
+
+ @Override
+ public Enumeration<String> getHeaders(String name) {
+ LOG.log(Level.INFO, "getHeaders");
+ // our protocol assumes no multiple headers
+ return Collections.enumeration(Arrays.asList(requestHeaders.get(name)));
+ }
+
+ @Override
+ public int getIntHeader(String name) {
+ LOG.log(Level.INFO, "getIntHeader");
+ String v = requestHeaders.get(name);
+ return v == null ? -1 : Integer.parseInt(v);
+ }
+
+ @Override
+ public String getMethod() {
+ LOG.log(Level.INFO, "getMethod");
+ return requestHeaders.get(METHOD_KEY);
+ }
+
+ @Override
+ public Part getPart(String name) throws IOException, ServletException {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getPart");
+ return null;
+ }
+
+ @Override
+ public Collection<Part> getParts() throws IOException, ServletException {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getParts");
+ return null;
+ }
+
+ @Override
+ public String getPathInfo() {
+ LOG.log(Level.INFO, "getPathInfo");
+ String uri = requestHeaders.get("$uri");
+ String servletpath = websocket.getRequestProperty("servletPath", String.class);
+ //TODO remove the query string part
+ //REVISIT may cache this value in requstHeaders?
+ return uri.substring(servletpath.length());
+ }
+
+ @Override
+ public String getPathTranslated() {
+ LOG.log(Level.INFO, "getPathTranslated");
+ String path = getPathInfo();
+ String opathtrans = websocket.getRequestProperty("pathTranslated", String.class);
+ String opathinfo = websocket.getRequestProperty("pathInfo", String.class);
+ int pos = opathtrans.indexOf(opathinfo);
+ //REVISIT may cache this value in requstHeaders?
+ return new StringBuilder().append(opathtrans.substring(0, pos)).append(path).toString();
+ }
+
+ @Override
+ public String getQueryString() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getQueryString");
+ return null;
+ }
+
+ @Override
+ public String getRemoteUser() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getRemoteUser");
+ return null;
+ }
+
+ @Override
+ public String getRequestURI() {
+ LOG.log(Level.INFO, "getRequestURI");
+ return requestHeaders.get(URI_KEY);
+ }
+
+ @Override
+ public StringBuffer getRequestURL() {
+ LOG.log(Level.INFO, "getRequestURL");
+ String url = websocket.getRequestProperty("requestURL", String.class);
+ String ouri = websocket.getRequestProperty("requestURI", String.class);
+ StringBuffer sb = new StringBuffer();
+ String uri = getRequestURI();
+ //REVISIT the way to reject the requeist uri that does not match the original request
+ if (!uri.startsWith(ouri)) {
+ sb.append(url).append("invalid").append(uri);
+ } else {
+ sb.append(url).append(uri.substring(ouri.length()));
+ }
+
+ return sb;
+ }
+
+ @Override
+ public String getRequestedSessionId() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getRequestedSessionId");
+ return null;
+ }
+
+ @Override
+ public String getServletPath() {
+ LOG.log(Level.INFO, "getServletPath");
+ return websocket.getRequestProperty("servletPath", String.class);
+ }
+
+ @Override
+ public HttpSession getSession() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getSession");
+ return null;
+ }
+
+ @Override
+ public HttpSession getSession(boolean create) {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getSession");
+ return null;
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ LOG.log(Level.INFO, "getUserPrincipal");
+ return websocket.getRequestProperty("userPrincipal", Principal.class);
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromCookie() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "isRequestedSessionIdFromCookie");
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromURL() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "isRequestedSessionIdFromURL");
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromUrl() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "isRequestedSessionIdFromUrl");
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdValid() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "isRequestedSessionIdValid");
+ return false;
+ }
+
+ @Override
+ public boolean isUserInRole(String role) {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "isUserInRole");
+ return false;
+ }
+
+ @Override
+ public void login(String username, String password) throws ServletException {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "login");
+
+ }
+
+ @Override
+ public void logout() throws ServletException {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "logout");
+
+ }
+ }
+
+ //TODO need to make the header setting to be written to the body (as symmetric to the request behavior)
+ static class WebSocketVirtualServletResponse implements HttpServletResponse {
+ private JettyWebSocket websocket;
+ private Map<String, String> responseHeaders;
+ private boolean flushed;
+
+ public WebSocketVirtualServletResponse(JettyWebSocket websocket) {
+ this.websocket = websocket;
+ this.responseHeaders = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
+ }
+
+ @Override
+ public void flushBuffer() throws IOException {
+ LOG.log(Level.INFO, "flushBuffer()");
+ if (!flushed) {
+ //REVISIT this mechanism to determine if the headers have been flushed
+ if (responseHeaders.get(FLUSHED_KEY) == null) {
+ byte[] data = buildResponse(responseHeaders, null, 0, 0);
+ websocket.write(data, 0, data.length);
+ responseHeaders.put(FLUSHED_KEY, "true");
+ }
+ flushed = true;
+ }
+ }
+
+ @Override
+ public int getBufferSize() {
+ LOG.log(Level.INFO, "getBufferSize()");
+ return 0;
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getCharacterEncoding()");
+ return null;
+ }
+
+ @Override
+ public String getContentType() {
+ LOG.log(Level.INFO, "getContentType()");
+ return responseHeaders.get("Content-Type");
+ }
+
+ @Override
+ public Locale getLocale() {
+ // TODO Auto-generated method stub
+ LOG.log(Level.INFO, "getLocale");
+ return null;
+ }
+
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ LOG.log(Level.INFO, "getOutputStream()");
+ return websocket.getServletOutputStream(responseHeaders);
+ }
+
+ @Override
+ public PrintWriter getWriter() throws IOException {
+ LOG.log(Level.INFO, "getWriter()");
+ return new PrintWriter(websocket.getOutputStream(responseHeaders));
+ }
+
+ @Override
+ public boolean isCommitted() {
+ return false;
+ }
+
+ @Override
+ public void reset() {
+ }
+
+ @Override
+ public void resetBuffer() {
+ LOG.log(Level.INFO, "resetBuffer()");
+ }
+
+ @Override
+ public void setBufferSize(int size) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setBufferSize({0})", size);
+ }
+ }
+
+ @Override
+ public void setCharacterEncoding(String charset) {
+ // TODO
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setCharacterEncoding({0})", charset);
+ }
+ }
+
+ @Override
+ public void setContentLength(int len) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setContentLength({0})", len);
+ }
+ responseHeaders.put("Content-Length", Integer.toString(len));
+ }
+
+ @Override
+ public void setContentType(String type) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setContentType({0})", type);
+ }
+ responseHeaders.put("Content-Type", type);
+ }
+
+ @Override
+ public void setLocale(Locale loc) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setLocale({0})", loc);
+ }
+ }
+
+ @Override
+ public void addCookie(Cookie cookie) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "addCookie({0})", cookie);
+ }
+ }
+
+ @Override
+ public void addDateHeader(String name, long date) {
+ // TODO
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "addDateHeader({0}, {1})", new Object[]{name, date});
+ }
+ }
+
+ @Override
+ public void addHeader(String name, String value) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "addHeader({0}, {1})", new Object[]{name, value});
+ }
+ responseHeaders.put(name, value);
+ }
+
+ @Override
+ public void addIntHeader(String name, int value) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "addIntHeader({0}, {1})", new Object[]{name, value});
+ }
+ responseHeaders.put(name, Integer.toString(value));
+ }
+
+ @Override
+ public boolean containsHeader(String name) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "containsHeader({0})", name);
+ }
+ return responseHeaders.containsKey(name);
+ }
+
+ @Override
+ public String encodeRedirectURL(String url) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "encodeRedirectURL({0})", url);
+ }
+ return null;
+ }
+
+ @Override
+ public String encodeRedirectUrl(String url) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "encodeRedirectUrl({0})", url);
+ }
+ return null;
+ }
+
+ @Override
+ public String encodeURL(String url) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "encodeURL({0})", url);
+ }
+ return null;
+ }
+
+ @Override
+ public String encodeUrl(String url) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "encodeUrl({0})", url);
+ }
+ return null;
+ }
+
+ @Override
+ public String getHeader(String name) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "getHeader({0})", name);
+ }
+ return null;
+ }
+
+ @Override
+ public Collection<String> getHeaderNames() {
+ LOG.log(Level.INFO, "getHeaderNames()");
+ return null;
+ }
+
+ @Override
+ public Collection<String> getHeaders(String name) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "getHeaders({0})", name);
+ }
+ return null;
+ }
+
+ @Override
+ public int getStatus() {
+ LOG.log(Level.INFO, "getStatus()");
+ String v = responseHeaders.get(SC_KEY);
+ return v == null ? 200 : Integer.parseInt(v);
+ }
+
+ @Override
+ public void sendError(int sc) throws IOException {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "sendError{0}", sc);
+ }
+ responseHeaders.put(SC_KEY, Integer.toString(sc));
+ }
+
+ @Override
+ public void sendError(int sc, String msg) throws IOException {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "sendError({0}, {1})", new Object[]{sc, msg});
+ }
+ responseHeaders.put(SC_KEY, Integer.toString(sc));
+ responseHeaders.put(SM_KEY, msg);
+ }
+
+ @Override
+ public void sendRedirect(String location) throws IOException {
+ // TODO Auto-generated method stub
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "sendRedirect({0})", location);
+ }
+ }
+
+ @Override
+ public void setDateHeader(String name, long date) {
+ // ignore
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setDateHeader({0}, {1})", new Object[]{name, date});
+ }
+ }
+
+ @Override
+ public void setHeader(String name, String value) {
+ // TODO Auto-generated method stub
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setHeader({0}, {1})", new Object[]{name, value});
+ }
+ }
+
+ @Override
+ public void setIntHeader(String name, int value) {
+ // TODO Auto-generated method stub
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setIntHeader({0}, {1})", new Object[]{name, value});
+ }
+ }
+
+ @Override
+ public void setStatus(int sc) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setStatus({0})", sc);
+ }
+ responseHeaders.put(SC_KEY, Integer.toString(sc));
+ }
+
+ @Override
+ public void setStatus(int sc, String sm) {
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, "setStatus({0}, {1})", new Object[]{sc, sm});
+ }
+ responseHeaders.put(SC_KEY, Integer.toString(sc));
+ responseHeaders.put(SM_KEY, sm);
+ }
+ }
+
+ /*
+ * We accept only a restricted syntax as we have the syntax in our control.
+ * Do not allow multiline or line-wrapped headers.
+ * Do not allow charset other than utf-8. (although i would have preferred iso-8859-1 ;-)
+ */
+ private static Map<String, String> readHeaders(InputStream in) throws IOException {
+ Map<String, String> headers = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
+ // read the request line
+ String line = readLine(in);
+ int del = line.indexOf(' ');
+ if (del < 0) {
+ throw new IOException("invalid request: " + line);
+ }
+ headers.put(METHOD_KEY, line.substring(0, del).trim());
+ headers.put(URI_KEY, line.substring(del + 1).trim());
+
+ // read headers
+ while ((line = readLine(in)) != null) {
+ if (line.length() > 0) {
+ del = line.indexOf(':');
+ if (del < 0) {
+ headers.put(line.trim(), "");
+ } else {
+ headers.put(line.substring(0, del).trim(), line.substring(del + 1).trim());
+ }
+ }
+ }
+
+ return headers;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T getValue(Map<String, Object> properties, String name, Class<T> cls) {
+ return (T)properties.get(name);
+ }
+
+
+ ///// this is copied from AttachmentDeserializer with a minor change. think about putting this method to IOUtils
+ private static String readLine(InputStream in) throws IOException {
+ StringBuilder buffer = new StringBuilder(128);
+
+ int c;
+
+ while ((c = in.read()) != -1) {
+ // a linefeed is a terminator, always.
+ if (c == '\n') {
+ break;
+ } else if (c == '\r') {
+ //just ignore the CR. The next character SHOULD be an NL. If not, we're
+ //just going to discard this
+ continue;
+ } else {
+ // just add to the buffer
+ buffer.append((char)c);
+ }
+ }
+
+ // no characters found...this was either an eof or a null line.
+ if (buffer.length() == 0) {
+ return null;
+ }
+
+ return buffer.toString();
+ }
+ ///// END
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketDestination.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketDestination.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketDestination.java
new file mode 100644
index 0000000..f849713
--- /dev/null
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketDestination.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.websocket.jetty;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.http.DestinationRegistry;
+import org.apache.cxf.transport.http_jetty.JettyHTTPDestination;
+import org.apache.cxf.transport.http_jetty.JettyHTTPHandler;
+import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngineFactory;
+
+/**
+ *
+ */
+public class JettyWebSocketDestination extends JettyHTTPDestination {
+
+ public JettyWebSocketDestination(Bus bus, DestinationRegistry registry, EndpointInfo ei,
+ JettyHTTPServerEngineFactory serverEngineFactory) throws IOException {
+ super(bus, registry, ei, serverEngineFactory);
+ }
+
+ @Override
+ protected String getAddress(EndpointInfo endpointInfo) {
+ String address = endpointInfo.getAddress();
+ if (address.startsWith("ws")) {
+ address = "http" + address.substring(2);
+ }
+ return address;
+ }
+
+
+ @Override
+ protected String getBasePath(String contextPath) throws IOException {
+ if (StringUtils.isEmpty(endpointInfo.getAddress())) {
+ return "";
+ }
+ return new URL(getAddress(endpointInfo)).getPath();
+ }
+
+ @Override
+ protected JettyHTTPHandler createJettyHTTPHandler(JettyHTTPDestination jhd, boolean cmExact) {
+ return new JettyWebSocketHandler(jhd, cmExact);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketHandler.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketHandler.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketHandler.java
new file mode 100644
index 0000000..be09dce
--- /dev/null
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketHandler.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.transport.websocket.jetty;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.cxf.transport.http_jetty.JettyHTTPDestination;
+import org.apache.cxf.transport.http_jetty.JettyHTTPHandler;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.websocket.WebSocket;
+import org.eclipse.jetty.websocket.WebSocketFactory;
+
+/**
+ * The extended version of JettyHTTPHandler that can support websocket.
+ */
+class JettyWebSocketHandler extends JettyHTTPHandler implements WebSocketFactory.Acceptor {
+ private JettyWebSocketManager webSocketManager;
+
+ public JettyWebSocketHandler(JettyHTTPDestination jhd, boolean cmExact) {
+ super(jhd, cmExact);
+ webSocketManager = new JettyWebSocketManager();
+ webSocketManager.init(this, jhd);
+ }
+
+ public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
+ return new JettyWebSocket(webSocketManager, request, protocol);
+ }
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request,
+ HttpServletResponse response) throws IOException, ServletException {
+ // only switch to websocket if websocket is enabled for this destination
+ if (webSocketManager.acceptWebSocket(request, response)) {
+ baseRequest.setHandled(true);
+ } else {
+ super.handle(target, baseRequest, request, response);
+ }
+ }
+
+ public boolean checkOrigin(HttpServletRequest request, String protocol) {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketManager.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketManager.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketManager.java
new file mode 100644
index 0000000..139b1a6
--- /dev/null
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketManager.java
@@ -0,0 +1,114 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.websocket.jetty;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.cxf.transport.http.AbstractHTTPDestination;
+import org.apache.cxf.transport.http_jetty.JettyHTTPDestination;
+import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
+import org.eclipse.jetty.websocket.WebSocketFactory;
+import org.eclipse.jetty.websocket.WebSocketFactory.Acceptor;
+
+/**
+ *
+ */
+public class JettyWebSocketManager {
+ private WebSocketFactory webSocketFactory;
+
+ // either servlet is set or destination + servletContext are set
+ private CXFNonSpringServlet servlet;
+ private AbstractHTTPDestination destination;
+ private ServletContext servletContext;
+
+ public void init(JettyWebSocketHandler handler, JettyHTTPDestination dest) {
+ this.destination = dest;
+ //TODO customize websocket factory configuration options when using the destination.
+
+ webSocketFactory = new WebSocketFactory((Acceptor)handler, 8192);
+ }
+
+ public void init(CXFNonSpringServlet srvlt, ServletConfig sc) throws ServletException {
+ this.servlet = srvlt;
+ try {
+
+ String bs = srvlt.getInitParameter("bufferSize");
+
+ webSocketFactory = new WebSocketFactory((Acceptor)srvlt, bs == null ? 8192 : Integer.parseInt(bs));
+ webSocketFactory.start();
+
+ String max = srvlt.getInitParameter("maxIdleTime");
+ if (max != null) {
+ webSocketFactory.setMaxIdleTime(Integer.parseInt(max));
+ }
+ max = srvlt.getInitParameter("maxTextMessageSize");
+ if (max != null) {
+ webSocketFactory.setMaxTextMessageSize(Integer.parseInt(max));
+ }
+ max = srvlt.getInitParameter("maxBinaryMessageSize");
+ if (max != null) {
+ webSocketFactory.setMaxBinaryMessageSize(Integer.parseInt(max));
+ }
+ } catch (Exception e) {
+ throw e instanceof ServletException ? (ServletException)e : new ServletException(e);
+ }
+ }
+
+ void setServletContext(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ }
+
+ public void destroy() {
+ try {
+ webSocketFactory.stop();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ public boolean acceptWebSocket(ServletRequest req, ServletResponse res) throws IOException {
+ try {
+ HttpServletRequest request = (HttpServletRequest) req;
+ HttpServletResponse response = (HttpServletResponse) res;
+ if (webSocketFactory.acceptWebSocket(request, response) || response.isCommitted()) {
+ return true;
+ }
+ } catch (ClassCastException e) {
+ // ignore
+ }
+ return false;
+ }
+
+ public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
+ if (destination != null) {
+ destination.invoke(null, servletContext, request, response);
+ } else if (servlet != null) {
+ ((CXFJettyWebSocketServletService)servlet).serviceInternal(request, response);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/resources/META-INF/cxf/bus-extensions.txt
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/resources/META-INF/cxf/bus-extensions.txt b/rt/transports/websocket/src/main/resources/META-INF/cxf/bus-extensions.txt
new file mode 100644
index 0000000..133e3b2
--- /dev/null
+++ b/rt/transports/websocket/src/main/resources/META-INF/cxf/bus-extensions.txt
@@ -0,0 +1,4 @@
+org.apache.cxf.transport.websocket.WebSocketTransportFactory::true
+
+
+
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/WebSocketTransportFactoryTest.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/WebSocketTransportFactoryTest.java b/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/WebSocketTransportFactoryTest.java
new file mode 100644
index 0000000..d53339a
--- /dev/null
+++ b/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/WebSocketTransportFactoryTest.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.websocket;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.Destination;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class WebSocketTransportFactoryTest extends Assert {
+
+ @Test
+ public void testGetDestination() throws Exception {
+ Bus bus = BusFactory.getDefaultBus();
+ EndpointInfo ei = new EndpointInfo();
+ ei.setAddress("ws://localhost:8888/bar/foo");
+ WebSocketTransportFactory factory = bus.getExtension(WebSocketTransportFactory.class);
+ assertNotNull(factory);
+ Destination dest = factory.getDestination(ei, bus);
+ assertNotNull(dest);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketManagerTest.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketManagerTest.java b/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketManagerTest.java
new file mode 100644
index 0000000..a74b1f1
--- /dev/null
+++ b/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/jetty/JettyWebSocketManagerTest.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.websocket.jetty;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.cxf.transport.http_jetty.JettyHTTPDestination;
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class JettyWebSocketManagerTest extends Assert {
+ private IMocksControl control;
+
+ @Before
+ public void setUp() {
+ control = EasyMock.createNiceControl();
+ }
+
+ @Test
+ public void testServiceUsingDestination() throws Exception {
+ JettyWebSocketManager jwsm = new JettyWebSocketManager();
+
+ JettyWebSocketHandler handler = control.createMock(JettyWebSocketHandler.class);
+ JettyHTTPDestination dest = control.createMock(JettyHTTPDestination.class);
+
+ HttpServletRequest request = control.createMock(HttpServletRequest.class);
+ HttpServletResponse response = control.createMock(HttpServletResponse.class);
+
+ dest.invoke(EasyMock.isNull(ServletConfig.class), EasyMock.isNull(ServletContext.class),
+ EasyMock.eq(request), EasyMock.eq(response));
+ EasyMock.expectLastCall();
+ control.replay();
+ jwsm.init(handler, dest);
+
+ jwsm.service(request, response);
+ control.verify();
+ }
+
+ @Test
+ public void testServiceUsingServlet() throws Exception {
+ JettyWebSocketManager jwsm = new JettyWebSocketManager();
+
+ HttpServletRequest request = control.createMock(HttpServletRequest.class);
+ HttpServletResponse response = control.createMock(HttpServletResponse.class);
+
+ CXFNonSpringJettyWebSocketServlet srvlt = control.createMock(CXFNonSpringJettyWebSocketServlet.class);
+ ServletConfig sc = control.createMock(ServletConfig.class);
+
+ srvlt.serviceInternal(EasyMock.eq(request), EasyMock.eq(response));
+ EasyMock.expectLastCall();
+ control.replay();
+ jwsm.init(srvlt, sc);
+
+ jwsm.service(request, response);
+ control.verify();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/systests/jaxrs/pom.xml
----------------------------------------------------------------------
diff --git a/systests/jaxrs/pom.xml b/systests/jaxrs/pom.xml
index f7fe056..b51e50e 100644
--- a/systests/jaxrs/pom.xml
+++ b/systests/jaxrs/pom.xml
@@ -170,6 +170,11 @@
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-transports-websocket</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-features-clustering</artifactId>
<version>${project.version}</version>
</dependency>
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/BookServerWebSocket.java
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/BookServerWebSocket.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/BookServerWebSocket.java
index e5275df..e9bd712 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/BookServerWebSocket.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/BookServerWebSocket.java
@@ -19,32 +19,19 @@
package org.apache.cxf.systest.jaxrs.websocket;
-import java.util.Collections;
-import java.util.Map;
-
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
import org.apache.cxf.systest.jaxrs.BookStorePerRequest;
import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
-import org.apache.cxf.transport.http_jetty.JettyHTTPDestination;
public class BookServerWebSocket extends AbstractBusTestServerBase {
public static final String PORT = allocatePort(BookServerWebSocket.class);
org.apache.cxf.endpoint.Server server;
- private Map< ? extends String, ? extends Object > properties;
public BookServerWebSocket() {
- this(Collections.< String, Object >emptyMap());
- }
-
- /**
- * Allow to specified custom contextual properties to be passed to factory bean
- */
- public BookServerWebSocket(final Map< ? extends String, ? extends Object > properties) {
- this.properties = properties;
}
protected void run() {
@@ -55,10 +42,9 @@ public class BookServerWebSocket extends AbstractBusTestServerBase {
sf.setResourceClasses(BookStoreWebSocket.class, BookStorePerRequest.class);
sf.setResourceProvider(BookStoreWebSocket.class,
new SingletonResourceProvider(new BookStoreWebSocket(), true));
- sf.setAddress("http://localhost:" + PORT + "/");
+ sf.setAddress("ws://localhost:" + PORT + "/");
server = sf.create();
- ((JettyHTTPDestination)server.getDestination())
- .setEnableWebSocket(Boolean.parseBoolean((String)properties.get("enableWebSocket")));
+
BusFactory.setDefaultBus(null);
BusFactory.setThreadDefaultBus(null);
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketSpringTest.java
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketSpringTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketSpringTest.java
new file mode 100644
index 0000000..56e6262
--- /dev/null
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketSpringTest.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.jaxrs.websocket;
+
+import org.junit.BeforeClass;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * JAXRSClientServerWebSocket test with jaxrs:server using the embedded jetty server.
+ */
+public class JAXRSClientServerWebSocketSpringTest extends JAXRSClientServerWebSocketTest {
+ public static final String PORT = BookServerWebSocket.PORT;
+ @BeforeClass
+ public static void startServers() throws Exception {
+
+ @SuppressWarnings("unused")
+ ApplicationContext appctxt =
+ new ClassPathXmlApplicationContext(
+ JAXRSClientServerWebSocketSpringTest.class.getResource(
+ "/jaxrs_websocket/beans-embedded.xml").toString());
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketSpringWebAppTest.java
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketSpringWebAppTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketSpringWebAppTest.java
new file mode 100644
index 0000000..4522d99
--- /dev/null
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketSpringWebAppTest.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.jaxrs.websocket;
+
+import java.net.URISyntaxException;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+import org.junit.BeforeClass;
+
+/**
+ * JAXRSClientServerWebSocket test with jaxrs:server using the jetty webapp server.
+ */
+public class JAXRSClientServerWebSocketSpringWebAppTest extends JAXRSClientServerWebSocketTest {
+ public static final String PORT = BookServerWebSocket.PORT;
+
+ @BeforeClass
+ public static void startServers() throws Exception {
+ org.eclipse.jetty.server.Server server = new org.eclipse.jetty.server.Server();
+
+ SelectChannelConnector connector = new SelectChannelConnector();
+ connector.setPort(Integer.parseInt(PORT));
+ server.setConnectors(new Connector[] {connector});
+
+ WebAppContext webappcontext = new WebAppContext();
+ String contextPath = null;
+ try {
+ contextPath = JAXRSClientServerWebSocketSpringWebAppTest.class
+ .getResource("/jaxrs_websocket").toURI().getPath();
+ } catch (URISyntaxException e1) {
+ e1.printStackTrace();
+ }
+ webappcontext.setContextPath("/");
+
+ webappcontext.setWar(contextPath);
+ HandlerCollection handlers = new HandlerCollection();
+ handlers.setHandlers(new Handler[] {webappcontext, new DefaultHandler()});
+ server.setHandler(handlers);
+ server.start();
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketTest.java
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketTest.java
index 9688197..9a5aa8c 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketTest.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/websocket/JAXRSClientServerWebSocketTest.java
@@ -19,9 +19,7 @@
package org.apache.cxf.systest.jaxrs.websocket;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
@@ -34,14 +32,11 @@ public class JAXRSClientServerWebSocketTest extends AbstractBusClientServerTestB
@BeforeClass
public static void startServers() throws Exception {
- final Map< String, Object > properties = new HashMap< String, Object >();
- properties.put("enableWebSocket", "true");
-
AbstractResourceInfo.clearAllMaps();
- assertTrue("server did not launch correctly", launchServer(new BookServerWebSocket(properties)));
+ assertTrue("server did not launch correctly", launchServer(new BookServerWebSocket()));
createStaticBus();
}
-
+
@Test
public void testBookWithWebSocket() throws Exception {
String address = "ws://localhost:" + PORT + "/web/bookstore";
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/systests/jaxrs/src/test/resources/jaxrs_websocket/WEB-INF/beans.xml
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/resources/jaxrs_websocket/WEB-INF/beans.xml b/systests/jaxrs/src/test/resources/jaxrs_websocket/WEB-INF/beans.xml
new file mode 100644
index 0000000..45701db
--- /dev/null
+++ b/systests/jaxrs/src/test/resources/jaxrs_websocket/WEB-INF/beans.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!-- START SNIPPET: beans -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:http="http://cxf.apache.org/transports/http/configuration"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:jaxrs="http://cxf.apache.org/jaxrs"
+ xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
+ xmlns:cxf="http://cxf.apache.org/core"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
+ http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
+ http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+ http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd
+ http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
+ <import resource="classpath:META-INF/cxf/cxf.xml"/>
+ <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
+
+ <bean class="org.apache.cxf.systest.jaxrs.websocket.BookStoreWebSocket" id="serviceBean"/>
+
+ <jaxrs:server id="bookservice" address="/" transportId="http://cxf.apache.org/transports/websockt">
+ <jaxrs:serviceBeans>
+ <ref bean="serviceBean"/>
+ </jaxrs:serviceBeans>
+ </jaxrs:server>
+</beans>
+<!-- END SNIPPET: beans -->
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/systests/jaxrs/src/test/resources/jaxrs_websocket/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/resources/jaxrs_websocket/WEB-INF/web.xml b/systests/jaxrs/src/test/resources/jaxrs_websocket/WEB-INF/web.xml
new file mode 100644
index 0000000..7619cdf
--- /dev/null
+++ b/systests/jaxrs/src/test/resources/jaxrs_websocket/WEB-INF/web.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!-- START SNIPPET: webxml -->
+<web-app>
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>WEB-INF/beans.xml</param-value>
+ </context-param>
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+ <servlet>
+ <servlet-name>CXFJettyWebSocketServlet</servlet-name>
+ <display-name>CXF JettyWebSocketServlet</display-name>
+ <servlet-class>org.apache.cxf.transport.websocket.jetty.CXFJettyWebSocketServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>CXFJettyWebSocketServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
+<!-- END SNIPPET: webxml -->
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/systests/jaxrs/src/test/resources/jaxrs_websocket/beans-embedded.xml
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/resources/jaxrs_websocket/beans-embedded.xml b/systests/jaxrs/src/test/resources/jaxrs_websocket/beans-embedded.xml
new file mode 100644
index 0000000..03c5c5a
--- /dev/null
+++ b/systests/jaxrs/src/test/resources/jaxrs_websocket/beans-embedded.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!-- START SNIPPET: beans -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:http="http://cxf.apache.org/transports/http/configuration"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:jaxrs="http://cxf.apache.org/jaxrs"
+ xmlns:cxf="http://cxf.apache.org/core"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
+ http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
+ http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+ http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
+ <import resource="classpath:META-INF/cxf/cxf.xml"/>
+ <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
+
+ <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+
+ <bean class="org.apache.cxf.systest.jaxrs.websocket.BookStoreWebSocket" id="serviceBean"/>
+
+ <jaxrs:server id="bookservice" address="ws://localhost:${testutil.ports.BookServerWebSocket}/">
+ <jaxrs:serviceBeans>
+ <ref bean="serviceBean"/>
+ </jaxrs:serviceBeans>
+ </jaxrs:server>
+</beans>
+<!-- END SNIPPET: beans -->
[2/2] git commit: refactor websocket (CXF-5339) into a seprate
transport component
Posted by ay...@apache.org.
refactor websocket (CXF-5339) into a seprate transport component
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/8fe4fc13
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/8fe4fc13
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/8fe4fc13
Branch: refs/heads/master
Commit: 8fe4fc13a8652912315fae881aaf3066f823def5
Parents: c9c4430
Author: Akitoshi Yoshida <ay...@apache.org>
Authored: Mon Mar 10 16:48:13 2014 +0100
Committer: Akitoshi Yoshida <ay...@apache.org>
Committed: Mon Mar 10 16:49:53 2014 +0100
----------------------------------------------------------------------
rt/pom.xml | 1 +
rt/transports/http-jetty/pom.xml | 7 -
.../http_jetty/JettyHTTPDestination.java | 31 +-
.../http_jetty/JettyHTTPExtendedHandler.java | 60 -
.../transport/http_jetty/JettyWebSocket.java | 1085 -----------------
.../transport/servlet/CXFNonSpringServlet.java | 2 +-
rt/transports/websocket/pom.xml | 168 +++
.../websocket/WebSocketDestinationFactory.java | 49 +
.../websocket/WebSocketTransportFactory.java | 135 +++
.../jetty/CXFJettyWebSocketServlet.java | 110 ++
.../jetty/CXFJettyWebSocketServletService.java | 33 +
.../CXFNonSpringJettyWebSocketServlet.java | 116 ++
.../websocket/jetty/JettyWebSocket.java | 1111 ++++++++++++++++++
.../jetty/JettyWebSocketDestination.java | 66 ++
.../websocket/jetty/JettyWebSocketHandler.java | 63 +
.../websocket/jetty/JettyWebSocketManager.java | 114 ++
.../resources/META-INF/cxf/bus-extensions.txt | 4 +
.../WebSocketTransportFactoryTest.java | 43 +
.../jetty/JettyWebSocketManagerTest.java | 84 ++
systests/jaxrs/pom.xml | 5 +
.../jaxrs/websocket/BookServerWebSocket.java | 18 +-
.../JAXRSClientServerWebSocketSpringTest.java | 43 +
...RSClientServerWebSocketSpringWebAppTest.java | 65 +
.../JAXRSClientServerWebSocketTest.java | 9 +-
.../resources/jaxrs_websocket/WEB-INF/beans.xml | 45 +
.../resources/jaxrs_websocket/WEB-INF/web.xml | 41 +
.../jaxrs_websocket/beans-embedded.xml | 45 +
27 files changed, 2353 insertions(+), 1200 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/pom.xml
----------------------------------------------------------------------
diff --git a/rt/pom.xml b/rt/pom.xml
index 1a7b0ad..8472491 100644
--- a/rt/pom.xml
+++ b/rt/pom.xml
@@ -50,6 +50,7 @@
<module>transports/http-netty/netty-client</module>
<module>transports/jms</module>
<module>transports/udp</module>
+ <module>transports/websocket</module>
<module>ws/policy</module>
<module>ws/addr</module>
<module>ws/security</module>
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/http-jetty/pom.xml
----------------------------------------------------------------------
diff --git a/rt/transports/http-jetty/pom.xml b/rt/transports/http-jetty/pom.xml
index cb2c4e3..06df9ca 100644
--- a/rt/transports/http-jetty/pom.xml
+++ b/rt/transports/http-jetty/pom.xml
@@ -34,7 +34,6 @@
<cxf.bundle.activator>org.apache.cxf.transport.http_jetty.osgi.HTTPJettyTransportActivator</cxf.bundle.activator>
<cxf.osgi.import>
javax.servlet*;version="${cxf.osgi.javax.servlet.version}",
- org.eclipse.jetty.websocket;version="${cxf.jetty.osgi.version}";resolution:=optional,
org.eclipse.jetty*;version="${cxf.jetty.osgi.version}",
org.apache.aries*;version="${cxf.aries.version.range}";resolution:=optional,
org.springframework*;resolution:="optional";version="${cxf.osgi.spring.version}"
@@ -101,12 +100,6 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-websocket</artifactId>
- <version>${cxf.jetty.version}</version>
- <optional>true</optional>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jmx</artifactId>
<version>${cxf.jetty.version}</version>
<optional>true</optional>
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java
----------------------------------------------------------------------
diff --git a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java
index 02a678d..c82a9ba 100644
--- a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java
+++ b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java
@@ -23,7 +23,6 @@ import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
@@ -63,7 +62,6 @@ public class JettyHTTPDestination extends AbstractHTTPDestination {
private static final Logger LOG =
LogUtils.getL7dLogger(JettyHTTPDestination.class);
- private static Constructor<?> handlerConstructor;
protected JettyHTTPServerEngine engine;
protected JettyHTTPServerEngineFactory serverEngineFactory;
@@ -71,17 +69,6 @@ public class JettyHTTPDestination extends AbstractHTTPDestination {
protected URL nurl;
protected ClassLoader loader;
-
- static {
- try {
- Class<?> cls = ClassUtils.forName("org.apache.cxf.transport.http_jetty.JettyHTTPExtendedHandler",
- JettyHTTPDestination.class.getClassLoader());
- handlerConstructor = cls.getDeclaredConstructor(new Class<?>[]{JettyHTTPDestination.class, boolean.class});
- } catch (Throwable t) {
- //ignore
- }
- }
-
/**
* This variable signifies that finalizeConfig() has been called.
* It gets called after this object has been spring configured.
@@ -108,7 +95,7 @@ public class JettyHTTPDestination extends AbstractHTTPDestination {
//Add the default port if the address is missing it
super(bus, registry, ei, getAddressValue(ei, true).getAddress(), true);
this.serverEngineFactory = serverEngineFactory;
- nurl = new URL(endpointInfo.getAddress());
+ nurl = new URL(getAddress(endpointInfo));
loader = bus.getExtension(ClassLoader.class);
}
@@ -169,6 +156,10 @@ public class JettyHTTPDestination extends AbstractHTTPDestination {
}
configFinalized = true;
}
+
+ protected String getAddress(EndpointInfo endpointInfo) {
+ return endpointInfo.getAddress();
+ }
/**
* Activate receipt of incoming messages.
@@ -178,7 +169,7 @@ public class JettyHTTPDestination extends AbstractHTTPDestination {
LOG.log(Level.FINE, "Activating receipt of incoming messages");
URL url = null;
try {
- url = new URL(endpointInfo.getAddress());
+ url = new URL(getAddress(endpointInfo));
} catch (Exception e) {
throw new Fault(e);
}
@@ -188,16 +179,8 @@ public class JettyHTTPDestination extends AbstractHTTPDestination {
}
- private JettyHTTPHandler createJettyHTTPHandler(JettyHTTPDestination jhd,
+ protected JettyHTTPHandler createJettyHTTPHandler(JettyHTTPDestination jhd,
boolean cmExact) {
- if (handlerConstructor != null) {
- try {
- return (JettyHTTPHandler)handlerConstructor.newInstance(new Object[]{jhd, cmExact});
- } catch (Exception e) {
- //ignore
- }
- }
- // use the default handler
return new JettyHTTPHandler(jhd, cmExact);
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPExtendedHandler.java
----------------------------------------------------------------------
diff --git a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPExtendedHandler.java b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPExtendedHandler.java
deleted file mode 100644
index a15c5ff..0000000
--- a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPExtendedHandler.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.transport.http_jetty;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.websocket.WebSocket;
-import org.eclipse.jetty.websocket.WebSocketFactory;
-
-/**
- * The extended version of JettyHTTPHandler that can support websocket.
- */
-class JettyHTTPExtendedHandler extends JettyHTTPHandler implements WebSocketFactory.Acceptor {
- private final WebSocketFactory webSocketFactory = new WebSocketFactory(this);
-
- public JettyHTTPExtendedHandler(JettyHTTPDestination jhd, boolean cmExact) {
- super(jhd, cmExact);
- }
-
- public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
- return new JettyWebSocket(jettyHTTPDestination, servletContext, request, protocol);
- }
-
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request,
- HttpServletResponse response) throws IOException, ServletException {
- // only switch to websocket if websocket is enabled for this destination
- if (jettyHTTPDestination != null && jettyHTTPDestination.isEnableWebSocket()
- && (webSocketFactory.acceptWebSocket(request, response) || response.isCommitted())) {
- baseRequest.setHandled(true);
- } else {
- super.handle(target, baseRequest, request, response);
- }
- }
-
- public boolean checkOrigin(HttpServletRequest request, String protocol) {
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyWebSocket.java
----------------------------------------------------------------------
diff --git a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyWebSocket.java b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyWebSocket.java
deleted file mode 100644
index 247545d..0000000
--- a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyWebSocket.java
+++ /dev/null
@@ -1,1085 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.cxf.transport.http_jetty;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.security.Principal;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.AsyncContext;
-import javax.servlet.DispatcherType;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.Part;
-
-import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.helpers.CastUtils;
-import org.eclipse.jetty.websocket.WebSocket;
-
-class JettyWebSocket implements WebSocket.OnBinaryMessage, WebSocket.OnTextMessage {
- private static final Logger LOG = LogUtils.getL7dLogger(JettyWebSocket.class);
- private static final String CRLF = "\r\n";
-
- private JettyHTTPDestination jettyHTTPDestination;
- private ServletContext servletContext;
- private Connection webSocketConnection;
- private Map<String, Object> requestProperties;
- private String protocol;
-
- public JettyWebSocket(JettyHTTPDestination jettyHTTPDestination, ServletContext servletContext,
- HttpServletRequest request, String protocol) {
- this.jettyHTTPDestination = jettyHTTPDestination;
- this.servletContext = servletContext;
- this.protocol = protocol;
- this.requestProperties = readProperties(request);
- }
-
- private Map<String, Object> readProperties(HttpServletRequest request) {
- Map<String, Object> properties = new HashMap<String, Object>();
- properties.put("servletPath", request.getServletPath());
- properties.put("requestURI", request.getRequestURI());
- properties.put("requestURL", request.getRequestURL().toString());
- properties.put("contextPath", request.getContextPath());
- properties.put("servletPath", request.getServletPath());
- properties.put("pathInfo", request.getPathInfo());
- properties.put("protocol", protocol);
- // some additional ones
- properties.put("localAddr", request.getLocalAddr());
- properties.put("localName", request.getLocalName());
- properties.put("localPort", request.getLocalPort());
- properties.put("locale", request.getLocale());
- properties.put("locales", request.getLocales());
- properties.put("remoteHost", request.getRemoteHost());
- properties.put("remoteAddr", request.getRemoteAddr());
- properties.put("serverName", request.getServerName());
- properties.put("secure", request.isSecure());
-
- return properties;
- }
-
- @Override
- public void onClose(int closeCode, String message) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "onClose({0}, {1})", new Object[]{closeCode, message});
- }
- }
-
- @Override
- public void onOpen(Connection connection) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "onOpen({0}))", connection);
- }
- this.webSocketConnection = connection;
- }
-
- @Override
- public void onMessage(String data) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "onMessage({0})", data);
- }
- try {
- byte[] bdata = data.getBytes("utf-8");
- jettyHTTPDestination.invoke(null, servletContext,
- createServletRequest(bdata, 0, bdata.length),
- createServletResponse());
- } catch (Exception e) {
- LOG.log(Level.WARNING, "Failed to invoke service", e);
- }
- }
-
- @Override
- public void onMessage(byte[] data, int offset, int length) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "onMessage({0}, {1}, {2})", new Object[]{data, offset, length});
- }
- try {
- jettyHTTPDestination.invoke(null, servletContext,
- createServletRequest(data, offset, length),
- createServletResponse());
- } catch (Exception e) {
- LOG.log(Level.WARNING, "Failed to invoke service", e);
- }
- }
-
- private <T> T getRequestProperty(String name, Class<T> cls) {
- return getValue(requestProperties, name, cls);
- }
-
- private WebSocketVirtualServletRequest createServletRequest(byte[] data, int offset, int length)
- throws IOException {
- return new WebSocketVirtualServletRequest(servletContext, this, new ByteArrayInputStream(data, offset, length));
- }
-
- private WebSocketVirtualServletResponse createServletResponse() throws IOException {
- return new WebSocketVirtualServletResponse(this);
- }
-
- /**
- * Writes to the underlining socket.
- *
- * @param data
- * @param offset
- * @param length
- */
- void write(byte[] data, int offset, int length) throws IOException {
- LOG.log(Level.INFO, "write(byte[], offset, length)");
- webSocketConnection.sendMessage(data, offset, length);
- }
-
- private static byte[] buildResponse(Map<String, String> headers, byte[] data, int offset, int length) {
- StringBuilder sb = new StringBuilder();
- String v = headers.get("$sc");
- sb.append(v == null ? "200" : v).append(CRLF);
- v = headers.get("Content-Type");
- if (v != null) {
- sb.append("Content-Type: ").append(v).append(CRLF);
- }
- sb.append(CRLF);
-
- byte[] hb = sb.toString().getBytes();
- byte[] longdata = new byte[hb.length + length];
- System.arraycopy(hb, 0, longdata, 0, hb.length);
- if (data != null && length > 0) {
- System.arraycopy(data, offset, longdata, hb.length, length);
- }
- return longdata;
- }
-
- private static byte[] buildResponse(byte[] data, int offset, int length) {
- byte[] longdata = new byte[length + 2];
- longdata[0] = 0x0d;
- longdata[1] = 0x0a;
- System.arraycopy(data, offset, longdata, 2, length);
- return longdata;
- }
-
- ServletOutputStream getServletOutputStream(final Map<String, String> headers) {
- LOG.log(Level.INFO, "getServletOutputStream()");
- return new ServletOutputStream() {
-
- @Override
- public void write(int b) throws IOException {
- byte[] data = new byte[1];
- data[0] = (byte)b;
- write(data, 0, 1);
- }
-
- @Override
- public void write(byte[] data, int offset, int length) throws IOException {
- if (headers.get("$flushed") == null) {
- data = buildResponse(headers, data, offset, length);
- headers.put("$flushed", "true");
- } else {
- data = buildResponse(data, offset, length);
- }
- webSocketConnection.sendMessage(data, 0, data.length);
- }
- };
- }
-
- OutputStream getOutputStream(final Map<String, String> headers) {
- LOG.log(Level.INFO, "getServletOutputStream()");
- return new OutputStream() {
-
- @Override
- public void write(int b) throws IOException {
- byte[] data = new byte[1];
- data[0] = (byte)b;
- write(data, 0, 1);
- }
-
- @Override
- public void write(byte[] data, int offset, int length) throws IOException {
- if (headers.get("$flushed") == null) {
- data = buildResponse(headers, data, offset, length);
- headers.put("$flushed", "true");
- } else {
- data = buildResponse(data, offset, length);
- }
- webSocketConnection.sendMessage(data, 0, data.length);
- }
- };
-
- }
-
- //
- static class WebSocketVirtualServletRequest implements HttpServletRequest {
- private ServletContext context;
- private JettyWebSocket websocket;
- private InputStream in;
- private Map<String, String> requestHeaders;
-
- public WebSocketVirtualServletRequest(ServletContext context, JettyWebSocket websocket, InputStream in)
- throws IOException {
- this.context = context;
- this.websocket = websocket;
- this.in = in;
-
- requestHeaders = readHeaders(in);
- String path = requestHeaders.get("$path");
- String origin = websocket.getRequestProperty("requestURI", String.class);
- if (path.startsWith(origin)) {
- //REVISIT for now, log it here and reject the request later.
- LOG.log(Level.WARNING, "invalid path: {0} not within {1}", new Object[]{path, origin});
- }
- }
-
- @Override
- public AsyncContext getAsyncContext() {
- return null;
- }
-
- @Override
- public Object getAttribute(String name) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "getAttribute({0})", name);
- }
- return null;
- }
-
- @Override
- public Enumeration<String> getAttributeNames() {
- LOG.log(Level.INFO, "getAttributeNames()");
- return null;
- }
-
- @Override
- public String getCharacterEncoding() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getCharacterEncoding()");
- return null;
- }
-
- @Override
- public int getContentLength() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getContentLength()");
- return 0;
- }
-
- @Override
- public String getContentType() {
- LOG.log(Level.INFO, "getContentType()");
- return requestHeaders.get("Content-Type");
- }
-
- @Override
- public DispatcherType getDispatcherType() {
- LOG.log(Level.INFO, "getDispatcherType()");
- return null;
- }
-
- @Override
- public ServletInputStream getInputStream() throws IOException {
- return new ServletInputStream() {
- @Override
- public int read() throws IOException {
- return in.read();
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- return in.read(b, off, len);
- }
- };
- }
-
- @Override
- public String getLocalAddr() {
- LOG.log(Level.INFO, "getLocalAddr()");
- return websocket.getRequestProperty("localAddr", String.class);
- }
-
- @Override
- public String getLocalName() {
- LOG.log(Level.INFO, "getLocalName()");
- return websocket.getRequestProperty("localName", String.class);
- }
-
- @Override
- public int getLocalPort() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getLocalPort()");
- return 0;
- }
-
- @Override
- public Locale getLocale() {
- LOG.log(Level.INFO, "getLocale()");
- return websocket.getRequestProperty("locale", Locale.class);
- }
-
- @Override
- public Enumeration<Locale> getLocales() {
- LOG.log(Level.INFO, "getLocales()");
- return CastUtils.cast(websocket.getRequestProperty("locales", Enumeration.class));
- }
-
- @Override
- public String getParameter(String name) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "getParameter({0})", name);
- }
- return null;
- }
-
- @Override
- public Map<String, String[]> getParameterMap() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getParameterMap()");
- return null;
- }
-
- @Override
- public Enumeration<String> getParameterNames() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getParameterNames()");
- return null;
- }
-
- @Override
- public String[] getParameterValues(String name) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "getParameterValues({0})", name);
- }
- return null;
- }
-
- @Override
- public String getProtocol() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getProtocol");
- return null;
- }
-
- @Override
- public BufferedReader getReader() throws IOException {
- LOG.log(Level.INFO, "getReader");
- return new BufferedReader(new InputStreamReader(in, "utf-8"));
- }
-
- @Override
- public String getRealPath(String path) {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getRealPath");
- return null;
- }
-
- @Override
- public String getRemoteAddr() {
- LOG.log(Level.INFO, "getRemoteAddr");
- return websocket.getRequestProperty("remoteAddr", String.class);
- }
-
- @Override
- public String getRemoteHost() {
- LOG.log(Level.INFO, "getRemoteHost");
- return websocket.getRequestProperty("remoteHost", String.class);
- }
-
- @Override
- public int getRemotePort() {
- LOG.log(Level.INFO, "getRemotePort");
- return websocket.getRequestProperty("remotePort", int.class);
- }
-
- @Override
- public RequestDispatcher getRequestDispatcher(String path) {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getRequestDispatcher");
- return null;
- }
-
- @Override
- public String getScheme() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getScheme");
- return null;
- }
-
- @Override
- public String getServerName() {
- return websocket.getRequestProperty("serverName", String.class);
- }
-
- @Override
- public int getServerPort() {
- LOG.log(Level.INFO, "getServerPort");
- return websocket.getRequestProperty("serverPoart", int.class);
- }
-
- @Override
- public ServletContext getServletContext() {
- LOG.log(Level.INFO, "getServletContext");
- return context;
- }
-
- @Override
- public boolean isAsyncStarted() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "isAsyncStarted");
- return false;
- }
-
- @Override
- public boolean isAsyncSupported() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "isAsyncSupported");
- return false;
- }
-
- @Override
- public boolean isSecure() {
- LOG.log(Level.INFO, "isSecure");
- return websocket.getRequestProperty("secure", boolean.class);
- }
-
- @Override
- public void removeAttribute(String name) {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "removeAttribute");
- }
-
- @Override
- public void setAttribute(String name, Object o) {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "setAttribute");
- }
-
- @Override
- public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
- LOG.log(Level.INFO, "setCharacterEncoding");
- // ignore as we stick to utf-8.
- }
-
- @Override
- public AsyncContext startAsync() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "startAsync");
- return null;
- }
-
- @Override
- public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "startAsync");
- return null;
- }
-
- @Override
- public boolean authenticate(HttpServletResponse servletResponse) throws IOException, ServletException {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "authenticate");
- return false;
- }
-
- @Override
- public String getAuthType() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getAuthType");
- return null;
- }
-
- @Override
- public String getContextPath() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getContextPath");
- return null;
- }
-
- @Override
- public Cookie[] getCookies() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getCookies");
- return null;
- }
-
- @Override
- public long getDateHeader(String name) {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getDateHeader");
- return 0;
- }
-
- @Override
- public String getHeader(String name) {
- LOG.log(Level.INFO, "getHeader");
- return requestHeaders.get(name);
- }
-
- @Override
- public Enumeration<String> getHeaderNames() {
- LOG.log(Level.INFO, "getHeaderNames");
- return Collections.enumeration(requestHeaders.keySet());
- }
-
- @Override
- public Enumeration<String> getHeaders(String name) {
- LOG.log(Level.INFO, "getHeaders");
- // our protocol assumes no multiple headers
- return Collections.enumeration(Arrays.asList(requestHeaders.get(name)));
- }
-
- @Override
- public int getIntHeader(String name) {
- LOG.log(Level.INFO, "getIntHeader");
- String v = requestHeaders.get(name);
- return v == null ? -1 : Integer.parseInt(v);
- }
-
- @Override
- public String getMethod() {
- LOG.log(Level.INFO, "getMethod");
- return requestHeaders.get("$method");
- }
-
- @Override
- public Part getPart(String name) throws IOException, ServletException {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getPart");
- return null;
- }
-
- @Override
- public Collection<Part> getParts() throws IOException, ServletException {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getParts");
- return null;
- }
-
- @Override
- public String getPathInfo() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getPathInfo");
- return null;
- }
-
- @Override
- public String getPathTranslated() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getPathTranslated");
- return null;
- }
-
- @Override
- public String getQueryString() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getQueryString");
- return null;
- }
-
- @Override
- public String getRemoteUser() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getRemoteUser");
- return null;
- }
-
- @Override
- public String getRequestURI() {
- LOG.log(Level.INFO, "getRequestURI");
- return requestHeaders.get("$path");
- }
-
- @Override
- public StringBuffer getRequestURL() {
- LOG.log(Level.INFO, "getRequestURL");
- String url = websocket.getRequestProperty("requestURL", String.class);
- String origin = websocket.getRequestProperty("requestURI", String.class);
- StringBuffer sb = new StringBuffer();
- String uri = getRequestURI();
- //REVISIT the way to reject the requeist uri that does not match the original request
- if (!uri.startsWith(origin)) {
- sb.append(url).append("invalid").append(uri);
- } else {
- sb.append(url).append(uri.substring(origin.length()));
- }
-
- return sb;
- }
-
- @Override
- public String getRequestedSessionId() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getRequestedSessionId");
- return null;
- }
-
- @Override
- public String getServletPath() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getServletPath");
- return null;
- }
-
- @Override
- public HttpSession getSession() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getSession");
- return null;
- }
-
- @Override
- public HttpSession getSession(boolean create) {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getSession");
- return null;
- }
-
- @Override
- public Principal getUserPrincipal() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getUserPrincipal");
- return null;
- }
-
- @Override
- public boolean isRequestedSessionIdFromCookie() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "isRequestedSessionIdFromCookie");
- return false;
- }
-
- @Override
- public boolean isRequestedSessionIdFromURL() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "isRequestedSessionIdFromURL");
- return false;
- }
-
- @Override
- public boolean isRequestedSessionIdFromUrl() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "isRequestedSessionIdFromUrl");
- return false;
- }
-
- @Override
- public boolean isRequestedSessionIdValid() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "isRequestedSessionIdValid");
- return false;
- }
-
- @Override
- public boolean isUserInRole(String role) {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "isUserInRole");
- return false;
- }
-
- @Override
- public void login(String username, String password) throws ServletException {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "login");
-
- }
-
- @Override
- public void logout() throws ServletException {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "logout");
-
- }
- }
-
- //TODO need to make the header setting to be written to the body (as symmetric to the request behavior)
- static class WebSocketVirtualServletResponse implements HttpServletResponse {
- private JettyWebSocket websocket;
- private Map<String, String> responseHeaders;
- private boolean flushed;
-
- public WebSocketVirtualServletResponse(JettyWebSocket websocket) {
- this.websocket = websocket;
- this.responseHeaders = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
- }
-
- @Override
- public void flushBuffer() throws IOException {
- LOG.log(Level.INFO, "flushBuffer()");
- if (!flushed) {
- //REVISIT this mechanism to determine if the headers have been flushed
- if (responseHeaders.get("$flushed") == null) {
- byte[] data = buildResponse(responseHeaders, null, 0, 0);
- websocket.write(data, 0, data.length);
- responseHeaders.put("$flushed", "true");
- }
- flushed = true;
- }
- }
-
- @Override
- public int getBufferSize() {
- LOG.log(Level.INFO, "getBufferSize()");
- return 0;
- }
-
- @Override
- public String getCharacterEncoding() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getCharacterEncoding()");
- return null;
- }
-
- @Override
- public String getContentType() {
- LOG.log(Level.INFO, "getContentType()");
- return responseHeaders.get("Content-Type");
- }
-
- @Override
- public Locale getLocale() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getLocale");
- return null;
- }
-
- @Override
- public ServletOutputStream getOutputStream() throws IOException {
- LOG.log(Level.INFO, "getOutputStream()");
- return websocket.getServletOutputStream(responseHeaders);
- }
-
- @Override
- public PrintWriter getWriter() throws IOException {
- LOG.log(Level.INFO, "getWriter()");
- return new PrintWriter(websocket.getOutputStream(responseHeaders));
- }
-
- @Override
- public boolean isCommitted() {
- return false;
- }
-
- @Override
- public void reset() {
- }
-
- @Override
- public void resetBuffer() {
- LOG.log(Level.INFO, "resetBuffer()");
- }
-
- @Override
- public void setBufferSize(int size) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setBufferSize({0})", size);
- }
- }
-
- @Override
- public void setCharacterEncoding(String charset) {
- // TODO
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setCharacterEncoding({0})", charset);
- }
- }
-
- @Override
- public void setContentLength(int len) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setContentLength({0})", len);
- }
- responseHeaders.put("Content-Length", Integer.toString(len));
- }
-
- @Override
- public void setContentType(String type) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setContentType({0})", type);
- }
- responseHeaders.put("Content-Type", type);
- }
-
- @Override
- public void setLocale(Locale loc) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setLocale({0})", loc);
- }
- }
-
- @Override
- public void addCookie(Cookie cookie) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "addCookie({0})", cookie);
- }
- }
-
- @Override
- public void addDateHeader(String name, long date) {
- // TODO
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "addDateHeader({0}, {1})", new Object[]{name, date});
- }
- }
-
- @Override
- public void addHeader(String name, String value) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "addHeader({0}, {1})", new Object[]{name, value});
- }
- responseHeaders.put(name, value);
- }
-
- @Override
- public void addIntHeader(String name, int value) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "addIntHeader({0}, {1})", new Object[]{name, value});
- }
- responseHeaders.put(name, Integer.toString(value));
- }
-
- @Override
- public boolean containsHeader(String name) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "containsHeader({0})", name);
- }
- return false;
- }
-
- @Override
- public String encodeRedirectURL(String url) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "encodeRedirectURL({0})", url);
- }
- return null;
- }
-
- @Override
- public String encodeRedirectUrl(String url) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "encodeRedirectUrl({0})", url);
- }
- return null;
- }
-
- @Override
- public String encodeURL(String url) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "encodeURL({0})", url);
- }
- return null;
- }
-
- @Override
- public String encodeUrl(String url) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "encodeUrl({0})", url);
- }
- return null;
- }
-
- @Override
- public String getHeader(String name) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "getHeader({0})", name);
- }
- return null;
- }
-
- @Override
- public Collection<String> getHeaderNames() {
- // TODO Auto-generated method stub
- LOG.log(Level.INFO, "getHeaderNames()");
- return null;
- }
-
- @Override
- public Collection<String> getHeaders(String name) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "getHeaders({0})", name);
- }
- return null;
- }
-
- @Override
- public int getStatus() {
- LOG.log(Level.INFO, "getStatus()");
- String v = responseHeaders.get("$sc");
- return v == null ? 200 : Integer.parseInt(v);
- }
-
- @Override
- public void sendError(int sc) throws IOException {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "sendError{0}", sc);
- }
- responseHeaders.put("$sc", Integer.toString(sc));
- }
-
- @Override
- public void sendError(int sc, String msg) throws IOException {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "sendError({0}, {1})", new Object[]{sc, msg});
- }
- responseHeaders.put("$sc", Integer.toString(sc));
- responseHeaders.put("$sm", msg);
- }
-
- @Override
- public void sendRedirect(String location) throws IOException {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "sendRedirect({0})", location);
- }
- }
-
- @Override
- public void setDateHeader(String name, long date) {
- // ignore
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setDateHeader({0}, {1})", new Object[]{name, date});
- }
- }
-
- @Override
- public void setHeader(String name, String value) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setHeader({0}, {1})", new Object[]{name, value});
- }
- }
-
- @Override
- public void setIntHeader(String name, int value) {
- // TODO Auto-generated method stub
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setIntHeader({0}, {1})", new Object[]{name, value});
- }
- }
-
- @Override
- public void setStatus(int sc) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setStatus({0})", sc);
- }
- responseHeaders.put("$sc", Integer.toString(sc));
- }
-
- @Override
- public void setStatus(int sc, String sm) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, "setStatus({0}, {1})", new Object[]{sc, sm});
- }
- responseHeaders.put("$sc", Integer.toString(sc));
- responseHeaders.put("$sm", sm);
- }
- }
-
- /*
- * We accept only a restricted syntax as we have the syntax in our control.
- * Do not allow multiline or line-wrapped headers.
- * Do not allow charset other than utf-8. (although i would have preferred iso-8859-1 ;-)
- */
- private static Map<String, String> readHeaders(InputStream in) throws IOException {
- Map<String, String> headers = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
- // read the request line
- String line = readLine(in);
- int del = line.indexOf(' ');
- if (del < 0) {
- throw new IOException("invalid request: " + line);
- }
- headers.put("$method", line.substring(0, del).trim());
- headers.put("$path", line.substring(del + 1).trim());
-
- // read headers
- while ((line = readLine(in)) != null) {
- if (line.length() > 0) {
- del = line.indexOf(':');
- if (del < 0) {
- headers.put(line.trim(), "");
- } else {
- headers.put(line.substring(0, del).trim(), line.substring(del + 1).trim());
- }
- }
- }
-
- return headers;
- }
-
- @SuppressWarnings("unchecked")
- private static <T> T getValue(Map<String, Object> properties, String name, Class<T> cls) {
- return (T)properties.get(name);
- }
-
-
- ///// this is copied from AttachmentDeserializer with a minor change. think about putting this method to IOUtils
- private static String readLine(InputStream in) throws IOException {
- StringBuilder buffer = new StringBuilder(128);
-
- int c;
-
- while ((c = in.read()) != -1) {
- // a linefeed is a terminator, always.
- if (c == '\n') {
- break;
- } else if (c == '\r') {
- //just ignore the CR. The next character SHOULD be an NL. If not, we're
- //just going to discard this
- continue;
- } else {
- // just add to the buffer
- buffer.append((char)c);
- }
- }
-
- // no characters found...this was either an eof or a null line.
- if (buffer.length() == 0) {
- return null;
- }
-
- return buffer.toString();
- }
- ///// END
-}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/CXFNonSpringServlet.java
----------------------------------------------------------------------
diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/CXFNonSpringServlet.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/CXFNonSpringServlet.java
index 2a6b8a2..e8e2c45 100644
--- a/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/CXFNonSpringServlet.java
+++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/CXFNonSpringServlet.java
@@ -92,7 +92,7 @@ public class CXFNonSpringServlet extends AbstractHTTPServlet {
return bus.getExtension(ClassLoader.class);
}
- private static DestinationRegistry getDestinationRegistryFromBus(Bus bus) {
+ protected DestinationRegistry getDestinationRegistryFromBus(Bus bus) {
DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class);
try {
DestinationFactory df = dfm
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/pom.xml
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/pom.xml b/rt/transports/websocket/pom.xml
new file mode 100644
index 0000000..346c32e
--- /dev/null
+++ b/rt/transports/websocket/pom.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cxf-rt-transports-websocket</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache CXF Runtime WebSocket Transport</name>
+ <description>Apache CXF Runtime WebSocket Transport</description>
+ <url>http://cxf.apache.org</url>
+ <parent>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ <relativePath>../../../parent/pom.xml</relativePath>
+ </parent>
+ <properties>
+<!--
+ <cxf.bundle.activator>org.apache.cxf.transport.websocket.osgi.WebSocketTransportActivator</cxf.bundle.activator>
+ org.eclipse.jetty.websocket;version="${cxf.jetty.osgi.version}";resolution:=optional,
+
+-->
+ <cxf.osgi.import>
+ javax.servlet*;version="${cxf.osgi.javax.servlet.version}",
+ org.eclipse.jetty*;version="${cxf.jetty.osgi.version}",
+ org.apache.aries*;version="${cxf.aries.version.range}";resolution:=optional,
+ org.springframework*;resolution:="optional";version="${cxf.osgi.spring.version}"
+ </cxf.osgi.import>
+ <cxf.osgi.dynamic.import>
+ org.eclipse.jetty.jmx
+ </cxf.osgi.dynamic.import>
+ <!-- keep in sync with services exported in activator -->
+ <cxf.export.service>
+ org.apache.aries.blueprint.NamespaceHandler;osgi.service.blueprint.namespace="http://cxf.apache.org/transports/websocket/configuration"
+ </cxf.export.service>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.aries.blueprint</groupId>
+ <artifactId>org.apache.aries.blueprint.core</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-transports-http</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-transports-http-jetty</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${cxf.jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-security</artifactId>
+ <version>${cxf.jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ <version>${cxf.jetty.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jmx</artifactId>
+ <version>${cxf.jetty.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>${cxf.servlet-api.group}</groupId>
+ <artifactId>${cxf.servlet-api.artifact}</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-testutils</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-wsdl</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/WebSocketDestinationFactory.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/WebSocketDestinationFactory.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/WebSocketDestinationFactory.java
new file mode 100644
index 0000000..1c539d6
--- /dev/null
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/WebSocketDestinationFactory.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.transport.websocket;
+
+import java.io.IOException;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.injection.NoJSR250Annotations;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.http.AbstractHTTPDestination;
+import org.apache.cxf.transport.http.DestinationRegistry;
+import org.apache.cxf.transport.http.HttpDestinationFactory;
+import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngineFactory;
+import org.apache.cxf.transport.servlet.ServletDestination;
+import org.apache.cxf.transport.websocket.jetty.JettyWebSocketDestination;
+
+@NoJSR250Annotations()
+public class WebSocketDestinationFactory implements HttpDestinationFactory {
+
+ public AbstractHTTPDestination createDestination(EndpointInfo endpointInfo, Bus bus,
+ DestinationRegistry registry) throws IOException {
+
+ if (endpointInfo.getAddress().startsWith("ws")) {
+ //TODO for now jetty specific,
+ JettyHTTPServerEngineFactory serverEngineFactory = bus
+ .getExtension(JettyHTTPServerEngineFactory.class);
+ return new JettyWebSocketDestination(bus, registry, endpointInfo, serverEngineFactory);
+ } else {
+ return new ServletDestination(bus, registry, endpointInfo, endpointInfo.getAddress());
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/WebSocketTransportFactory.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/WebSocketTransportFactory.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/WebSocketTransportFactory.java
new file mode 100644
index 0000000..b90aded
--- /dev/null
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/WebSocketTransportFactory.java
@@ -0,0 +1,135 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.websocket;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.injection.NoJSR250Annotations;
+import org.apache.cxf.configuration.Configurer;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.AbstractTransportFactory;
+import org.apache.cxf.transport.Conduit;
+import org.apache.cxf.transport.ConduitInitiator;
+import org.apache.cxf.transport.Destination;
+import org.apache.cxf.transport.DestinationFactory;
+import org.apache.cxf.transport.http.AbstractHTTPDestination;
+import org.apache.cxf.transport.http.DestinationRegistry;
+import org.apache.cxf.transport.http.DestinationRegistryImpl;
+import org.apache.cxf.transport.http.HttpDestinationFactory;
+import org.apache.cxf.ws.addressing.EndpointReferenceType;
+
+@NoJSR250Annotations
+public class WebSocketTransportFactory extends AbstractTransportFactory implements ConduitInitiator,
+ DestinationFactory {
+
+ public static final List<String> DEFAULT_NAMESPACES
+ = Arrays.asList(
+ "http://cxf.apache.org/transports/websockt",
+ "http://cxf.apache.org/transports/websocket/configuration"
+ );
+
+ private static final Set<String> URI_PREFIXES = new HashSet<String>();
+ static {
+ URI_PREFIXES.add("ws://");
+ URI_PREFIXES.add("wss://");
+ }
+
+ protected final DestinationRegistry registry;
+
+ protected final HttpDestinationFactory factory = new WebSocketDestinationFactory();
+
+ public WebSocketTransportFactory() {
+ this(new DestinationRegistryImpl());
+ }
+
+ public WebSocketTransportFactory(DestinationRegistry registry) {
+ super(DEFAULT_NAMESPACES);
+ if (registry == null) {
+ registry = new DestinationRegistryImpl();
+ }
+ this.registry = registry;
+ }
+ public DestinationRegistry getRegistry() {
+ return registry;
+ }
+
+ /**
+ * This call uses the Configurer from the bus to configure
+ * a bean.
+ *
+ * @param bean
+ */
+ protected void configure(Bus b, Object bean) {
+ configure(b, bean, null, null);
+ }
+
+ protected void configure(Bus bus, Object bean, String name, String extraName) {
+ Configurer configurer = bus.getExtension(Configurer.class);
+ if (null != configurer) {
+ configurer.configureBean(name, bean);
+ if (extraName != null) {
+ configurer.configureBean(extraName, bean);
+ }
+ }
+ }
+
+
+ public Conduit getConduit(EndpointInfo endpointInfo, Bus b) throws IOException {
+ return getConduit(endpointInfo, endpointInfo.getTarget(), b);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Conduit getConduit(EndpointInfo endpointInfo, EndpointReferenceType target, Bus bus)
+ throws IOException {
+ //TODO add on implementation using ning
+ throw new RuntimeException("not implemented yet");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Destination getDestination(EndpointInfo endpointInfo, Bus bus) throws IOException {
+ if (endpointInfo == null) {
+ throw new IllegalArgumentException("EndpointInfo cannot be null");
+ }
+ synchronized (registry) {
+ AbstractHTTPDestination d = registry.getDestinationForPath(endpointInfo.getAddress());
+ if (d == null) {
+ d = factory.createDestination(endpointInfo, bus, registry);
+ registry.addDestination(d);
+ configure(bus, d);
+ d.finalizeConfig();
+ }
+ return d;
+ }
+ }
+
+ public Set<String> getUriPrefixes() {
+ return URI_PREFIXES;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFJettyWebSocketServlet.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFJettyWebSocketServlet.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFJettyWebSocketServlet.java
new file mode 100644
index 0000000..a3e68df
--- /dev/null
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFJettyWebSocketServlet.java
@@ -0,0 +1,110 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.websocket.jetty;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusException;
+import org.apache.cxf.transport.DestinationFactory;
+import org.apache.cxf.transport.DestinationFactoryManager;
+import org.apache.cxf.transport.http.DestinationRegistry;
+import org.apache.cxf.transport.servlet.CXFServlet;
+import org.apache.cxf.transport.websocket.WebSocketTransportFactory;
+import org.eclipse.jetty.websocket.WebSocket;
+import org.eclipse.jetty.websocket.WebSocketFactory;
+
+/**
+ *
+ */
+public class CXFJettyWebSocketServlet extends CXFServlet
+ implements CXFJettyWebSocketServletService, WebSocketFactory.Acceptor {
+ private static final long serialVersionUID = 3955992016049976728L;
+ private JettyWebSocketManager websocketManager;
+
+ public CXFJettyWebSocketServlet() {
+ }
+
+ public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
+ return new JettyWebSocket(websocketManager, request, protocol);
+ }
+
+
+ public boolean checkOrigin(HttpServletRequest request, String origin) {
+ return true;
+ }
+
+ @Override
+ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
+ if (websocketManager.acceptWebSocket(req, res)) {
+ return;
+ }
+ super.service(req, res);
+ }
+
+ @Override
+ public void serviceInternal(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
+ super.service(req, resp);
+ }
+
+
+ @Override
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ websocketManager = new JettyWebSocketManager();
+ websocketManager.init(this, sc);
+ }
+
+ @Override
+ protected DestinationRegistry getDestinationRegistryFromBus(Bus bus) {
+ DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class);
+ try {
+ DestinationFactory df = dfm
+ .getDestinationFactory("http://cxf.apache.org/transports/websocket/configuration");
+ if (df instanceof WebSocketTransportFactory) {
+ WebSocketTransportFactory transportFactory = (WebSocketTransportFactory)df;
+ return transportFactory.getRegistry();
+ }
+ } catch (BusException e) {
+ // why are we throwing a busexception if the DF isn't found?
+ }
+ return null;
+ }
+
+
+
+ @Override
+ public void destroy() {
+ try {
+ websocketManager.destroy();
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ super.destroy();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFJettyWebSocketServletService.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFJettyWebSocketServletService.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFJettyWebSocketServletService.java
new file mode 100644
index 0000000..89e18c2
--- /dev/null
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFJettyWebSocketServletService.java
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.websocket.jetty;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ *
+ */
+interface CXFJettyWebSocketServletService {
+ void serviceInternal(ServletRequest req, ServletResponse resp) throws ServletException, IOException;
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/8fe4fc13/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFNonSpringJettyWebSocketServlet.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFNonSpringJettyWebSocketServlet.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFNonSpringJettyWebSocketServlet.java
new file mode 100644
index 0000000..74dce02
--- /dev/null
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/jetty/CXFNonSpringJettyWebSocketServlet.java
@@ -0,0 +1,116 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.websocket.jetty;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusException;
+import org.apache.cxf.transport.DestinationFactory;
+import org.apache.cxf.transport.DestinationFactoryManager;
+import org.apache.cxf.transport.http.DestinationRegistry;
+import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
+import org.apache.cxf.transport.websocket.WebSocketTransportFactory;
+import org.eclipse.jetty.websocket.WebSocket;
+import org.eclipse.jetty.websocket.WebSocketFactory;
+
+/**
+ *
+ */
+public class CXFNonSpringJettyWebSocketServlet extends CXFNonSpringServlet
+ implements CXFJettyWebSocketServletService, WebSocketFactory.Acceptor {
+ private static final long serialVersionUID = 6921073894009215482L;
+ private JettyWebSocketManager websocketManager;
+
+ public CXFNonSpringJettyWebSocketServlet() {
+ }
+
+ public CXFNonSpringJettyWebSocketServlet(DestinationRegistry destinationRegistry, boolean loadBus) {
+ super(destinationRegistry, loadBus);
+ }
+
+ public CXFNonSpringJettyWebSocketServlet(DestinationRegistry destinationRegistry) {
+ super(destinationRegistry);
+ }
+
+ public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
+ return new JettyWebSocket(websocketManager, request, protocol);
+ }
+
+
+ public boolean checkOrigin(HttpServletRequest request, String origin) {
+ return true;
+ }
+
+ @Override
+ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
+ if (websocketManager.acceptWebSocket(req, res)) {
+ return;
+ }
+ super.service(req, res);
+ }
+
+ @Override
+ public void serviceInternal(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
+ super.service(req, resp);
+ }
+
+
+ @Override
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ websocketManager = new JettyWebSocketManager();
+ websocketManager.init(this, sc);
+ }
+
+ @Override
+ protected DestinationRegistry getDestinationRegistryFromBus(Bus bus) {
+ DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class);
+ try {
+ DestinationFactory df = dfm
+ .getDestinationFactory("http://cxf.apache.org/transports/websocket/configuration");
+ if (df instanceof WebSocketTransportFactory) {
+ WebSocketTransportFactory transportFactory = (WebSocketTransportFactory)df;
+ return transportFactory.getRegistry();
+ }
+ } catch (BusException e) {
+ // why are we throwing a busexception if the DF isn't found?
+ }
+ return null;
+ }
+
+ @Override
+ public void destroy() {
+ try {
+ websocketManager.destroy();
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ super.destroy();
+ }
+ }
+}