/*
* NOTE: This copyright does *not* cover user programs that use Hyperic
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004-2010], VMware, Inc.
* This file is part of Hyperic.
*
* Hyperic is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.install;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.UUID;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.hyperic.util.InetPortPinger;
import org.hyperic.util.JDK;
import org.hyperic.util.StringUtil;
import org.hyperic.util.config.ConfigOptionDisplay;
import org.hyperic.util.config.ConfigResponse;
import org.hyperic.util.config.ConfigSchema;
import org.hyperic.util.config.EarlyExitException;
import org.hyperic.util.config.EnumerationConfigOption;
import org.hyperic.util.config.HiddenConfigOption;
import org.hyperic.util.config.InstallConfigOption;
import org.hyperic.util.config.InvalidOptionValueException;
import org.hyperic.util.config.IpAddressConfigOption;
import org.hyperic.util.config.PortConfigOption;
import org.hyperic.util.config.ReturnStepsException;
import org.hyperic.util.config.StringConfigOption;
import org.hyperic.util.config.YesNoConfigOption;
import org.hyperic.util.jdbc.DriverLoadException;
import org.hyperic.util.security.SecurityUtil;
public class ServerConfig
extends BaseConfig {
public static final String ctx = ServerConfig.class.getName();
// convenience, PN for "product name"
public static final String PN = PRODUCT;
//environments names for selection as an installation profile
public static final String ENV_SMALL = "small";
public static final String ENV_MEDIUM = "medium";
public static final String ENV_LARGE = "large";
public static final String ENV_SMALL_DESC = " (less than 50 platforms)";
public static final String ENV_MEDIUM_DESC = " (50-250 platforms)";
public static final String ENV_LARGE_DESC = " (larger than 250 platforms)";
// database names that appear in the select list
public static final String DBC_PGSQL = "PostgreSQL";
public static final String DBC_BUILTIN = "HQ Built-in Database";
// database names we need to use internally
public static final String DB_PGSQL = "PostgreSQL";
// Required for postgresql
public static final String PGSQL_PROTOCOL = "?protocolVersion=2";
public static final String Q_POSTGRESQL_PORT = "What port should HQ's built-in database use?";
public static final String Q_PRODUCT_TYPE = "What kind of " + PN +
" server should be installed?";
public static final String Q_CLUSTER_BINDADDR = "What IP address should the cluster server bind to?";
public static final String Q_MULTICAST_ADDR = "What is the cluster's multicast address?";
public static final String Q_MULTICAST_PORT = "What is the cluster's multicast port?";
public static final String Q_OVERWRITE = "Should we overwrite the existing " + PN +
" server installation?";
public static final String Q_OVERWRITE_DB = "An HQ server database already exists at the JDBC connection URL.\n"
+ "What should be done with this database?";
public static final String DB_CHOICE_UPGRADE = "Upgrade the HQ server database";
public static final String DB_CHOICE_OVERWRITE = "Overwrite the HQ server database (ERASE all existing data)";
public static final String DB_CHOICE_CANCEL = "Exit the installer";
public static final String[] DB_CHOICES = { DB_CHOICE_UPGRADE,
DB_CHOICE_OVERWRITE,
DB_CHOICE_CANCEL };
public static final String Q_CREATE_DB = "Should we create the " + PN +
" server database? If this is " +
"an upgrade, answer no. Otherwise, answer yes for a new install.";
public static final String Q_PORT_WEBAPP = "What port should the " + PN +
" server's web-based GUI listen " +
"on for http communication?";
public static final String Q_PORT_WEBAPP_SECURE = "What port should the " + PN +
" server's web-based GUI listen " +
"on for secure https communication?";
public static final String Q_WEBAPP_URL = "Enter the base URL for the " + PN +
" server's web-based GUI";
public static final String Q_MAIL_HOST = "Enter the fully qualified domain name of the SMTP server that " +
PN + " will use to send email messages";
public static final String Q_MAIL_FROM = "Enter the email address that " + PN +
" will use as the sender for " + "email messages";
public static final String Q_DATABASE = "The " + PN + " built-in database is provided for EVALUATION PURPOSES ONLY. " +
"For production purposes use vPosgreSQL. " +
"What backend database should the " + PN +
" server use?";
public static final String Q_DB_HOSTNAME = "Enter the vPostgres DB hostname";
public static final String Q_DB_PORT = "Enter the vPostgres DB port";
public static final String Q_DB_NAME = "Enter the vPostgres DB name";
public static final String Q_JDBC_URL = "Override the JDBC connection URL for the %%DBNAME%% database";
public static final String Q_JDBC_USER = "Enter the username to use to connect to the database";
public static final String Q_JDBC_PASSWORD = "Enter the password to use to connect to the database.";
public static final String Q_ENCRYPTION_KEY_CREATE = "Would you like to use an auto generated encryption key to encrypt the database password?";
public static final String Q_ENCRYPTION_KEY = "Enter an encryption key to use to encrypt the database password.";
public static final String Q_ADMIN_USER = "What should the username be for the initial admin user?";
public static final String Q_ADMIN_PASSWORD = "What should the password be for the initial admin user?";
public static final String Q_ADMIN_EMAIL = "What should the email address be for the initial admin user?";
public static final String Q_USE_CUSTOM_KEYSTORE = "Would you like to use your own java keystore?";
public static final String Q_SERVER_KEYSTORE_PATH = "What is the file path to your java keystore?";
public static final String Q_SERVER_KEYSTORE_PASSWORD = "What is the password to your java keystore?";
private static final String SERVER_DATABASE_UPGRADE_CHOICE = "server.database.upgrade.choice";
public static final String Q_PROFILE = "What is the installation profile?";
// convenience constants
private static final String nl = System.getProperty("line.separator");
public ServerConfig() {
super("server");
}
@Override
public String getName() {
return PN + " server";
}
@Override
protected ConfigSchema getUpgradeSchema(ConfigResponse previous, int iterationCount)
throws EarlyExitException {
ConfigSchema schema = super.getUpgradeSchema(previous, iterationCount);
if (schema == null)
schema = new ConfigSchema();
// TODO Remove this code once we no longer support HQ version less than 4.6
// This is solely to maintain backwards compatibility with older HQ agents
// that don't handle SSL communication correctly.
// For the upgrade case, we want to automatically import unverified certificates
schema.addOption(new HiddenConfigOption("accept.unverified.certificates", Boolean.TRUE.toString()));
switch (iterationCount) {
case 0:
schema.addOption(new HiddenConfigOption("server.overwrite", YesNoConfigOption.NO));
return schema;
case 1:
return schema;
default:
return null;
}
}
@Override
protected ConfigSchema getInstallSchema(ConfigResponse previous, int iterationCount)
throws EarlyExitException {
ConfigSchema schema = super.getInstallSchema(previous, iterationCount);
String portChoice;
String fqdn;
String domain;
String senderChoice;
String dbChoiceStr;
String dbChoice;
StringConfigOption usernameOption;
StringConfigOption passwordOption;
String serverInstallDir;
String dbHost;
String dbPort;
String dbName;
InstallMode installMode = new InstallMode(getProjectProperty("install.mode"));
// ...this property allows us to change installer behavior so that it's
// .org or EE specific,
// currently the eula is only shown for EE, so it's a pretty good
// indicator right now...
boolean isEEInstall = Boolean.parseBoolean(getProjectProperty("eula.present"));
// Do we have an builtin-postgresql packaged with us?
//Remove embedded DB on win system
boolean haveBuiltinDB;
if (JDK.IS_WIN32) {
haveBuiltinDB = false;
}
else{
haveBuiltinDB = getReleaseHasBuiltinDB();
}
// TODO Remove this code once we no longer support HQ version less than 4.6
// This is solely to maintain backwards compatibility with older HQ agents
// that don't handle SSL communication correctly
// For the new install case, we do not want to automatically import unverified certificates
schema.addOption(new HiddenConfigOption("accept.unverified.certificates", Boolean.FALSE.toString()));
switch (iterationCount) {
case 0:
break;
case 1:
schema.addOption(new HiddenConfigOption("server.multicast.addr", "227.0.0.1"));
schema.addOption(new HiddenConfigOption("server.multicast.port", "3030"));
schema.addOption(new HiddenConfigOption("server.ha.bind_addr",
IpAddressConfigOption.DEFAULT_ADDR));
break;
case 2:
// Is there in fact an installation we should worry about?
serverInstallDir = previous.getValue("server.installdir");
if (serverAlreadyInstalled(serverInstallDir)) {
schema.addOption(new YesNoConfigOption("server.overwrite", Q_OVERWRITE,
YesNoConfigOption.NO));
} else {
// No server installed, just assume the answer is no,
// which will be a 'safe bet'
schema.addOption(new HiddenConfigOption("server.overwrite",
YesNoConfigOption.NO));
}
break;
case 3:
// If they chose not to overwrite, and the server exists, bail
// out
serverInstallDir = previous.getValue("server.installdir");
if (serverAlreadyInstalled(serverInstallDir) &&
"No".equals(previous.getValue("server.overwrite"))) {
throw new EarlyExitException("Exiting setup: " + PN + " server " +
"already installed in " + serverInstallDir);
}
if (installMode.isQuick()) {
schema.addOption(new HiddenConfigOption("server.webapp.port", "7080"));
schema.addOption(new HiddenConfigOption("server.webapp.secure.port", "7443"));
} else {
schema.addOption(new PortConfigOption("server.webapp.port", Q_PORT_WEBAPP,
new Integer(7080)));
schema.addOption(new PortConfigOption("server.webapp.secure.port",
Q_PORT_WEBAPP_SECURE, new Integer(7443)));
}
if (installMode.isQuick()) {
schema.addOption(new HiddenConfigOption("server.use.custom.keystore", YesNoConfigOption.NO));
} else {
schema.addOption(new YesNoConfigOption("server.use.custom.keystore", Q_USE_CUSTOM_KEYSTORE, YesNoConfigOption.NO));
}
break;
case 4:
String useCustomKeystore = previous.getValue("server.use.custom.keystore");
schema.addOption(new StringConfigOption("server.keystore.path", Q_SERVER_KEYSTORE_PATH, ""));
if (YesNoConfigOption.YES.equals(useCustomKeystore)) { //yes implies it's not a quick install (default is no)
schema.addOption(new StringConfigOption("server.keystore.password", Q_SERVER_KEYSTORE_PASSWORD, ""));
} else {
// TODO not sure if there's a cleaner way to do this. The problem is we technically don't know the real install path bc
// the archive hasn't been unzipped at this point. So we use a token and replace it later in the ant script with the real path
schema.addOption(new HiddenConfigOption("server.keystore.path", "../../conf/hyperic.keystore"));
schema.addOption(new HiddenConfigOption("server.keystore.password", "hyperic"));
}
break;
case 5:
portChoice = previous.getValue("server.webapp.port");
fqdn = computeFQDN();
domain = computeDomain(fqdn);
// only collect baseurl property if we're initially
// creating the database, since we don't yet run dbsetup
// for upgrades
String computedBaseUrl = computeHTTPBaseUrl(fqdn, portChoice);
if (installMode.isQuick()) {
schema.addOption(new HiddenConfigOption("server.webapp.baseurl",
computedBaseUrl));
} else {
schema.addOption(new StringConfigOption("server.webapp.baseurl", Q_WEBAPP_URL,
computedBaseUrl));
}
// Do we have a local MTA?
if (haveLocalMTA()) {
schema.addOption(new HiddenConfigOption("server.mail.host", "127.0.0.1"));
} else {
schema.addOption(new StringConfigOption("server.mail.host", Q_MAIL_HOST, fqdn));
}
// We always ask for username and password now per HQ-3627,
// so probably shouldn't auto enter the email value
schema.addOption(new StringConfigOption("server.mail.sender", Q_MAIL_FROM, "hqadmin@" + domain));
ConfigOptionDisplay smallOption = new ConfigOptionDisplay(ENV_SMALL, ENV_SMALL_DESC);
ConfigOptionDisplay mediumOption = new ConfigOptionDisplay(ENV_MEDIUM, ENV_MEDIUM_DESC);
ConfigOptionDisplay largeOption = new ConfigOptionDisplay(ENV_LARGE, ENV_LARGE_DESC);
ConfigOptionDisplay[] envs = {smallOption, mediumOption, largeOption};
if(!installMode.isQuick() && isEEInstall)
schema.addOption(new InstallConfigOption("install.profile", Q_PROFILE, smallOption, envs));
else
schema.addOption(new HiddenConfigOption("install.profile", ENV_SMALL));
break;
case 6:
boolean usingSmallEnv = previous.getValue("install.profile").contentEquals(ENV_SMALL);
if (installMode.isPostgres()) {
schema.addOption(new HiddenConfigOption("server.database.choice", DBC_PGSQL));
}
else if (installMode.isQuick() && haveBuiltinDB) {
schema.addOption(new HiddenConfigOption("server.database.choice", DBC_BUILTIN));
}
else {
if (!haveBuiltinDB) {
schema.addOption(new HiddenConfigOption("server.database.choice", DBC_PGSQL));
}
else {
ConfigOptionDisplay builtInOption = new ConfigOptionDisplay(DBC_BUILTIN);
if (!usingSmallEnv) {
builtInOption = new ConfigOptionDisplay(DBC_BUILTIN + "(not recommended since you have selected " + previous.getValue("install.profile") +
" installation profile and the build in DB should be used only with small profiles)");
}
ConfigOptionDisplay postgresOption = new ConfigOptionDisplay(DBC_PGSQL);
ConfigOptionDisplay defaultDB = builtInOption;
ConfigOptionDisplay[] dbs = new ConfigOptionDisplay[] { builtInOption, postgresOption};
schema.addOption(new InstallConfigOption("server.database.choice", Q_DATABASE,
defaultDB, dbs));
}
}
break;
case 7:
// determine server.database from server.database.choice...
dbChoiceStr = previous.getValue("server.database.choice");
if (dbChoiceStr.startsWith(DBC_PGSQL)){
dbChoice = DB_PGSQL;
}
else if (dbChoiceStr.startsWith(DBC_BUILTIN)) {
dbChoice = DB_PGSQL;
schema.addOption(new HiddenConfigOption("using.builtin.db", "true"));
}
else{
throw new IllegalStateException("Invalid database: " + dbChoiceStr);
}
schema.addOption(new HiddenConfigOption("server.database", dbChoice));
if(!dbChoiceStr.startsWith(DBC_BUILTIN)) {
schema.addOption(new StringConfigOption("server.database.host", Q_DB_HOSTNAME, "localhost"));
}
if (dbChoiceStr.startsWith(DBC_PGSQL) && !dbChoiceStr.startsWith(DBC_BUILTIN)) {
schema.addOption(new PortConfigOption("server.database.port", Q_DB_PORT, 5432));
}
if(!dbChoiceStr.startsWith(DBC_BUILTIN)) {
schema.addOption(new StringConfigOption("server.database.name", Q_DB_NAME, PRODUCT));
}
break;
case 8:
dbChoiceStr = previous.getValue("server.database.choice");
dbChoice = previous.getValue("server.database");
dbHost = previous.getValue("server.database.host");
dbPort = previous.getValue("server.database.port");
dbName = previous.getValue("server.database.name");
if (dbChoiceStr.startsWith(DBC_PGSQL)) {
schema.addOption(new StringConfigOption("server.database-url", StringUtil
.replace(Q_JDBC_URL, "%%DBNAME%%", dbChoiceStr),
"jdbc:postgresql://" + dbHost + ":" + dbPort + "/" + dbName + PGSQL_PROTOCOL));
schema.addOption(new HiddenConfigOption("server.database-driver",
"org.postgresql.Driver"));
schema.addOption(new HiddenConfigOption("server.quartzDelegate",
"org.quartz.impl.jdbcjobstore.PostgreSQLDelegate"));
schema.addOption(new HiddenConfigOption("server.hibernate.dialect",
"org.hyperic.hibernate.dialect.PostgreSQLDialect"));
schema.addOption(new HiddenConfigOption("server.connection-validation-sql",
"select 1"));
}
else {
if (!installMode.isQuick()) {
// In "full" mode, we even let them pick the pgsql port
schema.addOption(new PortConfigOption("server.postgresql.port",
Q_POSTGRESQL_PORT, new Integer(9432)));
} else {
schema.addOption(new HiddenConfigOption("server.postgresql.port", "9432"));
}
schema.addOption(new HiddenConfigOption("server.database-driver",
"org.postgresql.Driver"));
schema.addOption(new HiddenConfigOption("server.quartzDelegate",
"org.quartz.impl.jdbcjobstore.PostgreSQLDelegate"));
schema.addOption(new HiddenConfigOption("server.hibernate.dialect",
"org.hyperic.hibernate.dialect.PostgreSQLDialect"));
schema.addOption(new HiddenConfigOption("server.connection-validation-sql",
"select 1"));
}
if (dbChoiceStr.startsWith(DBC_BUILTIN)) {
schema.addOption(new HiddenConfigOption("server.database-user", "hqadmin"));
schema.addOption(new HiddenConfigOption("server.database-password", "hqadmin"));
} else {
schema.addOption(new StringConfigOption("server.database-user", Q_JDBC_USER));
passwordOption = new StringConfigOption("server.database-password",
Q_JDBC_PASSWORD);
passwordOption.setSecret(true);
schema.addOption(passwordOption);
}
schema.addOption(new YesNoConfigOption("server.encryption-key.auto", Q_ENCRYPTION_KEY_CREATE,
YesNoConfigOption.YES));
break;
case 9:
dbChoiceStr = previous.getValue("server.database.choice");
if(!dbChoiceStr.startsWith(DBC_BUILTIN)) {
try {
FileWriter fstream = new FileWriter("/tmp/out.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write(previous.getValue("server.database-url") + "\n");
out.write(previous.getValue("server.database-user") + "\n");
out.write(previous.getValue("server.database-password") + "\n");
out.close();
}
catch (Exception e) {
// TODO: handle exception
}
boolean exists = InstallDBUtil.checkConnectionExists(previous.getValue("server.database-url"), previous.getValue("server.database-user"),
previous.getValue("server.database-password"));
if (!exists) {
//If we cannot connect the data base we need to return to step 7
throw new ReturnStepsException("Error connecting to the database, please enter the database information again - ", 7);
}
}
if("yes".equalsIgnoreCase(previous.getValue("server.encryption-key.auto"))) {
//Create an auto generated random key
String encryptionKey = UUID.randomUUID().toString().substring(0, 13).replaceAll("-", "");
schema.addOption(new HiddenConfigOption("server.encryption-key", encryptionKey));
break;
}
StringConfigOption encryptionKeyOption = new StringConfigOption(
"server.encryption-key", Q_ENCRYPTION_KEY);
encryptionKeyOption.setMinLength(8);
schema.addOption(encryptionKeyOption);
break;
case 10:
// Get encryption key
String encryptionKey = previous.getValue("server.encryption-key");
// Encrypt database password
String encryptedPw = encryptPassword("PBEWithMD5AndDES", encryptionKey, previous
.getValue("server.database-password")).replaceAll("\\r|\\n", "");
schema.addOption(new HiddenConfigOption("server.encryption-key", encryptionKey));
//Make this optional for non-interactive installers so the default value created here will be used instead
HiddenConfigOption encryptedPwOption = new HiddenConfigOption("server.database-password-encrypted",
encryptedPw.toString());
encryptedPwOption.setOptional(true);
schema.addOption(encryptedPwOption);
senderChoice = previous.getValue("server.mail.sender");
// dont ask about admin username if this is an HA node
// this should have already been set up
// We always ask for username and password now per HQ-3627
usernameOption = new AdminUsernameConfigOption("server.admin.username", Q_ADMIN_USER, "hqadmin");
schema.addOption(usernameOption);
passwordOption = new StringConfigOption("server.admin.password", Q_ADMIN_PASSWORD, null);
passwordOption.setSecret(true);
passwordOption.setMinLength(6);
passwordOption.setMaxLength(40);
schema.addOption(passwordOption);
// probably shouldn't auto enter the email value, since we're asking for username...
schema.addOption(new StringConfigOption("server.admin.email", Q_ADMIN_EMAIL, senderChoice));
break;
case 11:
// For servers using the builtinDB we have only gotten the port
// at
// this point. Now we setup the url based on the port selection
dbChoiceStr = previous.getValue("server.database.choice");
if (dbChoiceStr.startsWith(DBC_BUILTIN)) {
String pgport = previous.getValue("server.postgresql.port");
schema.addOption(new HiddenConfigOption("server.database-url",
"jdbc:postgresql://127.0.0.1:" + pgport + "/hqdb" + PGSQL_PROTOCOL));
}
break;
case 12:
// Now that they have made their jdbc selections, do a sanity
// check:
// If we are in "quick" mode and the database already exists,
// then STOP ask the user what to do.
dbChoiceStr = previous.getValue("server.database.choice");
if (!dbChoiceStr.startsWith(DBC_BUILTIN)) {
if (installMode.isQuick())
{
// Like Built-in DB, overwrite the db - in case of silent install with exists db
schema.addOption(new HiddenConfigOption(SERVER_DATABASE_UPGRADE_CHOICE,
DB_CHOICE_OVERWRITE));
}else{
if (databaseExists(previous)) {
// Bug 9722 only check for db upgrade if this isnt an HA
// node
schema.addOption(new EnumerationConfigOption(
SERVER_DATABASE_UPGRADE_CHOICE, Q_OVERWRITE_DB, DB_CHOICE_CANCEL,
DB_CHOICES, DB_CHOICE_OVERWRITE));
} else {
schema.addOption(new HiddenConfigOption(SERVER_DATABASE_UPGRADE_CHOICE,
DB_CHOICE_OVERWRITE));
}
}
} else {
// Built-in DB, overwrite the db
schema.addOption(new HiddenConfigOption(SERVER_DATABASE_UPGRADE_CHOICE,
DB_CHOICE_OVERWRITE));
}
break;
case 13:
String dbUpgradeChoice = previous.getValue(SERVER_DATABASE_UPGRADE_CHOICE);
if (dbUpgradeChoice.equals(DB_CHOICE_OVERWRITE)) {
schema.addOption(new HiddenConfigOption("server.database.create",
YesNoConfigOption.YES));
} else if (dbUpgradeChoice.equals(DB_CHOICE_UPGRADE)) {
schema.addOption(new HiddenConfigOption("server.database.upgrade",
YesNoConfigOption.YES));
} else {
throw new EarlyExitException("No modifications made to existing database. "
+ "Exiting installer.");
}
break;
case 14:
if(isEEInstall) {
schema.addOption(new HiddenConfigOption("accept.eula",YesNoConfigOption.NO));
}
break;
default:
return null;
}
return schema;
}
private String computeBaseUrl(String scheme, String fqdn, String port, String defaultPort) {
if (fqdn == null) {
return null;
}
StringBuffer buf = new StringBuffer(scheme);
buf.append("://");
buf.append(fqdn);
if (port != null && !port.equals(defaultPort)) {
buf.append(":");
buf.append(port.toString());
}
buf.append("/");
return buf.toString();
}
protected String computeHTTPBaseUrl(String fqdn, String port) {
return computeBaseUrl("http", fqdn, port, "80");
}
protected String computeDomain(String fqdn) {
String domainname;
StringTokenizer token = new StringTokenizer(fqdn, ".");
if (token.countTokens() > 2) {
int index = fqdn.indexOf('.');
domainname = fqdn.substring(++index);
} else {
domainname = fqdn;
}
return domainname;
}
protected String computeFQDN() {
String fqdn = null;
try {
fqdn = new Sigar().getFQDN();
} catch (SigarException e) {
// this machine is seriously misconfigured. that's
// ok, you just don't get a default. have fun
// typing!
}
// Actually, just assume localhost if no fqdn
if (fqdn == null || fqdn.length() == 0)
fqdn = "localhost";
return fqdn;
}
protected boolean serverAlreadyInstalled(String dir) {
String serverFile = dir + File.separator + "server-" + getProjectProperty("version") +
File.separator + "hq-engine";
if (Boolean.parseBoolean(getProjectProperty("eula.present"))) {
serverFile = dir + File.separator + "server-" + getProjectProperty("version") + "-EE" +
File.separator + "hq-engine";
}
File f = new File(serverFile);
return f.exists();
}
public boolean haveLocalMTA() {
InetPortPinger ip = new InetPortPinger("127.0.0.1", 25, 10);
return ip.check();
}
public static final String[] MARKER_FILES = { "bin/hq-server.sh",
"bin/hq-server.exe",
"bin/hq-server.bat",
"bin/ams-server.sh",
"bin/ams-server.exe" };
@Override
protected String[] getMarkerFiles() {
return MARKER_FILES;
}
@Override
public void canUpgrade(String dir) throws InvalidOptionValueException {
// If the 'dir' points to a pointbase-backed installation, we can't
// upgrade it.
// First we look in conf/hq-server.conf if it exists. If this is an
// older release, we look in hq-ds.xml file for the <connection-url>
// element.
File confFile = new File(dir, StringUtil.normalizePath("conf/hq-server.conf"));
if (confFile.exists()) {
Properties props = new Properties();
FileInputStream fi = null;
try {
fi = new FileInputStream(confFile.getAbsolutePath());
props.load(fi);
} catch (IOException e) {
throw new InvalidOptionValueException("Error reading hq-server.conf file: " +
confFile.getAbsolutePath() + e.getMessage());
} finally {
if (fi != null) {
try {
fi.close();
} catch (IOException e) {
}
}
}
String driverClass = props.getProperty("server.database-driver");
if (driverClass == null) {
throw new InvalidOptionValueException(
"No server.database-driver property found in: " + confFile.getAbsolutePath());
}
if (driverClass.indexOf("com.pointbase.") != -1) {
throw new InvalidOptionValueException(
"Cannot upgrade HQ server: upgrade not supported for "
+ "HQ servers that use the PointBase database");
}
return;
} else {
throw new EarlyExitException("__ll__\nCannot upgrade HQ server\n(file not found: " +
confFile.getAbsolutePath() +
")\n\nOnly versions 1.3.x and higher can " +
"be upgraded using the installer.\nTo upgrade earlier " +
"versions, follow the instructions in README.txt\n\n__ll__");
}
}
@Override
public String getProductInstallDir(ConfigResponse config) {
String installDir = getInstallDir(config);
if (Boolean.parseBoolean(getProjectProperty("eula.present"))) {
return installDir + getBaseName() + "-" + getProjectProperty("version") + "-EE" +
File.separator;
} else {
return installDir + getBaseName() + "-" + getProjectProperty("version") +
File.separator;
}
}
@Override
public String getCompletionText(ConfigResponse config) {
StringBuffer s = new StringBuffer();
String sp = File.separator;
String startup = getProductInstallDir(config);
startup += "bin" + sp + PN.toLowerCase() + "-server" + getExtension();
s.append("__ll__").append(getServerStartupText(startup).toString());
if (isUpgrade()) {
s.append(nl).append(nl).append(" Your HQ server has been successfully upgraded.")
.append(nl).append(nl).append(
" Once you start up your HQ server, you can log in using any of your existing")
.append(nl).append(" HQ user accounts.");
} else if (isDBUpgrade(config)) {
s.append(nl).append(nl).append(
" Once the HQ server reports that it has successfully started, you can log in")
.append(nl).append(" to your HQ server at: ").append(nl).append(nl).append(" ")
.append(config.getValue("server.webapp.baseurl")).append(nl).append(nl).append(
" You can log in using any of your existing HQ user accounts.");
} else {
// A new/fresh install
s
.append(nl)
.append(nl)
.append(
" Once the HQ server reports that it has successfully started, you can log in")
.append(nl)
.append(" to your HQ server at: ")
.append(nl)
.append(nl)
.append(" ")
.append(config.getValue("server.webapp.baseurl"))
.append(nl)
.append(" username: ")
.append(config.getValue("server.admin.username"))
.append(nl)
.append(nl)
.append(
" To change your password, log in to the HQ server, click the \"Administration\"")
.append(nl).append(
" link, choose \"List Users\", then click on the \"hqadmin\" user.");
}
s.append(nl).append("__ll__");
return s.toString();
}
private StringBuffer getServerStartupText(String startup) {
StringBuffer s = new StringBuffer();
s.append(nl);
if (JDK.IS_WIN32) {
s
.append(
" You should now install the HQ server as a Windows Service using this command:")
.append(nl)
.append(nl)
.append(" ")
.append(startup)
.append(" install")
.append(nl)
.append(nl)
.append(
" You can then use the Service Control Manager (Control Panel->Services) to ")
.append(nl)
.append(
" start the HQ server. Note that the first time the HQ server starts up it may")
.append(nl)
.append(
" take several minutes to initialize. Subsequent startups will be much faster.");
} else {
s
.append(nl)
.append(" You can now start your HQ server by running this command:")
.append(nl)
.append(nl)
.append(" ")
.append(startup)
.append(" start")
.append(nl)
.append(nl)
.append(
" Note that the first time the HQ server starts up it may take several minutes")
.append(nl).append(" to initialize. Subsequent startups will be much faster.");
}
return s;
}
private String encryptPassword(String algorithm, String encryptionKey, String clearTextPassword) {
return SecurityUtil.encrypt(algorithm, encryptionKey, clearTextPassword);
}
protected boolean databaseExists(ConfigResponse config) throws EarlyExitException {
String user = config.getValue("server.database-user");
String password = config.getValue("server.database-password");
String url = config.getValue("server.database-url");
try {
return InstallDBUtil.checkTableExists(url, user, password, "EAM_CONFIG_PROPS");
} catch (DriverLoadException e) {
throw new EarlyExitException("Error connecting to database " + "(" + url + "): " +
e.getMessage());
} catch (SQLException e) {
throw new EarlyExitException("Error checking for existing " + "database: " +
e.getMessage());
}
}
private boolean isDBUpgrade(ConfigResponse config) {
String dbUpgrade = config.getValue("server.database.upgrade");
return (dbUpgrade != null && dbUpgrade.equals(YesNoConfigOption.YES));
}
protected boolean getReleaseHasBuiltinDB() {
File hqdbDir = new File(getProjectProperty("install.dir") + File.separator + "data" +
File.separator + "hqdb");
return (hqdbDir.exists() && hqdbDir.isDirectory() && hqdbDir.canRead());
}
private class InstallMode {
boolean _postgresQuickMode = false;
boolean _quickMode = false;
InstallMode(String mode) {
_postgresQuickMode = mode.equals(INSTALLMODE_POSTGRESQL);
_quickMode = mode.equals(INSTALLMODE_QUICK);
}
boolean isPostgres() {
return _postgresQuickMode;
}
boolean isQuick() {
return _postgresQuickMode || _quickMode;
}
}
}