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