001: /**
002: * com.mckoi.database.control.TCPJDBCServer 27 Mar 2002
003: *
004: * Mckoi SQL Database ( http://www.mckoi.com/database )
005: * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * Version 2 as published by the Free Software Foundation.
010: *
011: * This program 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 Version 2 for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * Version 2 along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: * Change Log:
021: *
022: *
023: */package com.mckoi.database.control;
024:
025: import java.net.InetAddress;
026: import java.net.UnknownHostException;
027: import com.mckoi.database.jdbcserver.TCPServer;
028:
029: /**
030: * Attaches to a DBSystem, and binds a TCP port and serves queries for JDBC
031: * connections. This object is used to programmatically create a TCP JDBC
032: * server on the local machine.
033: * <p>
034: * Note that multiple servers can be constructed to serve the same DBSystem.
035: * You can not use this object to connect a single TCP server to multiple
036: * DBSystem objects.
037: * <p>
038: * If the underlying database is shut down then this server is also shut down.
039: *
040: * @author Tobias Downer
041: */
042:
043: public class TCPJDBCServer {
044:
045: /**
046: * The default TCP port for Mckoi SQL Database.
047: */
048: private final static int DEFAULT_TCP_PORT = 9157;
049:
050: /**
051: * The DBSystem object that we are serving.
052: */
053: private DBSystem system;
054:
055: /**
056: * An InetAddress representing the interface that server is bound to - useful
057: * for multi-homed machines. null means we bind to all interfaces.
058: */
059: private InetAddress bind_address;
060:
061: /**
062: * The TCP port that this server is bound to.
063: */
064: private int tcp_port;
065:
066: /**
067: * The TCPServer object that is managing the connections to this database.
068: */
069: private TCPServer server;
070:
071: /**
072: * Constructs the TCP JDBC with the given DBSystem object, and sets the
073: * inet address and TCP port that we serve the database from.
074: * <p>
075: * Constructing this server does not open the port to receive connections
076: * from outside. To start the JDBC server you need to call the 'start'
077: * method.
078: */
079: public TCPJDBCServer(DBSystem system, InetAddress bind_address,
080: int tcp_port) {
081: this .system = system;
082: this .bind_address = bind_address;
083: this .tcp_port = tcp_port;
084: registerShutdownDelegate();
085: }
086:
087: /**
088: * Constructs the TCP JDBC with the given DBSystem object, and sets the
089: * TCP port that we serve the database from. This binds the server to all
090: * interfaces on the local machine.
091: * <p>
092: * Constructing this server does not open the port to receive connections
093: * from outside. To start the JDBC server you need to call the 'start'
094: * method.
095: */
096: public TCPJDBCServer(DBSystem system, int tcp_port) {
097: this (system, null, tcp_port);
098: }
099:
100: /**
101: * Constructs the TCP JDBC with the given DBSystem object, and sets the
102: * TCP port and address (for multi-homed computers) to the setting of the
103: * configuration in 'system'.
104: * <p>
105: * Constructing this server does not open the port to receive connections
106: * from outside. To start the JDBC server you need to call the 'start'
107: * method.
108: */
109: public TCPJDBCServer(DBSystem system) {
110: this .system = system;
111:
112: DBConfig config = system.getConfig();
113:
114: int jdbc_port = DEFAULT_TCP_PORT;
115: InetAddress interface_address = null;
116:
117: // Read the JDBC config properties.
118: String jdbc_port_str = config.getValue("jdbc_server_port");
119: String interface_addr_str = config
120: .getValue("jdbc_server_address");
121:
122: if (jdbc_port_str != null) {
123: try {
124: jdbc_port = Integer.parseInt(jdbc_port_str);
125: } catch (Exception e) {
126: throw new RuntimeException(
127: "Unable to parse 'jdbc_server_port'");
128: }
129: }
130: if (interface_addr_str != null) {
131: try {
132: interface_address = InetAddress
133: .getByName(interface_addr_str);
134: } catch (UnknownHostException e) {
135: throw new RuntimeException("Unknown host: "
136: + e.getMessage());
137: }
138: }
139:
140: // Set up this port and bind address
141: this .tcp_port = jdbc_port;
142: this .bind_address = interface_address;
143:
144: registerShutdownDelegate();
145: }
146:
147: /**
148: * Registers the delegate that closes this server when the database
149: * shuts down.
150: */
151: private void registerShutdownDelegate() {
152: system.getDatabase().registerShutDownDelegate(new Runnable() {
153: public void run() {
154: if (server != null) {
155: stop();
156: }
157: }
158: });
159: }
160:
161: /**
162: * Starts the server and binds it to the given port. This method will start
163: * a new thread that listens for incoming connections.
164: */
165: public synchronized void start() {
166: if (server == null) {
167: server = new TCPServer(system.getDatabase());
168: server.start(bind_address, tcp_port, "multi_threaded");
169: } else {
170: throw new RuntimeException(
171: "'start' method called when a server was already started.");
172: }
173: }
174:
175: /**
176: * Stops the server running on the given port. This method will stop any
177: * threads that are listening for incoming connections.
178: * <p>
179: * Note that this does NOT close the underlying DBSystem object. The
180: * DBSystem object must be closed separately.
181: */
182: public synchronized void stop() {
183: if (server != null) {
184: server.close();
185: server = null;
186: } else {
187: throw new RuntimeException(
188: "'stop' method called when no server was started.");
189: }
190: }
191:
192: /**
193: * Returns a string that contains some information about the server that
194: * is running.
195: */
196: public String toString() {
197: return server.toString();
198: }
199:
200: }
|