/* * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.statuspanel; import java.io.IOException; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.opends.server.core.DirectoryServer; import org.opends.server.util.LDIFException; import org.opends.server.util.LDIFReader; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeValue; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.ObjectClass; import org.opends.statuspanel.i18n.ResourceProvider; import org.opends.quicksetup.util.Utils; import org.opends.quicksetup.Installation; /** * This class is used to retrieve configuration information directly from the * config.ldif file. * */ public class ConfigFromFile { private final ObjectClass connectionHandlerOc = DirectoryServer.getObjectClass("ds-cfg-connection-handler", true); private final ObjectClass ldapConnectionHandlerOc = DirectoryServer.getObjectClass("ds-cfg-ldap-connection-handler", true); private final ObjectClass jmxConnectionHandlerOc = DirectoryServer.getObjectClass("ds-cfg-jmx-connection-handler", true); private final ObjectClass backendOc = DirectoryServer.getObjectClass("ds-cfg-backend", true); private final ObjectClass administrativeUserOc = DirectoryServer.getObjectClass("ds-cfg-root-dn", true); private final ObjectClass syncProviderOc = DirectoryServer.getObjectClass("ds-cfg-synchronization-provider", true); private final ObjectClass replicationConfigOc = DirectoryServer.getObjectClass("ds-cfg-replication-domain-config", true); private DN replicationDomainDN; private HashSet listeners = new HashSet(); private HashSet databases = new HashSet(); private HashSet administrativeUsers = new HashSet(); private String errorMessage; private boolean replicationConfigured = false; private HashSet replicatedSuffixes = new HashSet(); /** * Default constructor. * */ public ConfigFromFile() { } /** * Reads the configuration from the config.ldif file. When calling this * method the thread is blocked until all the configuration is read. * */ public void readConfiguration() { errorMessage = null; listeners.clear(); databases.clear(); administrativeUsers.clear(); replicationConfigured = false; replicatedSuffixes.clear(); try { Installation installation = new Installation(Utils.getInstallPathFromClasspath()); LDIFImportConfig c = new LDIFImportConfig( Utils.getPath(installation.getCurrentConfigurationFile())); LDIFReader reader = new LDIFReader(c); for (Entry entry = reader.readEntry(false); entry != null; entry = reader.readEntry(false)) { updateConfig(entry); } updateReplication(); } catch (IOException ioe) { errorMessage = Utils.getThrowableMsg(getI18n(), "error-reading-config-file", null, ioe); } catch (LDIFException le) { errorMessage = Utils.getThrowableMsg(getI18n(), "error-reading-config-file", null, le); } catch (Throwable t) { // Bug t.printStackTrace(); errorMessage = Utils.getThrowableMsg(getI18n(), "error-reading-config-file", null, t); } } /** * Returns the Administrative User DNs found in the config.ldif. * @return the Administrative User DNs found in the config.ldif. */ public HashSet getAdministrativeUsers() { return administrativeUsers; } /** * Returns the database descriptors found in the config.ldif. * @return the database descriptors found in the config.ldif. */ public HashSet getDatabases() { return databases; } /** * Returns the listener descriptors found in the config.ldif. * @return the listeners descriptors found in the config.ldif. */ public HashSet getListeners() { return listeners; } /** * Returns the error message that we got when retrieving the information * from the config.ldif file. * @return the error message that we got when retrieving the information * from the config.ldif file. */ public String getErrorMessage() { return errorMessage; } /** * Returns the ldap URL that we can use to connect to the server based in * what we found in the config.ldif file. * @return the ldap URL that we can use to connect to the server based in * what we found in the config.ldif file. */ public String getLDAPURL() { String url = null; for (ListenerDescriptor desc : getListeners()) { if (desc.getState() == ListenerDescriptor.State.ENABLED) { int port = -1; try { String addressPort = desc.getAddressPort(); int index = addressPort.indexOf(":"); if (index != -1) { port = Integer.parseInt(addressPort.substring(index+1)); } else { port = Integer.parseInt(addressPort); } } catch (Exception ex) { // Could not get the port } if (port != -1) { if (desc.getProtocol() == ListenerDescriptor.Protocol.LDAP) { url = "ldap://localhost:"+port; /* We prefer to test using the LDAP port: do not continue * searching */ break; } else if (desc.getProtocol() == ListenerDescriptor.Protocol.LDAPS) { url = "ldaps://localhost:"+port; } } } } return url; } /** * An convenience method to know if the provided ID corresponds to a * configuration backend or not. * @param id the backend ID to analyze * @return true if the the id corresponds to a configuration * backend and false otherwise. */ static boolean isConfigBackend(String id) { return "tasks".equalsIgnoreCase(id) || "schema".equalsIgnoreCase(id) || "config".equalsIgnoreCase(id) || "monitor".equalsIgnoreCase(id) || "backup".equalsIgnoreCase(id); } /** * Updates the configuration data we expose to the user with the provided * entry object. * @param entry the entry to analyze. */ private void updateConfig(Entry entry) { if (entry.hasObjectClass(connectionHandlerOc)) { updateConfigWithConnectionHandler(entry); } else if (entry.hasObjectClass(backendOc)) { updateConfigWithBackend(entry); } else if (entry.hasObjectClass(administrativeUserOc)) { updateConfigWithAdministrativeUser(entry); } else if (entry.hasObjectClass(syncProviderOc)) { updateConfigWithSyncProviderEntry(entry); } else if (entry.hasObjectClass(replicationConfigOc)) { updateConfigWithReplConfig(entry); } } /** * Updates the listener configuration data we expose to the user with the * provided entry object. * @param entry the entry to analyze. */ private void updateConfigWithConnectionHandler(Entry entry) { String address = getFirstValue(entry, "ds-cfg-listen-address"); String port = getFirstValue(entry, "ds-cfg-listen-port"); String addressPort; boolean isSecure = "true".equalsIgnoreCase( getFirstValue(entry, "ds-cfg-use-ssl")); ListenerDescriptor.Protocol protocol; String protocolDescription; ListenerDescriptor.State state; if (entry.hasObjectClass(ldapConnectionHandlerOc)) { addressPort = address+":"+port; if (isSecure) { protocolDescription = getMsg("ldaps-protocol-label"); protocol = ListenerDescriptor.Protocol.LDAPS; } else { protocolDescription = getMsg("ldap-protocol-label"); protocol = ListenerDescriptor.Protocol.LDAP; } boolean enabled = "true".equalsIgnoreCase( getFirstValue(entry, "ds-cfg-connection-handler-enabled")); if (enabled) { state = ListenerDescriptor.State.ENABLED; } else { state = ListenerDescriptor.State.DISABLED; } } else if (entry.hasObjectClass(jmxConnectionHandlerOc)) { addressPort = "0.0.0.0:"+port; if (isSecure) { protocolDescription = getMsg("jmx-secure-protocol-label"); protocol = ListenerDescriptor.Protocol.JMXS; } else { protocolDescription = getMsg("jmx-protocol-label"); protocol = ListenerDescriptor.Protocol.JMX; } boolean enabled = "true".equalsIgnoreCase( getFirstValue(entry, "ds-cfg-connection-handler-enabled")); if (enabled) { state = ListenerDescriptor.State.ENABLED; } else { state = ListenerDescriptor.State.DISABLED; } } else { addressPort = getMsg("unknown-label"); protocolDescription = null; protocol = ListenerDescriptor.Protocol.OTHER; /* Try to figure a name from the cn */ String cn = getFirstValue(entry, "cn"); if (cn != null) { int index = cn.toLowerCase().indexOf("connection handler"); if (index > 0) { protocolDescription = cn.substring(0, index).trim(); } else { protocolDescription = cn; } } else { protocolDescription = getMsg("undefined-protocol-label"); } state = ListenerDescriptor.State.UNKNOWN; } listeners.add(new ListenerDescriptor(addressPort, protocol, protocolDescription, state)); } /** * Updates the database configuration data we expose to the user with the * provided entry object. * @param entry the entry to analyze. */ private void updateConfigWithBackend(Entry entry) { String id = getFirstValue(entry, "ds-cfg-backend-id"); int nEntries = -1; // Unknown if (!isConfigBackend(id)) { Set baseDns = new TreeSet(); baseDns.addAll(getValues(entry, "ds-cfg-backend-base-dn")); Set replicas = new LinkedHashSet(); for (String baseDn : baseDns) { replicas.add(getBaseDNDescriptor(entry, baseDn)); } DatabaseDescriptor db = new DatabaseDescriptor(id, replicas, nEntries); databases.add(db); for (BaseDNDescriptor rep: replicas) { rep.setDatabase(db); } } } /** * Updates the administrative user configuration data we expose to the user * with the provided entry object. * @param entry the entry to analyze. */ private void updateConfigWithAdministrativeUser(Entry entry) { administrativeUsers.addAll(getValues(entry, "ds-cfg-alternate-bind-dn")); } /** * Updates the replication configuration data we expose to the user with * the provided entry object. * @param entry the entry to analyze. */ private void updateConfigWithSyncProviderEntry(Entry entry) { if ("true".equalsIgnoreCase(getFirstValue(entry, "ds-cfg-synchronization-provider-enabled"))) { replicationConfigured = true; } else { replicationConfigured = false; } } /** * Updates the databases suffixes with the list of replicated suffixes * found. */ private void updateReplication() { if (replicationConfigured) { for (String suffixDn: replicatedSuffixes) { BaseDNDescriptor replica = null; for (DatabaseDescriptor db: databases) { Set replicas = db.getBaseDns(); for (BaseDNDescriptor rep: replicas) { if (Utils.areDnsEqual(rep.getDn(), suffixDn)) { replica = rep; break; } } if (replica != null) { break; } } if (replica != null) { replica.setType(BaseDNDescriptor.Type.REPLICATED); } } } } /** * Updates the replication configuration data we expose to the user with * the provided entry object. * @param entry the entry to analyze. */ private void updateConfigWithReplConfig(Entry entry) { if (replicationDomainDN == null) { try { replicationDomainDN = DN.decode( "cn=domains,cn=Multimaster Synchronization,"+ "cn=Synchronization Providers,cn=config"); } catch (Throwable t) { // Bug throw new IllegalStateException("Bug: "+t, t); } } if (entry.getDN().isDescendantOf(replicationDomainDN)) { replicatedSuffixes.addAll(getValues(entry, "ds-cfg-replication-dn")); } } /** * The following three methods are just commodity methods to get localized * messages. */ private String getMsg(String key) { return getI18n().getMsg(key); } private ResourceProvider getI18n() { return ResourceProvider.getInstance(); } /* * The following 2 methods are convenience methods to retrieve String values * from an entry. */ private Set getValues(Entry entry, String attrName) { Set values = new HashSet(); List attrs = entry.getAttribute(attrName); if ((attrs != null) && attrs.size() > 0) { Attribute attr = attrs.iterator().next(); LinkedHashSet vs = attr.getValues(); if ((vs != null) && (vs.size() > 0)) { for (AttributeValue v : vs) { values.add(v.getStringValue()); } } } return values; } private String getFirstValue(Entry entry, String attrName) { String v = null; Set values = getValues(entry, attrName); if (values.size() > 0) { v = values.iterator().next(); } return v; } /** * Create a non replicated base DN descriptor. */ private BaseDNDescriptor getBaseDNDescriptor(Entry entry, String baseDn) { return new BaseDNDescriptor(BaseDNDescriptor.Type.NOT_REPLICATED, baseDn, null, -1, -1); } }