<commit_before>package ibis.connect.socketFactory;

import java.util.Vector;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Enumeration;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

import java.lang.reflect.Constructor;

import ibis.connect.util.MyDebug;


/* A generalized SocketFactory which supports:
   -- client/server connection scheme
   -- brokered connections through a control link
 */
public class ExtSocketFactory
{
    /** Vector of SocketTypes in the order of preference
     * for the current strategy.
     */
    private static Vector types = new Vector();

    /** Map which converts a SocketType nicknames into
     * the class name which implements it.
     */
    private static Hashtable nicknames = new Hashtable();

    private static SocketType defaultClientServer = null;
    private static SocketType defaultBrokeredLink = null;

    // Some possible default strategies...
    // -1- Plain TCP only- no firewall support.
    private static final String[] strategyTCP = 
    { "PlainTCP" };

    // -2- full range of conection methods: supports firewalls
    private static final String[] strategyFirewall = 
    { "TCPSplice", "RoutedMessages", "PlainTCP" }; 

    // -3- supports firewall for control only, no splicing. Usefull for tests only.
    private static final String[] strategyControl = 
    { "RoutedMessages", "PlainTCP" };
     
    // -4- TCP splicing only- for tests.
    private static final String[] strategySplicing = 
    { "TCPSplice", "PlainTCP" }; 

    // Pick one of the above choices for defaults
    private static String[] defaultTypes = strategyTCP;

    /* static constructor
     */
    static {
	if(MyDebug.VERBOSE())
	    System.out.println("# ### ExtSocketFactory: starting configuration.");
	
	// init types table
	declareNickname("PlainTCP", 
			"ibis.connect.socketFactory.PlainTCPSocketType");
	declareNickname("TCPSplice",
			"ibis.connect.tcpSplicing.TCPSpliceSocketType");
	declareNickname("RoutedMessages", 
			"ibis.connect.routedMessages.RoutedMessagesSocketType");
	declareNickname("ParallelStreams",
			"ibis.connect.parallelStreams.ParallelStreamsSocketType");
	declareNickname("PortRange",
			"ibis.connect.socketFactory.PortRangeSocketType");
	declareNickname("SSL", 
			"ibis.connect.socketFactory.SSLSocketType");

	Properties p = System.getProperties();
	String bl = p.getProperty("ibis.connect.data_links");
	String cs = p.getProperty("ibis.connect.control_links");
	if(bl == null || cs == null) {
	    if(MyDebug.VERBOSE())
		System.out.println("# Loading defaults...");
	    for(int i=0; i<defaultTypes.length; i++)
		{
		    String n = defaultTypes[i];
		    loadSocketType(n);
		}
	}
	if(bl == null) {
	    defaultBrokeredLink = findBrokeredType();
	} else {
	    defaultBrokeredLink = loadSocketType(bl);
	}
	if(cs == null) {
	    defaultClientServer = findClientServerType();
	} else {
	    defaultClientServer = loadSocketType(cs);
	}
	if(MyDebug.VERBOSE()) {
	    System.out.println("# Default for client-server: " +
			       defaultClientServer.getSocketTypeName());
	    System.out.println("# Default for brokered link: " +
			       defaultBrokeredLink.getSocketTypeName());
	    System.out.println("# ### ExtSocketFactory: configuration ok.");
	}
    }

    /* static destructor
     */
    public static void shutdown()
    {
	for(int i=0; i<types.size(); i++)
	    {
		SocketType t = (SocketType)types.get(i);
		t.destroySocketType();
	    }
    }

    private static void declareNickname(String nickname, String className)
    {
	nicknames.put(nickname.toLowerCase(), className);
    }

    /* loads a SocketType into the factory
     *   name: a fully-qualified class name which extends SocketType
     */
    private static synchronized SocketType loadSocketType(String socketType)
    {
	SocketType t = null;
	Constructor cons;
	String className = (String)nicknames.get(socketType.toLowerCase());
	if(className == null) {
	    System.out.println("# ExtSocketFactory: socket type "+socketType+" not found.");
	    System.out.println("#   known types are:");
	    Enumeration e = nicknames.keys();
	    while(e.hasMoreElements()) {
		System.out.println((String)e.nextElement());
	    }
	    throw new Error("ExtSocketFactory: socket type "+socketType+" not found.");
	}
	try {
	    Class c = Class.forName(className);
	    cons = c.getConstructor(null);
	} catch(Exception e) {
	    System.out.println("# ExtSocketFactory: error while loading socket type.");
	    throw new Error("ExtSocketFactory: class not found: "+className, e);
	}
	try {
	    t = (SocketType)cons.newInstance(null);
	    if (MyDebug.VERBOSE()) {
		System.out.println("# Registering socket type: "+t.getSocketTypeName());
		System.out.println("#   class name: "+t.getClass().getName());
		System.out.println("#   supports client/server:  "+t.supportsClientServer());
		System.out.println("#   supports brokered links: "+t.supportsBrokeredLinks());
	    }
	    types.add(t);
	} catch(Exception e) {
	    System.out.println("# ExtSocketFactory: *not* adding: "+t.getSocketTypeName());
	}
	return t;
    }

