/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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. * * For further information about Alkacon Software GmbH, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.setup; import org.opencms.configuration.CmsConfigurationException; import org.opencms.configuration.CmsConfigurationManager; import org.opencms.configuration.CmsImportExportConfiguration; import org.opencms.configuration.CmsModuleConfiguration; import org.opencms.configuration.CmsParameterConfiguration; import org.opencms.configuration.CmsPersistenceUnitConfiguration; import org.opencms.configuration.CmsSearchConfiguration; import org.opencms.configuration.CmsSystemConfiguration; import org.opencms.configuration.CmsVfsConfiguration; import org.opencms.configuration.CmsWorkplaceConfiguration; import org.opencms.configuration.I_CmsXmlConfiguration; import org.opencms.db.CmsDbPool; import org.opencms.db.jpa.CmsSqlManager; import org.opencms.file.CmsObject; import org.opencms.file.CmsResource; import org.opencms.i18n.CmsEncoder; import org.opencms.i18n.CmsMessageContainer; import org.opencms.importexport.CmsImportParameters; import org.opencms.loader.CmsImageLoader; import org.opencms.main.CmsLog; import org.opencms.main.CmsRuntimeException; import org.opencms.main.CmsShell; import org.opencms.main.CmsSystemInfo; import org.opencms.main.I_CmsShellCommands; import org.opencms.main.OpenCms; import org.opencms.main.OpenCmsServlet; import org.opencms.module.CmsModule; import org.opencms.module.CmsModuleManager; import org.opencms.report.CmsShellReport; import org.opencms.setup.comptest.CmsSetupTestResult; import org.opencms.setup.comptest.CmsSetupTestSimapi; import org.opencms.setup.comptest.I_CmsSetupTest; import org.opencms.setup.xml.CmsSetupXmlHelper; import org.opencms.util.CmsCollectionsGenericWrapper; import org.opencms.util.CmsFileUtil; import org.opencms.util.CmsStringUtil; import org.opencms.util.CmsUUID; import org.opencms.workplace.tools.CmsIdentifiableObjectContainer; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.LineNumberReader; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import org.apache.commons.logging.Log; /** * A java bean as a controller for the OpenCms setup wizard.<p> * * It is not allowed to customize this bean with methods for a specific database server setup!<p> * * Database server specific settings should be set/read using get/setDbProperty, as for example like: * * <pre> * setDbProperty("oracle.defaultTablespace", value); * </pre> * <p> * * @since 6.0.0 */ public class CmsSetupBean implements I_CmsShellCommands { /** DB provider constant for as400. */ public static final String AS400_PROVIDER = "as400"; /** The name of the components properties file. */ public static final String COMPONENTS_PROPERTIES = "components.properties"; /** DB provider constant for db2. */ public static final String DB2_PROVIDER = "db2"; /** jpa type constant. */ public static final byte DRIVER_TYPE_JPA = 1; /** jpa type constant. */ public static final byte DRIVER_TYPE_SQL = 0; /** Folder constant name.<p> */ public static final String FOLDER_BACKUP = "backup" + File.separatorChar; /** Folder constant name.<p> */ public static final String FOLDER_DATABASE = "database" + File.separatorChar; /** Folder constant name.<p> */ public static final String FOLDER_LIB = "lib" + File.separatorChar; /** Folder constant name.<p> */ public static final String FOLDER_SETUP = "setup" + File.separatorChar; /** DB provider constant. */ public static final String GENERIC_PROVIDER = "generic"; /** DB provider constant for hsqldb. */ public static final String HSQLDB_PROVIDER = "hsqldb"; /** Name of the property file containing HTML fragments for setup wizard and error dialog. */ public static final String HTML_MESSAGE_FILE = "org/opencms/setup/htmlmsg.properties"; /** The jpa CmsDbContextFactory for the opencms-system.xml node: runtimeclasses -> runtimeinfo. */ public static final String JPA_FACTOTY = "org.opencms.db.jpa.CmsDbContextFactory"; /** DB provider constant for jpa. */ public static final String JPA_PROVIDER = "jpa"; /** DB provider constant for maxdb. */ public static final String MAXDB_PROVIDER = "maxdb"; /** DB provider constant for mssql. */ public static final String MSSQL_PROVIDER = "mssql"; /** DB provider constant for mysql. */ public static final String MYSQL_PROVIDER = "mysql"; /** DB provider constant for oracle. */ public static final String ORACLE_PROVIDER = "oracle"; /** DB provider constant for postgresql. */ public static final String POSTGRESQL_PROVIDER = "postgresql"; /** The default component position, is missing. */ protected static final int DEFAULT_POSITION = 9999; /** Properties file key constant post fix. */ protected static final String PROPKEY_CHECKED = ".checked"; /** Properties file key constant prefix. */ protected static final String PROPKEY_COMPONENT = "component."; /** Properties file key constant. */ protected static final String PROPKEY_COMPONENTS = "components"; /** Properties file key constant post fix. */ protected static final String PROPKEY_DEPENDENCIES = ".dependencies"; /** Properties file key constant post fix. */ protected static final String PROPKEY_DESCRIPTION = ".description"; /** True if OpenCms supports a generic JPA driver implementation. */ protected static final String PROPKEY_JPA_SUPPORTED = "jpaSupported"; /** Properties file key constant post fix. */ protected static final String PROPKEY_MODULES = ".modules"; /** Properties file key constant post fix. */ protected static final String PROPKEY_NAME = ".name"; /** Properties file key constant post fix. */ protected static final String PROPKEY_POSITION = ".position"; /** True if OpenCms supports a native SQL driver implementation. */ protected static final String PROPKEY_SQL_SUPPORTED = "sqlSupported"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(CmsSetupBean.class); /** Contains HTML fragments for the output in the JSP pages of the setup wizard. */ private static Properties m_htmlProps; /** Required files per database setup (for AS400 and DB2). */ private static final String[] REQUIRED_DB2_DB_SETUP_FILES = { "step_4_database_setup.jsp", "database.properties", "create_tables.sql", "drop_tables.sql"}; /** Required files per database setup (for jpa only supported dbs). */ private static final String[] REQUIRED_JPA_DB_SETUP_FILES = { "step_4_database_setup.jsp", "database.properties", "drop_tables.sql"}; /** Required files per database setup (for sql supported dbs). */ private static final String[] REQUIRED_SQL_DB_SETUP_FILES = { "step_4_database_setup.jsp", "database.properties", "create_db.sql", "create_tables.sql", "drop_db.sql", "drop_tables.sql"}; /** A map with all available modules. */ protected Map<String, CmsModule> m_availableModules; /** A CmsObject to execute shell commands. */ protected CmsObject m_cms; /** A list with the package names of the modules to be installed .*/ protected List<String> m_installModules; /** Location for log file. */ protected String m_logFile = CmsSystemInfo.FOLDER_WEBINF + CmsLog.FOLDER_LOGS + "setup.log"; /** Location for logs relative to the webapp folder. */ protected String m_logsFolder = CmsSystemInfo.FOLDER_WEBINF + CmsLog.FOLDER_LOGS; /** A map with lists of dependent module package names keyed by module package names. */ protected Map<String, List<String>> m_moduleDependencies; /** A map with all available modules filenames. */ protected Map<String, String> m_moduleFilenames; /** Location for module archives relative to the webapp folder. */ protected String m_modulesFolder = CmsSystemInfo.FOLDER_WEBINF + CmsSystemInfo.FOLDER_PACKAGES + CmsSystemInfo.FOLDER_MODULES; /** The new logging offset in the workplace import thread. */ protected int m_newLoggingOffset; /** The lod logging offset in the workplace import thread. */ protected int m_oldLoggingOffset; /** The absolute path to the home directory of the OpenCms webapp. */ protected String m_webAppRfsPath; /** Contains all defined components. */ private CmsIdentifiableObjectContainer<CmsSetupComponent> m_components; /** The absolute path to the config sub directory of the OpenCms web application. */ private String m_configRfsPath; /** Key of the selected database server (e.g. "mysql", "generic" or "oracle") */ private String m_databaseKey; /** List of keys of all available database server setups (e.g. "mysql", "generic" or "oracle") */ private List<String> m_databaseKeys; /** Map of database setup properties of all available database server setups keyed by their database keys. */ private Map<String, Properties> m_databaseProperties; /** Password used for the JDBC connection when the OpenCms database is created. */ private String m_dbCreatePwd; /** The name of the default web application (in web.xml). */ private String m_defaultWebApplication; /** Driver implementation should be used (SQL or JPA). */ private byte m_driverType; /** Contains the error messages to be displayed in the setup wizard. */ private List<String> m_errors; /** Contains the properties of "opencms.properties". */ private CmsParameterConfiguration m_configuration; /** The full key of the selected database including the "_jpa" or "_sql" information. */ private String m_fullDatabaseKey; /** A reference to the persistence configuration. */ private CmsPersistenceUnitConfiguration m_peristenceConfigurator; /** The Database Provider used in setup. */ private String m_provider; /** A map with tokens ${...} to be replaced in SQL scripts. */ private Map<String, String> m_replacer; /** The initial servlet configuration. */ private ServletConfig m_servletConfig; /** The servlet mapping (in web.xml). */ private String m_servletMapping; /** List of sorted keys by ranking of all available database server setups (e.g. "mysql", "generic" or "oracle") */ private List<String> m_sortedDatabaseKeys; /** The workplace import thread. */ private CmsSetupWorkplaceImportThread m_workplaceImportThread; /** Xml read/write helper object. */ private CmsSetupXmlHelper m_xmlHelper; /** * Default constructor.<p> */ public CmsSetupBean() { initHtmlParts(); } /** * Restores the opencms.xml either to or from a backup file, depending * whether the setup wizard is executed the first time (the backup * does not exist) or not (the backup exists). * * @param filename something like e.g. "opencms.xml" * @param originalFilename the configurations real file name, e.g. "opencms.xml.ori" */ public void backupConfiguration(String filename, String originalFilename) { // ensure backup folder exists File backupFolder = new File(m_configRfsPath + FOLDER_BACKUP); if (!backupFolder.exists()) { backupFolder.mkdirs(); } // copy file to (or from) backup folder originalFilename = FOLDER_BACKUP + originalFilename; File file = new File(m_configRfsPath + originalFilename); if (file.exists()) { copyFile(originalFilename, filename); } else { copyFile(filename, originalFilename); } } /** * Returns a map of dependencies.<p> * * The component dependencies are get from the setup and module components.properties files found.<p> * * @return a Map of component ids as keys and a list of dependency names as values */ public Map<String, List<String>> buildDepsForAllComponents() { Map<String, List<String>> ret = new HashMap<String, List<String>>(); Iterator<CmsSetupComponent> itComponents = CmsCollectionsGenericWrapper.<CmsSetupComponent> list( m_components.elementList()).iterator(); while (itComponents.hasNext()) { CmsSetupComponent component = itComponents.next(); // if component a depends on component b, and component c depends also on component b: // build a map with a list containing "a" and "c" keyed by "b" to get a // list of components depending on component "b"... Iterator<String> itDeps = component.getDependencies().iterator(); while (itDeps.hasNext()) { String dependency = itDeps.next(); // get the list of dependent modules List<String> componentDependencies = ret.get(dependency); if (componentDependencies == null) { // build a new list if "b" has no dependent modules yet componentDependencies = new ArrayList<String>(); ret.put(dependency, componentDependencies); } // add "a" as a module depending on "b" componentDependencies.add(component.getId()); } } itComponents = CmsCollectionsGenericWrapper.<CmsSetupComponent> list(m_components.elementList()).iterator(); while (itComponents.hasNext()) { CmsSetupComponent component = itComponents.next(); if (ret.get(component.getId()) == null) { ret.put(component.getId(), new ArrayList<String>()); } } return ret; } /** * Checks the ethernet address value and generates a dummy address, if necessary.<p> * */ public void checkEthernetAddress() { // check the ethernet address in order to generate a random address, if not available if (CmsStringUtil.isEmpty(getEthernetAddress())) { setEthernetAddress(CmsUUID.getDummyEthernetAddress()); } } /** * Copies a given file.<p> * * @param source the source file * @param target the destination file */ public void copyFile(String source, String target) { try { CmsFileUtil.copy(m_configRfsPath + source, m_configRfsPath + target); } catch (IOException e) { m_errors.add("Could not copy " + source + " to " + target + " \n"); m_errors.add(e.toString() + "\n"); } } /** * Returns html code to display an error.<p> * * @param pathPrefix to adjust the path * * @return html code */ public String displayError(String pathPrefix) { if (pathPrefix == null) { pathPrefix = ""; } StringBuffer html = new StringBuffer(512); html.append("<table border='0' cellpadding='5' cellspacing='0' style='width: 100%; height: 100%;'>"); html.append("\t<tr>"); html.append("\t\t<td style='vertical-align: middle; height: 100%;'>"); html.append(getHtmlPart("C_BLOCK_START", "Error")); html.append("\t\t\t<table border='0' cellpadding='0' cellspacing='0' style='width: 100%;'>"); html.append("\t\t\t\t<tr>"); html.append("\t\t\t\t\t<td><img src='").append(pathPrefix).append("resources/error.png' border='0'></td>"); html.append("\t\t\t\t\t<td>  </td>"); html.append("\t\t\t\t\t<td style='width: 100%;'>"); html.append("\t\t\t\t\t\tThe Alkacon OpenCms setup wizard has not been started correctly!<br>"); html.append("\t\t\t\t\t\tPlease click <a href='").append(pathPrefix); html.append("index.jsp'>here</a> to restart the wizard."); html.append("\t\t\t\t\t</td>"); html.append("\t\t\t\t</tr>"); html.append("\t\t\t</table>"); html.append(getHtmlPart("C_BLOCK_END")); html.append("\t\t</td>"); html.append("\t</tr>"); html.append("</table>"); return html.toString(); } /** * Returns html code to display the errors occurred.<p> * * @param pathPrefix to adjust the path * * @return html code */ public String displayErrors(String pathPrefix) { if (pathPrefix == null) { pathPrefix = ""; } StringBuffer html = new StringBuffer(512); html.append("<table border='0' cellpadding='5' cellspacing='0' style='width: 100%; height: 100%;'>"); html.append("\t<tr>"); html.append("\t\t<td style='vertical-align: middle; height: 100%;'>"); html.append(getHtmlPart("C_BLOCK_START", "Error")); html.append("\t\t\t<table border='0' cellpadding='0' cellspacing='0' style='width: 100%;'>"); html.append("\t\t\t\t<tr>"); html.append("\t\t\t\t\t<td><img src='").append(pathPrefix).append("resources/error.png' border='0'></td>"); html.append("\t\t\t\t\t<td>  </td>"); html.append("\t\t\t\t\t<td style='width: 100%;'>"); Iterator<String> iter = getErrors().iterator(); while (iter.hasNext()) { String msg = iter.next(); html.append("\t\t\t\t\t\t"); html.append(msg); html.append("<br/>"); } html.append("\t\t\t\t\t</td>"); html.append("\t\t\t\t</tr>"); html.append("\t\t\t</table>"); html.append(getHtmlPart("C_BLOCK_END")); html.append("\t\t</td>"); html.append("\t</tr>"); html.append("</table>"); return html.toString(); } /** * Returns a map with all available modules.<p> * * The map contains maps keyed by module package names. Each of these maps contains various * information about the module such as the module name, version, description, and a list of * it's dependencies. You should refer to the source code of this method to understand the data * structure of the map returned by this method!<p> * * @return a map with all available modules */ public Map<String, CmsModule> getAvailableModules() { if ((m_availableModules == null) || m_availableModules.isEmpty()) { m_availableModules = new HashMap<String, CmsModule>(); m_moduleDependencies = new HashMap<String, List<String>>(); m_moduleFilenames = new HashMap<String, String>(); m_components = new CmsIdentifiableObjectContainer<CmsSetupComponent>(true, true); try { addComponentsFromPath(m_webAppRfsPath + FOLDER_SETUP); Map<CmsModule, String> modules = CmsModuleManager.getAllModulesFromPath(getModuleFolder()); Iterator<Map.Entry<CmsModule, String>> itMods = modules.entrySet().iterator(); while (itMods.hasNext()) { Map.Entry<CmsModule, String> entry = itMods.next(); CmsModule module = entry.getKey(); // put the module information into a map keyed by the module packages names m_availableModules.put(module.getName(), module); m_moduleFilenames.put(module.getName(), entry.getValue()); addComponentsFromPath(getModuleFolder() + entry.getValue()); } } catch (CmsConfigurationException e) { throw new CmsRuntimeException(e.getMessageContainer()); } initializeComponents(new HashSet<String>(m_availableModules.keySet())); } return m_availableModules; } /** * Returns the "config" path in the OpenCms web application.<p> * * @return the config path */ public String getConfigRfsPath() { return m_configRfsPath; } /** * Returns the key of the selected database server (e.g. "mysql", "generic" or "oracle").<p> * * @return the key of the selected database server (e.g. "mysql", "generic" or "oracle") */ public String getDatabase() { if (m_databaseKey == null) { m_databaseKey = getExtProperty("db.name"); } if (CmsStringUtil.isEmpty(m_databaseKey)) { m_databaseKey = getSortedDatabases().get(0); } return m_databaseKey; } /** * Returns the URI of a database config page (in step 3) for a specified database key.<p> * * @param key the database key (e.g. "mysql", "generic" or "oracle") * @return the URI of a database config page */ public String getDatabaseConfigPage(String key) { // don't use File.separatorChar here, result must be a valid URL with "/" path delimiters String configUri = FOLDER_DATABASE + key + "/" + "step_4_database_setup.jsp"; return CmsStringUtil.substitute(configUri, File.separator, "/"); } /** * Returns a list of needed jar filenames for a database server setup specified by a database key (e.g. "mysql", "generic" or "oracle").<p> * * @param databaseKey a database key (e.g. "mysql", "generic" or "oracle") * * @return a list of needed jar filenames */ public List<String> getDatabaseLibs(String databaseKey) { List<String> lst; if (JPA_PROVIDER.equalsIgnoreCase(m_provider)) { lst = new ArrayList<String>(); } else { lst = CmsStringUtil.splitAsList( getDatabaseProperties().get(databaseKey).getProperty(databaseKey + ".libs"), ',', true); } return lst; } /** * Returns the clear text name for a database server setup specified by a database key (e.g. "mysql", "generic" or "oracle").<p> * * @param databaseKey a database key (e.g. "mysql", "generic" or "oracle") * @return the clear text name for a database server setup */ public String getDatabaseName(String databaseKey) { return getDatabaseProperties().get(databaseKey).getProperty(databaseKey + PROPKEY_NAME); } /** * Returns a map with the database properties of *all* available database configurations keyed * by their database keys (e.g. "mysql", "generic" or "oracle").<p> * * @return a map with the database properties of *all* available database configurations */ public Map<String, Properties> getDatabaseProperties() { if (m_databaseProperties == null) { readDatabaseConfig(); } return m_databaseProperties; } /** * Returns a list with they keys (e.g. "mysql", "generic" or "oracle") of all available * database server setups found in "/setup/database/".<p> * * @return a list with they keys (e.g. "mysql", "generic" or "oracle") of all available database server setups */ public List<String> getDatabases() { if (m_databaseKeys == null) { readDatabaseConfig(); } return m_databaseKeys; } /** * Returns the database name.<p> * * @return the database name */ public String getDb() { return getDbProperty(m_databaseKey + ".dbname"); } /** * Returns the JDBC connect URL parameters.<p> * * @return the JDBC connect URL parameters */ public String getDbConStrParams() { return getDbProperty(m_databaseKey + ".constr.params"); } /** * Returns the database create statement.<p> * * @return the database create statement */ public String getDbCreateConStr() { return getDbProperty(m_databaseKey + ".constr"); } /** * Returns the password used for database creation.<p> * * @return the password used for database creation */ public String getDbCreatePwd() { return (m_dbCreatePwd != null) ? m_dbCreatePwd : ""; } /** * Returns the database user that is used to connect to the database.<p> * * @return the database user */ public String getDbCreateUser() { return getDbProperty(m_databaseKey + ".user"); } /** * Returns the database driver belonging to the database * from the default configuration.<p> * * @return name of the database driver */ public String getDbDriver() { return getDbProperty(m_databaseKey + ".driver"); } /** * Returns the value for a given key from the database properties. * * @param key the property key * * @return the string value for a given key */ public String getDbProperty(String key) { // extract the database key out of the entire key String databaseKey = key.substring(0, key.indexOf('.')); Properties databaseProperties = getDatabaseProperties().get(databaseKey); return databaseProperties.getProperty(key, ""); } /** * Returns the validation query belonging to the database * from the default configuration .<p> * * @return query used to validate connections */ public String getDbTestQuery() { return getDbProperty(m_databaseKey + ".testQuery"); } /** * Returns a connection string.<p> * * @return the connection string used by the OpenCms core */ public String getDbWorkConStr() { if (m_provider.equals(POSTGRESQL_PROVIDER)) { return getDbProperty(m_databaseKey + ".constr.newDb"); } else { return getExtProperty(CmsDbPool.KEY_DATABASE_POOL + '.' + getPool() + ".jdbcUrl"); } } /** * Returns the password of the database from the properties .<p> * * @return the password for the OpenCms database user */ public String getDbWorkPwd() { return getExtProperty(CmsDbPool.KEY_DATABASE_POOL + '.' + getPool() + ".password"); } /** * Returns the user of the database from the properties.<p> * * @return the database user used by the opencms core */ public String getDbWorkUser() { String user = getExtProperty(CmsDbPool.KEY_DATABASE_POOL + '.' + getPool() + ".user"); if (CmsStringUtil.isEmptyOrWhitespaceOnly(user)) { return getDbCreateUser(); } return user; } /** * Returns the default content encoding.<p> * @return String */ public String getDefaultContentEncoding() { return getExtProperty("defaultContentEncoding"); } /** * Returns the name of the default web application, configured in <code>web.xml</code>.<p> * * By default this is <code>"ROOT"</code>.<p> * * @return the name of the default web application, configured in <code>web.xml</code> */ public String getDefaultWebApplication() { return m_defaultWebApplication; } /** * Returns the display string for a given module.<p> * * @param module a module * * @return the display string for the given module */ public String getDisplayForModule(CmsModule module) { String name = module.getNiceName(); String group = module.getGroup(); String version = module.getVersion().getVersion(); String display = name; if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(group)) { display = group + ": " + display; } if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(version)) { display += " (" + version + ")"; } return display; } /** * Returns the error messages.<p> * * @return a vector of error messages */ public List<String> getErrors() { return m_errors; } /** * Returns the mac ethernet address.<p> * * @return the mac ethernet addess */ public String getEthernetAddress() { return getExtProperty("server.ethernet.address"); } /** * Returns the fullDatabaseKey.<p> * * @return the fullDatabaseKey */ public String getFullDatabaseKey() { if (m_fullDatabaseKey == null) { m_fullDatabaseKey = getExtProperty("db.name") + "_sql"; } if (CmsStringUtil.isEmpty(m_fullDatabaseKey) || m_fullDatabaseKey.equals("_sql")) { m_fullDatabaseKey = getSortedDatabases().get(0) + "_sql"; } return m_fullDatabaseKey; } /** * Generates the HTML code for the drop down for db selection.<p> * * @return the generated HTML */ public String getHtmlForDbSelection() { StringBuffer buf = new StringBuffer(2048); buf.append("<select name=\"fullDatabaseKey\" style=\"width: 250px;\" size=\"1\" onchange=\"location.href='../../step_3_database_selection.jsp?fullDatabaseKey='+this.options[this.selectedIndex].value;\">"); buf.append("<!-- --------------------- JSP CODE --------------------------- -->"); // get all available databases List<String> databases = getSortedDatabases(); // List all databases found in the dbsetup.properties if ((databases != null) && (databases.size() > 0)) { List<String> sqlDbs = new ArrayList<String>(); List<String> jpaDbs = new ArrayList<String>(); // devide sql dbs from jpa dbs for (String dbKey : databases) { boolean isJpaSupported = isJpaSupported(dbKey); boolean isSqlSupported = isSqlSupported(dbKey); if (isJpaSupported && isSqlSupported) { sqlDbs.add(dbKey); jpaDbs.add(dbKey); } else if (isJpaSupported && !isSqlSupported) { jpaDbs.add(dbKey); } else if (!isJpaSupported && isSqlSupported) { sqlDbs.add(dbKey); } } // show the sql dbs first for (String dbKey : sqlDbs) { String dn = getDatabaseName(dbKey); String selected = ""; if (getFullDatabaseKey().equals(dbKey + "_sql")) { selected = "selected"; } buf.append("<option value='" + dbKey + "_sql' " + selected + ">" + dn); } // then show the jpa dbs for (String dbKey : jpaDbs) { String dn = getDatabaseName(dbKey); String selected = ""; if (getFullDatabaseKey().equals(dbKey + "_jpa")) { selected = "selected"; } buf.append("<option value='" + dbKey + "_jpa' " + selected + ">" + dn + " [JPA]"); } } else { buf.append("<option value='null'>no database found"); } buf.append("<!-- --------------------------------------------------------- -->"); buf.append("</select>"); return buf.toString(); } /** * Returns a help image icon tag to display a help text in the setup wizard.<p> * * @param id the id of the desired help div * @param pathPrefix the path prefix to the image * @return the HTML part for the help icon or an empty String, if the part was not found */ public String getHtmlHelpIcon(String id, String pathPrefix) { String value = m_htmlProps.getProperty("C_HELP_IMG"); if (value == null) { return ""; } else { value = CmsStringUtil.substitute(value, "$replace$", id); return CmsStringUtil.substitute(value, "$path$", pathPrefix); } } /** * Returns the specified HTML part of the HTML property file to create the output.<p> * * @param part the name of the desired part * @return the HTML part or an empty String, if the part was not found */ public String getHtmlPart(String part) { return getHtmlPart(part, ""); } /** * Returns the specified HTML part of the HTML property file to create the output.<p> * * @param part the name of the desired part * @param replaceString String which is inserted in the found HTML part at the location of "$replace$" * @return the HTML part or an empty String, if the part was not found */ public String getHtmlPart(String part, String replaceString) { String value = m_htmlProps.getProperty(part); if (value == null) { return ""; } else { return CmsStringUtil.substitute(value, "$replace$", replaceString); } } /** * Returns the path to the /WEB-INF/lib folder.<p> * * @return the path to the /WEB-INF/lib folder */ public String getLibFolder() { return getWebAppRfsPath() + CmsSystemInfo.FOLDER_WEBINF + FOLDER_LIB; } /** * Returns the name of the log file.<p> * * @return the name of the log file */ public String getLogName() { return new StringBuffer(m_webAppRfsPath).append(m_logFile).toString(); } /** * Returns a map with lists of dependent module package names keyed by module package names.<p> * * @return a map with lists of dependent module package names keyed by module package names */ public Map<String, List<String>> getModuleDependencies() { if ((m_moduleDependencies == null) || m_moduleDependencies.isEmpty()) { try { // open the folder "/WEB-INF/packages/modules/" m_moduleDependencies = CmsModuleManager.buildDepsForAllModules(getModuleFolder(), true); } catch (CmsConfigurationException e) { throw new CmsRuntimeException(e.getMessageContainer()); } } return m_moduleDependencies; } /** * Returns the absolute path to the module root folder.<p> * * @return the absolute path to the module root folder */ public String getModuleFolder() { return new StringBuffer(m_webAppRfsPath).append(m_modulesFolder).toString(); } /** * Returns A list with the package names of the modules to be installed.<p> * * @return A list with the package names of the modules to be installed */ public List<String> getModulesToInstall() { if ((m_installModules == null) || m_installModules.isEmpty()) { return Collections.emptyList(); } return Collections.unmodifiableList(m_installModules); } /** * Gets the default pool.<p> * * @return name of the default pool */ public String getPool() { return CmsStringUtil.splitAsArray(getExtProperty("db.pools"), ",")[0]; } /** * Returns the parameter configuration.<p> * * @return the parameter configuration */ public CmsParameterConfiguration getProperties() { return m_configuration; } /** * Returns the replacer.<p> * * @return the replacer */ public Map<String, String> getReplacer() { return m_replacer; } /** * Return the OpenCms server name.<p> * * @return the OpenCms server name */ public String getServerName() { return getExtProperty("server.name"); } /** * Returns the initial servlet configuration.<p> * * @return the initial servlet configuration */ public ServletConfig getServletConfig() { return m_servletConfig; } /** * Returns the OpenCms servlet mapping, configured in <code>web.xml</code>.<p> * * By default this is <code>"/opencms/*"</code>.<p> * * @return the OpenCms servlet mapping, configured in <code>web.xml</code> */ public String getServletMapping() { return m_servletMapping; } /** * Returns a sorted list with they keys (e.g. "mysql", "generic" or "oracle") of all available * database server setups found in "/setup/database/" sorted by their ranking property.<p> * * @return a sorted list with they keys (e.g. "mysql", "generic" or "oracle") of all available database server setups */ public List<String> getSortedDatabases() { if (m_sortedDatabaseKeys == null) { List<String> databases = m_databaseKeys; List<String> sortedDatabases = new ArrayList<String>(databases.size()); SortedMap<Integer, String> mappedDatabases = new TreeMap<Integer, String>(); for (int i = 0; i < databases.size(); i++) { String key = databases.get(i); Integer ranking = new Integer(0); try { ranking = Integer.valueOf(getDbProperty(key + ".ranking")); } catch (Exception e) { // ignore } mappedDatabases.put(ranking, key); } while (mappedDatabases.size() > 0) { // get database with highest ranking Integer key = mappedDatabases.lastKey(); String database = mappedDatabases.get(key); sortedDatabases.add(database); mappedDatabases.remove(key); } m_sortedDatabaseKeys = sortedDatabases; } return m_sortedDatabaseKeys; } /** * Returns the absolute path to the OpenCms home directory.<p> * * @return the path to the OpenCms home directory */ public String getWebAppRfsPath() { return m_webAppRfsPath; } /** * Checks if the setup wizard is enabled.<p> * * @return true if the setup wizard is enables, false otherwise */ public boolean getWizardEnabled() { return Boolean.valueOf(getExtProperty("wizard.enabled")).booleanValue(); } /** * Returns the workplace import thread.<p> * * @return the workplace import thread */ public CmsSetupWorkplaceImportThread getWorkplaceImportThread() { return m_workplaceImportThread; } /** * Return the OpenCms workplace site.<p> * * @return the OpenCms workplace site */ public String getWorkplaceSite() { return getExtProperty("site.workplace"); } /** * Returns the xml Helper object.<p> * * @return the xml Helper object */ public CmsSetupXmlHelper getXmlHelper() { if (m_xmlHelper == null) { // lazzy initialization m_xmlHelper = new CmsSetupXmlHelper(getConfigRfsPath()); } return m_xmlHelper; } /** * Returns the html code for component selection.<p> * * @return html code */ public String htmlComponents() { StringBuffer html = new StringBuffer(1024); Iterator<CmsSetupComponent> itComponents = CmsCollectionsGenericWrapper.<CmsSetupComponent> list( m_components.elementList()).iterator(); while (itComponents.hasNext()) { CmsSetupComponent component = itComponents.next(); html.append(htmlComponent(component)); } return html.toString(); } /** * Returns html code for the module descriptions in help ballons.<p> * * @return html code */ public String htmlModuleHelpDescriptions() { StringBuffer html = new StringBuffer(1024); Iterator<String> itModules = sortModules(getAvailableModules().values()).iterator(); for (int i = 0; itModules.hasNext(); i++) { String moduleName = itModules.next(); CmsModule module = getAvailableModules().get(moduleName); if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(module.getDescription())) { html.append(getHtmlPart("C_HELP_START", "" + i)); html.append(module.getDescription()); html.append("\n"); html.append(getHtmlPart("C_HELP_END")); html.append("\n"); } } return html.toString(); } /** * Returns html for displaying a module selection box.<p> * * @return html code */ public String htmlModules() { StringBuffer html = new StringBuffer(1024); Iterator<String> itModules = sortModules(getAvailableModules().values()).iterator(); for (int i = 0; itModules.hasNext(); i++) { String moduleName = itModules.next(); CmsModule module = getAvailableModules().get(moduleName); html.append(htmlModule(module, i)); } return html.toString(); } /** * Installed all modules that have been set using {@link #setInstallModules(String)}.<p> * * This method is invoked as a shell command.<p> * * @throws Exception if something goes wrong */ public void importModulesFromSetupBean() throws Exception { // read here how the list of modules to be installed is passed from the setup bean to the // setup thread, and finally to the shell process that executes the setup script: // 1) the list with the package names of the modules to be installed is saved by setInstallModules // 2) the setup thread gets initialized in a JSP of the setup wizard // 3) the instance of the setup bean is passed to the setup thread by setAdditionalShellCommand // 4) the setup bean is passed to the shell by startSetup // 5) because the setup bean implements I_CmsShellCommands, the shell constructor can pass the shell's CmsObject back to the setup bean // 6) thus, the setup bean can do things with the Cms if ((m_cms != null) && (m_installModules != null)) { for (int i = 0; i < m_installModules.size(); i++) { String filename = m_moduleFilenames.get(m_installModules.get(i)); try { importModuleFromDefault(filename); } catch (Exception e) { // log a exception during module import, but make sure the next module is still imported e.printStackTrace(System.err); } } } } /** * Creates a new instance of the setup Bean from a JSP page.<p> * * @param pageContext the JSP's page context */ public void init(PageContext pageContext) { // check for OpenCms installation directory path String webAppRfsPath = pageContext.getServletConfig().getServletContext().getRealPath("/"); // read the the OpenCms servlet mapping from the servlet context parameters String servletMapping = pageContext.getServletContext().getInitParameter( OpenCmsServlet.SERVLET_PARAM_OPEN_CMS_SERVLET); // read the the default context name from the servlet context parameters String defaultWebApplication = pageContext.getServletContext().getInitParameter( OpenCmsServlet.SERVLET_PARAM_DEFAULT_WEB_APPLICATION); m_servletConfig = pageContext.getServletConfig(); init(webAppRfsPath, servletMapping, defaultWebApplication); } /** * Creates a new instance of the setup Bean.<p> * * @param webAppRfsPath path to the OpenCms web application * @param servletMapping the OpenCms servlet mapping * @param defaultWebApplication the name of the default web application * */ public void init(String webAppRfsPath, String servletMapping, String defaultWebApplication) { try { // explicit set to null to overwrite exiting values from session m_availableModules = null; m_fullDatabaseKey = null; m_databaseKey = null; m_databaseKeys = null; m_databaseProperties = null; m_configuration = null; m_installModules = null; m_moduleDependencies = null; m_sortedDatabaseKeys = null; m_moduleFilenames = null; if (servletMapping == null) { servletMapping = "/opencms/*"; } if (defaultWebApplication == null) { defaultWebApplication = "ROOT"; } m_servletMapping = servletMapping; m_defaultWebApplication = defaultWebApplication; setWebAppRfsPath(webAppRfsPath); m_errors = new ArrayList<String>(); // init persistence configurator String inFileName = m_webAppRfsPath + CmsSystemInfo.FOLDER_WEBINF + CmsSystemInfo.FILE_PERSISTENCE; m_peristenceConfigurator = new CmsPersistenceUnitConfiguration( CmsSqlManager.JPA_PERSISTENCE_UNIT, inFileName); if (CmsStringUtil.isNotEmpty(webAppRfsPath)) { // workaround for JUnit test cases, this must not be executed in a test case m_configuration = new CmsParameterConfiguration(m_configRfsPath + CmsSystemInfo.FILE_PROPERTIES); readDatabaseConfig(); } if (m_workplaceImportThread != null) { if (m_workplaceImportThread.isAlive()) { m_workplaceImportThread.kill(); } m_workplaceImportThread = null; m_newLoggingOffset = 0; m_oldLoggingOffset = 0; } } catch (Exception e) { e.printStackTrace(); m_errors.add(e.toString()); } } /** * This method reads the properties from the htmlmsg.property file * and sets the HTML part properties with the matching values.<p> */ public void initHtmlParts() { if (m_htmlProps != null) { // html already initialized return; } try { m_htmlProps = new Properties(); m_htmlProps.load(getClass().getClassLoader().getResourceAsStream(HTML_MESSAGE_FILE)); } catch (Exception e) { e.printStackTrace(); m_errors.add(e.toString()); } } /** * @see org.opencms.main.I_CmsShellCommands#initShellCmsObject(org.opencms.file.CmsObject, org.opencms.main.CmsShell) */ public void initShellCmsObject(CmsObject cms, CmsShell shell) { m_cms = cms; } /** * Over simplistic helper to compare two strings to check radio buttons. * * @param value1 the first value * @param value2 the second value * @return "checked" if both values are equal, the empty String "" otherwise */ public String isChecked(String value1, String value2) { if ((value1 == null) || (value2 == null)) { return ""; } if (value1.trim().equalsIgnoreCase(value2.trim())) { return "checked"; } return ""; } /** * Returns true if this setup bean is correctly initialized.<p> * * @return true if this setup bean is correctly initialized */ public boolean isInitialized() { return m_configuration != null; } /** * Returns true if jpa is supported for the given dbKey.<p> * * @param dbKey the database key to check the jpa support for * * @return true if jpa is supported for the given dbKey */ public boolean isJpaSupported(String dbKey) { String key = dbKey + "." + PROPKEY_JPA_SUPPORTED; return Boolean.valueOf(getDbProperty(key)).booleanValue(); } /** * Returns true if sql is supported for the given dbKey.<p> * * @param dbKey the database key to check the sql support for * * @return true if sql is supported for the given dbKey */ public boolean isSqlSupported(String dbKey) { String key = dbKey + "." + PROPKEY_SQL_SUPPORTED; return Boolean.valueOf(getDbProperty(key)).booleanValue(); } /** * Returns js code with array definition for the available component dependencies.<p> * * @return js code */ public String jsComponentDependencies() { List<CmsSetupComponent> components = CmsCollectionsGenericWrapper.list(m_components.elementList()); Map<String, List<String>> componentDependencies = buildDepsForAllComponents(); StringBuffer jsCode = new StringBuffer(1024); jsCode.append("\t// an array holding the dependent components for the n-th component\n"); jsCode.append("\tvar componentDependencies = new Array("); jsCode.append(components.size()); jsCode.append(");\n"); for (int i = 0; i < components.size(); i++) { CmsSetupComponent component = components.get(i); List<String> dependencies = componentDependencies.get(component.getId()); jsCode.append("\tcomponentDependencies[" + i + "] = new Array("); if (dependencies != null) { for (int j = 0; j < dependencies.size(); j++) { jsCode.append("\"" + dependencies.get(j) + "\""); if (j < (dependencies.size() - 1)) { jsCode.append(", "); } } } jsCode.append(");\n"); } jsCode.append("\n\n"); return jsCode.toString(); } /** * Returns js code with array definition for the component modules.<p> * * @return js code */ public String jsComponentModules() { List<CmsSetupComponent> components = CmsCollectionsGenericWrapper.list(m_components.elementList()); StringBuffer jsCode = new StringBuffer(1024); jsCode.append("\t// an array holding the components modules\n"); jsCode.append("\tvar componentModules = new Array("); jsCode.append(components.size()); jsCode.append(");\n"); for (int i = 0; i < components.size(); i++) { CmsSetupComponent component = components.get(i); jsCode.append("\tcomponentModules[" + i + "] = \""); List<String> modules = getComponentModules(component); for (int j = 0; j < modules.size(); j++) { jsCode.append(modules.get(j)); if (j < (modules.size() - 1)) { jsCode.append("|"); } } jsCode.append("\";\n"); } jsCode.append("\n\n"); return jsCode.toString(); } /** * Returns js code with array definition for the available components names.<p> * * @return js code */ public String jsComponentNames() { StringBuffer jsCode = new StringBuffer(1024); jsCode.append("\t// an array from 1...n holding the component names\n"); jsCode.append("\tvar componentNames = new Array("); jsCode.append(m_components.elementList().size()); jsCode.append(");\n"); for (int i = 0; i < m_components.elementList().size(); i++) { CmsSetupComponent component = m_components.elementList().get(i); jsCode.append("\tcomponentNames[" + i + "] = \"" + component.getId() + "\";\n"); } jsCode.append("\n\n"); return jsCode.toString(); } /** * Returns js code with array definition for the available module dependencies.<p> * * @return js code */ public String jsModuleDependencies() { List<String> moduleNames = sortModules(getAvailableModules().values()); StringBuffer jsCode = new StringBuffer(1024); jsCode.append("\t// an array holding the dependent modules for the n-th module\n"); jsCode.append("\tvar moduleDependencies = new Array("); jsCode.append(moduleNames.size()); jsCode.append(");\n"); for (int i = 0; i < moduleNames.size(); i++) { String moduleName = moduleNames.get(i); List<String> dependencies = getModuleDependencies().get(moduleName); jsCode.append("\tmoduleDependencies[" + i + "] = new Array("); if (dependencies != null) { for (int j = 0; j < dependencies.size(); j++) { jsCode.append("\"" + dependencies.get(j) + "\""); if (j < (dependencies.size() - 1)) { jsCode.append(", "); } } } jsCode.append(");\n"); } jsCode.append("\n\n"); return jsCode.toString(); } /** * Returns js code with array definition for the available module names.<p> * * @return js code */ public String jsModuleNames() { List<String> moduleNames = sortModules(getAvailableModules().values()); StringBuffer jsCode = new StringBuffer(1024); jsCode.append("\t// an array from 1...n holding the module package names\n"); jsCode.append("\tvar modulePackageNames = new Array("); jsCode.append(moduleNames.size()); jsCode.append(");\n"); for (int i = 0; i < moduleNames.size(); i++) { String moduleName = moduleNames.get(i); jsCode.append("\tmodulePackageNames[" + i + "] = \"" + moduleName + "\";\n"); } jsCode.append("\n\n"); return jsCode.toString(); } /** * Locks (i.e. disables) the setup wizard.<p> * */ public void lockWizard() { setExtProperty("wizard.enabled", CmsStringUtil.FALSE); } /** * Prepares step 10 of the setup wizard.<p> */ public void prepareStep10() { if (isInitialized()) { // lock the wizard for further use lockWizard(); // save Properties to file "opencms.properties" saveProperties(getProperties(), CmsSystemInfo.FILE_PROPERTIES, false); setSchemaGeneration(false); m_peristenceConfigurator.save(); } } /** * Prepares step 8 of the setup wizard.<p> * * @return true if the workplace should be imported */ public boolean prepareStep8() { if (isInitialized()) { try { checkEthernetAddress(); // backup the XML configuration backupConfiguration( CmsImportExportConfiguration.DEFAULT_XML_FILE_NAME, CmsImportExportConfiguration.DEFAULT_XML_FILE_NAME + CmsConfigurationManager.POSTFIX_ORI); backupConfiguration( CmsModuleConfiguration.DEFAULT_XML_FILE_NAME, CmsModuleConfiguration.DEFAULT_XML_FILE_NAME + CmsConfigurationManager.POSTFIX_ORI); backupConfiguration( CmsSearchConfiguration.DEFAULT_XML_FILE_NAME, CmsSearchConfiguration.DEFAULT_XML_FILE_NAME + CmsConfigurationManager.POSTFIX_ORI); backupConfiguration( CmsSystemConfiguration.DEFAULT_XML_FILE_NAME, CmsSystemConfiguration.DEFAULT_XML_FILE_NAME + CmsConfigurationManager.POSTFIX_ORI); backupConfiguration( CmsVfsConfiguration.DEFAULT_XML_FILE_NAME, CmsVfsConfiguration.DEFAULT_XML_FILE_NAME + CmsConfigurationManager.POSTFIX_ORI); backupConfiguration( CmsWorkplaceConfiguration.DEFAULT_XML_FILE_NAME, CmsWorkplaceConfiguration.DEFAULT_XML_FILE_NAME + CmsConfigurationManager.POSTFIX_ORI); backupConfiguration( CmsConfigurationManager.DEFAULT_XML_FILE_NAME, CmsConfigurationManager.DEFAULT_XML_FILE_NAME + CmsConfigurationManager.POSTFIX_ORI); // save Properties to file "opencms.properties" setDatabase(m_databaseKey); if (m_driverType == DRIVER_TYPE_JPA) { setEntityManagerPoolSize(getDbProperty(m_databaseKey + "." + CmsDbPool.KEY_ENTITY_MANAGER_POOL_SIZE)); } saveProperties(getProperties(), CmsSystemInfo.FILE_PROPERTIES, true); // if has sql driver the sql scripts will be eventualy executed setSchemaGeneration(!isSqlSupported(m_databaseKey)); m_peristenceConfigurator.save(); CmsSetupTestResult testResult = new CmsSetupTestSimapi().execute(this); if (testResult.getResult().equals(I_CmsSetupTest.RESULT_FAILED)) { // "/opencms/vfs/resources/resourceloaders/loader[@class='org.opencms.loader.CmsImageLoader']/param[@name='image.scaling.enabled']"; StringBuffer xp = new StringBuffer(256); xp.append("/").append(CmsConfigurationManager.N_ROOT); xp.append("/").append(CmsVfsConfiguration.N_VFS); xp.append("/").append(CmsVfsConfiguration.N_RESOURCES); xp.append("/").append(CmsVfsConfiguration.N_RESOURCELOADERS); xp.append("/").append(CmsVfsConfiguration.N_LOADER); xp.append("[@").append(I_CmsXmlConfiguration.A_CLASS); xp.append("='").append(CmsImageLoader.class.getName()); xp.append("']/").append(I_CmsXmlConfiguration.N_PARAM); xp.append("[@").append(I_CmsXmlConfiguration.A_NAME); xp.append("='").append(CmsImageLoader.CONFIGURATION_SCALING_ENABLED).append("']"); getXmlHelper().setValue( CmsVfsConfiguration.DEFAULT_XML_FILE_NAME, xp.toString(), Boolean.FALSE.toString()); } // /opencms/system/sites/workplace-server StringBuffer xp = new StringBuffer(256); xp.append("/").append(CmsConfigurationManager.N_ROOT); xp.append("/").append(CmsSystemConfiguration.N_SYSTEM); xp.append("/").append(CmsSystemConfiguration.N_SITES); xp.append("/").append(CmsSystemConfiguration.N_WORKPLACE_SERVER); getXmlHelper().setValue(CmsSystemConfiguration.DEFAULT_XML_FILE_NAME, xp.toString(), getWorkplaceSite()); // /opencms/system/sites/site[@uri='/sites/default/']/@server xp = new StringBuffer(256); xp.append("/").append(CmsConfigurationManager.N_ROOT); xp.append("/").append(CmsSystemConfiguration.N_SYSTEM); xp.append("/").append(CmsSystemConfiguration.N_SITES); xp.append("/").append(I_CmsXmlConfiguration.N_SITE); xp.append("[@").append(I_CmsXmlConfiguration.A_URI); xp.append("='").append(CmsResource.VFS_FOLDER_SITES); xp.append("/default/']/@").append(CmsSystemConfiguration.A_SERVER); getXmlHelper().setValue(CmsSystemConfiguration.DEFAULT_XML_FILE_NAME, xp.toString(), getWorkplaceSite()); if (m_driverType == DRIVER_TYPE_JPA) { // /opencms/system/runtimeclasses/runtimeinfo xp = new StringBuffer(256); xp.append("/").append(CmsConfigurationManager.N_ROOT); xp.append("/").append(CmsSystemConfiguration.N_SYSTEM); xp.append("/").append(CmsSystemConfiguration.N_RUNTIMECLASSES); xp.append("/").append(CmsSystemConfiguration.N_RUNTIMEINFO); getXmlHelper().setAttribute( CmsSystemConfiguration.DEFAULT_XML_FILE_NAME, xp.toString(), "class", JPA_FACTOTY); } getXmlHelper().writeAll(); } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error(e.getLocalizedMessage(), e); } } } return true; } /** * Prepares step 8b of the setup wizard.<p> */ public void prepareStep8b() { if (!isInitialized()) { return; } if ((m_workplaceImportThread != null) && (m_workplaceImportThread.isFinished())) { // setup is already finished, just wait for client to collect final data return; } if (m_workplaceImportThread == null) { m_workplaceImportThread = new CmsSetupWorkplaceImportThread(this); } if (!m_workplaceImportThread.isAlive()) { m_workplaceImportThread.start(); } } /** * Generates the output for step 8b of the setup wizard.<p> * * @param out the JSP print stream * @throws IOException in case errors occur while writing to "out" */ public void prepareStep8bOutput(JspWriter out) throws IOException { if ((m_workplaceImportThread == null) || (m_workplaceImportThread.getLoggingThread() == null)) { return; } m_oldLoggingOffset = m_newLoggingOffset; m_newLoggingOffset = m_workplaceImportThread.getLoggingThread().getMessages().size(); if (isInitialized()) { for (int i = m_oldLoggingOffset; i < m_newLoggingOffset; i++) { String str = m_workplaceImportThread.getLoggingThread().getMessages().get(i).toString(); str = CmsEncoder.escapeWBlanks(str, CmsEncoder.ENCODING_UTF_8); out.println("output[" + (i - m_oldLoggingOffset) + "] = \"" + str + "\";"); } } else { out.println("output[0] = 'ERROR';"); } boolean threadFinished = m_workplaceImportThread.isFinished(); boolean allWritten = m_oldLoggingOffset >= m_workplaceImportThread.getLoggingThread().getMessages().size(); out.println("function initThread() {"); if (isInitialized()) { out.print("send();"); if (threadFinished && allWritten) { out.println("setTimeout('top.display.finish()', 1000);"); } else { int timeout = 5000; if (getWorkplaceImportThread().getLoggingThread().getMessages().size() < 20) { timeout = 2000; } out.println("setTimeout('location.reload()', " + timeout + ");"); } } out.println("}"); } /** * Saves properties to specified file.<p> * * @param properties the properties to be saved * @param file the file to save the properties to * @param backup if true, create a backupfile */ public void saveProperties(CmsParameterConfiguration properties, String file, boolean backup) { if (new File(m_configRfsPath + file).isFile()) { String backupFile = file + CmsConfigurationManager.POSTFIX_ORI; String tempFile = file + ".tmp"; m_errors.clear(); if (backup) { // make a backup copy copyFile(file, FOLDER_BACKUP + backupFile); } //save to temporary file copyFile(file, tempFile); // save properties save(properties, tempFile, file, null); // delete temp file File temp = new File(m_configRfsPath + tempFile); temp.delete(); } else { m_errors.add("No valid file: " + file + "\n"); } } /** * Saves properties to specified file.<p> * * @param properties the properties to be saved * @param file the file to save the properties to * @param backup if true, create a backupfile * @param forceWrite the keys for the properties which should always be written, even if they don't exist in the configuration file */ public void saveProperties(CmsParameterConfiguration properties, String file, boolean backup, Set<String> forceWrite) { if (new File(m_configRfsPath + file).isFile()) { String backupFile = file + CmsConfigurationManager.POSTFIX_ORI; String tempFile = file + ".tmp"; m_errors.clear(); if (backup) { // make a backup copy copyFile(file, FOLDER_BACKUP + backupFile); } //save to temporary file copyFile(file, tempFile); // save properties save(properties, tempFile, file, forceWrite); // delete temp file File temp = new File(m_configRfsPath + tempFile); temp.delete(); } else { m_errors.add("No valid file: " + file + "\n"); } } /** * Sets the database drivers to the given value.<p> * * @param databaseKey the key of the selected database server (e.g. "mysql", "generic" or "oracle") */ public void setDatabase(String databaseKey) { m_databaseKey = databaseKey; String vfsDriver; String userDriver; String projectDriver; String historyDriver; String subscriptionDriver; String sqlManager; if (m_driverType == DRIVER_TYPE_JPA) { vfsDriver = "org.opencms.db.jpa.CmsVfsDriver"; userDriver = "org.opencms.db.jpa.CmsUserDriver"; projectDriver = "org.opencms.db.jpa.CmsProjectDriver"; historyDriver = "org.opencms.db.jpa.CmsHistoryDriver"; sqlManager = "org.opencms.db.jpa.CmsSqlManager"; subscriptionDriver = "org.opencms.db.jpa.CmsSubscriptionDriver"; } else { vfsDriver = getDbProperty(m_databaseKey + ".vfs.driver"); userDriver = getDbProperty(m_databaseKey + ".user.driver"); projectDriver = getDbProperty(m_databaseKey + ".project.driver"); historyDriver = getDbProperty(m_databaseKey + ".history.driver"); subscriptionDriver = getDbProperty(m_databaseKey + ".subscription.driver"); sqlManager = getDbProperty(m_databaseKey + ".sqlmanager"); } // set the db properties setExtProperty("db.name", m_databaseKey); setExtProperty("db.vfs.driver", vfsDriver); setExtProperty("db.vfs.sqlmanager", sqlManager); setExtProperty("db.user.driver", userDriver); setExtProperty("db.user.sqlmanager", sqlManager); setExtProperty("db.project.driver", projectDriver); setExtProperty("db.project.sqlmanager", sqlManager); setExtProperty("db.history.driver", historyDriver); setExtProperty("db.history.sqlmanager", sqlManager); setExtProperty("db.subscription.driver", subscriptionDriver); setExtProperty("db.subscription.sqlmanager", sqlManager); } /** * Sets the database name.<p> * * @param db the database name to set */ public void setDb(String db) { setDbProperty(m_databaseKey + ".dbname", db); } /** * Sets the JDBC connect URL parameters.<p> * * @param value the JDBC connect URL parameters */ public void setDbConStrParams(String value) { setDbProperty(m_databaseKey + ".constr.params", value); } /** * Sets the database create statement.<p> * * @param dbCreateConStr the database create statement */ public void setDbCreateConStr(String dbCreateConStr) { setDbProperty(m_databaseKey + ".constr", dbCreateConStr); } /** * Sets the password used for the initial OpenCms database creation.<p> * * This password will not be stored permanently, * but used only in the setup wizard.<p> * * @param dbCreatePwd the password used for the initial OpenCms database creation */ public void setDbCreatePwd(String dbCreatePwd) { m_dbCreatePwd = dbCreatePwd; } /** * Set the database user that is used to connect to the database.<p> * * @param dbCreateUser the user to set */ public void setDbCreateUser(String dbCreateUser) { setDbProperty(m_databaseKey + ".user", dbCreateUser); } /** * Sets the database driver belonging to the database.<p> * * @param driver name of the opencms driver */ public void setDbDriver(String driver) { setDbProperty(m_databaseKey + ".driver", driver); } /** * Sets the needed database parameters.<p> * * @param request the http request * @param provider the db provider * * @return true if already submitted */ public boolean setDbParamaters(HttpServletRequest request, String provider) { String conStr = request.getParameter("dbCreateConStr"); // store the DB provider m_provider = provider; // ensure that the driver type and the provider is set accordingly to the full database key if (getFullDatabaseKey().toLowerCase().endsWith(JPA_PROVIDER) || JPA_PROVIDER.equalsIgnoreCase(m_provider)) { m_driverType = DRIVER_TYPE_JPA; } else { m_driverType = DRIVER_TYPE_SQL; } boolean isFormSubmitted = ((request.getParameter("submit") != null) && (conStr != null)); if (conStr == null) { conStr = ""; } String database = ""; if (provider.equals(MYSQL_PROVIDER) || provider.equals(MSSQL_PROVIDER) || provider.equals(DB2_PROVIDER) || provider.equals(AS400_PROVIDER)) { database = request.getParameter("db"); } else if (provider.equals(POSTGRESQL_PROVIDER)) { database = request.getParameter("dbName"); } if (provider.equals(MYSQL_PROVIDER) || provider.equals(MSSQL_PROVIDER) || provider.equals(POSTGRESQL_PROVIDER) || provider.equals(AS400_PROVIDER) || provider.equals(DB2_PROVIDER)) { isFormSubmitted = (isFormSubmitted && (database != null)); } if (isInitialized()) { String createDb = request.getParameter("createDb"); if ((createDb == null) || provider.equals(DB2_PROVIDER) || provider.equals(AS400_PROVIDER)) { createDb = ""; } String createTables = request.getParameter("createTables"); if (createTables == null) { createTables = ""; } if (isFormSubmitted) { if (m_driverType == DRIVER_TYPE_JPA) { if (isJpaSupported(m_databaseKey) && !isSqlSupported(m_databaseKey)) { // driver name should be specified for only JPA supported databases String driverName = request.getParameter("jdbcDriver"); setDbDriver(driverName); } } if (provider.equals(POSTGRESQL_PROVIDER)) { setDb(database); String templateDb = request.getParameter("templateDb"); setDbProperty(getDatabase() + ".templateDb", templateDb); setDbProperty(getDatabase() + ".newDb", database); if (!conStr.endsWith("/")) { conStr += "/"; } setDbProperty(getDatabase() + ".constr", conStr + getDbProperty(getDatabase() + ".templateDb")); setDbProperty(getDatabase() + ".constr.newDb", conStr + getDbProperty(getDatabase() + ".newDb")); conStr += database; } else if (provider.equals(MYSQL_PROVIDER) || provider.equals(DB2_PROVIDER) || provider.equals(MSSQL_PROVIDER) || provider.equals(POSTGRESQL_PROVIDER)) { if (!conStr.endsWith("/")) { conStr += "/"; } conStr += database; } else if (provider.equals(AS400_PROVIDER)) { if (conStr.endsWith("/")) { conStr = conStr.substring(0, conStr.length() - 1); } if (!conStr.endsWith(";")) { conStr += ";"; } conStr += "libraries='" + database + "'"; } else if (isJpaSupported(m_databaseKey) && !isSqlSupported(m_databaseKey)) { conStr = request.getParameter("dbCreateConStr") + getDbProperty(m_databaseKey + "." + "separator") + request.getParameter("db"); setDbProperty(getDatabase() + ".constr", conStr + getDbProperty(getDatabase() + ".newDb")); setDbWorkConStr(conStr); boolean createTbls = "true".equalsIgnoreCase(request.getParameter("createTables")) ? true : false; request.getSession().setAttribute("createTables", Boolean.valueOf(createTbls)); } setDbWorkConStr(conStr); if (provider.equals(POSTGRESQL_PROVIDER)) { setDb(database); } String dbCreateUser = request.getParameter("dbCreateUser"); String dbCreatePwd = request.getParameter("dbCreatePwd"); String dbWorkUser = request.getParameter("dbWorkUser"); String dbWorkPwd = request.getParameter("dbWorkPwd"); if ((dbCreateUser != null) && !provider.equals(DB2_PROVIDER) && !provider.equals(AS400_PROVIDER)) { setDbCreateUser(dbCreateUser); } setDbCreatePwd(dbCreatePwd); if (dbWorkUser.equals("")) { dbWorkUser = request.getContextPath(); } if (dbWorkUser.equals("")) { dbWorkUser = "opencms"; } if (dbWorkUser.startsWith("/")) { dbWorkUser = dbWorkUser.substring(1, dbWorkUser.length()); } setDbWorkUser(dbWorkUser); setDbWorkPwd(dbWorkPwd); if (provider.equals(ORACLE_PROVIDER)) { String dbDefaultTablespace = request.getParameter("dbDefaultTablespace"); String dbTemporaryTablespace = request.getParameter("dbTemporaryTablespace"); String dbIndexTablespace = request.getParameter("dbIndexTablespace"); setDbProperty(getDatabase() + ".defaultTablespace", dbDefaultTablespace); setDbProperty(getDatabase() + ".temporaryTablespace", dbTemporaryTablespace); setDbProperty(getDatabase() + ".indexTablespace", dbIndexTablespace); } Map<String, String> replacer = new HashMap<String, String>(); if (!provider.equals(MYSQL_PROVIDER) || provider.equals(MSSQL_PROVIDER)) { replacer.put("${user}", dbWorkUser); replacer.put("${password}", dbWorkPwd); } if (provider.equals(MYSQL_PROVIDER) || provider.equals(MSSQL_PROVIDER) || provider.equals(POSTGRESQL_PROVIDER)) { replacer.put("${database}", database); } if (provider.equals(ORACLE_PROVIDER)) { replacer.put("${defaultTablespace}", getDbProperty(getDatabase() + ".defaultTablespace")); replacer.put("${indexTablespace}", getDbProperty(getDatabase() + ".indexTablespace")); replacer.put("${temporaryTablespace}", getDbProperty(getDatabase() + ".temporaryTablespace")); } setReplacer(replacer); if (provider.equals(GENERIC_PROVIDER) || provider.equals(ORACLE_PROVIDER) || provider.equals(DB2_PROVIDER) || provider.equals(AS400_PROVIDER) || provider.equals(MAXDB_PROVIDER)) { request.getSession().setAttribute("createTables", createTables); } request.getSession().setAttribute("createDb", createDb); } else { String dbName = "opencms"; // initialize the database name with the app name if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(request.getContextPath())) { dbName = request.getContextPath().substring(1); } if (provider.equals(ORACLE_PROVIDER) || provider.equals(POSTGRESQL_PROVIDER) || provider.equals(MAXDB_PROVIDER)) { setDbWorkUser(dbName); } else if (dbName != null) { setDb(dbName); } } } return isFormSubmitted; } /** * This method sets the value for a given key in the database properties.<p> * * @param key The key of the property * @param value The value of the property */ public void setDbProperty(String key, String value) { // extract the database key out of the entire key String databaseKey = key.substring(0, key.indexOf('.')); Properties databaseProperties = getDatabaseProperties().get(databaseKey); databaseProperties.put(key, value); } /** * Sets the connection string to the database to the given value.<p> * * @param dbWorkConStr the connection string used by the OpenCms core */ public void setDbWorkConStr(String dbWorkConStr) { String driver; String pool = '.' + getPool() + '.'; if (m_driverType == DRIVER_TYPE_JPA) { driver = getDbDriver(); } else { driver = getDbProperty(m_databaseKey + ".driver"); } setExtProperty(CmsDbPool.KEY_DATABASE_POOL + pool + CmsDbPool.KEY_JDBC_DRIVER, driver); setExtProperty(CmsDbPool.KEY_DATABASE_POOL + pool + CmsDbPool.KEY_JDBC_URL, dbWorkConStr); setExtProperty(CmsDbPool.KEY_DATABASE_POOL + pool + CmsDbPool.KEY_TEST_QUERY, getDbTestQuery()); setExtProperty(CmsDbPool.KEY_DATABASE_POOL + pool + CmsDbPool.KEY_JDBC_URL_PARAMS, getDbConStrParams()); } /** * Sets the password of the database to the given value.<p> * * @param dbWorkPwd the password for the OpenCms database user */ public void setDbWorkPwd(String dbWorkPwd) { setExtProperty(CmsDbPool.KEY_DATABASE_POOL + '.' + getPool() + '.' + CmsDbPool.KEY_PASSWORD, dbWorkPwd); } /** * Sets the user of the database to the given value.<p> * * @param dbWorkUser the database user used by the opencms core */ public void setDbWorkUser(String dbWorkUser) { setExtProperty(CmsDbPool.KEY_DATABASE_POOL + '.' + getPool() + '.' + CmsDbPool.KEY_POOL_USER, dbWorkUser); } /** * Sets the driver type.<p> * * @param type the type to set */ public void setDriverType(String type) { m_driverType = JPA_PROVIDER.equalsIgnoreCase(type) ? DRIVER_TYPE_JPA : DRIVER_TYPE_SQL; } /** * Set the mac ethernet address, required for UUID generation.<p> * * @param ethernetAddress the mac addess to set */ public void setEthernetAddress(String ethernetAddress) { setExtProperty("server.ethernet.address", ethernetAddress); } /** * Sets the fullDatabaseKey.<p> * * @param fullDatabaseKey the fullDatabaseKey to set */ public void setFullDatabaseKey(String fullDatabaseKey) { m_fullDatabaseKey = fullDatabaseKey; String driverPart = fullDatabaseKey.substring(fullDatabaseKey.lastIndexOf("_"), fullDatabaseKey.length()); if (driverPart.toLowerCase().contains(JPA_PROVIDER)) { setDriverType(JPA_PROVIDER); } String keyPart = fullDatabaseKey.substring(0, fullDatabaseKey.lastIndexOf("_")); setDatabase(keyPart); } /** * Sets the list with the package names of the modules to be installed.<p> * * @param value a string with the package names of the modules to be installed delimited by the pipe symbol "|" */ public void setInstallModules(String value) { m_installModules = CmsStringUtil.splitAsList(value, "|", true); try { m_installModules = CmsModuleManager.topologicalSort(m_installModules, getModuleFolder()); } catch (CmsConfigurationException e) { throw new RuntimeException(e); } } /** * Sets the replacer.<p> * * @param map the replacer to set */ public void setReplacer(Map<String, String> map) { m_replacer = map; } /** * Sets the OpenCms server name.<p> * * @param name the OpenCms server name */ public void setServerName(String name) { setExtProperty("server.name", name); } /** * Sets the OpenCms workplace site.<p> * * @param newSite the OpenCms workplace site */ public void setWorkplaceSite(String newSite) { String oldSite = getWorkplaceSite(); // get the site list String siteList = getExtProperty("site.root.list"); // replace old site URL in site list with new site URL siteList = CmsStringUtil.substitute(siteList, oldSite, newSite); setExtProperty("site.root.list", siteList); setExtProperty("site.workplace", newSite); } /** * @see org.opencms.main.I_CmsShellCommands#shellExit() */ public void shellExit() { System.out.println(); System.out.println(); System.out.println("The setup is finished!\nThe OpenCms system used for the setup will now shut down."); } /** * @see org.opencms.main.I_CmsShellCommands#shellStart() */ public void shellStart() { System.out.println(); System.out.println("Starting Workplace import and database setup for OpenCms!"); String[] copy = org.opencms.main.Messages.COPYRIGHT_BY_ALKACON; for (int i = copy.length - 1; i >= 0; i--) { System.out.println(copy[i]); } System.out.println("This is OpenCms " + OpenCms.getSystemInfo().getVersionNumber()); System.out.println(); System.out.println(); } /** * Sorts the modules for display.<p> * * @param modules the list of {@link CmsModule} objects * * @return a sorted list of module names */ public List<String> sortModules(Collection<CmsModule> modules) { List<CmsModule> aux = new ArrayList<CmsModule>(modules); Collections.sort(aux, new Comparator<CmsModule>() { public int compare(CmsModule module1, CmsModule module2) { return getDisplayForModule(module1).compareTo(getDisplayForModule(module2)); } }); List<String> ret = new ArrayList<String>(aux.size()); for (Iterator<CmsModule> it = aux.iterator(); it.hasNext();) { CmsModule module = it.next(); ret.add(module.getName()); } return ret; } /** * Checks the jdbc driver.<p> * * @return <code>true</code> if at least one of the recommended drivers is found */ public boolean validateJdbc() { boolean result = false; // There is not defined libraries for supported databases from OpenJPA if (m_driverType == DRIVER_TYPE_JPA) { return true; } String libFolder = getLibFolder(); Iterator<String> it = getDatabaseLibs(getDatabase()).iterator(); while (it.hasNext()) { String libName = it.next(); File libFile = new File(libFolder, libName); if (libFile.exists()) { result = true; } } return result; } /** * Reads all components from the given location, a folder or a zip file.<p> * * @param fileName the location to read the components from * * @throws CmsConfigurationException if something goes wrong */ protected void addComponentsFromPath(String fileName) throws CmsConfigurationException { CmsParameterConfiguration configuration; try { configuration = getComponentsProperties(fileName); } catch (FileNotFoundException e) { if (LOG.isDebugEnabled()) { LOG.debug(e.getLocalizedMessage(), e); } return; } for (String componentId : configuration.getList(PROPKEY_COMPONENTS)) { CmsSetupComponent componentBean = new CmsSetupComponent(); componentBean.setId(componentId); componentBean.setName(configuration.get(PROPKEY_COMPONENT + componentId + PROPKEY_NAME)); componentBean.setDescription(configuration.get(PROPKEY_COMPONENT + componentId + PROPKEY_DESCRIPTION)); componentBean.setModulesRegex(configuration.get(PROPKEY_COMPONENT + componentId + PROPKEY_MODULES)); componentBean.setDependencies(configuration.getList(PROPKEY_COMPONENT + componentId + PROPKEY_DEPENDENCIES)); componentBean.setPosition(configuration.getInteger( PROPKEY_COMPONENT + componentId + PROPKEY_POSITION, DEFAULT_POSITION)); componentBean.setChecked(configuration.getBoolean(PROPKEY_COMPONENT + componentId + PROPKEY_CHECKED, false)); m_components.addIdentifiableObject(componentBean.getId(), componentBean, componentBean.getPosition()); } } /** * Reads all properties from the components.properties file at the given location, a folder or a zip file.<p> * * @param location the location to read the properties from * * @return the read properties * * @throws FileNotFoundException if the properties file could not be found * @throws CmsConfigurationException if the something else goes wrong */ protected CmsParameterConfiguration getComponentsProperties(String location) throws FileNotFoundException, CmsConfigurationException { InputStream stream = null; ZipFile zipFile = null; try { // try to interpret the fileName as a folder File folder = new File(location); // if it is a file it must be a zip-file if (folder.isFile()) { zipFile = new ZipFile(location); ZipEntry entry = zipFile.getEntry(COMPONENTS_PROPERTIES); // path to file might be relative, too if ((entry == null) && location.startsWith("/")) { entry = zipFile.getEntry(location.substring(1)); } if (entry == null) { throw new FileNotFoundException(org.opencms.importexport.Messages.get().getBundle().key( org.opencms.importexport.Messages.LOG_IMPORTEXPORT_FILE_NOT_FOUND_IN_ZIP_1, location + "/" + COMPONENTS_PROPERTIES)); } stream = zipFile.getInputStream(entry); } else { // it is a folder File file = new File(folder, COMPONENTS_PROPERTIES); stream = new FileInputStream(file); } return new CmsParameterConfiguration(stream); } catch (Throwable ioe) { if (stream != null) { try { stream.close(); } catch (IOException e) { if (LOG.isDebugEnabled()) { LOG.debug(e.getLocalizedMessage(), e); } } } if (zipFile != null) { try { zipFile.close(); } catch (IOException e) { if (LOG.isDebugEnabled()) { LOG.debug(e.getLocalizedMessage(), e); } } } if (ioe instanceof FileNotFoundException) { throw (FileNotFoundException)ioe; } CmsMessageContainer msg = org.opencms.importexport.Messages.get().container( org.opencms.importexport.Messages.ERR_IMPORTEXPORT_ERROR_READING_FILE_1, location + "/" + COMPONENTS_PROPERTIES); if (LOG.isErrorEnabled()) { LOG.error(msg.key(), ioe); } throw new CmsConfigurationException(msg, ioe); } } /** * Returns the value for a given key from the extended properties. * * @param key the property key * @return the string value for a given key */ protected String getExtProperty(String key) { return m_configuration.getString(key, ""); } /** * Returns html for the given component to fill the selection list.<p> * * @param component the component to generate the code for * * @return html code */ protected String htmlComponent(CmsSetupComponent component) { StringBuffer html = new StringBuffer(256); html.append("\t<tr>\n"); html.append("\t\t<td>\n"); html.append("\t\t\t<input type='checkbox' name='availableComponents' value='"); html.append(component.getId()); html.append("'"); if (component.isChecked()) { html.append(" checked='checked'"); } html.append(" onClick=\"checkComponentDependencies('"); html.append(component.getId()); html.append("');\">\n"); html.append("\t\t</td>\n"); html.append("\t\t<td style='width: 100%; '>\n\t\t\t"); html.append(component.getName()); html.append("\n\t\t</td>\n"); html.append("\t</tr>\n"); html.append("\t<tr>\n"); html.append("\t\t<td> </td>\n"); html.append("\t\t<td style='vertical-align: top; width: 100%; padding-bottom: 8px; font-style: italic;'>\n\t\t\t"); html.append(component.getDescription()); html.append("\n\t\t</td>\n"); html.append("\t</tr>\n"); return html.toString(); } /** * Returns html for the given module to fill the selection list.<p> * * @param module the module to generate the code for * @param pos the position in the list * * @return html code */ protected String htmlModule(CmsModule module, int pos) { StringBuffer html = new StringBuffer(256); html.append("\t<tr>\n"); html.append("\t\t<td style='vertical-align: top;'>\n"); html.append("\t\t\t<input type='checkbox' name='availableModules' value='"); html.append(module.getName()); html.append("' checked='checked' onClick=\"checkModuleDependencies('"); html.append(module.getName()); html.append("');\">\n"); html.append("\t\t</td>\n"); html.append("\t\t<td style='vertical-align: top; width: 100%; padding-top: 4px;'>\n\t\t\t"); html.append(getDisplayForModule(module)); html.append("\n\t\t</td>\n"); html.append("\t\t<td style='vertical-align: top; text-align: right;'>\n"); if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(module.getDescription())) { html.append("\t\t\t"); html.append(getHtmlHelpIcon("" + pos, "")); } html.append("\t\t</td>\n"); html.append("\t</tr>\n"); return html.toString(); } /** * Imports a module (zipfile) from the default module directory, * creating a temporary project for this.<p> * * @param importFile the name of the import module located in the default module directory * * @throws Exception if something goes wrong * * @see org.opencms.importexport.CmsImportExportManager#importData(CmsObject, org.opencms.report.I_CmsReport, CmsImportParameters) */ protected void importModuleFromDefault(String importFile) throws Exception { String fileName = getModuleFolder() + importFile; OpenCms.getImportExportManager().importData( m_cms, new CmsShellReport(m_cms.getRequestContext().getLocale()), new CmsImportParameters(fileName, "/", true)); } /** * Initializes and validates the read components.<p> * * @param modules a modifiable list of the modules to be imported */ protected void initializeComponents(Collection<String> modules) { Iterator<CmsSetupComponent> itGroups = new ArrayList<CmsSetupComponent>( CmsCollectionsGenericWrapper.<CmsSetupComponent> list(m_components.elementList())).iterator(); while (itGroups.hasNext()) { CmsSetupComponent component = itGroups.next(); String errMsg = ""; String warnMsg = ""; // check name if (CmsStringUtil.isEmptyOrWhitespaceOnly(component.getName())) { errMsg += Messages.get().container(Messages.ERR_COMPONENT_NAME_EMPTY_1, component.getId()).key(); errMsg += "\n"; } // check description if (CmsStringUtil.isEmptyOrWhitespaceOnly(component.getName())) { warnMsg += Messages.get().container(Messages.LOG_WARN_COMPONENT_DESC_EMPTY_1, component.getId()).key(); warnMsg += "\n"; } // check position if (component.getPosition() == DEFAULT_POSITION) { warnMsg += Messages.get().container(Messages.LOG_WARN_COMPONENT_POS_EMPTY_1, component.getId()).key(); warnMsg += "\n"; } // check dependencies Iterator<String> itDeps = component.getDependencies().iterator(); while (itDeps.hasNext()) { String dependency = itDeps.next(); if (m_components.getObject(dependency) == null) { errMsg += Messages.get().container( Messages.LOG_WARN_COMPONENT_DEPENDENCY_BROKEN_2, component.getId(), dependency).key(); errMsg += "\n"; } } // check modules match boolean match = false; Iterator<String> itModules = modules.iterator(); while (itModules.hasNext()) { String module = itModules.next(); if (component.match(module)) { match = true; itModules.remove(); } } if (!match) { errMsg += Messages.get().container(Messages.ERR_COMPONENT_MODULES_EMPTY_1, component.getId()).key(); errMsg += "\n"; } if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(errMsg)) { m_components.removeObject(component.getId()); if (LOG.isErrorEnabled()) { LOG.error(errMsg); } } if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(warnMsg)) { if (LOG.isWarnEnabled()) { LOG.warn(warnMsg); } } } if (!modules.isEmpty()) { if (LOG.isWarnEnabled()) { LOG.warn(Messages.get().container(Messages.LOG_WARN_MODULES_LEFT_1, modules.toString())); } } } /** * Stores the properties of all available database configurations in a * map keyed by their database key names (e.g. "mysql", "generic" or "oracle").<p> */ protected void readDatabaseConfig() { m_databaseKeys = new ArrayList<String>(); m_databaseProperties = new HashMap<String, Properties>(); FileInputStream input = null; File childResource = null; List<String> databaseKeys = new ArrayList<String>(); Map<String, Properties> databaseProperties = new HashMap<String, Properties>(); try { File databaseSetupFolder = new File(m_webAppRfsPath + FOLDER_SETUP + FOLDER_DATABASE); File[] childResources = databaseSetupFolder.listFiles(); // collect all possible db configurations if (childResources != null) { for (int i = 0; i < childResources.length; i++) { childResource = childResources[i]; if (childResource.exists() && childResource.isDirectory() && childResource.canRead()) { databaseKeys.add(childResource.getName().trim()); } } } // create the properties with all possible configurations if (databaseSetupFolder.exists()) { for (String key : databaseKeys) { String configPath = m_webAppRfsPath + "setup" + File.separatorChar + "database" + File.separatorChar + key + File.separatorChar + "database.properties"; try { input = new FileInputStream(new File(configPath)); Properties databaseProps = new Properties(); databaseProps.load(input); databaseProperties.put(key, databaseProps); } catch (Exception e) { System.err.println(e.toString()); e.printStackTrace(System.err); continue; } } } // add the properties and the keys to the memeber variables if all needed files exist if (childResources != null) { for (int i = 0; i < childResources.length; i++) { childResource = childResources[i]; if (childResource.exists() && childResource.isDirectory() && childResource.canRead()) { String dataBasekey = childResource.getName().trim(); Properties props = databaseProperties.get(dataBasekey); boolean supportsJPA = Boolean.valueOf( props.getProperty(dataBasekey + "." + PROPKEY_JPA_SUPPORTED)).booleanValue(); boolean supportsSQL = Boolean.valueOf( props.getProperty(dataBasekey + "." + PROPKEY_SQL_SUPPORTED)).booleanValue(); boolean isAS400orDB2 = dataBasekey.equalsIgnoreCase(AS400_PROVIDER) || dataBasekey.equalsIgnoreCase(DB2_PROVIDER); if (isAS400orDB2) { if (checkFilesExists(REQUIRED_DB2_DB_SETUP_FILES, childResource)) { m_databaseKeys.add(childResource.getName().trim()); m_databaseProperties.put(dataBasekey, props); } } else if (supportsSQL) { if (checkFilesExists(REQUIRED_SQL_DB_SETUP_FILES, childResource)) { m_databaseKeys.add(childResource.getName().trim()); m_databaseProperties.put(dataBasekey, props); } } else if (supportsJPA && !supportsSQL) { if (checkFilesExists(REQUIRED_JPA_DB_SETUP_FILES, childResource)) { m_databaseKeys.add(childResource.getName().trim()); m_databaseProperties.put(dataBasekey, props); } } } } } } catch (Exception e) { System.err.println(e.toString()); e.printStackTrace(System.err); } finally { try { if (input != null) { input.close(); } } catch (Exception e) { // noop } } } /** * This method sets the value for a given key in the extended properties. * * @param key The key of the property * @param value The value of the property */ protected void setExtProperty(String key, String value) { m_configuration.put(key, value); } /** * Checks if the necessary files for the configuration are existent or not.<p> * * @param requiredFiles the required files * @param childResource the folder to check * * @return true if the files are existent */ private boolean checkFilesExists(String[] requiredFiles, File childResource) { File setupFile = null; boolean hasMissingSetupFiles = false; for (int j = 0; j < requiredFiles.length; j++) { setupFile = new File(childResource.getPath() + File.separatorChar + requiredFiles[j]); if (!setupFile.exists() || !setupFile.isFile() || !setupFile.canRead()) { hasMissingSetupFiles = true; System.err.println("[" + getClass().getName() + "] missing or unreadable database setup file: " + setupFile.getPath()); break; } if (!hasMissingSetupFiles) { return true; } } return false; } /** * Creates an string out of the given array to store back in the property file.<p> * * @param values the array with the values to create a string from * * @return a string with the values of the array which is ready to store in the property file */ private String createValueString(String[] values) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < values.length; i++) { // escape commas and equals in value values[i] = CmsStringUtil.substitute(values[i], ",", "\\,"); values[i] = CmsStringUtil.substitute(values[i], "=", "\\="); buf.append("\t" + values[i] + ((i < (values.length - 1)) ? ",\\\n" : "")); } return buf.toString(); } /** * Returns a list of matching modules for the given component.<p> * * @param component the component to get the modules for * * @return a list of matching module names */ private List<String> getComponentModules(CmsSetupComponent component) { List<String> modules = new ArrayList<String>(); Iterator<String> itModules = m_availableModules.keySet().iterator(); while (itModules.hasNext()) { String moduleName = itModules.next(); if (component.match(moduleName)) { modules.add(moduleName); } } return modules; } /** * Returns the text which should be written to the configuration file for a given property value.<p> * * @param obj the property value * * @return the text to write for that property value */ private String getPropertyValueToWrite(Object obj) { String value; String valueToWrite = null; if (obj instanceof List<?>) { String[] values = {}; values = CmsCollectionsGenericWrapper.list(obj).toArray(values); // write it valueToWrite = "\\\n" + createValueString(values); } else { value = String.valueOf(obj).trim(); // escape commas and equals in value value = CmsStringUtil.substitute(value, ",", "\\,"); // value = CmsStringUtil.substitute(value, "=", "\\="); // write it valueToWrite = value; } return valueToWrite; } /** * Saves the properties to a file.<p> * * @param properties the properties to be saved * @param source the source file to get the keys from * @param target the target file to save the properties to * @param forceWrite the keys of the properties which should always be written, even if they don't exist in the configuration file */ private void save(CmsParameterConfiguration properties, String source, String target, Set<String> forceWrite) { try { Set<String> alreadyWritten = new HashSet<String>(); LineNumberReader lnr = new LineNumberReader(new FileReader(new File(m_configRfsPath + source))); FileWriter fw = new FileWriter(new File(m_configRfsPath + target)); while (true) { String line = lnr.readLine(); if (line == null) { break; } line = line.trim(); if ("".equals(line)) { // output empty line fw.write("\n"); } else if (line.startsWith("#")) { // output comment fw.write(line); fw.write("\n"); } else { int index = line.indexOf('='); int index1 = line.indexOf("\\="); if ((line.indexOf('=') > -1) && (index1 != (index - 1))) { String key = line.substring(0, line.indexOf('=')).trim(); if (alreadyWritten.contains(key)) { continue; } // write key fw.write((key + "=")); try { Object obj = properties.getObject(key); if (obj != null) { String valueToWrite = getPropertyValueToWrite(obj); fw.write(valueToWrite); } } catch (NullPointerException e) { // no value found - do nothing } // add trailing line feed fw.write("\n"); // remember that this properties is already written (multi values) alreadyWritten.add(key); } } } if (forceWrite != null) { for (String forced : forceWrite) { if (!alreadyWritten.contains(forced) && properties.containsKey(forced)) { fw.write("\n\n"); fw.write(forced + "="); try { Object obj = properties.getObject(forced); if (obj != null) { String valueToWrite = getPropertyValueToWrite(obj); fw.write(valueToWrite); } } catch (NullPointerException e) { // no value found - do nothing } fw.write("\n"); } } } lnr.close(); fw.close(); } catch (Exception e) { m_errors.add("Could not save properties to " + target + " \n"); m_errors.add(e.toString() + "\n"); } } /** * @param dbProperty */ private void setEntityManagerPoolSize(String poolSize) { setExtProperty( CmsDbPool.KEY_DATABASE_POOL + '.' + getPool() + '.' + CmsDbPool.KEY_ENTITY_MANAGER_POOL_SIZE, poolSize); } /** * Lock/unlock schema generation in persistence xml file.<p> * * @param generate - true schema generation is on. */ private void setSchemaGeneration(boolean generate) { if (generate) { m_peristenceConfigurator.setPropertyValue( CmsPersistenceUnitConfiguration.ATTR_GENERATE_SCHEMA, CmsPersistenceUnitConfiguration.ATTR_GENERATE_SCHEMA_VALUE); } else { m_peristenceConfigurator.removeProperty(CmsPersistenceUnitConfiguration.ATTR_GENERATE_SCHEMA); } } /** * Sets the path to the OpenCms home directory.<p> * * @param webInfRfsPath path to OpenCms home directory */ private void setWebAppRfsPath(String webInfRfsPath) { m_webAppRfsPath = webInfRfsPath; if ("".equals(webInfRfsPath)) { // required for test cases m_configRfsPath = ""; return; } if (!m_webAppRfsPath.endsWith(File.separator)) { // make sure that Path always ends with a separator, not always the case in different // environments since getServletContext().getRealPath("/") does not end with a "/" in // all servlet runtimes m_webAppRfsPath += File.separator; } if (CmsStringUtil.isNotEmpty(System.getProperty(CmsSystemInfo.CONFIG_FOLDER_PROPERTY))) { m_configRfsPath = System.getProperty(CmsSystemInfo.CONFIG_FOLDER_PROPERTY); } else { m_configRfsPath = m_webAppRfsPath + CmsSystemInfo.FOLDER_WEBINF + CmsSystemInfo.FOLDER_CONFIG_DEFAULT; } } }