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.tcp; 018 019import java.io.IOException; 020import java.net.URI; 021import java.net.URISyntaxException; 022import java.net.UnknownHostException; 023import java.util.HashMap; 024import java.util.Map; 025 026import javax.net.ServerSocketFactory; 027import javax.net.SocketFactory; 028import javax.net.ssl.SSLServerSocketFactory; 029import javax.net.ssl.SSLSocketFactory; 030 031import org.apache.activemq.broker.SslContext; 032import org.apache.activemq.transport.Transport; 033import org.apache.activemq.transport.TransportServer; 034import org.apache.activemq.util.IOExceptionSupport; 035import org.apache.activemq.util.IntrospectionSupport; 036import org.apache.activemq.util.URISupport; 037import org.apache.activemq.wireformat.WireFormat; 038import org.slf4j.Logger; 039import org.slf4j.LoggerFactory; 040 041/** 042 * An implementation of the TcpTransportFactory using SSL. The major 043 * contribution from this class is that it is aware of SslTransportServer and 044 * SslTransport classes. All Transports and TransportServers created from this 045 * factory will have their needClientAuth option set to false. 046 */ 047public class SslTransportFactory extends TcpTransportFactory { 048 049 private static final Logger LOG = LoggerFactory.getLogger(SslTransportFactory.class); 050 051 /** 052 * Overriding to use SslTransportServer and allow for proper reflection. 053 */ 054 @Override 055 public TransportServer doBind(final URI location) throws IOException { 056 try { 057 Map<String, String> options = new HashMap<String, String>(URISupport.parseParameters(location)); 058 059 ServerSocketFactory serverSocketFactory = createServerSocketFactory(); 060 SslTransportServer server = createSslTransportServer(location, (SSLServerSocketFactory)serverSocketFactory); 061 server.setWireFormatFactory(createWireFormatFactory(options)); 062 IntrospectionSupport.setProperties(server, options); 063 Map<String, Object> transportOptions = IntrospectionSupport.extractProperties(options, "transport."); 064 server.setTransportOption(transportOptions); 065 server.bind(); 066 067 return server; 068 } catch (URISyntaxException e) { 069 throw IOExceptionSupport.create(e); 070 } 071 } 072 073 /** 074 * Allows subclasses of SslTransportFactory to create custom instances of 075 * SslTransportServer. 076 * 077 * @param location 078 * @param serverSocketFactory 079 * @return a new SslTransportServer initialized from the given location and socket factory. 080 * @throws IOException 081 * @throws URISyntaxException 082 */ 083 protected SslTransportServer createSslTransportServer(final URI location, SSLServerSocketFactory serverSocketFactory) throws IOException, URISyntaxException { 084 return new SslTransportServer(this, location, serverSocketFactory); 085 } 086 087 /** 088 * Overriding to allow for proper configuration through reflection but delegate to get common 089 * configuration 090 */ 091 @Override 092 @SuppressWarnings("rawtypes") 093 public Transport compositeConfigure(Transport transport, WireFormat format, Map options) { 094 SslTransport sslTransport = transport.narrow(SslTransport.class); 095 IntrospectionSupport.setProperties(sslTransport, options); 096 097 return super.compositeConfigure(transport, format, options); 098 } 099 100 /** 101 * Overriding to use SslTransports. 102 */ 103 @Override 104 protected Transport createTransport(URI location, WireFormat wf) throws UnknownHostException, IOException { 105 URI localLocation = null; 106 String path = location.getPath(); 107 // see if the path is a local URI location 108 if (path != null && path.length() > 0) { 109 int localPortIndex = path.indexOf(':'); 110 try { 111 Integer.parseInt(path.substring(localPortIndex + 1, path.length())); 112 String localString = location.getScheme() + ":/" + path; 113 localLocation = new URI(localString); 114 } catch (Exception e) { 115 LOG.warn("path isn't a valid local location for SslTransport to use", e); 116 } 117 } 118 SocketFactory socketFactory = createSocketFactory(); 119 return new SslTransport(wf, (SSLSocketFactory)socketFactory, location, localLocation, false); 120 } 121 122 /** 123 * Creates a new SSL ServerSocketFactory. The given factory will use 124 * user-provided key and trust managers (if the user provided them). 125 * 126 * @return Newly created (Ssl)ServerSocketFactory. 127 * @throws IOException 128 */ 129 @Override 130 protected ServerSocketFactory createServerSocketFactory() throws IOException { 131 if( SslContext.getCurrentSslContext()!=null ) { 132 SslContext ctx = SslContext.getCurrentSslContext(); 133 try { 134 return ctx.getSSLContext().getServerSocketFactory(); 135 } catch (Exception e) { 136 throw IOExceptionSupport.create(e); 137 } 138 } else { 139 return SSLServerSocketFactory.getDefault(); 140 } 141 } 142 143 /** 144 * Creates a new SSL SocketFactory. The given factory will use user-provided 145 * key and trust managers (if the user provided them). 146 * 147 * @return Newly created (Ssl)SocketFactory. 148 * @throws IOException 149 */ 150 @Override 151 protected SocketFactory createSocketFactory() throws IOException { 152 if( SslContext.getCurrentSslContext()!=null ) { 153 SslContext ctx = SslContext.getCurrentSslContext(); 154 try { 155 return ctx.getSSLContext().getSocketFactory(); 156 } catch (Exception e) { 157 throw IOExceptionSupport.create(e); 158 } 159 } else { 160 return SSLSocketFactory.getDefault(); 161 } 162 } 163}