/** * This file is part of SecureNIO. Copyright (C) 2014 K. Dermitzakis * <dermitza@gmail.com> * * SecureNIO is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * SecureNIO is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with SecureNIO. If not, see <http://www.gnu.org/licenses/>. */ package ch.dermitza.securenio.util; import ch.dermitza.securenio.util.logging.LoggerHandler; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; /** * A static helper implementation for setting up static runtime options. The * options are located in a {@link Properties} file. For further information on * the options set, please look at the supplied setup.properties. * * @author K. Dermitzakis * @version 0.19 * @since 0.19 */ public class PropertiesReader { private static final Logger logger = LoggerHandler.getLogger(PropertiesReader.class.getName()); private static final String settings_loc = "setup.properties"; private static final Properties props = new Properties(); static { try (FileInputStream fis = new FileInputStream(settings_loc)) { props.load(fis); } catch (FileNotFoundException ex) { logger.log(Level.SEVERE, "Properties file not found, exiting", ex); System.exit(-1); } catch (IOException ex) { logger.log(Level.SEVERE, "IOException while reading properties, exiting", ex); System.exit(-1); } } /** * Return whether the selector should handle {@link javax.net.ssl.SSLEngine} * tasks in the same thread. If not, a * {@link ch.dermitza.securenio.socket.secure.TaskWorker} is initialized and * used for that purpose. * * @return whether the selector should handle * {@link javax.net.ssl.SSLEngine} tasks in the same thread. * @see ch.dermitza.securenio.socket.secure.TaskWorker */ public static boolean getSelectorSingleThreaded() { return getPropAsBool("selector.single_threaded"); } /** * Return whether the selector thread should process all * {@link ch.dermitza.securenio.ChangeRequest}s at each iteration. If not, * the values from {@link #getMaxChanges()} and * {@link #getSelectorTimeoutMS()} are used. * * @return whether the selector thread should process all * {@link ch.dermitza.securenio.ChangeRequest}s * * @see #getMaxChanges() * @see #getSelectorTimeoutMS() * @see ch.dermitza.securenio.AbstractSelector#processChanges() */ public static boolean getSelectorProcessAll() { return getPropAsBool("selector.process_all_changes"); } /** * If the selector thread should process all * {@link ch.dermitza.securenio.ChangeRequest}s at each iteration, this * method returns the maximum changes to be processed at each iteration. * * @return the maximum {@link ch.dermitza.securenio.ChangeRequest}s * processed at each iteration * * @see #getMaxChanges() * @see #getSelectorTimeoutMS() * @see ch.dermitza.securenio.AbstractSelector#processChanges() */ public static int getMaxChanges() { int i = getPropAsInt("socket.max_changes"); if (i < 0) { logger.log(Level.SEVERE, "socket.max_changes value is invalid: {0}. Shutting down", i); System.exit(-1); } return i; } /** * If the selector thread should process all * {@link ch.dermitza.securenio.ChangeRequest}s at each iteration, this * method returns the maximum time (MS) the selector should wait on a * select() before returning to process the remaining changes. * * @return the maximum time (MS) the selector should wait on a select() * before returning to process the remaining changes. * * @see #getMaxChanges() * @see #getSelectorTimeoutMS() * @see ch.dermitza.securenio.AbstractSelector#processChanges() */ public static long getSelectorTimeoutMS() { long l = getPropAsLong("socket.max_changes"); if (l < 0) { logger.log(Level.SEVERE, "socket.max_changes value is invalid: {0}. Shutting down", l); System.exit(-1); } return l; } /** * Returns the timeout period (MS) for a * {@link ch.dermitza.securenio.socket.secure.SecureSocket} to wait on an * empty buffer during handshaking. * * @return the timeout period (MS) for a * {@link ch.dermitza.securenio.socket.secure.SecureSocket} to wait on an * empty buffer during handshaking. */ public static long getTimeoutMS() { long l = getPropAsLong("timeout.period_ms"); if (l < 0) { logger.log(Level.SEVERE, "socket.max_changes value is invalid: {0}. Shutting down", l); System.exit(-1); } return l; } /** * Returns the size of the backlog (socket number) of a * {@link java.nio.channels.ServerSocketChannel}. * * @return the size of the backlog (socket number) of a * {@link java.nio.channels.ServerSocketChannel}. */ public static int getBacklog() { int i = getPropAsInt("socket.backlog"); if (i < 0) { logger.log(Level.SEVERE, "socket.backlog value is invalid: {0}. Shutting down", i); System.exit(-1); } return i; } /** * Returns the default size (bytes) of the * {@link ch.dermitza.securenio.packet.worker.AbstractPacketWorker}. Note * that the size can grow if the data received overflows on a particular * socket. * * @return the default size (bytes) of the * {@link ch.dermitza.securenio.packet.worker.AbstractPacketWorker}. * * @see * ch.dermitza.securenio.packet.worker.AbstractPacketWorker#addData(ch.dermitza.securenio.socket.SocketIF, * java.nio.ByteBuffer, int) */ public static int getPacketBufSize() { int i = getPropAsInt("packetworker.buffer_size"); if (i < 0) { logger.log(Level.SEVERE, "packetworker.buffer_size value is invalid: {0}. Shutting down", i); System.exit(-1); } return i; } /** * Returns the SO_SNDBUF size (bytes) to be set for each socket. * * @return the SO_SNDBUF size (bytes) to be set for each socket. * * @see java.net.StandardSocketOptions#SO_SNDBUF */ public static int getSoSndBuf() { int i = getPropAsInt("socket.so_sndbuf"); if (i < 0) { logger.log(Level.SEVERE, "socket.so_sndbuf value is invalid: {0}. Shutting down", i); System.exit(-1); } return i; } /** * Returns the SO_RCVBUF size (bytes) to be set for each socket. * * @return the SO_RCVBUF size (bytes) to be set for each socket. * * @see java.net.StandardSocketOptions#SO_RCVBUF */ public static int getSoRcvBuf() { int i = getPropAsInt("socket.so_rcvbuf"); if (i < 0) { logger.log(Level.SEVERE, "socket.so_rcvbuf value is invalid: {0}. Shutting down", i); System.exit(-1); } return i; } /** * Returns the IP_TOS to be set for each socket. * * @return the IP_TOS to be set for each socket. * * @see java.net.StandardSocketOptions#IP_TOS */ public static int getIPTos() { int i = getPropAsInt("socket.ip_tos"); if (i < 0) { logger.log(Level.SEVERE, "socket.ip_tos value is invalid: {0}. Shutting down", i); System.exit(-1); } return i; } /** * Get the enabled protocols to be used with a * {@link javax.net.ssl.SSLEngine}. * * @return the enabled protocols to be used with a * {@link javax.net.ssl.SSLEngine}. */ public static String[] getProtocols() { String[] ret = getPropAsStrArr("secure.protocols"); return ret; } /** * Get the enabled cipher suites to be used with a * {@link javax.net.ssl.SSLEngine}. * * @return the enabled cipher suites to be used with a * {@link javax.net.ssl.SSLEngine}. */ public static String[] getCipherSuites() { String[] ret = getPropAsStrArr("secure.cipherSuites"); return ret; } /** * Returns the TCP_NODELAY size (bytes) to be set for each socket. * * @return the TCP_NODELAY size (bytes) to be set for each socket. * * @see java.net.StandardSocketOptions#TCP_NODELAY */ public static boolean getTCPNoDelay() { return getPropAsBool("socket.tcp_nodelay"); } /** * Returns the SO_KEEPALIVE size (bytes) to be set for each socket. * * @return the SO_KEEPALIVE size (bytes) to be set for each socket. * * @see java.net.StandardSocketOptions#SO_KEEPALIVE */ public static boolean getKeepAlive() { return getPropAsBool("socket.so_keepalive"); } /** * Returns the SO_REUSEADDR size (bytes) to be set for each socket. * * @return the SO_REUSEADDR size (bytes) to be set for each socket. * * @see java.net.StandardSocketOptions#SO_REUSEADDR */ public static boolean getReuseAddress() { return getPropAsBool("socket.so_reuseaddr"); } /** * Return a property as a String array. * * @param key The key used to retrieve the property * @return the returned String array */ private static String[] getPropAsStrArr(String key) { String str = getProp(key); String[] ret = str.split(" "); return ret; } /** * Return a property as a long. An error is thrown if the number is smaller * than zero. * * @param key The key used to retrieve the property * @return the returned long */ private static long getPropAsLong(String key) { String str = getProp(key); long l = -1; try { l = Long.parseLong(str); } catch (NumberFormatException nfe) { logger.log(Level.SEVERE, key + " value is invalid, shutting down", nfe); System.exit(-1); } return l; } /** * Return a property as an int. An error is thrown if the number is smaller * than zero. * * @param key The key used to retrieve the property * @return the returned int */ private static int getPropAsInt(String key) { String str = getProp(key); int i = -1; try { i = Integer.parseInt(str); } catch (NumberFormatException nfe) { logger.log(Level.SEVERE, key + " value is invalid, shutting down", nfe); System.exit(-1); } return i; } /** * Return a property as a boolean. An error is thrown if the values are * anything other than "true" or "false". * * @param key The key used to retrieve the property * @return the returned boolean */ private static boolean getPropAsBool(String key) { String str = getProp(key); if (!str.equals("true") && !str.equals("false")) { logger.log(Level.SEVERE, "{0} value is invalid: {1}. Shutting down", new Object[]{key, str}); System.exit(-1); } return Boolean.parseBoolean(str); } /** * Get a property. An error is thrown if the value of the property is not * found or is empty. * * @param key The key used to retrieve the property * @return the associated property */ private static String getProp(String key) { String str = props.getProperty(key); if (str == null || str.isEmpty()) { // Fail, these are essential properties logger.log(Level.SEVERE, "{0} value not found, shutting down.", key); System.exit(-1); } return str; } private PropertiesReader() { // Static class, disallow instantiation } //public static void main(String[] args) { //PropertiesReader.getSoSndBuf(); //String[] s = PropertiesReader.getPropAsStrArr("secure.cipherSuites"); //for (int i = 0; i < s.length; i++) { // System.out.println(s[i]); //} //} }