001/**
002 * Copyright (C) 2014  Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/
003 *
004 * This file is part of Dicoogle/dicoogle.
005 *
006 * Dicoogle/dicoogle is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * Dicoogle/dicoogle is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with Dicoogle.  If not, see <http://www.gnu.org/licenses/>.
018 */
019/*
020 * To change this template, choose Tools | Templates
021 * and open the template in the editor.
022 */
023
024package pt.ua.dicoogle.rGUI;
025
026import java.io.IOException;
027import java.io.Serializable;
028import java.net.InetSocketAddress;
029import java.net.Socket;
030import java.net.SocketAddress;
031import java.net.SocketException;
032import java.nio.channels.Channel;
033import java.nio.channels.SelectionKey;
034import java.nio.channels.Selector;
035import java.nio.channels.SocketChannel;
036import java.rmi.RMISecurityManager;
037import java.rmi.server.RMIClientSocketFactory;
038import java.util.ArrayList;
039import java.util.List;
040import java.util.Set;
041import javax.rmi.ssl.SslRMIClientSocketFactory;
042
043/**
044 * 
045 * @author Samuel Campos <samuelcampos@ua.pt>
046 */
047@Deprecated
048public class MultihomeSslRMIClientSocketFactory extends SslRMIClientSocketFactory
049        implements RMIClientSocketFactory, Serializable {
050    private static final long serialVersionUID = 11L;
051
052    //private final SslRMIClientSocketFactory factory;
053
054    public MultihomeSslRMIClientSocketFactory() {
055        super();
056    }
057
058    @Override
059    public Socket createSocket(String hostString, int port) throws IOException {
060        final String[] hosts = hostString.split("!");
061        final int nhosts = hosts.length;
062        
063        if (nhosts < 2)
064            return super.createSocket(hostString, port);
065
066        List<IOException> exceptions = new ArrayList<IOException>();
067
068        Selector selector = Selector.open();
069        
070        for (String host : hosts) {
071            SocketChannel channel = SocketChannel.open();
072            channel.configureBlocking(false);
073            channel.register(selector, SelectionKey.OP_CONNECT);
074            SocketAddress addr = new InetSocketAddress(host, port);
075            
076            
077            try{
078                channel.connect(addr);
079            }catch(SocketException e){
080                //System.err.println("Sockect Exception: "+ e.getMessage() + ", Host: " + host + ", Port: "+ port);
081            }
082        }
083        SocketChannel connectedChannel = null;
084
085        connect:
086        while (true) {
087            if (selector.keys().isEmpty()) {
088                throw new IOException("Connection failed for " + hostString +
089                        ": " + exceptions);
090            }
091            selector.select();  // you can add a timeout parameter in millseconds
092            Set<SelectionKey> keys = selector.selectedKeys();
093            if (keys.isEmpty()) {
094                throw new IOException("Selection keys unexpectedly empty for " +
095                        hostString + "[exceptions: " + exceptions + "]");
096            }
097            for (SelectionKey key : keys) {
098                SocketChannel channel = (SocketChannel) key.channel();
099                key.cancel();
100                try {
101                    channel.configureBlocking(true);
102                    channel.finishConnect();
103                    connectedChannel = channel;
104                    break connect;
105                } catch (IOException e) {
106                    exceptions.add(e);
107                }
108            }
109        }
110
111        assert connectedChannel != null;
112
113        // Close the channels that didn't connect
114        for (SelectionKey key : selector.keys()) {
115            Channel channel = key.channel();
116            if (channel != connectedChannel)
117                channel.close();
118        }
119
120        final Socket socket = connectedChannel.socket();
121
122        // We've determined that we can connect to this host but we didn't use
123        // the right factory so we have to reconnect with the factory.
124        String host = socket.getInetAddress().getHostAddress();
125        socket.close();
126        return super.createSocket(host, port);
127    }
128
129}