/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2006-2010 Sun Microsystems, Inc. * Portions Copyright 2013-2015 ForgeRock AS. */ package org.opends.quicksetup; import org.opends.quicksetup.util.Utils; import java.io.File; import java.io.FileReader; import java.io.BufferedReader; import java.io.IOException; import java.util.Set; import java.util.HashSet; /** * Represents the contents of an OpenDS configuration file. */ public class Configuration { private String contents; private String lowerCaseContents; private Installation install; private File file; /** * Create a Configuration from a file. * @param install of which this configuration is part * @param file config.ldif file */ public Configuration(Installation install, File file) { if (install == null) { throw new NullPointerException("config file cannot be null"); } if (file == null) { throw new NullPointerException("config file cannot be null"); } else if ( // Leave open the possibility that the file might be // config.ldif. !file.getName().startsWith("config.ldif")) { throw new IllegalArgumentException("file must be a config.ldif file"); } this.install = install; this.file = file; } /** * Returns the list of directory manager dns as they appear in the * configuration file. * * @return the list of directory manager dns as they appear in the * configuration file. * @throws IOException if there were problems reading the information from * the configuration file. */ public Set getDirectoryManagerDns() throws IOException { return getConfigurationValues("ds-cfg-alternate-bind-dn"); } /** * Provides the LDAP port as is specified in the config.ldif file. * * @return the LDAP port specified in the config.ldif file. * @throws IOException if there were problems reading the information from * the configuration file. */ public int getPort() throws IOException { return getLDAPPort("ds-cfg-listen-port"); } /** * Provides the administration port as is specified in the config.ldif file. * * @return the administration port specified in the config.ldif file. * @throws IOException if there were problems reading the information from * the configuration file. */ public int getAdminConnectorPort() throws IOException { return getAdminConnectorPort("ds-cfg-listen-port"); } /** * Tells whether this server is configured as a replication server or not. * @return true if the server is configured as a Replication * Server and false otherwise. * @throws IOException if there were problems reading the information from * the configuration file. */ public boolean isReplicationServer() throws IOException { return getReplicationPort() != -1; } /** * Provides the Replication port as is specified in the config.ldif file. * Returns -1 if this server is not a Replication Server. * * @return the Replication port specified in the config.ldif file. * @throws IOException if there were problems reading the information from * the configuration file. */ public int getReplicationPort() throws IOException { int port = -1; String contents = getLowerCaseContents(); int index = contents.indexOf("cn=replication server"); if (index != -1) { String attrWithPoints = "ds-cfg-replication-port:"; int index1 = contents.indexOf(attrWithPoints, index); if (index1 != -1) { int index2 = contents.indexOf(Constants.LINE_SEPARATOR, index1); if (index2 != -1) { String sPort = contents.substring(attrWithPoints.length() + index1, index2).trim(); try { port = Integer.parseInt(sPort); } catch (NumberFormatException nfe) { // do nothing; } } } } return port; } /** * Returns the list of paths where the logs files are located as they appear * in the configuration file. * * @return the list of paths where the logs files are located as they appear * in the configuration file. * @throws IOException if there were problems reading the information from * the configuration file. */ public Set getLogPaths() throws IOException { return getConfigurationValues("ds-cfg-log-file"); } private int extractPort(String portAttr, int index) { int port = -1; String attrWithPoints = portAttr + ":"; int index1 = contents.indexOf(attrWithPoints, index); if (index1 != -1) { int index2 = contents.indexOf(Constants.LINE_SEPARATOR, index1); if (index2 != -1) { String sPort = contents.substring(attrWithPoints.length() + index1, index2).trim(); try { port = Integer.parseInt(sPort); } catch (NumberFormatException nfe) { // do nothing; } } } return port; } private int getLDAPPort(String portAttr) throws IOException { String contents = getLowerCaseContents(); int index = contents.indexOf("cn=ldap connection handler"); if (index != -1) { return extractPort (portAttr, index); } return -1; } private int getAdminConnectorPort(String portAttr) throws IOException { String contents = getLowerCaseContents(); int index = contents.indexOf("cn=administration connector"); if (index != -1) { return extractPort(portAttr, index); } return -1; } /** * Indicates whether the config.ldif file has been modified (compared to what * we had in the zip file). This is used to know if we have configured the * current binaries or not. * * @return true if the config.ldif file has been modified, or * false if not. * @throws IOException if there were problems reading the information from * the configuration file. */ public boolean hasBeenModified() throws IOException { boolean isConfigFileModified = getPort() != 389; if (!isConfigFileModified) { // TODO: this is not really stable // Note: a better way might be to diff this file with // /config/ldif/upgrade/config.ldif. isConfigFileModified = !getLowerCaseContents().contains("# cddl header start"); } return isConfigFileModified; } /** * Returns a Set of relative paths containing the log paths outside the * installation. * @return a Set of relative paths containing the log paths outside the * installation. * @throws IOException if there is trouble reading the config file */ public Set getOutsideLogs() throws IOException { return getOutsidePaths(getLogPaths()); } /** * Returns a Set of relative paths containing the db paths outside the * installation. * @return a Set of relative paths containing the db paths outside the * installation. * @throws IOException if there is trouble reading the config file */ public Set getOutsideDbs() throws IOException { return getOutsidePaths(getDatabasePaths()); } private Set getOutsidePaths(Set paths) { Set outsidePaths = new HashSet<>(); for (String path : paths) { File fullDbPath; File pathFile = new File(path); if (pathFile.isAbsolute()) { fullDbPath = pathFile; } else { fullDbPath = new File(install.getInstanceDirectory(), path); } if (!Utils.isDescendant(fullDbPath, install.getInstanceDirectory())) { outsidePaths.add(Utils.getPath(fullDbPath)); } } return outsidePaths; } /** * Provides the contents of the config.ldif file in a String. * * @return a String representing the contents of the config.ldif file. * @throws IOException if there was a problem reading the file */ public String getContents() throws IOException { if (contents == null) { load(); } return contents; } /** * Provides the contents of the config.ldif file in a lower case String. * * @return a lower case String representing the contents of the config.ldif * file. * @throws IOException if there was a problem reading the file */ public String getLowerCaseContents() throws IOException { if (lowerCaseContents == null) { load(); } return lowerCaseContents; } /** * Returns the list of paths where the databases are installed as they appear * in the configuration file. * * @return the list of paths where the databases are installed as they appear * in the configuration file. * @throws IOException if there is a problem reading the config file. */ public Set getDatabasePaths() throws IOException { return getConfigurationValues("ds-cfg-db-directory"); } /** * Returns the list of base dns as they appear in the configuration file. * * @return the list of base dns as they appear in the configuration file. * @throws IOException if there is a problem reading the config file. */ public Set getBaseDNs() throws IOException { return getConfigurationValues("ds-cfg-base-dn"); } /** * Loads the contents of the configuration file into memory. * @throws IOException if there were problems loading the file */ public void load() throws IOException { StringBuilder buf = new StringBuilder(); FileReader reader = new FileReader(file); BufferedReader in = new BufferedReader(reader); String line; // We do not care about encoding: we are just interested in the ports while ((line = in.readLine()) != null) { buf.append(line).append(Constants.LINE_SEPARATOR); } reader.close(); contents = buf.toString(); lowerCaseContents = contents.toLowerCase(); } private Set getConfigurationValues(String attrName) throws IOException { Set set = new HashSet<>(); attrName += ":"; String lowerCaseContents = getLowerCaseContents(); String contents = getContents(); int index1 = lowerCaseContents.indexOf(attrName); while (index1 != -1) { int index2 = lowerCaseContents.indexOf(Constants.LINE_SEPARATOR, index1); String value; if (index2 > index1 + attrName.length()) { value = contents.substring(attrName.length() + index1, index2).trim(); } else if (lowerCaseContents.length() > index1 + attrName.length()) { // Assume end of file value = contents.substring(attrName.length() + index1).trim(); } else { value = null; } if (value != null && value.length() > 0) { set.add(value); } index1 = lowerCaseContents.indexOf(attrName, index1 + attrName.length()); } return set; } }