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.rmi.server.RMISocketFactory; 039import java.util.ArrayList; 040import java.util.List; 041import java.util.Set; 042 043@Deprecated 044public class MultihomeRMIClientSocketFactory 045 implements RMIClientSocketFactory, Serializable { 046 private static final long serialVersionUID = 7033753601964541325L; 047 048 private final RMIClientSocketFactory factory; 049 050 public MultihomeRMIClientSocketFactory() { 051 this.factory = RMISocketFactory.getSocketFactory(); 052 /* System.setProperty("java.security.policy","java.policy"); 053 System.setProperty("java.rmi.server.codebase", "file:/c:/pluginClasses/");*/ 054 } 055 056 @Override 057 public Socket createSocket(String hostString, int port) throws IOException { 058 //System.setProperty("java.security.policy", "my.policy"); 059 final String[] hosts = hostString.split("!"); 060 final int nhosts = hosts.length; 061 062 if (nhosts < 2) 063 return factory().createSocket(hostString, port); 064 065 List<IOException> exceptions = new ArrayList<IOException>(); 066 Selector selector = Selector.open(); 067 for (String host : hosts) { 068 SocketChannel channel = SocketChannel.open(); 069 channel.configureBlocking(false); 070 channel.register(selector, SelectionKey.OP_CONNECT); 071 SocketAddress addr = new InetSocketAddress(host, port); 072 073 try{ 074 channel.connect(addr); 075 }catch(SocketException e){ 076 //System.err.println("Sockect Exception: "+ e.getMessage() + ", Host: " + host + ", Port: "+ port); 077 } 078 } 079 SocketChannel connectedChannel = null; 080 081 connect: 082 while (true) { 083 if (selector.keys().isEmpty()) { 084 throw new IOException("Connection failed for " + hostString + 085 ": " + exceptions); 086 } 087 selector.select(); // you can add a timeout parameter in millseconds 088 Set<SelectionKey> keys = selector.selectedKeys(); 089 if (keys.isEmpty()) { 090 throw new IOException("Selection keys unexpectedly empty for " + 091 hostString + "[exceptions: " + exceptions + "]"); 092 } 093 for (SelectionKey key : keys) { 094 SocketChannel channel = (SocketChannel) key.channel(); 095 key.cancel(); 096 try { 097 channel.configureBlocking(true); 098 channel.finishConnect(); 099 connectedChannel = channel; 100 break connect; 101 } catch (IOException e) { 102 exceptions.add(e); 103 } 104 } 105 } 106 107 assert connectedChannel != null; 108 109 // Close the channels that didn't connect 110 for (SelectionKey key : selector.keys()) { 111 Channel channel = key.channel(); 112 if (channel != connectedChannel) 113 channel.close(); 114 } 115 116 final Socket socket = connectedChannel.socket(); 117 if (factory == null && RMISocketFactory.getSocketFactory() == null) 118 return socket; 119 120 // We've determined that we can connect to this host but we didn't use 121 // the right factory so we have to reconnect with the factory. 122 String host = socket.getInetAddress().getHostAddress(); 123 socket.close(); 124 return factory().createSocket(host, port); 125 } 126 127 private RMIClientSocketFactory factory() { 128 if (factory != null) 129 return factory; 130 RMIClientSocketFactory f = RMISocketFactory.getSocketFactory(); 131 if (f != null) 132 return f; 133 return RMISocketFactory.getDefaultSocketFactory(); 134 } 135 136 // Thanks to "km" for the reminder that I need these: 137 @Override 138 public boolean equals(Object x) { 139 if (x.getClass() != this.getClass()) 140 return false; 141 MultihomeRMIClientSocketFactory f = (MultihomeRMIClientSocketFactory) x; 142 return ((factory == null) ? 143 (f.factory == null) : 144 (factory.equals(f.factory))); 145 } 146 147 @Override 148 public int hashCode() { 149 int h = getClass().hashCode(); 150 if (factory != null) 151 h += factory.hashCode(); 152 return h; 153 } 154}