// Path: core/src/main/java/io/bigio/Parameters.java
// public enum Parameters {
//     INSTANCE;
//     
//     private final Logger LOG;
//     private final int MAX_DEPTH;
//     private final Properties properties;
//     private final FileSystem fileSystem;
//     private final Path configDir;
// 
//     private static OperatingSystem os;
// 
//     /**
//      * Protected constructor.
//      */
//     Parameters() {
//         LOG = LoggerFactory.getLogger(Parameters.class);
//         MAX_DEPTH = 10;
//         properties = new Properties();
//         fileSystem = FileSystems.getDefault();
//         configDir = fileSystem.getPath("config");
//     
//         init();
//     }
// 
//     /**
//      * Get a property.
//      * 
//      * @param name the name of the property.
//      * @return the property value, or null if the property does not exist.
//      */
//     public String getProperty(String name) {
//         return properties.getProperty(name);
//     }
//     
//     /**
//      * Get a property. If the property doesn't exist, the default value will
//      * be returned.
//      * 
//      * @param name the name of the property.
//      * @param defaultValue the default value of the property.
//      * @return the value should the property exist, or the default property 
//      * if it does not.
//      */
//     public String getProperty(String name, String defaultValue) {
//         return properties.getProperty(name, defaultValue);
//     }
// 
//     /**
//      * Set a property.
//      * 
//      * @param name the name of the property.
//      * @param value the value of the property.
//      */
//     public void setProperty(String name, String value) {
//         properties.setProperty(name, value);
//     }
// 
//     /**
//      * Get the operating system.
//      * 
//      * @return the operating system.
//      */
//     public OperatingSystem currentOS() {
//         return os;
//     }
// 
//     /**
//      * Load the configuration.
//      */
//     private void init() {
//         String osName = System.getProperty("os.name");
//         String osArch = System.getProperty("os.arch");
// 
//         if(osName.contains("Windows")) {
//             if(osArch.contains("amd64")) {
//                 os = OperatingSystem.WIN_64;
//             } else {
//                 os = OperatingSystem.WIN_32;
//             }
//         } else if(osName.contains("Linux")) {
//             if(osArch.contains("amd64")) {
//                 os = OperatingSystem.LINUX_64;
//             } else {
//                 os = OperatingSystem.LINUX_32;
//             }
//         } else {
//             if(osArch.contains("amd64")) {
//                 os = OperatingSystem.MAC_64;
//             } else {
//                 os = OperatingSystem.MAC_32;
//             }
//         }
//         
//         Set<FileVisitOption> options = new TreeSet<>();
//         options.add(FileVisitOption.FOLLOW_LINKS);
// 
//         try {
//             if(Files.isDirectory(configDir)) {
//                 Files.walkFileTree(configDir, options, MAX_DEPTH, new SimpleFileVisitor<Path>() {
//                     @Override
//                     public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
//                         if(file.getFileName().toString().endsWith("properties")) {
//                             LOG.debug("Loading configuration file '" + file.toString() + "'");
// 
//                             try (BufferedReader in = Files.newBufferedReader(file, Charset.defaultCharset())) {
//                                 properties.load(in);
//                             }
//                         }
// 
//                         return FileVisitResult.CONTINUE;
//                     }
//                 });
//             } else {
//                 LOG.info("Cannot find default configuration directory. Using default configuration values.");
//             }
//         } catch(IOException ex) {
//             LOG.error("Error while loading configuration.", ex);
//         }
// 
//         properties.entrySet().stream().forEach((entry) -> {
//             System.getProperties().setProperty(entry.getKey().toString(), entry.getValue().toString());
//         });
// 
//         System.getProperties().entrySet().stream().forEach((entry) -> {
//             properties.setProperty(entry.getKey().toString(), entry.getValue().toString());
//         });
//     }
// }


