001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.tasks; 028 029 import static org.opends.server.loggers.debug.DebugLogger.*; 030 import org.opends.server.loggers.debug.DebugTracer; 031 import static org.opends.server.config.ConfigConstants.*; 032 import static org.opends.server.loggers.ErrorLogger.*; 033 import static org.opends.messages.ToolMessages.*; 034 import static org.opends.messages.ConfigMessages. 035 INFO_CONFIG_BACKEND_ATTR_DESCRIPTION_BACKEND_ID; 036 import static org.opends.server.util.StaticUtils.*; 037 038 import org.opends.server.api.Backend; 039 import org.opends.server.config.ConfigEntry; 040 import org.opends.server.config.ConfigException; 041 import org.opends.server.config.StringConfigAttribute; 042 import org.opends.server.core.DirectoryServer; 043 import org.opends.server.core.ModifyOperation; 044 import org.opends.server.types.DebugLogLevel; 045 046 import org.opends.messages.TaskMessages; 047 import org.opends.messages.Message; 048 import org.opends.server.protocols.asn1.ASN1OctetString; 049 import org.opends.server.protocols.ldap.LDAPAttribute; 050 import org.opends.server.protocols.ldap.LDAPModification; 051 import org.opends.server.protocols.internal.InternalClientConnection; 052 import org.opends.server.types.Attribute; 053 import org.opends.server.types.AttributeValue; 054 import org.opends.server.types.DirectoryException; 055 import org.opends.server.types.DN; 056 import org.opends.server.types.ModificationType; 057 import org.opends.server.types.RawModification; 058 import org.opends.server.types.ResultCode; 059 import org.opends.server.admin.std.server.BackendCfg; 060 import org.opends.server.admin.std.server.RootCfg; 061 import org.opends.server.admin.server.ServerManagementContext; 062 063 import java.util.ArrayList; 064 import java.util.LinkedHashSet; 065 import java.util.List; 066 import java.util.Map; 067 import java.util.HashMap; 068 069 /** 070 * This class defines a number of static utility methods for server tasks. 071 */ 072 public class TaskUtils 073 { 074 /** 075 * The tracer object for the debug logger. 076 */ 077 private static final DebugTracer TRACER = getTracer(); 078 079 080 081 082 /** 083 * Get the backend ID of a backend configuration entry. 084 * 085 * @param configEntry A backend configuration entry. 086 * @return The backend ID. 087 */ 088 public static String getBackendID(ConfigEntry configEntry) 089 { 090 try 091 { 092 093 StringConfigAttribute idStub = 094 new StringConfigAttribute( 095 ATTR_BACKEND_ID, 096 INFO_CONFIG_BACKEND_ATTR_DESCRIPTION_BACKEND_ID.get(), 097 true, false, true); 098 StringConfigAttribute idAttr = 099 (StringConfigAttribute) configEntry.getConfigAttribute(idStub); 100 return idAttr.activeValue(); 101 } 102 catch (ConfigException ce) 103 { 104 Message message = ERR_CANNOT_DETERMINE_BACKEND_ID.get( 105 String.valueOf(configEntry.getDN()), ce.getMessage()); 106 logError(message); 107 return null; 108 } 109 catch (Exception e) 110 { 111 Message message = ERR_CANNOT_DETERMINE_BACKEND_ID.get( 112 String.valueOf(configEntry.getDN()), getExceptionMessage(e)); 113 logError(message); 114 return null; 115 } 116 } 117 118 /** 119 * Get all the backend configuration entries defined in the server mapped 120 * by their backend ID. 121 * @return A map of backend IDs to their corresponding configuration entries. 122 */ 123 public static Map<String,ConfigEntry> getBackendConfigEntries() 124 { 125 Map<String,ConfigEntry> configEntries = new HashMap<String,ConfigEntry>(); 126 127 // FIXME The error messages should not be the LDIF import messages 128 129 // Get the base entry for all backend configuration. 130 DN backendBaseDN; 131 try 132 { 133 backendBaseDN = DN.decode(DN_BACKEND_BASE); 134 } 135 catch (DirectoryException de) 136 { 137 Message message = ERR_CANNOT_DECODE_BACKEND_BASE_DN.get( 138 DN_BACKEND_BASE, de.getMessageObject()); 139 logError(message); 140 return configEntries; 141 } 142 catch (Exception e) 143 { 144 Message message = ERR_CANNOT_DECODE_BACKEND_BASE_DN.get( 145 DN_BACKEND_BASE, getExceptionMessage(e)); 146 logError(message); 147 return configEntries; 148 } 149 150 ConfigEntry baseEntry; 151 try 152 { 153 baseEntry = DirectoryServer.getConfigEntry(backendBaseDN); 154 } 155 catch (ConfigException ce) 156 { 157 Message message = ERR_CANNOT_RETRIEVE_BACKEND_BASE_ENTRY.get( 158 DN_BACKEND_BASE, ce.getMessage()); 159 logError(message); 160 return configEntries; 161 } 162 catch (Exception e) 163 { 164 Message message = ERR_CANNOT_RETRIEVE_BACKEND_BASE_ENTRY.get( 165 DN_BACKEND_BASE, getExceptionMessage(e)); 166 logError(message); 167 return configEntries; 168 } 169 170 171 // Iterate through the immediate children, attempting to parse them as 172 // backends. 173 for (ConfigEntry configEntry : baseEntry.getChildren().values()) 174 { 175 // Get the backend ID attribute from the entry. If there isn't one, then 176 // skip the entry. 177 String backendID; 178 try 179 { 180 181 StringConfigAttribute idStub = 182 new StringConfigAttribute( 183 ATTR_BACKEND_ID, 184 INFO_CONFIG_BACKEND_ATTR_DESCRIPTION_BACKEND_ID.get(), 185 true, false, true); 186 StringConfigAttribute idAttr = 187 (StringConfigAttribute) configEntry.getConfigAttribute(idStub); 188 if (idAttr == null) 189 { 190 continue; 191 } 192 else 193 { 194 backendID = idAttr.activeValue(); 195 } 196 } 197 catch (ConfigException ce) 198 { 199 Message message = ERR_CANNOT_DETERMINE_BACKEND_ID.get( 200 String.valueOf(configEntry.getDN()), ce.getMessage()); 201 logError(message); 202 continue; 203 } 204 catch (Exception e) 205 { 206 Message message = ERR_CANNOT_DETERMINE_BACKEND_ID.get( 207 String.valueOf(configEntry.getDN()), getExceptionMessage(e)); 208 logError(message); 209 continue; 210 } 211 212 configEntries.put(backendID, configEntry); 213 } 214 215 return configEntries; 216 } 217 218 /** 219 * Get the configuration entry for a given backend. 220 * 221 * @param backend The backend whose configuration entry is wanted. 222 * @return The configuration entry of the backend, or null if it could not 223 * be found. 224 */ 225 public static BackendCfg getConfigEntry(Backend backend) 226 { 227 RootCfg root = ServerManagementContext.getInstance(). 228 getRootConfiguration(); 229 try 230 { 231 return root.getBackend(backend.getBackendID()); 232 } 233 catch (ConfigException e) 234 { 235 return null; 236 } 237 } 238 239 240 241 /** 242 * Enables a backend using an internal modify operation on the 243 * backend configuration entry. 244 * 245 * @param backendID Identifies the backend to be enabled. 246 * @throws DirectoryException If the internal modify operation failed. 247 */ 248 public static void enableBackend(String backendID) 249 throws DirectoryException 250 { 251 DN configEntryDN; 252 RootCfg root = ServerManagementContext.getInstance().getRootConfiguration(); 253 try 254 { 255 BackendCfg cfg = root.getBackend(backendID); 256 configEntryDN = cfg.dn(); 257 } 258 catch (ConfigException e) 259 { 260 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 261 e.getMessageObject(), e); 262 } 263 264 ArrayList<ASN1OctetString> valueList = new ArrayList<ASN1OctetString>(1); 265 valueList.add(new ASN1OctetString("TRUE")); 266 LDAPAttribute a = new LDAPAttribute(ATTR_BACKEND_ENABLED, valueList); 267 268 LDAPModification m = new LDAPModification(ModificationType.REPLACE, a); 269 270 ArrayList<RawModification> modList = new ArrayList<RawModification>(1); 271 modList.add(m); 272 273 InternalClientConnection conn = 274 InternalClientConnection.getRootConnection(); 275 String backendDNString = configEntryDN.toString(); 276 ASN1OctetString rawEntryDN = 277 new ASN1OctetString(backendDNString); 278 ModifyOperation internalModify = conn.processModify(rawEntryDN, modList); 279 280 ResultCode resultCode = internalModify.getResultCode(); 281 if (resultCode != ResultCode.SUCCESS) 282 { 283 Message message = 284 TaskMessages.ERR_TASK_CANNOT_ENABLE_BACKEND.get(backendDNString); 285 throw new DirectoryException(resultCode, message); 286 } 287 } 288 289 290 291 /** 292 * Disables a backend using an internal modify operation on the 293 * backend configuration entry. 294 * 295 * @param backendID Identifies the backend to be disabled. 296 * @throws DirectoryException If the internal modify operation failed. 297 */ 298 public static void disableBackend(String backendID) 299 throws DirectoryException 300 { 301 DN configEntryDN; 302 RootCfg root = ServerManagementContext.getInstance().getRootConfiguration(); 303 try 304 { 305 BackendCfg cfg = root.getBackend(backendID); 306 configEntryDN = cfg.dn(); 307 } 308 catch (ConfigException e) 309 { 310 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 311 e.getMessageObject(), e); 312 } 313 314 ArrayList<ASN1OctetString> valueList = new ArrayList<ASN1OctetString>(1); 315 valueList.add(new ASN1OctetString("FALSE")); 316 LDAPAttribute a = new LDAPAttribute(ATTR_BACKEND_ENABLED, valueList); 317 318 LDAPModification m = new LDAPModification(ModificationType.REPLACE, a); 319 320 ArrayList<RawModification> modList = new ArrayList<RawModification>(1); 321 modList.add(m); 322 323 InternalClientConnection conn = 324 InternalClientConnection.getRootConnection(); 325 String backendDNString = configEntryDN.toString(); 326 ASN1OctetString rawEntryDN = 327 new ASN1OctetString(backendDNString); 328 ModifyOperation internalModify = conn.processModify(rawEntryDN, modList); 329 330 ResultCode resultCode = internalModify.getResultCode(); 331 if (resultCode != ResultCode.SUCCESS) 332 { 333 Message message = 334 TaskMessages.ERR_TASK_CANNOT_DISABLE_BACKEND.get(backendDNString); 335 throw new DirectoryException(resultCode, message); 336 } 337 } 338 339 340 341 /** 342 * Get the single boolean value of an entry attribute that is defined in the 343 * schema as a single valued boolean attribute, and that is not expected to 344 * have attribute options. 345 * 346 * @param attrList The attribute value of the entry attribute. 347 * @param defaultValue The default value to be returned if there is no 348 * recognizable boolean attribute value. 349 * @return The boolean value of the attribute, or the provided default value 350 * if there is no value. 351 */ 352 public static boolean getBoolean(List<Attribute> attrList, 353 boolean defaultValue) 354 { 355 if ((attrList == null) || attrList.isEmpty()) 356 { 357 return defaultValue; 358 } 359 360 for (Attribute a : attrList) 361 { 362 for (AttributeValue v : a.getValues()) 363 { 364 String valueString = toLowerCase(v.getStringValue()); 365 if (valueString.equals("true") || valueString.equals("yes") || 366 valueString.equals("on") || valueString.equals("1")) 367 { 368 return true; 369 } 370 else if (valueString.equals("false") || valueString.equals("no") || 371 valueString.equals("off") || valueString.equals("0")) 372 { 373 return false; 374 } 375 } 376 } 377 378 return defaultValue; 379 } 380 381 382 383 /** 384 * Get the multiple string values of an entry attribute that is defined in the 385 * schema as a multi-valued string attribute, and that is not expected to 386 * have attribute options. 387 * 388 * @param attrList The attribute values of the entry attribute. 389 * @return The string values of the attribute, empty if there are none. 390 */ 391 public static ArrayList<String> getMultiValueString(List<Attribute> attrList) 392 { 393 ArrayList<String> valueStrings = new ArrayList<String>(); 394 395 if (attrList != null && !attrList.isEmpty()) 396 { 397 Attribute attr = attrList.get(0); 398 LinkedHashSet<AttributeValue> values = attr.getValues(); 399 if ((values != null) && (! values.isEmpty())) 400 { 401 for (AttributeValue value : values) 402 { 403 valueStrings.add(value.getStringValue()); 404 } 405 } 406 } 407 return valueStrings; 408 } 409 410 411 412 /** 413 * Get the single string value of an entry attribute that is defined in the 414 * schema as a single valued string attribute, and that is not expected to 415 * have attribute options. 416 * 417 * @param attrList The attribute value of the entry attribute. 418 * @return The string value of the attribute, or null if there is none. 419 */ 420 public static String getSingleValueString(List<Attribute> attrList) 421 { 422 if (attrList == null || attrList.isEmpty()) 423 { 424 return null; 425 } 426 String valueString = null; 427 Attribute attr = attrList.get(0); 428 LinkedHashSet<AttributeValue> values = attr.getValues(); 429 if ((values != null) && (! values.isEmpty())) 430 { 431 valueString = values.iterator().next().getStringValue(); 432 } 433 return valueString; 434 } 435 436 437 /** 438 * Get the single integer value of an entry attribute that is defined in the 439 * schema as a single valued integer attribute, and that is not expected to 440 * have attribute options. 441 * 442 * @param attrList The attribute value of the entry attribute. 443 * @param defaultValue The default value to be returned if there is no 444 * recognizable integer attribute value. 445 * @return The integer value of the attribute, or the provided default value 446 * if there is no value. 447 */ 448 public static int getSingleValueInteger(List<Attribute> attrList, 449 int defaultValue) 450 { 451 if (attrList != null && !attrList.isEmpty()) 452 { 453 Attribute attr = attrList.get(0); 454 LinkedHashSet<AttributeValue> values = attr.getValues(); 455 if ((values != null) && (! values.isEmpty())) 456 { 457 String valueString = values.iterator().next().getStringValue(); 458 try 459 { 460 return Integer.parseInt(valueString); 461 } 462 catch (NumberFormatException e) 463 { 464 if (debugEnabled()) 465 { 466 TRACER.debugCaught(DebugLogLevel.ERROR, e); 467 } 468 } 469 } 470 } 471 472 return defaultValue; 473 } 474 }