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