import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import io.bigio.Parameters;
    protected int gossipPort;
    protected MemberHolder memberHolder;
    protected byte[] publicKey = null;
    
    public abstract void initialize();
    public abstract void shutdown();

    protected boolean useSSL;
    protected boolean useSelfSigned;
    protected String certChainFile;
    protected String keyFile;
    protected String keyPassword;

    public static final String SSL_PROPERTY = "io.bigio.ssl";
    private static final String DEFAULT_SSL = "false";
    public static final String SSL_SELFSIGNED_PROPERTY = "io.bigio.ssl.selfSigned";
    private static final String DEFAULT_SELFSIGNED = "true";
    public static final String SSL_CERTCHAINFILE_PROPERTY = "io.bigio.ssl.certChainFile";
    private static final String DEFAULT_CERTCHAINFILE = "conf/certChain.pem";
    public static final String SSL_KEYFILE_PROPERTY = "io.bigio.ssl.keyFile";
    private static final String DEFAULT_KEYFILE = "conf/keyfile.pem";
    public static final String SSL_KEYPASSWORD_PROPERTY = "io.bigio.ssl.keyPassword";

    public AbstractMember(MemberHolder memberHolder) {
        this.memberHolder = memberHolder;

        useSSL = Boolean.parseBoolean(
                Parameters.INSTANCE.getProperty(SSL_PROPERTY, DEFAULT_SSL));
        useSelfSigned = Boolean.parseBoolean(
                Parameters.INSTANCE.getProperty(SSL_SELFSIGNED_PROPERTY, DEFAULT_SELFSIGNED));
// Path: core/src/main/java/io/bigio/Parameters.java
// public enum Parameters {
//     INSTANCE;
//     
//     private final Logger LOG;
//     private final int MAX_DEPTH;
//     private final Properties properties;
//     private final FileSystem fileSystem;
//     private final Path configDir;
// 
//     private static OperatingSystem os;
// 
//     /**
//      * Protected constructor.
//      */
//     Parameters() {
//         LOG = LoggerFactory.getLogger(Parameters.class);
//         MAX_DEPTH = 10;
//         properties = new Properties();
//         fileSystem = FileSystems.getDefault();
//         configDir = fileSystem.getPath("config");
//     
//         init();
//     }
// 
//     /**
//      * Get a property.
//      * 
//      * @param name the name of the property.
//      * @return the property value, or null if the property does not exist.
//      */
//     public String getProperty(String name) {
//         return properties.getProperty(name);
//     }
//     
//     /**
//      * Get a property. If the property doesn't exist, the default value will
//      * be returned.
//      * 
//      * @param name the name of the property.
//      * @param defaultValue the default value of the property.
//      * @return the value should the property exist, or the default property 
//      * if it does not.
//      */
//     public String getProperty(String name, String defaultValue) {
//         return properties.getProperty(name, defaultValue);
//     }
// 
//     /**
//      * Set a property.
//      * 
//      * @param name the name of the property.
//      * @param value the value of the property.
//      */
//     public void setProperty(String name, String value) {
//         properties.setProperty(name, value);
//     }
// 
//     /**
//      * Get the operating system.
//      * 
//      * @return the operating system.
//      */
//     public OperatingSystem currentOS() {
//         return os;
//     }
// 
//     /**
//      * Load the configuration.
//      */
//     private void init() {
//         String osName = System.getProperty("os.name");
//         String osArch = System.getProperty("os.arch");
// 
//         if(osName.contains("Windows")) {
//             if(osArch.contains("amd64")) {
//                 os = OperatingSystem.WIN_64;
//             } else {
//                 os = OperatingSystem.WIN_32;
//             }
//         } else if(osName.contains("Linux")) {
//             if(osArch.contains("amd64")) {
//                 os = OperatingSystem.LINUX_64;
//             } else {
//                 os = OperatingSystem.LINUX_32;
//             }
//         } else {
//             if(osArch.contains("amd64")) {
//                 os = OperatingSystem.MAC_64;
//             } else {
//                 os = OperatingSystem.MAC_32;
//             }
//         }
//         
//         Set<FileVisitOption> options = new TreeSet<>();
//         options.add(FileVisitOption.FOLLOW_LINKS);
// 
//         try {
//             if(Files.isDirectory(configDir)) {
//                 Files.walkFileTree(configDir, options, MAX_DEPTH, new SimpleFileVisitor<Path>() {
//                     @Override
//                     public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
//                         if(file.getFileName().toString().endsWith("properties")) {
//                             LOG.debug("Loading configuration file '" + file.toString() + "'");
// 
//                             try (BufferedReader in = Files.newBufferedReader(file, Charset.defaultCharset())) {
//                                 properties.load(in);
//                             }
//                         }
// 
//                         return FileVisitResult.CONTINUE;
//                     }
//                 });
//             } else {
//                 LOG.info("Cannot find default configuration directory. Using default configuration values.");
//             }
//         } catch(IOException ex) {
//             LOG.error("Error while loading configuration.", ex);
//         }
// 
//         properties.entrySet().stream().forEach((entry) -> {
//             System.getProperties().setProperty(entry.getKey().toString(), entry.getValue().toString());
//         });
// 
//         System.getProperties().entrySet().stream().forEach((entry) -> {
//             properties.setProperty(entry.getKey().toString(), entry.getValue().toString());
//         });
//     }
// }


// Path: core/src/main/java/io/bigio/core/member/AbstractMember.java
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import io.bigio.Parameters;

    protected int gossipPort;
    protected MemberHolder memberHolder;
    protected byte[] publicKey = null;
    
    public abstract void initialize();
    public abstract void shutdown();

    protected boolean useSSL;
    protected boolean useSelfSigned;
    protected String certChainFile;
    protected String keyFile;
    protected String keyPassword;

    public static final String SSL_PROPERTY = "io.bigio.ssl";
    private static final String DEFAULT_SSL = "false";
    public static final String SSL_SELFSIGNED_PROPERTY = "io.bigio.ssl.selfSigned";
    private static final String DEFAULT_SELFSIGNED = "true";
    public static final String SSL_CERTCHAINFILE_PROPERTY = "io.bigio.ssl.certChainFile";
    private static final String DEFAULT_CERTCHAINFILE = "conf/certChain.pem";
    public static final String SSL_KEYFILE_PROPERTY = "io.bigio.ssl.keyFile";
    private static final String DEFAULT_KEYFILE = "conf/keyfile.pem";
    public static final String SSL_KEYPASSWORD_PROPERTY = "io.bigio.ssl.keyPassword";

    public AbstractMember(MemberHolder memberHolder) {
        this.memberHolder = memberHolder;

        useSSL = Boolean.parseBoolean(
                Parameters.INSTANCE.getProperty(SSL_PROPERTY, DEFAULT_SSL));
        useSelfSigned = Boolean.parseBoolean(
                Parameters.INSTANCE.getProperty(SSL_SELFSIGNED_PROPERTY, DEFAULT_SELFSIGNED));
        certChainFile = Parameters.INSTANCE.getProperty(SSL_CERTCHAINFILE_PROPERTY, DEFAULT_CERTCHAINFILE);