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