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.activemq.transport; 018 019import java.io.File; 020import java.net.InetAddress; 021import java.net.URI; 022import java.util.Map; 023 024import org.apache.activemq.util.InetAddressUtil; 025import org.apache.activemq.util.IntrospectionSupport; 026import org.eclipse.jetty.security.ConstraintMapping; 027import org.eclipse.jetty.security.ConstraintSecurityHandler; 028import org.eclipse.jetty.server.Connector; 029import org.eclipse.jetty.server.Server; 030import org.eclipse.jetty.util.resource.Resource; 031import org.eclipse.jetty.util.security.Constraint; 032import org.eclipse.jetty.xml.XmlConfiguration; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036abstract public class WebTransportServerSupport extends TransportServerSupport { 037 038 private final static Logger LOG = LoggerFactory.getLogger(WebTransportServerSupport.class); 039 040 protected URI bindAddress; 041 protected Server server; 042 protected Connector connector; 043 protected SocketConnectorFactory socketConnectorFactory; 044 protected String host; 045 protected final HttpOptions httpOptions = new HttpOptions(); 046 protected final JettyOptions jettyOptions = new JettyOptions(); 047 048 public WebTransportServerSupport(URI location) { 049 super(location); 050 } 051 052 private <T> void setConnectorProperty(String name, Class<T> type, T value) throws Exception { 053 connector.getClass().getMethod("set" + name, type).invoke(connector, value); 054 } 055 056 protected void createServer() { 057 LOG.info("Starting Jetty server"); 058 if (jettyOptions.getConfig() != null) { 059 try { 060 LOG.info("Configuring Jetty server using {}", jettyOptions.getConfig()); 061 File file = new File(jettyOptions.getConfig()); 062 if (!file.exists()) { 063 throw new IllegalArgumentException("Jetty XML not found: " + file.getAbsolutePath()); 064 } 065 XmlConfiguration xmlConfiguration = new XmlConfiguration(Resource.newResource(file)); 066 server = (Server) xmlConfiguration.configure(); 067 } catch (Throwable t) { 068 throw new IllegalStateException("Jetty configuration can't be loaded", t); 069 } 070 } else { 071 server = new Server(); 072 } 073 try { 074 server.getClass().getMethod("setStopTimeout", Long.TYPE).invoke(server, 500l); 075 } catch (Throwable t) { 076 //ignore, jetty 8. 077 } 078 } 079 080 public URI bind() throws Exception { 081 URI bind = getBindLocation(); 082 String bindHost = bind.getHost(); 083 bindHost = (bindHost == null || bindHost.length() == 0) ? "localhost" : bindHost; 084 InetAddress addr = InetAddress.getByName(bindHost); 085 host = addr.getCanonicalHostName(); 086 if (server.getConnectors().length == 0) { 087 LOG.info("Creating Jetty connector"); 088 setConnectorProperty("Host", String.class, host); 089 setConnectorProperty("Port", Integer.TYPE, bindAddress.getPort()); 090 server.addConnector(connector); 091 } else { 092 LOG.info("Using Jetty configured connector"); 093 connector = server.getConnectors()[0]; 094 for (Connector c : server.getConnectors()) { 095 if (c.getName() != null && c.getName().equalsIgnoreCase("activemq")) { 096 connector = c; 097 } 098 } 099 setConnectorProperty("Host", String.class, host); 100 setConnectorProperty("Port", Integer.TYPE, bindAddress.getPort()); 101 server.addConnector(connector); 102 } 103 if (addr.isAnyLocalAddress()) { 104 host = InetAddressUtil.getLocalHostName(); 105 } 106 URI boundUri = new URI(bind.getScheme(), bind.getUserInfo(), host, bindAddress.getPort(), bind.getPath(), bind.getQuery(), bind.getFragment()); 107 setConnectURI(boundUri); 108 return boundUri; 109 } 110 111 protected void configureTraceMethod(ConstraintSecurityHandler securityHandler, 112 boolean enableTrace) { 113 Constraint constraint = new Constraint(); 114 constraint.setName("trace-security"); 115 //If enableTrace is true, then we want to set authenticate to false to allow it 116 constraint.setAuthenticate(!enableTrace); 117 ConstraintMapping mapping = new ConstraintMapping(); 118 mapping.setConstraint(constraint); 119 mapping.setMethod("TRACE"); 120 mapping.setPathSpec("/"); 121 securityHandler.addConstraintMapping(mapping); 122 } 123 124 public void setHttpOptions(Map<String, Object> options) { 125 if (options != null) { 126 IntrospectionSupport.setProperties(this.httpOptions, options); 127 } 128 } 129 130 public void setJettyOptions(Map<String, Object> options) { 131 if (options != null) { 132 IntrospectionSupport.setProperties(this.jettyOptions, options); 133 } 134 } 135 136 protected static class HttpOptions { 137 private boolean enableTrace = false; 138 139 public boolean isEnableTrace() { 140 return enableTrace; 141 } 142 143 public void setEnableTrace(boolean enableTrace) { 144 this.enableTrace = enableTrace; 145 } 146 } 147 148 protected static class JettyOptions { 149 private String config; 150 151 public String getConfig() { 152 return config; 153 } 154 155 public void setConfig(String config) { 156 this.config = config; 157 } 158 } 159 160}