/* Copyright (c) 2001-2019, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb.server;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;

import org.hsqldb.lib.HashMap;
import org.hsqldb.lib.IntKeyHashMap;
import org.hsqldb.lib.Iterator;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.persist.HsqlProperties;

A subclass HsqlProperties with functionality needed for the HSQLDB Server implementations.

A property object is checked once and all the errors are stored in collections to be used Meta records specify accepted keys and policies for the expected values.

Policy for defaults:

  • If (non-null) default is specified for the Meta record, then behavior is obvious.
  • If pattern-type Meta record, then there is no default. A value is required for the property.
  • Otherwise null is specified for the Meta record and user must set a value.
If a range is specified in the Meta record, then the value is checked against the range.

If a set of values specified in the Meta record, then the value is checked against the set.

Author:Fred Toussi (fredt@users dot sourceforge.net)
Version:2.2.7
Since:1.9.0
/** * A subclass HsqlProperties with functionality needed for the HSQLDB Server * implementations.<p> * * A property object is checked once and all the errors are stored in * collections to be used * * Meta records specify accepted keys and policies for the expected values.<p> * * Policy for defaults: <ul> * <li>If (non-null) default is specified for the Meta record, then * behavior is obvious. * <li>If pattern-type Meta record, then there is no default. * A value is required for the property. * <li>Otherwise null is specified for the Meta record and user must set * a value. * </ul> * * If a range is specified in the Meta record, then the value is checked * against the range.<p> * * If a set of values specified in the Meta record, then the value is checked * against the set.<p> * * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 2.2.7 * @since 1.9.0 */
public class ServerProperties extends HsqlProperties { // types of properties static final int SERVER_PROPERTY = 0; static final int SERVER_MULTI_PROPERTY = 1; static final int SYSTEM_PROPERTY = 2; // keys to properties static final String sc_key_prefix = "server"; static final String sc_key_address = "server.address"; static final String sc_key_autorestart_server = "server.restart_on_shutdown"; static final String sc_key_database = "server.database"; static final String sc_key_dbname = "server.dbname"; static final String sc_key_no_system_exit = "server.no_system_exit"; static final String sc_key_port = "server.port"; static final String sc_key_http_port = "server.port"; static final String sc_key_silent = "server.silent"; static final String sc_key_tls = "server.tls"; static final String sc_key_trace = "server.trace"; static final String sc_key_web_default_page = "server.default_page"; static final String sc_key_web_root = "server.root"; static final String sc_key_max_connections = "server.maxconnections"; static final String sc_key_remote_open_db = "server.remote_open"; static final String sc_key_max_databases = "server.maxdatabases"; static final String sc_key_acl = "server.acl"; static final String sc_key_daemon = "server.daemon"; static final String sc_key_props = "server.props"; static final String sc_key_system = "system"; // web server page defaults static final String sc_default_web_mime = "text/html"; static final String sc_default_web_page = "index.html"; static final String sc_default_web_root = "."; // static final HashMap meta = new HashMap(); static final OrderedHashSet prefixes = new OrderedHashSet(); // final int protocol; protected boolean initialised = false; // IntKeyHashMap idToAliasMap = new IntKeyHashMap(); IntKeyHashMap idToPathMap = new IntKeyHashMap(); public ServerProperties(int protocol, File file) throws IOException { FileInputStream fis = null; try { fis = new FileInputStream(file); stringProps.load(fis); } finally { if (fis != null) { fis.close(); } } this.protocol = protocol; } ServerProperties(int protocol) { this.protocol = protocol; } ServerProperties(int protocol, String path, String extension) { super(path, extension); this.protocol = protocol; }
Validates according to Meta map, and sets System Properties for those properties with names matching the requisite pattern.
/** * Validates according to Meta map, and sets System Properties for those * properties with names matching the requisite pattern. */
public void validate() { Enumeration en = stringProps.propertyNames(); while (en.hasMoreElements()) { String key = (String) en.nextElement(); Object[] metadata = (Object[]) meta.get(key); if (metadata == null) { metadata = getPrefixedMetadata(key); } if (metadata == null) { String error = "unsupported property: " + key; super.addError(ANY_ERROR, error); continue; } String error = null; if (((Integer) metadata[indexType]).intValue() == SYSTEM_PROPERTY) { error = validateSystemProperty(key, metadata); } else if (((Integer) metadata[indexType]).intValue() == SERVER_MULTI_PROPERTY) { error = validateMultiProperty(key, metadata); } else { String value = getProperty(key); if (value == null) { if (metadata[indexDefaultValue] == null) { error = "missing value for property: " + key; } else { setProperty(key, metadata[indexDefaultValue].toString()); } } else { error = HsqlProperties.validateProperty(key, value, metadata); } } if (error != null) { super.addError(ANY_ERROR, error); } } Iterator it = idToAliasMap.keySet().iterator(); while (it.hasNext()) { int number = it.nextInt(); if (!idToPathMap.containsKey(number)) { addError(ANY_ERROR, "no path for database id: " + number); } } it = idToPathMap.keySet().iterator(); while (it.hasNext()) { int number = it.nextInt(); if (!idToAliasMap.containsKey(number)) { addError(ANY_ERROR, "no alias for database id: " + number); } } initialised = true; } Object[] getPrefixedMetadata(String key) { for (int i = 0; i < prefixes.size(); i++) { String prefix = (String) prefixes.get(i); if (key.startsWith(prefix)) { return (Object[]) meta.get(prefix); } } return null; }
Checks an alias or database path. Duplicates are checked as duplicate numbering may result from different strings (e.g. 02 and 2).
/** * Checks an alias or database path. Duplicates are checked as duplicate * numbering may result from different strings (e.g. 02 and 2). */
String validateMultiProperty(String key, Object[] meta) { int dbNumber; String prefix = (String) meta[indexName]; if (meta[indexName].equals(sc_key_database)) { if (sc_key_database.equals(key)) { key = key + ".0"; } } try { dbNumber = Integer.parseInt(key.substring(prefix.length() + 1)); } catch (NumberFormatException e1) { return ("malformed database enumerator: " + key); } if (meta[indexName].equals(sc_key_dbname)) { String alias = stringProps.getProperty(key).toLowerCase(); Object existing = idToAliasMap.put(dbNumber, alias); if (existing != null) { return "duplicate database enumerator: " + key; } } else if (meta[indexName].equals(sc_key_database)) { String path = stringProps.getProperty(key); Object existing = idToPathMap.put(dbNumber, path); if (existing != null) { return "duplicate database enumerator: " + key; } } return null; }
System properties are currently not checked, as different libraries in the environment may need different names?
/** * System properties are currently not checked, as different libraries in * the environment may need different names? */
String validateSystemProperty(String key, Object[] meta) { String prefix = (String) meta[indexName]; String specificKey = key.substring(prefix.length() + 1); String value = stringProps.getProperty(key); if (value == null) { return "value required for property: " + key; } System.setProperty(specificKey, value); return null; } static { // properties with variable suffixes meta.put(sc_key_database, getMeta(sc_key_database, SERVER_MULTI_PROPERTY, null)); meta.put(sc_key_dbname, getMeta(sc_key_dbname, SERVER_MULTI_PROPERTY, null)); meta.put(sc_key_system, getMeta(sc_key_system, SYSTEM_PROPERTY, null)); // properties with fixed names meta.put(sc_key_silent, getMeta(sc_key_silent, SERVER_PROPERTY, false)); meta.put(sc_key_trace, getMeta(sc_key_trace, SERVER_PROPERTY, false)); meta.put(sc_key_tls, getMeta(sc_key_tls, SERVER_PROPERTY, false)); meta.put(sc_key_acl, getMeta(sc_key_acl, SERVER_PROPERTY, null)); meta.put(sc_key_autorestart_server, getMeta(sc_key_autorestart_server, SERVER_PROPERTY, false)); meta.put(sc_key_remote_open_db, getMeta(sc_key_remote_open_db, SERVER_PROPERTY, false)); meta.put(sc_key_no_system_exit, getMeta(sc_key_no_system_exit, SERVER_PROPERTY, false)); meta.put(sc_key_daemon, getMeta(sc_key_daemon, SERVER_PROPERTY, false)); meta.put(sc_key_address, getMeta(sc_key_address, SERVER_PROPERTY, null)); meta.put(sc_key_port, getMeta(sc_key_port, 0, 9001, 0, 65535)); meta.put(sc_key_http_port, getMeta(sc_key_http_port, 0, 80, 0, 65535)); meta.put(sc_key_max_connections, getMeta(sc_key_max_connections, 0, 100, 1, 10000)); meta.put(sc_key_max_databases, getMeta(sc_key_max_databases, 0, 10, 1, 1000)); // prefixes.add(sc_key_database); prefixes.add(sc_key_dbname); prefixes.add(sc_key_system); } }