1 30 31 32 package org.hsqldb; 33 34 import java.io.File ; 35 import java.io.IOException ; 36 import java.io.PrintWriter ; 37 import java.net.ServerSocket ; 38 import java.net.Socket ; 39 import java.net.UnknownHostException ; 40 import java.util.Enumeration ; 41 import java.util.StringTokenizer ; 42 43 import org.hsqldb.lib.ArrayUtil; 44 import org.hsqldb.lib.FileUtil; 45 import org.hsqldb.lib.HashSet; 46 import org.hsqldb.lib.Iterator; 47 import org.hsqldb.lib.StopWatch; 48 import org.hsqldb.lib.StringUtil; 49 import org.hsqldb.lib.WrapperIterator; 50 import org.hsqldb.lib.java.JavaSystem; 51 import org.hsqldb.persist.HsqlDatabaseProperties; 52 import org.hsqldb.persist.HsqlProperties; 53 import org.hsqldb.resources.BundleHandler; 54 55 67 214 public class Server implements HsqlSocketRequestHandler { 215 216 protected static final int serverBundleHandle = 218 BundleHandler.getBundleHandle("org_hsqldb_Server_messages", null); 219 220 HsqlProperties serverProperties; 222 223 HashSet serverConnSet; 225 226 private String [] dbAlias; 228 private String [] dbType; 229 private String [] dbPath; 230 private HsqlProperties[] dbProps; 231 private int[] dbID; 232 233 private int maxConnections; 235 236 protected String serverId; 238 protected int serverProtocol; 239 protected ThreadGroup serverConnectionThreadGroup; 240 protected HsqlSocketFactory socketFactory; 241 protected ServerSocket socket; 242 243 private Thread serverThread; 245 private Throwable serverError; 246 private volatile int serverState; 247 private volatile boolean isSilent; 248 private volatile boolean isRemoteOpen; 249 private PrintWriter logWriter; 250 private PrintWriter errWriter; 251 252 254 258 private class ServerThread extends Thread { 259 260 266 ServerThread(String name) { 267 268 super(name); 269 270 setName(name + '@' 271 + Integer.toString(Server.this.hashCode(), 16)); 272 } 273 274 277 public void run() { 278 Server.this.run(); 279 printWithThread("ServerThread.run() exited"); 280 } 281 } 282 283 286 public Server() { 287 this(ServerConstants.SC_PROTOCOL_HSQL); 288 } 289 290 302 protected Server(int protocol) { 303 init(protocol); 304 } 305 306 313 public static void main(String [] args) { 314 315 String propsPath = FileUtil.canonicalOrAbsolutePath("server"); 316 HsqlProperties fileProps = 317 ServerConfiguration.getPropertiesFromFile(propsPath); 318 HsqlProperties props = fileProps == null ? new HsqlProperties() 319 : fileProps; 320 HsqlProperties stringProps = HsqlProperties.argArrayToProps(args, 321 ServerConstants.SC_KEY_PREFIX); 322 323 if (stringProps != null) { 324 if (stringProps.getErrorKeys().length != 0) { 325 printHelp("server.help"); 326 327 return; 328 } 329 330 props.addProperties(stringProps); 331 } 332 333 ServerConfiguration.translateDefaultDatabaseProperty(props); 334 335 ServerConfiguration.translateDefaultNoSystemExitProperty(props); 340 341 Server server = new Server(); 343 344 server.setProperties(props); 345 346 server.print("Startup sequence initiated from main() method"); 348 349 if (fileProps != null) { 350 server.print("Loaded properties from [" + propsPath 351 + ".properties]"); 352 } else { 353 server.print("Could not load properties from file"); 354 server.print("Using cli/default properties only"); 355 } 356 357 server.start(); 358 } 359 360 369 public void checkRunning(boolean running) throws RuntimeException { 370 371 int state; 372 boolean error; 373 374 printWithThread("checkRunning(" + running + ") entered"); 375 376 state = getState(); 377 error = (running && state != ServerConstants.SERVER_STATE_ONLINE) 378 || (!running 379 && state != ServerConstants.SERVER_STATE_SHUTDOWN); 380 381 if (error) { 382 String msg = "server is " + (running ? "not " 383 : "") + "running"; 384 385 throw new RuntimeException (msg); 386 } 387 388 printWithThread("checkRunning(" + running + ") exited"); 389 } 390 391 398 public synchronized void signalCloseAllServerConnections() { 399 400 Iterator it; 401 402 printWithThread("signalCloseAllServerConnections() entered"); 403 404 synchronized (serverConnSet) { 405 406 it = new WrapperIterator(serverConnSet.toArray(null)); 408 } 409 410 for (; it.hasNext(); ) { 411 ServerConnection sc = (ServerConnection) it.next(); 412 413 printWithThread("Closing " + sc); 414 415 sc.signalClose(); 417 } 418 419 printWithThread("signalCloseAllServerConnections() exited"); 420 } 421 422 protected void finalize() throws Throwable { 423 424 if (serverThread != null) { 425 releaseServerSocket(); 426 } 427 } 428 429 438 public String getAddress() { 439 440 return socket == null 441 ? serverProperties.getProperty(ServerConstants.SC_KEY_ADDRESS) 442 : socket.getInetAddress().getHostAddress(); 443 } 444 445 471 public String getDatabaseName(int index, boolean asconfigured) { 472 473 if (asconfigured) { 474 return serverProperties.getProperty(ServerConstants.SC_KEY_DBNAME 475 + "." + index); 476 } else if (getState() == ServerConstants.SERVER_STATE_ONLINE) { 477 return (dbAlias == null || index < 0 || index >= dbAlias.length) 478 ? null 479 : dbAlias[index]; 480 } else { 481 return null; 482 } 483 } 484 485 512 public String getDatabasePath(int index, boolean asconfigured) { 513 514 if (asconfigured) { 515 return serverProperties.getProperty( 516 ServerConstants.SC_KEY_DATABASE + "." + index); 517 } else if (getState() == ServerConstants.SERVER_STATE_ONLINE) { 518 return (dbPath == null || index < 0 || index >= dbPath.length) 519 ? null 520 : dbPath[index]; 521 } else { 522 return null; 523 } 524 } 525 526 public String getDatabaseType(int index) { 527 return (dbType == null || index < 0 || index >= dbType.length) ? null 528 : dbType[index]; 529 } 530 531 541 public String getDefaultWebPage() { 542 return "[IGNORED]"; 543 } 544 545 551 public String getHelpString() { 552 return BundleHandler.getString(serverBundleHandle, "server.help"); 553 } 554 555 560 public PrintWriter getErrWriter() { 561 return errWriter; 562 } 563 564 569 public PrintWriter getLogWriter() { 570 return logWriter; 571 } 572 573 582 public int getPort() { 583 584 return serverProperties.getIntegerProperty( 585 ServerConstants.SC_KEY_PORT, 586 ServerConfiguration.getDefaultPort(serverProtocol, isTls())); 587 } 588 589 600 public String getProductName() { 601 return "HSQLDB server"; 602 } 603 604 615 public String getProductVersion() { 616 return HsqlDatabaseProperties.THIS_VERSION; 617 } 618 619 629 public String getProtocol() { 630 return isTls() ? "HSQLS" 631 : "HSQL"; 632 } 633 634 643 public Throwable getServerError() { 644 return serverError; 645 } 646 647 656 public String getServerId() { 657 return serverId; 658 } 659 660 678 public synchronized int getState() { 679 return serverState; 680 } 681 682 693 public String getStateDescriptor() { 694 695 String state; 696 Throwable t = getServerError(); 697 698 switch (serverState) { 699 700 case ServerConstants.SERVER_STATE_SHUTDOWN : 701 state = "SHUTDOWN"; 702 break; 703 704 case ServerConstants.SERVER_STATE_OPENING : 705 state = "OPENING"; 706 break; 707 708 case ServerConstants.SERVER_STATE_CLOSING : 709 state = "CLOSING"; 710 break; 711 712 case ServerConstants.SERVER_STATE_ONLINE : 713 state = "ONLINE"; 714 break; 715 716 default : 717 state = "UNKNOWN"; 718 break; 719 } 720 721 return state; 722 } 723 724 737 public String getWebRoot() { 738 return "[IGNORED]"; 739 } 740 741 747 public void handleConnection(Socket s) { 748 749 Thread t; 750 Runnable r; 751 String ctn; 752 753 printWithThread("handleConnection(" + s + ") entered"); 754 755 if (!allowConnection(s)) { 756 try { 757 s.close(); 758 } catch (Exception e) {} 759 760 printWithThread("allowConnection(): connection refused"); 761 printWithThread("handleConnection() exited"); 762 763 return; 764 } 765 766 if (socketFactory != null) { 769 socketFactory.configureSocket(s); 770 } 771 772 if (serverProtocol == ServerConstants.SC_PROTOCOL_HSQL) { 773 r = new ServerConnection(s, this); 774 ctn = ((ServerConnection) r).getConnectionThreadName(); 775 776 synchronized (serverConnSet) { 777 serverConnSet.add(r); 778 } 779 } else { 780 r = new WebServerConnection(s, (WebServer) this); 781 ctn = ((WebServerConnection) r).getConnectionThreadName(); 782 } 783 784 t = new Thread (serverConnectionThreadGroup, r, ctn); 785 786 t.start(); 787 printWithThread("handleConnection() exited"); 788 } 789 790 799 public boolean isNoSystemExit() { 800 return serverProperties.isPropertyTrue( 801 ServerConstants.SC_KEY_NO_SYSTEM_EXIT); 802 } 803 804 813 public boolean isRestartOnShutdown() { 814 return serverProperties.isPropertyTrue( 815 ServerConstants.SC_KEY_AUTORESTART_SERVER); 816 } 817 818 829 public boolean isSilent() { 830 return isSilent; 831 } 832 833 843 public boolean isTls() { 844 return serverProperties.isPropertyTrue(ServerConstants.SC_KEY_TLS); 845 } 846 847 857 public boolean isTrace() { 858 return serverProperties.isPropertyTrue(ServerConstants.SC_KEY_TRACE); 859 } 860 861 882 public boolean putPropertiesFromFile(String path) 883 throws RuntimeException { 884 885 if (getState() != ServerConstants.SERVER_STATE_SHUTDOWN) { 886 throw new RuntimeException (); 887 } 888 889 path = FileUtil.canonicalOrAbsolutePath(path); 890 891 HsqlProperties p = ServerConfiguration.getPropertiesFromFile(path); 892 893 if (p == null || p.isEmpty()) { 894 return false; 895 } 896 897 printWithThread("putPropertiesFromFile(): [" + path + ".properties]"); 898 setProperties(p); 899 900 return true; 901 } 902 903 922 public void putPropertiesFromString(String s) throws RuntimeException { 923 924 if (getState() != ServerConstants.SERVER_STATE_SHUTDOWN) { 925 throw new RuntimeException (); 926 } 927 928 if (StringUtil.isEmpty(s)) { 929 return; 930 } 931 932 printWithThread("putPropertiesFromString(): [" + s + "]"); 933 934 HsqlProperties p = HsqlProperties.delimitedArgPairsToProps(s, "=", 935 ";", ServerConstants.SC_KEY_PREFIX); 936 937 setProperties(p); 938 } 939 940 954 public void setAddress(String address) throws RuntimeException { 955 956 checkRunning(false); 957 958 if (org.hsqldb.lib.StringUtil.isEmpty(address)) { 959 address = ServerConstants.SC_DEFAULT_ADDRESS; 960 } 961 962 printWithThread("setAddress(" + address + ")"); 963 serverProperties.setProperty(ServerConstants.SC_KEY_ADDRESS, address); 964 } 965 966 989 public void setDatabaseName(int index, 990 String name) throws RuntimeException { 991 992 checkRunning(false); 993 printWithThread("setDatabaseName(" + index + "," + name + ")"); 994 serverProperties.setProperty(ServerConstants.SC_KEY_DBNAME + "." 995 + index, name); 996 } 997 998 1020 public void setDatabasePath(int index, 1021 String path) throws RuntimeException { 1022 1023 checkRunning(false); 1024 printWithThread("setDatabasePath(" + index + "," + path + ")"); 1025 serverProperties.setProperty(ServerConstants.SC_KEY_DATABASE + "." 1026 + index, path); 1027 } 1028 1029 1036 public void setDefaultWebPage(String file) { 1037 1038 checkRunning(false); 1039 printWithThread("setDefaultWebPage(" + file + ")"); 1040 1041 if (serverProtocol != ServerConstants.SC_PROTOCOL_HTTP) { 1042 return; 1043 } 1044 1045 serverProperties.setProperty(ServerConstants.SC_KEY_WEB_DEFAULT_PAGE, 1046 file); 1047 } 1048 1049 1056 public void setPort(int port) throws RuntimeException { 1057 1058 checkRunning(false); 1059 printWithThread("setPort(" + port + ")"); 1060 serverProperties.setProperty(ServerConstants.SC_KEY_PORT, port); 1061 } 1062 1063 1070 public void setErrWriter(PrintWriter pw) { 1071 errWriter = pw; 1072 } 1073 1074 1081 public void setLogWriter(PrintWriter pw) { 1082 logWriter = pw; 1083 } 1084 1085 1092 public void setNoSystemExit(boolean noExit) { 1093 1094 printWithThread("setNoSystemExit(" + noExit + ")"); 1095 serverProperties.setProperty(ServerConstants.SC_KEY_NO_SYSTEM_EXIT, 1096 noExit); 1097 } 1098 1099 1106 public void setRestartOnShutdown(boolean restart) { 1107 1108 printWithThread("setRestartOnShutdown(" + restart + ")"); 1109 serverProperties.setProperty( 1110 ServerConstants.SC_KEY_AUTORESTART_SERVER, restart); 1111 } 1112 1113 1121 public void setSilent(boolean silent) { 1122 1123 printWithThread("setSilent(" + silent + ")"); 1124 serverProperties.setProperty(ServerConstants.SC_KEY_SILENT, silent); 1125 1126 isSilent = silent; 1127 } 1128 1129 1137 public void setTls(boolean tls) { 1138 1139 checkRunning(false); 1140 printWithThread("setTls(" + tls + ")"); 1141 serverProperties.setProperty(ServerConstants.SC_KEY_TLS, tls); 1142 } 1143 1144 1152 public void setTrace(boolean trace) { 1153 1154 printWithThread("setTrace(" + trace + ")"); 1155 serverProperties.setProperty(ServerConstants.SC_KEY_TRACE, trace); 1156 JavaSystem.setLogToSystem(trace); 1157 } 1158 1159 1167 public void setWebRoot(String root) { 1168 1169 checkRunning(false); 1170 1171 root = (new File (root)).getAbsolutePath(); 1172 1173 printWithThread("setWebRoot(" + root + ")"); 1174 1175 if (serverProtocol != ServerConstants.SC_PROTOCOL_HTTP) { 1176 return; 1177 } 1178 1179 serverProperties.setProperty(ServerConstants.SC_KEY_WEB_ROOT, root); 1180 } 1181 1182 1187 public void setProperties(HsqlProperties p) { 1188 1189 checkRunning(false); 1190 1191 if (p != null) { 1192 serverProperties.addProperties(p); 1193 ServerConfiguration.translateAddressProperty(serverProperties); 1194 } 1195 1196 maxConnections = serverProperties.getIntegerProperty( 1197 ServerConstants.SC_KEY_MAX_CONNECTIONS, 16); 1198 1199 JavaSystem.setLogToSystem(isTrace()); 1200 1201 isSilent = 1202 serverProperties.isPropertyTrue(ServerConstants.SC_KEY_SILENT); 1203 isRemoteOpen = serverProperties.isPropertyTrue( 1204 ServerConstants.SC_KEY_REMOTE_OPEN_DB); 1205 } 1206 1207 1222 public int start() { 1223 1224 printWithThread("start() entered"); 1225 1226 int previousState = getState(); 1227 1228 if (serverThread != null) { 1229 printWithThread("start(): serverThread != null; no action taken"); 1230 1231 return previousState; 1232 } 1233 1234 setState(ServerConstants.SERVER_STATE_OPENING); 1235 1236 serverThread = new ServerThread("HSQLDB Server "); 1237 1238 serverThread.start(); 1239 1240 while (getState() == ServerConstants.SERVER_STATE_OPENING) { 1242 try { 1243 Thread.sleep(100); 1244 } catch (InterruptedException e) {} 1245 } 1246 1247 printWithThread("start() exiting"); 1248 1249 return previousState; 1250 } 1251 1252 1266 public int stop() { 1267 1268 printWithThread("stop() entered"); 1269 1270 int previousState = getState(); 1271 1272 if (serverThread == null) { 1273 printWithThread("stop() serverThread is null; no action taken"); 1274 1275 return previousState; 1276 } 1277 1278 releaseServerSocket(); 1279 printWithThread("stop() exiting"); 1280 1281 return previousState; 1282 } 1283 1284 1292 protected boolean allowConnection(Socket socket) { 1293 return true; 1294 } 1295 1296 1301 protected void init(int protocol) { 1302 1303 serverState = ServerConstants.SERVER_STATE_SHUTDOWN; 1305 serverConnSet = new HashSet(); 1306 serverId = toString(); 1307 serverId = serverId.substring(serverId.lastIndexOf('.') + 1); 1308 serverProtocol = protocol; 1309 serverProperties = ServerConfiguration.newDefaultProperties(protocol); 1310 logWriter = new PrintWriter (System.out); 1311 errWriter = new PrintWriter (System.err); 1312 1313 JavaSystem.setLogToSystem(isTrace()); 1314 } 1315 1316 1321 protected synchronized void setState(int state) { 1322 serverState = state; 1323 } 1324 1325 1328 1334 final void notify(int action, int id) { 1335 1336 printWithThread("notifiy(" + action + "," + id + ") entered"); 1337 1338 if (action != ServerConstants.SC_DATABASE_SHUTDOWN) { 1339 return; 1340 } 1341 1342 releaseDatabase(id); 1343 1344 boolean shutdown = true; 1345 1346 for (int i = 0; i < dbID.length; i++) { 1347 if (dbAlias[i] != null) { 1348 shutdown = false; 1349 } 1350 } 1351 1352 if (!isRemoteOpen && shutdown) { 1353 stop(); 1354 } 1355 } 1356 1357 1361 final synchronized void releaseDatabase(int id) { 1362 1363 Iterator it; 1364 boolean found = false; 1365 1366 printWithThread("releaseDatabase(" + id + ") entered"); 1367 1368 for (int i = 0; i < dbID.length; i++) { 1370 if (dbID[i] == id && dbAlias[i] != null) { 1371 dbID[i] = 0; 1372 dbAlias[i] = null; 1373 dbPath[i] = null; 1374 dbType[i] = null; 1375 dbProps[i] = null; 1376 } 1377 } 1378 1379 synchronized (serverConnSet) { 1380 it = new WrapperIterator(serverConnSet.toArray(null)); 1381 } 1382 1383 while (it.hasNext()) { 1384 ServerConnection sc = (ServerConnection) it.next(); 1385 1386 if (sc.dbID == id) { 1387 sc.signalClose(); 1388 serverConnSet.remove(sc); 1389 } 1390 } 1391 1392 printWithThread("releaseDatabase(" + id + ") exiting"); 1393 } 1394 1395 1401 protected synchronized void print(String msg) { 1402 1403 PrintWriter writer = logWriter; 1404 1405 if (writer != null) { 1406 writer.println("[" + serverId + "]: " + msg); 1407 writer.flush(); 1408 } 1409 } 1410 1411 1418 final void printResource(String key) { 1419 1420 String resource; 1421 StringTokenizer st; 1422 1423 if (serverBundleHandle < 0) { 1424 return; 1425 } 1426 1427 resource = BundleHandler.getString(serverBundleHandle, key); 1428 1429 if (resource == null) { 1430 return; 1431 } 1432 1433 st = new StringTokenizer (resource, "\n\r"); 1434 1435 while (st.hasMoreTokens()) { 1436 print(st.nextToken()); 1437 } 1438 } 1439 1440 1446 protected synchronized void printStackTrace(Throwable t) { 1447 1448 if (errWriter != null) { 1449 t.printStackTrace(errWriter); 1450 errWriter.flush(); 1451 } 1452 } 1453 1454 1461 final void printWithTimestamp(String msg) { 1462 print(HsqlDateTime.getSytemTimeString() + " " + msg); 1463 } 1464 1465 1472 protected void printWithThread(String msg) { 1473 1474 if (!isSilent()) { 1475 print("[" + Thread.currentThread() + "]: " + msg); 1476 } 1477 } 1478 1479 1486 protected synchronized void printError(String msg) { 1487 1488 PrintWriter writer = errWriter; 1489 1490 if (writer != null) { 1491 writer.print("[" + serverId + "]: "); 1492 writer.print("[" + Thread.currentThread() + "]: "); 1493 writer.println(msg); 1494 writer.flush(); 1495 } 1496 } 1497 1498 1520 final void printRequest(int cid, Result r) { 1521 1522 if (isSilent()) { 1523 return; 1524 } 1525 1526 StringBuffer sb = new StringBuffer (); 1527 1528 sb.append(cid); 1529 sb.append(':'); 1530 1531 switch (r.mode) { 1532 1533 case ResultConstants.SQLPREPARE : { 1534 sb.append("SQLCLI:SQLPREPARE "); 1535 sb.append(r.getMainString()); 1536 1537 break; 1538 } 1539 case ResultConstants.SQLEXECDIRECT : { 1540 if (r.getSize() < 2) { 1541 sb.append(r.getMainString()); 1542 } else { 1543 sb.append("SQLCLI:SQLEXECDIRECT:BATCHMODE\n"); 1544 1545 Iterator it = r.iterator(); 1546 1547 while (it.hasNext()) { 1548 Object [] data = (Object []) it.next(); 1549 1550 sb.append(data[0]).append('\n'); 1551 } 1552 } 1553 1554 break; 1555 } 1556 case ResultConstants.SQLEXECUTE : { 1557 sb.append("SQLCLI:SQLEXECUTE:"); 1558 1559 if (r.getSize() > 1) { 1560 sb.append("BATCHMODE:"); 1561 } 1562 1563 sb.append(r.getStatementID()); 1564 1565 1568 1574 break; 1575 } 1576 case ResultConstants.SQLFREESTMT : { 1577 sb.append("SQLCLI:SQLFREESTMT:"); 1578 sb.append(r.getStatementID()); 1579 1580 break; 1581 } 1582 case ResultConstants.GETSESSIONATTR : { 1583 sb.append("HSQLCLI:GETSESSIONATTR"); 1584 1585 break; 1586 } 1587 case ResultConstants.SETSESSIONATTR : { 1588 sb.append("HSQLCLI:SETSESSIONATTR:"); 1589 sb.append("AUTOCOMMIT "); 1590 sb.append(r.rRoot.data[Session.INFO_AUTOCOMMIT]); 1591 sb.append(" CONNECTION_READONLY "); 1592 sb.append(r.rRoot.data[Session.INFO_CONNECTION_READONLY]); 1593 1594 break; 1595 } 1596 case ResultConstants.SQLENDTRAN : { 1597 sb.append("SQLCLI:SQLENDTRAN:"); 1598 1599 switch (r.getEndTranType()) { 1600 1601 case ResultConstants.COMMIT : 1602 sb.append("COMMIT"); 1603 break; 1604 1605 case ResultConstants.ROLLBACK : 1606 sb.append("ROLLBACK"); 1607 break; 1608 1609 case ResultConstants.SAVEPOINT_NAME_RELEASE : 1610 sb.append("SAVEPOINT_NAME_RELEASE "); 1611 sb.append(r.getMainString()); 1612 break; 1613 1614 case ResultConstants.SAVEPOINT_NAME_ROLLBACK : 1615 sb.append("SAVEPOINT_NAME_ROLLBACK "); 1616 sb.append(r.getMainString()); 1617 break; 1618 1619 default : 1620 sb.append(r.getEndTranType()); 1621 } 1622 1623 break; 1624 } 1625 case ResultConstants.SQLSTARTTRAN : { 1626 sb.append("SQLCLI:SQLSTARTTRAN"); 1627 1628 break; 1629 } 1630 case ResultConstants.SQLDISCONNECT : { 1631 sb.append("SQLCLI:SQLDISCONNECT"); 1632 1633 break; 1634 } 1635 case ResultConstants.SQLSETCONNECTATTR : { 1636 sb.append("SQLCLI:SQLSETCONNECTATTR:"); 1637 1638 switch (r.getConnectionAttrType()) { 1639 1640 case ResultConstants.SQL_ATTR_SAVEPOINT_NAME : { 1641 sb.append("SQL_ATTR_SAVEPOINT_NAME "); 1642 sb.append(r.getMainString()); 1643 1644 break; 1645 } 1646 default : { 1647 sb.append(r.getConnectionAttrType()); 1648 } 1649 } 1650 1651 break; 1652 } 1653 default : { 1654 sb.append("SQLCLI:MODE:"); 1655 sb.append(r.mode); 1656 1657 break; 1658 } 1659 } 1660 1661 print(sb.toString()); 1662 } 1663 1664 1667 synchronized final int getDBID(String aliasPath) throws HsqlException { 1668 1669 int semipos = aliasPath.indexOf(';'); 1670 String alias = aliasPath; 1671 String filepath = null; 1672 1673 if (semipos != -1) { 1674 alias = aliasPath.substring(0, semipos); 1675 filepath = aliasPath.substring(semipos + 1); 1676 } 1677 1678 int dbIndex = ArrayUtil.find(dbAlias, alias); 1679 1680 if (dbIndex == -1) { 1681 if (filepath == null) { 1682 RuntimeException e = 1683 new RuntimeException ("database alias does not exist"); 1684 1685 printError("database alias=" + alias + " does not exist"); 1686 setServerError(e); 1687 1688 throw e; 1689 } else { 1690 return openDatabase(alias, filepath); 1691 } 1692 } else { 1693 return dbID[dbIndex]; 1694 } 1695 } 1696 1697 1700 final int openDatabase(String alias, 1701 String filepath) throws HsqlException { 1702 1703 if (!isRemoteOpen) { 1704 RuntimeException e = 1705 new RuntimeException ("remote open not allowed"); 1706 1707 printError("Remote database open not allowed"); 1708 setServerError(e); 1709 1710 throw e; 1711 } 1712 1713 int i = getFirstEmptyDatabaseIndex(); 1714 1715 if (i < -1) { 1716 RuntimeException e = 1717 new RuntimeException ("limit of open databases reached"); 1718 1719 printError("limit of open databases reached"); 1720 setServerError(e); 1721 1722 throw e; 1723 } 1724 1725 HsqlProperties newprops = DatabaseURL.parseURL(filepath, false); 1726 1727 if (newprops == null) { 1728 RuntimeException e = 1729 new RuntimeException ("invalid database path"); 1730 1731 printError("invalid database path"); 1732 setServerError(e); 1733 1734 throw e; 1735 } 1736 1737 String path = newprops.getProperty("database"); 1738 String type = newprops.getProperty("connection_type"); 1739 1740 try { 1741 int dbid = DatabaseManager.getDatabase(type, path, this, 1742 newprops); 1743 1744 dbID[i] = dbid; 1745 dbAlias[i] = alias; 1746 dbPath[i] = path; 1747 dbType[i] = type; 1748 dbProps[i] = newprops; 1749 1750 return dbid; 1751 } catch (HsqlException e) { 1752 printError("Database [index=" + i + "db=" + dbType[i] + dbPath[i] 1753 + ", alias=" + dbAlias[i] + "] did not open: " 1754 + e.toString()); 1755 setServerError(e); 1756 1757 throw e; 1758 } 1759 } 1760 1761 final int getFirstEmptyDatabaseIndex() { 1762 1763 for (int i = 0; i < dbAlias.length; i++) { 1764 if (dbAlias[i] == null) { 1765 return i; 1766 } 1767 } 1768 1769 return -1; 1770 } 1771 1772 1781 final boolean openDatabases() { 1782 1783 printWithThread("openDatabases() entered"); 1784 1785 boolean success = false; 1786 1787 setDBInfoArrays(); 1788 1789 for (int i = 0; i < dbAlias.length; i++) { 1790 if (dbAlias[i] == null) { 1791 continue; 1792 } 1793 1794 printWithThread("Opening database: [" + dbType[i] + dbPath[i] 1795 + "]"); 1796 1797 StopWatch sw = new StopWatch(); 1798 int id; 1799 1800 try { 1801 id = DatabaseManager.getDatabase(dbType[i], dbPath[i], this, 1802 dbProps[i]); 1803 dbID[i] = id; 1804 success = true; 1805 } catch (HsqlException e) { 1806 printError("Database [index=" + i + "db=" + dbType[i] 1807 + dbPath[i] + ", alias=" + dbAlias[i] 1808 + "] did not open: " + e.toString()); 1809 setServerError(e); 1810 1811 dbAlias[i] = null; 1812 dbPath[i] = null; 1813 dbType[i] = null; 1814 dbProps[i] = null; 1815 1816 continue; 1817 } 1818 1819 sw.stop(); 1820 1821 String msg = "Database [index=" + i + ", id=" + id + ", " + "db=" 1822 + dbType[i] + dbPath[i] + ", alias=" + dbAlias[i] 1823 + "] opened sucessfully"; 1824 1825 print(sw.elapsedTimeToMessage(msg)); 1826 } 1827 1828 printWithThread("openDatabases() exiting"); 1829 1830 if (isRemoteOpen) { 1831 success = true; 1832 } 1833 1834 if (!success && getServerError() == null) { 1835 1836 setServerError(Trace.error(Trace.SERVER_NO_DATABASE)); 1838 } 1839 1840 return success; 1841 } 1842 1843 1846 private void setDBInfoArrays() { 1847 1848 dbAlias = getDBNameArray(); 1849 dbPath = new String [dbAlias.length]; 1850 dbType = new String [dbAlias.length]; 1851 dbID = new int[dbAlias.length]; 1852 dbProps = new HsqlProperties[dbAlias.length]; 1853 1854 for (int i = 0; i < dbAlias.length; i++) { 1855 if (dbAlias[i] == null) { 1856 continue; 1857 } 1858 1859 String path = getDatabasePath(i, true); 1860 1861 if (path == null) { 1862 dbAlias[i] = null; 1863 1864 continue; 1865 } 1866 1867 HsqlProperties dbURL = DatabaseURL.parseURL(path, false); 1868 1869 if (dbURL == null) { 1870 dbAlias[i] = null; 1871 1872 continue; 1873 } 1874 1875 dbPath[i] = dbURL.getProperty("database"); 1876 dbType[i] = dbURL.getProperty("connection_type"); 1877 dbProps[i] = dbURL; 1878 } 1879 } 1880 1881 1885 private String [] getDBNameArray() { 1886 1887 final String prefix = ServerConstants.SC_KEY_DBNAME + "."; 1888 final int prefixLen = prefix.length(); 1889 String [] dblist = new String [10]; 1890 int maxindex = 0; 1891 1892 try { 1893 Enumeration en = serverProperties.propertyNames(); 1894 1895 for (; en.hasMoreElements(); ) { 1896 String key = (String ) en.nextElement(); 1897 1898 if (!key.startsWith(prefix)) { 1899 continue; 1900 } 1901 1902 try { 1903 int dbnum = Integer.parseInt(key.substring(prefixLen)); 1904 1905 maxindex = dbnum < maxindex ? maxindex 1906 : dbnum; 1907 dblist[dbnum] = 1908 serverProperties.getProperty(key).toLowerCase(); 1909 } catch (NumberFormatException e) { 1910 printWithThread("dblist: " + e.toString()); 1911 } 1912 } 1913 } catch (ArrayIndexOutOfBoundsException e) { 1914 printWithThread("dblist: " + e.toString()); 1915 } 1916 1917 return dblist; 1918 } 1919 1920 1926 private void openServerSocket() throws Exception { 1927 1928 String address; 1929 int port; 1930 String [] candidateAddrs; 1931 String emsg; 1932 StopWatch sw; 1933 1934 printWithThread("openServerSocket() entered"); 1935 1936 if (isTls()) { 1937 printWithThread("Requesting TLS/SSL-encrypted JDBC"); 1938 } 1939 1940 sw = new StopWatch(); 1941 socketFactory = HsqlSocketFactory.getInstance(isTls()); 1942 address = getAddress(); 1943 port = getPort(); 1944 1945 if (org.hsqldb.lib.StringUtil.isEmpty(address) 1946 || ServerConstants.SC_DEFAULT_ADDRESS.equalsIgnoreCase( 1947 address.trim())) { 1948 socket = socketFactory.createServerSocket(port); 1949 } else { 1950 try { 1951 socket = socketFactory.createServerSocket(port, address); 1952 } catch (UnknownHostException e) { 1953 candidateAddrs = 1954 ServerConfiguration.listLocalInetAddressNames(); 1955 1956 int messageID; 1957 Object [] messageParameters; 1958 1959 if (candidateAddrs.length > 0) { 1960 messageID = Trace.Server_openServerSocket; 1961 messageParameters = new Object [] { 1962 address, candidateAddrs 1963 }; 1964 } else { 1965 messageID = Trace.Server_openServerSocket2; 1966 messageParameters = new Object []{ address }; 1967 } 1968 1969 throw new UnknownHostException (Trace.getMessage(messageID, 1970 true, messageParameters)); 1971 } 1972 } 1973 1974 1978 socket.setSoTimeout(1000); 1979 printWithThread("Got server socket: " + socket); 1980 print(sw.elapsedTimeToMessage("Server socket opened successfully")); 1981 1982 if (socketFactory.isSecure()) { 1983 print("Using TLS/SSL-encrypted JDBC"); 1984 } 1985 1986 printWithThread("openServerSocket() exiting"); 1987 } 1988 1989 1990 private void printServerOnlineMessage() { 1991 1992 String s = getProductName() + " " + getProductVersion() 1993 + " is online"; 1994 1995 printWithTimestamp(s); 1996 printResource("online.help"); 1997 } 1998 1999 2002 protected void printProperties() { 2003 2004 Enumeration e; 2005 String key; 2006 String value; 2007 2008 if (isSilent()) { 2011 return; 2012 } 2013 2014 e = serverProperties.propertyNames(); 2015 2016 while (e.hasMoreElements()) { 2017 key = (String ) e.nextElement(); 2018 value = serverProperties.getProperty(key); 2019 2020 printWithThread(key + "=" + value); 2021 } 2022 } 2023 2024 2030 private void releaseServerSocket() { 2031 2032 printWithThread("releaseServerSocket() entered"); 2033 2034 if (socket != null) { 2035 printWithThread("Releasing server socket: [" + socket + "]"); 2036 setState(ServerConstants.SERVER_STATE_CLOSING); 2037 2038 try { 2039 socket.close(); 2040 } catch (IOException e) { 2041 printError("Exception closing server socket"); 2042 printError("releaseServerSocket(): " + e); 2043 } 2044 2045 socket = null; 2046 } 2047 2048 printWithThread("releaseServerSocket() exited"); 2049 } 2050 2051 2059 private void run() { 2060 2061 StopWatch sw; 2062 ThreadGroup tg; 2063 String tgName; 2064 2065 printWithThread("run() entered"); 2066 print("Initiating startup sequence..."); 2067 printProperties(); 2068 2069 sw = new StopWatch(); 2070 2071 setServerError(null); 2072 2073 try { 2074 2075 openServerSocket(); 2079 } catch (Exception e) { 2080 setServerError(e); 2081 printError("run()/openServerSocket(): "); 2082 printStackTrace(e); 2083 shutdown(true); 2084 2085 return; 2086 } 2087 2088 tgName = "HSQLDB Connections @" 2089 + Integer.toString(this.hashCode(), 16); 2090 tg = new ThreadGroup (tgName); 2091 2092 tg.setDaemon(false); 2093 2094 serverConnectionThreadGroup = tg; 2095 2096 if (openDatabases() == false) { 2100 setServerError(null); 2101 printError("run()/openDatabases(): "); 2102 shutdown(true); 2103 2104 return; 2105 } 2106 2107 setState(ServerConstants.SERVER_STATE_ONLINE); 2111 print(sw.elapsedTimeToMessage("Startup sequence completed")); 2112 printServerOnlineMessage(); 2113 2114 try { 2115 2120 while (true) { 2121 try { 2122 handleConnection(socket.accept()); 2123 } catch (java.io.InterruptedIOException e) {} 2124 } 2125 } catch (IOException e) { 2126 if (getState() == ServerConstants.SERVER_STATE_ONLINE) { 2127 setServerError(e); 2128 printError(this + ".run()/handleConnection(): "); 2129 printStackTrace(e); 2130 } 2131 } catch (Throwable t) { 2132 printWithThread(t.toString()); 2133 } finally { 2134 shutdown(false); } 2136 } 2137 2138 2143 protected void setServerError(Throwable t) { 2144 serverError = t; 2145 } 2146 2147 2150 public void shutdown() { 2151 shutdown(false); 2152 } 2153 2154 2160 protected synchronized void shutdown(boolean error) { 2161 2162 if (serverState == ServerConstants.SERVER_STATE_SHUTDOWN) { 2163 return; 2164 } 2165 2166 StopWatch sw; 2167 2168 printWithThread("shutdown() entered"); 2169 2170 sw = new StopWatch(); 2171 2172 print("Initiating shutdown sequence..."); 2173 releaseServerSocket(); 2174 DatabaseManager.deRegisterServer(this); 2175 2176 if (dbPath != null) { 2177 for (int i = 0; i < dbPath.length; i++) { 2178 releaseDatabase(dbID[i]); 2179 } 2180 } 2181 2182 if (serverConnectionThreadGroup != null) { 2185 if (!serverConnectionThreadGroup.isDestroyed()) { 2186 for (int i = 0; serverConnectionThreadGroup.activeCount() > 0; 2187 i++) { 2188 int count; 2189 2190 try { 2191 Thread.sleep(100); 2192 } catch (Exception e) { 2193 2194 } 2196 } 2197 2198 try { 2199 serverConnectionThreadGroup.destroy(); 2200 printWithThread(serverConnectionThreadGroup.getName() 2201 + " destroyed"); 2202 } catch (Throwable t) { 2203 printWithThread(serverConnectionThreadGroup.getName() 2204 + " not destroyed"); 2205 printWithThread(t.toString()); 2206 } 2207 } 2208 2209 serverConnectionThreadGroup = null; 2210 } 2211 2212 serverThread = null; 2213 2214 setState(ServerConstants.SERVER_STATE_SHUTDOWN); 2215 print(sw.elapsedTimeToMessage("Shutdown sequence completed")); 2216 2217 if (isNoSystemExit()) { 2218 printWithTimestamp("SHUTDOWN : System.exit() was not called"); 2219 printWithThread("shutdown() exited"); 2220 } else { 2221 printWithTimestamp("SHUTDOWN : System.exit() is called next"); 2222 printWithThread("shutdown() exiting..."); 2223 2224 try { 2225 System.exit(0); 2226 } catch (Throwable t) { 2227 printWithThread(t.toString()); 2228 } 2229 } 2230 } 2231 2232 2243 protected static void printHelp(String key) { 2244 System.out.print(BundleHandler.getString(serverBundleHandle, key)); 2245 } 2246} 2247 | Popular Tags |