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