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 */ 017 018package org.apache.activemq.transport.ws; 019 020import java.net.InetSocketAddress; 021import java.net.URI; 022import java.util.Map; 023 024import javax.servlet.Servlet; 025 026import org.apache.activemq.command.BrokerInfo; 027import org.apache.activemq.transport.SocketConnectorFactory; 028import org.apache.activemq.transport.WebTransportServerSupport; 029import org.apache.activemq.transport.ws.jetty9.WSServlet; 030import org.apache.activemq.util.IntrospectionSupport; 031import org.apache.activemq.util.ServiceStopper; 032import org.eclipse.jetty.server.Connector; 033import org.eclipse.jetty.server.Server; 034import org.eclipse.jetty.servlet.ServletContextHandler; 035import org.eclipse.jetty.servlet.ServletHolder; 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039/** 040 * Creates a web server and registers web socket server 041 * 042 */ 043public class WSTransportServer extends WebTransportServerSupport { 044 045 private static final Logger LOG = LoggerFactory.getLogger(WSTransportServer.class); 046 047 public WSTransportServer(URI location) { 048 super(location); 049 this.bindAddress = location; 050 socketConnectorFactory = new SocketConnectorFactory(); 051 } 052 053 @Override 054 protected void doStart() throws Exception { 055 createServer(); 056 057 if (connector == null) { 058 connector = socketConnectorFactory.createConnector(server); 059 } 060 061 URI boundTo = bind(); 062 063 ServletContextHandler contextHandler = 064 new ServletContextHandler(server, "/", ServletContextHandler.NO_SECURITY); 065 066 ServletHolder holder = new ServletHolder(); 067 Map<String, Object> webSocketOptions = IntrospectionSupport.extractProperties(transportOptions, "websocket."); 068 for(Map.Entry<String,Object> webSocketEntry : webSocketOptions.entrySet()) { 069 Object value = webSocketEntry.getValue(); 070 if (value != null) { 071 holder.setInitParameter(webSocketEntry.getKey(), value.toString()); 072 } 073 } 074 075 holder.setServlet(createWSServlet()); 076 contextHandler.addServlet(holder, "/"); 077 078 contextHandler.setAttribute("acceptListener", getAcceptListener()); 079 080 server.start(); 081 082 // Update the Connect To URI with our actual location in case the configured port 083 // was set to zero so that we report the actual port we are listening on. 084 085 int port = getConnectorLocalPort(); 086 if (port == -1) { 087 port = boundTo.getPort(); 088 } 089 090 setConnectURI(new URI(boundTo.getScheme(), 091 boundTo.getUserInfo(), 092 boundTo.getHost(), 093 port, 094 boundTo.getPath(), 095 boundTo.getQuery(), 096 boundTo.getFragment())); 097 098 LOG.info("Listening for connections at {}", getConnectURI()); 099 } 100 101 private Servlet createWSServlet() throws Exception { 102 WSServlet servlet = new WSServlet(); 103 servlet.setTransportOptions(transportOptions); 104 return servlet; 105 } 106 107 private int getConnectorLocalPort() throws Exception { 108 return (Integer)connector.getClass().getMethod("getLocalPort").invoke(connector); 109 } 110 111 @Override 112 protected void doStop(ServiceStopper stopper) throws Exception { 113 Server temp = server; 114 server = null; 115 if (temp != null) { 116 temp.stop(); 117 } 118 } 119 120 @Override 121 public InetSocketAddress getSocketAddress() { 122 return null; 123 } 124 125 @Override 126 public void setBrokerInfo(BrokerInfo brokerInfo) { 127 } 128 129 protected void setConnector(Connector connector) { 130 this.connector = connector; 131 } 132 133 @Override 134 public void setTransportOption(Map<String, Object> transportOptions) { 135 Map<String, Object> socketOptions = IntrospectionSupport.extractProperties(transportOptions, "transport."); 136 socketConnectorFactory.setTransportOptions(socketOptions); 137 super.setTransportOption(socketOptions); 138 } 139 140 @Override 141 public boolean isSslServer() { 142 return false; 143 } 144}