Java tutorial
/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program 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 Lesser General Public License for more details. * * Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.platform.web.hsqldb; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hsqldb.Server; import org.hsqldb.server.ServerConfiguration; import org.hsqldb.server.ServerConstants; import org.hsqldb.server.ServerProperties; import org.hsqldb.lib.FileUtil; import org.hsqldb.persist.HsqlProperties; import org.pentaho.platform.web.hsqldb.messages.Messages; import java.io.IOException; import java.net.ServerSocket; import java.text.MessageFormat; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; /** * The purpose of this Java class is to startup a HSQLDB databases. This class should not installed in production * environments. This is for samples / demoing only. * * You typically will configure a ServletContext parameter in your web.xml, named "hsqldb-databases" with a value that * follows this format: dbName@../path/to/database,@otherDbName@../path/to/other/database * */ public class HsqlDatabaseStarterBean { private static final Log logger = LogFactory.getLog(HsqlDatabaseStarterBean.class); private Server hsqlServer; private int port = 9001; // Default Port private int failoverPort = port; private Map<String, String> databases = new LinkedHashMap<String, String>(); private boolean allowFailoverToDefaultPort; protected boolean checkPort() { if ((port < 0) || (port > 65535)) { if (allowFailoverToDefaultPort) { logger.error(Messages.getErrorString("HsqlDatabaseStarterBean.ERROR_0004_INVALID_PORT", //$NON-NLS-1$ "" + failoverPort)); port = failoverPort; } else { return logFailure("HsqlDatabaseStarterBean.ERROR_0004_INVALID_PORT", "" + failoverPort); //$NON-NLS-1$ } } try { ServerSocket sock = new ServerSocket(port); sock.close(); } catch (IOException ex1) { if (port == failoverPort) { return logFailure("HsqlDatabaseStarterBean.ERROR_0006_DEFAULT_PORT_IN_USE"); //$NON-NLS-1$ } else { if (allowFailoverToDefaultPort) { logger.error(Messages.getErrorString("HsqlDatabaseStarterBean.ERROR_0005_SPECIFIED_PORT_IN_USE", //$NON-NLS-1$ Integer.toString(port), "" + failoverPort)); port = failoverPort; try { ServerSocket sock = new ServerSocket(port); sock.close(); } catch (IOException ex2) { return logFailure("HsqlDatabaseStarterBean.ERROR_0006_DEFAULT_PORT_IN_USE"); //$NON-NLS-1$ } } else { return logFailure("HsqlDatabaseStarterBean.ERROR_0008_SPECIFIED_PORT_IN_USE_NO_FAILOVER", //$NON-NLS-1$ Integer.toString(port)); } } } return true; } // Facilitate test cases protected HsqlProperties getServerProperties(String[] args) { // From HSQLDB Server.java main method... String propsPath = FileUtil.getFileUtil().canonicalOrAbsolutePath("server"); //$NON-NLS-1$ HsqlProperties fileProps = ServerConfiguration.getPropertiesFromFile(ServerConstants.SC_PROTOCOL_HSQL, propsPath, ".properties"); HsqlProperties props = fileProps == null ? new HsqlProperties() : fileProps; HsqlProperties stringProps = null; try { stringProps = HsqlProperties.argArrayToProps(args, "server"); props.addProperties(stringProps); } catch (ArrayIndexOutOfBoundsException ex) { logger.error(Messages.getErrorString("HsqlDatabaseStarterBean.ERROR_0001_INVALID_PARAMETERS")); //$NON-NLS-1$ ex.printStackTrace(); logger.warn(Messages.getString("HsqlDatabaseStarterBean.WARN_NO_DATABASES")); //$NON-NLS-1$ return null; } return props; } // Facilitate test cases protected Server getNewHSQLDBServer() { return new Server(); } /** * Starts hsqldb databases. * * @return true if the server was started properly. */ public boolean start() { if (!checkPort()) { return false; } ArrayList<String> startupArguments = getStartupArguments(); String[] args = startupArguments.toArray(new String[] {}); if (logger.isTraceEnabled()) { logger.trace("Assembled parameters"); //$NON-NLS-1$ for (int i = 0; i < args.length; i++) { logger.trace(String.format(" args[%d]=%s", i, args[i])); //$NON-NLS-1$ } } HsqlProperties props = getServerProperties(args); if (props == null) { // If props failed, return return false; } hsqlServer = getNewHSQLDBServer(); try { hsqlServer.setProperties(props); } catch (Exception e) { logger.error(Messages.getErrorString("HsqlDatabaseStarterBean.ERROR_0002_INVALID_CONFIGURATION")); //$NON-NLS-1$ e.printStackTrace(); logger.warn(Messages.getString("HsqlDatabaseStarterBean.WARN_NO_DATABASES")); //$NON-NLS-1$ return false; } hsqlServer.start(); return hsqlServer.getState() == ServerConstants.SERVER_STATE_ONLINE; } /** * Stops the hsqldb databases. * * @return true if the server stopped properly. */ public boolean stop() { if (hsqlServer != null) { try { logger.debug("Stopping embedded hsqldb databases"); //$NON-NLS-1$ logger.debug("Signaling connection close..."); //$NON-NLS-1$ hsqlServer.signalCloseAllServerConnections(); logger.debug("Stopping server listener threads.."); //$NON-NLS-1$ hsqlServer.stop(); int times = 0; logger.debug("Waiting for embedded server to complete shut down tasks..."); //$NON-NLS-1$ // Give it about 15 or so seconds to quit... while ((hsqlServer.getState() != ServerConstants.SERVER_STATE_SHUTDOWN) && (times < 100)) { try { Thread.sleep(times + 1 * 100); } catch (InterruptedException e) { //ignore } times++; } if (hsqlServer.getState() != ServerConstants.SERVER_STATE_SHUTDOWN) { logger.error(Messages.getErrorString("HsqlDatabaseStarterBean.ERROR_0003_DID_NOT_STOP")); //$NON-NLS-1$ return false; } return true; } finally { hsqlServer = null; } } return true; } private boolean logFailure(final String errorId) { logger.error(Messages.getErrorString(errorId)); logger.warn(Messages.getString("HsqlDatabaseStarterBean.WARN_NO_DATABASES")); //$NON-NLS-1$ return false; } private boolean logFailure(final String errorId, String param) { logger.error(Messages.getErrorString(errorId, param)); logger.warn(Messages.getString("HsqlDatabaseStarterBean.WARN_NO_DATABASES")); //$NON-NLS-1$ return false; } protected ArrayList<String> getStartupArguments() { ArrayList<String> rtnArgsList = new ArrayList<String>(); if (port != 9001) { rtnArgsList.add("-port"); //$NON-NLS-1$ rtnArgsList.add(Integer.toString(port)); } // Prevent system.exit(0); rtnArgsList.add("-no_system_exit"); //$NON-NLS-1$ rtnArgsList.add("true"); //$NON-NLS-1$ int idx = 0; for (Map.Entry<String, String> entry : databases.entrySet()) { rtnArgsList.add("-database." + idx); //$NON-NLS-1$ rtnArgsList.add(entry.getValue()); rtnArgsList.add("-dbname." + idx); //$NON-NLS-1$ rtnArgsList.add(entry.getKey()); logger.debug(MessageFormat.format("Hsqldb database {0} configured to start with name {1}", //$NON-NLS-1$ entry.getValue(), entry.getKey())); idx++; } return rtnArgsList; } /* * Getters and Setters */ public void setPort(int value) { port = value; } public int getPort() { return port; } public void setFailoverPort(int value) { failoverPort = value; } public int getFailoverPort() { return failoverPort; } public Map<String, String> getDatabases() { return databases; } public void setDatabases(Map<String, String> databases) { this.databases = databases; } public void setAllowPortFailover(boolean value) { allowFailoverToDefaultPort = value; } public boolean getAllowPortFailover() { return allowFailoverToDefaultPort; } }