    // Bootstrap client sockets: Socket(addr, port);
    public static Socket createClientSocket(InetAddress addr, int port)
	throws IOException
    {
	Socket s = null;
	SocketType t = defaultClientServer;
	if(t == null)
	    throw new Error("no socket type found!");
	ClientServerSocketFactory f = null;
	try {<commit_msg>Avoid null-deref in catch-clause<commit_after>package ibis.connect.socketFactory;

import java.util.Vector;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Enumeration;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

import java.lang.reflect.Constructor;

import ibis.connect.util.MyDebug;


/* A generalized SocketFactory which supports:
   -- client/server connection scheme
   -- brokered connections through a control link
 */
public class ExtSocketFactory
{
    /** Vector of SocketTypes in the order of preference
     * for the current strategy.
     */
    private static Vector types = new Vector();

    /** Map which converts a SocketType nicknames into
     * the class name which implements it.
     */
    private static Hashtable nicknames = new Hashtable();

    private static SocketType defaultClientServer = null;
    private static SocketType defaultBrokeredLink = null;

    // Some possible default strategies...
    // -1- Plain TCP only- no firewall support.
    private static final String[] strategyTCP = 
    { "PlainTCP" };

    // -2- full range of conection methods: supports firewalls
    private static final String[] strategyFirewall = 
    { "TCPSplice", "RoutedMessages", "PlainTCP" }; 

    // -3- supports firewall for control only, no splicing. Usefull for tests only.
    private static final String[] strategyControl = 
    { "RoutedMessages", "PlainTCP" };
     
    // -4- TCP splicing only- for tests.
    private static final String[] strategySplicing = 
    { "TCPSplice", "PlainTCP" }; 

    // Pick one of the above choices for defaults
    private static String[] defaultTypes = strategyTCP;

    /* static constructor
     */
    static {
	if(MyDebug.VERBOSE())
	    System.out.println("# ### ExtSocketFactory: starting configuration.");
	
	// init types table
	declareNickname("PlainTCP", 
			"ibis.connect.socketFactory.PlainTCPSocketType");
	declareNickname("TCPSplice",
			"ibis.connect.tcpSplicing.TCPSpliceSocketType");
	declareNickname("RoutedMessages", 
			"ibis.connect.routedMessages.RoutedMessagesSocketType");
	declareNickname("ParallelStreams",
			"ibis.connect.parallelStreams.ParallelStreamsSocketType");
	declareNickname("PortRange",
			"ibis.connect.socketFactory.PortRangeSocketType");
	declareNickname("SSL", 
			"ibis.connect.socketFactory.SSLSocketType");

	Properties p = System.getProperties();
	String bl = p.getProperty("ibis.connect.data_links");
	String cs = p.getProperty("ibis.connect.control_links");
	if(bl == null || cs == null) {
	    if(MyDebug.VERBOSE())
		System.out.println("# Loading defaults...");
	    for(int i=0; i<defaultTypes.length; i++)
		{
		    String n = defaultTypes[i];
		    loadSocketType(n);
		}
	}
	if(bl == null) {
	    defaultBrokeredLink = findBrokeredType();
	} else {
	    defaultBrokeredLink = loadSocketType(bl);
	}
	if(cs == null) {
	    defaultClientServer = findClientServerType();
	} else {
	    defaultClientServer = loadSocketType(cs);
	}
	if(MyDebug.VERBOSE()) {
	    System.out.println("# Default for client-server: " +
			       defaultClientServer.getSocketTypeName());
	    System.out.println("# Default for brokered link: " +
			       defaultBrokeredLink.getSocketTypeName());
	    System.out.println("# ### ExtSocketFactory: configuration ok.");
	}
    }

    /* static destructor
     */
    public static void shutdown()
    {
	for(int i=0; i<types.size(); i++)
	    {
		SocketType t = (SocketType)types.get(i);
		t.destroySocketType();
	    }
    }

    private static void declareNickname(String nickname, String className)
    {
	nicknames.put(nickname.toLowerCase(), className);
    }

    /* loads a SocketType into the factory
     *   name: a fully-qualified class name which extends SocketType
     */
    private static synchronized SocketType loadSocketType(String socketType)
    {
	SocketType t = null;
	Constructor cons;
	String className = (String)nicknames.get(socketType.toLowerCase());
	if(className == null) {
	    System.out.println("# ExtSocketFactory: socket type "+socketType+" not found.");
	    System.out.println("#   known types are:");
	    Enumeration e = nicknames.keys();
	    while(e.hasMoreElements()) {
		System.out.println((String)e.nextElement());
	    }
	    throw new Error("ExtSocketFactory: socket type "+socketType+" not found.");
	}
	try {
	    Class c = Class.forName(className);
	    cons = c.getConstructor(null);
	} catch(Exception e) {
	    System.out.println("# ExtSocketFactory: error while loading socket type.");
	    throw new Error("ExtSocketFactory: class not found: "+className, e);
	}
	try {
	    t = (SocketType)cons.newInstance(null);
	    if (MyDebug.VERBOSE()) {
		System.out.println("# Registering socket type: "+t.getSocketTypeName());
		System.out.println("#   class name: "+t.getClass().getName());
		System.out.println("#   supports client/server:  "+t.supportsClientServer());
		System.out.println("#   supports brokered links: "+t.supportsBrokeredLinks());
	    }
	    types.add(t);
	} catch(Exception e) {
	    System.out.println("# ExtSocketFactory: Socket type constructor " + className + " got exception:");
	    e.printStackTrace();
	    System.out.println("# ExtSocketFactory: loadSocketType returns null");
	}
	return t;
    }

    // Bootstrap client sockets: Socket(addr, port);
    public static Socket createClientSocket(InetAddress addr, int port)
	throws IOException
    {
	Socket s = null;
	SocketType t = defaultClientServer;
	if(t == null)
	    throw new Error("no socket type found!");
	ClientServerSocketFactory f = null;
	try {
{'fraction_non_alphanumeric': 0.12313204579218737, 'fraction_numerical': 0.0010486760464913046, 'mean_word_length': 3.6920869208692086, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7244531', 'n_tokens_mistral': 3560, 'n_tokens_neox': 3346, 'n_words': 846}