001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.protocol.ws.javax; 018 019import java.net.URI; 020import java.security.Principal; 021import java.util.List; 022import java.util.Map; 023 024import javax.websocket.Decoder; 025import javax.websocket.Encoder; 026import javax.websocket.Extension; 027import javax.websocket.HandshakeResponse; 028import javax.websocket.server.HandshakeRequest; 029import javax.websocket.server.ServerEndpointConfig; 030 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033 034/** 035 * A ServerEndpointConfig that uses custom Configurator to collect 036 * all available information from the passed HandshakeRequest 037 */ 038public class WicketServerEndpointConfig implements ServerEndpointConfig 039{ 040 /** 041 * A fake mount path used for WebSocket endpoint. 042 * WicketFilter should not process this path. 043 * @see org.apache.wicket.protocol.http.WicketFilter#ignorePaths 044 */ 045 static final String WICKET_WEB_SOCKET_PATH = "/wicket/websocket"; 046 047 private final ServerEndpointConfig delegate; 048 049 private Configurator configurator; 050 051 public WicketServerEndpointConfig() 052 { 053 this.delegate = ServerEndpointConfig.Builder.create(WicketEndpoint.class, WICKET_WEB_SOCKET_PATH).build(); 054 } 055 056 @Override 057 public Class<?> getEndpointClass() 058 { 059 return delegate.getEndpointClass(); 060 } 061 062 @Override 063 public String getPath() 064 { 065 return delegate.getPath(); 066 } 067 068 @Override 069 public List<String> getSubprotocols() 070 { 071 return delegate.getSubprotocols(); 072 } 073 074 @Override 075 public List<Extension> getExtensions() 076 { 077 return delegate.getExtensions(); 078 } 079 080 @Override 081 public Configurator getConfigurator() 082 { 083 if (configurator == null) 084 { 085 configurator = new JavaxWebSocketConfigurator(delegate.getConfigurator()); 086 } 087 return configurator; 088 } 089 090 @Override 091 public List<Class<? extends Encoder>> getEncoders() 092 { 093 return delegate.getEncoders(); 094 } 095 096 @Override 097 public List<Class<? extends Decoder>> getDecoders() 098 { 099 return delegate.getDecoders(); 100 } 101 102 @Override 103 public Map<String, Object> getUserProperties() 104 { 105 return delegate.getUserProperties(); 106 } 107 108 /** 109 * A custom Configurator that collects all available information from the HandshakeRequest 110 */ 111 private static class JavaxWebSocketConfigurator extends ServerEndpointConfig.Configurator 112 { 113 private static final Logger LOG = LoggerFactory.getLogger(JavaxWebSocketConfigurator.class); 114 115 private final ServerEndpointConfig.Configurator delegate; 116 117 public JavaxWebSocketConfigurator(ServerEndpointConfig.Configurator delegate) 118 { 119 this.delegate = delegate; 120 } 121 122 @Override 123 public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) 124 { 125 delegate.modifyHandshake(sec, request, response); 126 127 // do not store null keys/values because Tomcat 8 uses ConcurrentMap for UserProperties 128 129 Map<String, Object> userProperties = sec.getUserProperties(); 130 Object httpSession = request.getHttpSession(); 131 LOG.trace("httpSession: {}", httpSession); 132 if (httpSession != null) 133 { 134 userProperties.put("session", httpSession); 135 } 136 137 Map<String, List<String>> headers = request.getHeaders(); 138 LOG.trace("headers: {}", headers); 139 if (headers != null) 140 { 141 userProperties.put("headers", headers); 142 } 143 144 145 Map<String, List<String>> parameterMap = request.getParameterMap(); 146 LOG.trace("parameterMap: {}", parameterMap); 147 if (parameterMap != null) 148 { 149 userProperties.put("parameterMap", parameterMap); 150 } 151 152 153 String queryString = request.getQueryString(); 154 LOG.trace("queryString: {}", queryString); 155 if (queryString != null) 156 { 157 userProperties.put("queryString", queryString); 158 } 159 160 161 URI requestURI = request.getRequestURI(); 162 LOG.trace("requestURI: {}", requestURI); 163 if (requestURI != null) 164 { 165 userProperties.put("requestURI", requestURI); 166 } 167 168 Principal userPrincipal = request.getUserPrincipal(); 169 LOG.trace("userPrincipal: {}", userPrincipal); 170 if (userPrincipal != null) 171 { 172 userProperties.put("userPrincipal", userPrincipal); 173 } 174 } 175 176 @Override 177 public String getNegotiatedSubprotocol(List<String> supported, List<String> requested) 178 { 179 return delegate.getNegotiatedSubprotocol(supported, requested); 180 } 181 182 @Override 183 public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested) 184 { 185 return delegate.getNegotiatedExtensions(installed, requested); 186 } 187 188 @Override 189 public boolean checkOrigin(String originHeaderValue) 190 { 191 return delegate.checkOrigin(originHeaderValue); 192 } 193 194 @Override 195 public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException 196 { 197 return delegate.getEndpointInstance(endpointClass); 198 } 199 } 200}