001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2008 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2016 ForgeRock AS. 016 */ 017package org.opends.server.tools; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.forgerock.i18n.slf4j.LocalizedLogger; 023import org.forgerock.opendj.adapter.server3x.Converters; 024import org.forgerock.opendj.ldap.ByteString; 025import org.forgerock.opendj.ldap.DN; 026import org.forgerock.opendj.server.config.server.BackendCfg; 027import org.forgerock.opendj.server.config.server.RootCfg; 028import org.opends.server.api.Backend; 029import org.opends.server.config.ConfigurationHandler; 030import org.opends.server.core.DirectoryServer; 031import org.opends.server.types.Attribute; 032import org.opends.server.types.Entry; 033 034import static org.opends.messages.ToolMessages.*; 035import static org.opends.server.config.ConfigConstants.*; 036import static org.opends.server.util.StaticUtils.*; 037 038/** This class provides utility functions for all backend client tools. */ 039public class BackendToolUtils 040{ 041 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 042 043 private static final int ERROR = 1; 044 private static final int SUCCESS = 0; 045 046 /** 047 * Retrieves information about the backends defined in the Directory Server 048 * configuration. 049 * 050 * @param backendList 051 * A list into which instantiated (but not initialized) backend 052 * instances will be placed. 053 * @param entryList 054 * A list into which the config entries associated with the backends 055 * will be placed. 056 * @param dnList 057 * A list into which the set of base DNs for each backend will be 058 * placed. 059 * @return 0 if everything went fine. 1 if an error occurred. 060 */ 061 @SuppressWarnings({ "unchecked", "rawtypes" }) 062 public static int getBackends(final List<Backend<?>> backendList, final List<BackendCfg> entryList, 063 final List<List<DN>> dnList) 064 { 065 try 066 { 067 // Iterate through the immediate children, attempting to parse them as backends. 068 final RootCfg root = DirectoryServer.getInstance().getServerContext().getRootConfig(); 069 ConfigurationHandler configHandler = DirectoryServer.getConfigurationHandler(); 070 final DN backendBaseDN = getBackendBaseDN(); 071 for (final DN childrenDn : configHandler.getChildren(backendBaseDN)) 072 { 073 Entry configEntry = Converters.to(configHandler.getEntry(childrenDn)); 074 final String backendID = getBackendID(configEntry); 075 final String backendClassName = getBackendClassName(configEntry); 076 if (backendID == null || backendClassName == null) 077 { 078 continue; 079 } 080 081 final Class<?> backendClass = getBackendClass(backendClassName, configEntry); 082 final Backend backend; 083 final BackendCfg cfg; 084 try 085 { 086 backend = (Backend) backendClass.newInstance(); 087 backend.setBackendID(backendID); 088 cfg = root.getBackend(backendID); 089 backend.configureBackend(cfg, DirectoryServer.getInstance().getServerContext()); 090 } 091 catch (final Exception e) 092 { 093 logger.error( 094 ERR_CANNOT_INSTANTIATE_BACKEND_CLASS, backendClassName, configEntry.getName(), getExceptionMessage(e)); 095 return ERROR; 096 } 097 098 backendList.add(backend); 099 entryList.add(cfg); 100 dnList.add(getBaseDNsForEntry(configEntry)); 101 } 102 103 return SUCCESS; 104 } 105 catch (final Exception e) 106 { 107 // Error message has already been logged. 108 return ERROR; 109 } 110 } 111 112 /** 113 * Returns a string from the single valued attribute in provided entry. 114 * 115 * @param entry the entry 116 * @param attrName the attribute name 117 * @return the string value if available or {@code null} 118 */ 119 public static String getStringSingleValuedAttribute(Entry entry, String attrName) 120 { 121 List<Attribute> attributes = entry.getAttribute(attrName); 122 if (!attributes.isEmpty()) 123 { 124 Attribute attribute = attributes.get(0); 125 for (ByteString byteString : attribute) 126 { 127 return byteString.toString(); 128 } 129 } 130 return null; 131 } 132 133 private static List<DN> getBaseDNsForEntry(final Entry configEntry) throws Exception 134 { 135 try 136 { 137 List<Attribute> attributes = configEntry.getAttribute(ATTR_BACKEND_BASE_DN); 138 if (!attributes.isEmpty()) 139 { 140 Attribute attribute = attributes.get(0); 141 List<DN> dns = new ArrayList<>(); 142 for (ByteString byteString : attribute) 143 { 144 dns.add(DN.valueOf(byteString.toString())); 145 } 146 return dns; 147 } 148 logger.error(ERR_NO_BASES_FOR_BACKEND, configEntry.getName()); 149 return null; 150 } 151 catch (final Exception e) 152 { 153 logger.error(ERR_CANNOT_DETERMINE_BASES_FOR_BACKEND, configEntry.getName(), getExceptionMessage(e)); 154 throw e; 155 } 156 } 157 158 private static Class<?> getBackendClass(String backendClassName, Entry configEntry) throws Exception 159 { 160 try 161 { 162 return Class.forName(backendClassName); 163 } 164 catch (final Exception e) 165 { 166 logger.error(ERR_CANNOT_LOAD_BACKEND_CLASS, backendClassName, configEntry.getName(), getExceptionMessage(e)); 167 throw e; 168 } 169 } 170 171 private static String getBackendClassName(final Entry configEntry) throws Exception 172 { 173 try 174 { 175 return getStringSingleValuedAttribute(configEntry, ATTR_BACKEND_CLASS); 176 } 177 catch (final Exception e) 178 { 179 logger.error(ERR_CANNOT_DETERMINE_BACKEND_CLASS, configEntry.getName(), getExceptionMessage(e)); 180 throw e; 181 } 182 } 183 184 private static String getBackendID(final Entry configEntry) throws Exception 185 { 186 try 187 { 188 return getStringSingleValuedAttribute(configEntry, ATTR_BACKEND_ID); 189 } 190 catch (final Exception e) 191 { 192 logger.error(ERR_CANNOT_DETERMINE_BACKEND_ID, configEntry.getName(), getExceptionMessage(e)); 193 throw e; 194 } 195 } 196 197 private static DN getBackendBaseDN() throws Exception 198 { 199 try 200 { 201 return DN.valueOf(DN_BACKEND_BASE); 202 } 203 catch (final Exception e) 204 { 205 logger.error(ERR_CANNOT_DECODE_BACKEND_BASE_DN, DN_BACKEND_BASE, getExceptionMessage(e)); 206 throw e; 207 } 208 } 209}