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-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017package org.opends.server.tools.makeldif; 018 019import static org.opends.server.util.LDIFWriter.*; 020import static org.opends.server.util.StaticUtils.*; 021 022import java.io.BufferedWriter; 023import java.io.IOException; 024import java.util.ArrayList; 025import java.util.LinkedHashMap; 026import java.util.List; 027 028import org.forgerock.opendj.ldap.AVA; 029import org.forgerock.opendj.ldap.ByteString; 030import org.forgerock.opendj.ldap.DN; 031import org.forgerock.opendj.ldap.RDN; 032import org.forgerock.opendj.ldap.schema.AttributeType; 033import org.opends.server.core.DirectoryServer; 034import org.opends.server.types.Attribute; 035import org.opends.server.types.AttributeBuilder; 036import org.opends.server.types.LDIFExportConfig; 037import org.opends.server.types.ObjectClass; 038import org.opends.server.util.LDIFException; 039 040/** 041 * This class defines an entry that is generated using a MakeLDIF branch or 042 * template. 043 */ 044public class TemplateEntry 045{ 046 /** The branch used to generate this entry (if it is associated with a branch). */ 047 private Branch branch; 048 /** The DN for this template entry, if it is known. */ 049 private DN dn; 050 /** The DN of the parent entry for this template entry, if it is available. */ 051 private DN parentDN; 052 053 /** 054 * The set of attributes associated with this template entry, mapped from the 055 * lowercase name of the attribute to the list of generated values. 056 */ 057 private final LinkedHashMap<AttributeType, ArrayList<TemplateValue>> attributes = new LinkedHashMap<>(); 058 059 /** The template used to generate this entry (if it is associated with a template). */ 060 private Template template; 061 062 063 /** 064 * Creates a new template entry that will be associated with the provided 065 * branch. 066 * 067 * @param branch The branch to use when creating this template entry. 068 */ 069 public TemplateEntry(Branch branch) 070 { 071 this.branch = branch; 072 073 dn = branch.getBranchDN(); 074 } 075 076 077 078 /** 079 * Creates a new template entry that will be associated with the provided 080 * template. 081 * 082 * @param template The template used to generate this entry. 083 * @param parentDN The DN of the parent entry for this template entry. 084 */ 085 public TemplateEntry(Template template, DN parentDN) 086 { 087 this.template = template; 088 this.parentDN = parentDN; 089 } 090 091 092 093 /** 094 * Retrieves the branch used to generate this entry. 095 * 096 * @return The branch used to generate this entry, or <CODE>null</CODE> if it 097 * is associated with a template instead of a branch. 098 */ 099 public Branch getBranch() 100 { 101 return branch; 102 } 103 104 105 106 /** 107 * Retrieves the template used to generate this entry. 108 * 109 * @return The template used to generate this entry, or <CODE>null</CODE> if 110 * it is associated with a branch instead of a template. 111 */ 112 public Template getTemplate() 113 { 114 return template; 115 } 116 117 118 119 /** 120 * Retrieves the DN of the parent entry for this template entry. 121 * 122 * @return The DN of the parent entry for this template entry, or 123 * <CODE>null</CODE> if there is no parent DN. 124 */ 125 public DN getParentDN() 126 { 127 return parentDN; 128 } 129 130 131 132 /** 133 * Retrieves the DN for this template entry, if it is known. 134 * 135 * @return The DN for this template entry if it is known, or 136 * <CODE>null</CODE> if it cannot yet be determined. 137 */ 138 public DN getDN() 139 { 140 if (dn == null) 141 { 142 AttributeType[] rdnAttrs = template.getRDNAttributes(); 143 AVA[] avas = new AVA[rdnAttrs.length]; 144 for (int i = 0; i < rdnAttrs.length; i++) 145 { 146 AttributeType t = rdnAttrs[i]; 147 TemplateValue v = getValue(t); 148 if (v == null) 149 { 150 return null; 151 } 152 avas[i] = new AVA(t, v.getValue()); 153 } 154 155 dn = parentDN.child(new RDN(avas)); 156 } 157 158 return dn; 159 } 160 161 162 163 /** 164 * Indicates whether this entry contains one or more values for the specified 165 * attribute type. 166 * 167 * @param attributeType The attribute type for which to make the 168 * determination. 169 * 170 * @return <CODE>true</CODE> if this entry contains one or more values for 171 * the specified attribute type, or <CODE>false</CODE> if not. 172 */ 173 public boolean hasAttribute(AttributeType attributeType) 174 { 175 return attributes.containsKey(attributeType); 176 } 177 178 179 180 /** 181 * Retrieves the value for the specified attribute, if defined. If the 182 * specified attribute has multiple values, then the first will be returned. 183 * 184 * @param attributeType The attribute type for which to retrieve the value. 185 * 186 * @return The value for the specified attribute, or <CODE>null</CODE> if 187 * there are no values for that attribute type. 188 */ 189 public TemplateValue getValue(AttributeType attributeType) 190 { 191 ArrayList<TemplateValue> valueList = attributes.get(attributeType); 192 if (valueList != null && !valueList.isEmpty()) 193 { 194 return valueList.get(0); 195 } 196 return null; 197 } 198 199 200 201 /** 202 * Retrieves the set of values for the specified attribute, if defined. 203 * 204 * @param attributeType The attribute type for which to retrieve the set of 205 * values. 206 * 207 * @return The set of values for the specified attribute, or 208 * <CODE>null</CODE> if there are no values for that attribute type. 209 */ 210 public List<TemplateValue> getValues(AttributeType attributeType) 211 { 212 return attributes.get(attributeType); 213 } 214 215 216 217 /** 218 * Adds the provided template value to this entry. 219 * 220 * @param value The value to add to this entry. 221 */ 222 public void addValue(TemplateValue value) 223 { 224 ArrayList<TemplateValue> valueList = attributes.get(value.getAttributeType()); 225 if (valueList == null) 226 { 227 valueList = new ArrayList<>(); 228 attributes.put(value.getAttributeType(), valueList); 229 } 230 valueList.add(value); 231 } 232 233 234 /** 235 * Writes this entry in LDIF form. No filtering will be 236 * performed for this entry, nor will any export plugins be invoked. 237 * 238 * @param exportConfig The configuration that specifies how the 239 * entry should be written. 240 * 241 * @return <CODE>true</CODE> if the entry is actually written, or 242 * <CODE>false</CODE> if it is not for some reason. 243 * 244 * @throws IOException If a problem occurs while writing the 245 * information. 246 * 247 * @throws LDIFException If a problem occurs while trying to 248 * determine whether to write the entry. 249 */ 250 public boolean toLDIF(LDIFExportConfig exportConfig) 251 throws IOException, LDIFException 252 { 253 // Process all of the attributes for this entry. 254 LinkedHashMap<ObjectClass,String> objectClasses = new LinkedHashMap<>(); 255 LinkedHashMap<AttributeType,List<Attribute>> userAttributes = new LinkedHashMap<>(); 256 LinkedHashMap<AttributeType,List<Attribute>> operationalAttributes = new LinkedHashMap<>(); 257 LinkedHashMap<AttributeType, List<Attribute>> urlAttributes = new LinkedHashMap<>(); 258 LinkedHashMap<AttributeType, List<Attribute>> base64Attributes = new LinkedHashMap<>(); 259 260 for (AttributeType t : attributes.keySet()) 261 { 262 ArrayList<TemplateValue> valueList = attributes.get(t); 263 if (t.isObjectClass()) 264 { 265 for (TemplateValue v : valueList) 266 { 267 String ocName = toLowerCase(v.getValue().toString()); 268 ObjectClass oc = DirectoryServer.getObjectClass(ocName, true); 269 objectClasses.put(oc, ocName); 270 } 271 } 272 else if (t.isOperational()) 273 { 274 AttributeBuilder builder = new AttributeBuilder(t, t.getNameOrOID()); 275 for (TemplateValue v : valueList) 276 { 277 builder.add(v.getValue().toString()); 278 } 279 280 operationalAttributes.put(t, builder.toAttributeList()); 281 } 282 else 283 { 284 AttributeBuilder builder = new AttributeBuilder(t, t.getNameOrOID()); 285 AttributeBuilder urlBuilder = null; 286 AttributeBuilder base64Builder = null; 287 for (TemplateValue v : valueList) 288 { 289 ByteString value = ByteString.valueOfUtf8(v.getValue().toString()); 290 builder.add(value); 291 if (v.getTemplateLine().isURL()) 292 { 293 if (urlBuilder == null) 294 { 295 urlBuilder = new AttributeBuilder(t, t.getNameOrOID()); 296 } 297 urlBuilder.add(value); 298 } 299 else if (v.getTemplateLine().isBase64()) 300 { 301 if (base64Builder == null) 302 { 303 base64Builder = new AttributeBuilder(t, t.getNameOrOID()); 304 } 305 base64Builder.add(value); 306 } 307 } 308 309 userAttributes.put(t, builder.toAttributeList()); 310 if (urlBuilder != null) 311 { 312 urlAttributes.put(t, urlBuilder.toAttributeList()); 313 } 314 if (base64Builder != null) 315 { 316 base64Attributes.put(t, base64Builder.toAttributeList()); 317 } 318 } 319 } 320 321 // Get the information necessary to write the LDIF. 322 BufferedWriter writer = exportConfig.getWriter(); 323 int wrapColumn = exportConfig.getWrapColumn(); 324 boolean wrapLines = wrapColumn > 1; 325 326 327 // First, write the DN. It will always be included. 328 StringBuilder dnLine = new StringBuilder("dn"); 329 appendLDIFSeparatorAndValue(dnLine, 330 ByteString.valueOfUtf8(getDN().toString())); 331 writeLDIFLine(dnLine, writer, wrapLines, wrapColumn); 332 333 334 // Next, the set of objectclasses. 335 final boolean typesOnly = exportConfig.typesOnly(); 336 if (exportConfig.includeObjectClasses()) 337 { 338 if (typesOnly) 339 { 340 StringBuilder ocLine = new StringBuilder("objectClass:"); 341 writeLDIFLine(ocLine, writer, wrapLines, wrapColumn); 342 } 343 else 344 { 345 for (String s : objectClasses.values()) 346 { 347 StringBuilder ocLine = new StringBuilder("objectClass: ").append(s); 348 writeLDIFLine(ocLine, writer, wrapLines, wrapColumn); 349 } 350 } 351 } 352 353 354 // Now the set of user attributes. 355 for (AttributeType attrType : userAttributes.keySet()) 356 { 357 if (exportConfig.includeAttribute(attrType)) 358 { 359 for (Attribute a : userAttributes.get(attrType)) 360 { 361 if (a.isVirtual() && !exportConfig.includeVirtualAttributes()) 362 { 363 continue; 364 } 365 366 String attrName = a.getNameWithOptions(); 367 if (typesOnly) 368 { 369 StringBuilder attrLine = new StringBuilder(attrName); 370 attrLine.append(":"); 371 372 writeLDIFLine(attrLine, writer, wrapLines, wrapColumn); 373 } 374 else 375 { 376 List<Attribute> urlAttrList = urlAttributes.get(attrType); 377 List<Attribute> base64AttrList = base64Attributes.get(attrType); 378 379 for (ByteString v : a) 380 { 381 StringBuilder attrLine = new StringBuilder(attrName); 382 boolean isURLValue = contains(urlAttrList, v); 383 boolean isBase64Value = contains(base64AttrList, v); 384 appendLDIFSeparatorAndValue(attrLine, 385 v, 386 isURLValue, 387 isBase64Value); 388 writeLDIFLine(attrLine, writer, wrapLines, wrapColumn); 389 } 390 } 391 } 392 } 393 } 394 395 396 // Next, the set of operational attributes. 397 if (exportConfig.includeOperationalAttributes()) 398 { 399 for (AttributeType attrType : operationalAttributes.keySet()) 400 { 401 if (exportConfig.includeAttribute(attrType)) 402 { 403 for (Attribute a : operationalAttributes.get(attrType)) 404 { 405 if (a.isVirtual() && !exportConfig.includeVirtualAttributes()) 406 { 407 continue; 408 } 409 410 String attrName = a.getNameWithOptions(); 411 if (typesOnly) 412 { 413 StringBuilder attrLine = new StringBuilder(attrName); 414 attrLine.append(":"); 415 416 writeLDIFLine(attrLine, writer, wrapLines, wrapColumn); 417 } 418 else 419 { 420 for (ByteString v : a) 421 { 422 StringBuilder attrLine = new StringBuilder(attrName); 423 appendLDIFSeparatorAndValue(attrLine, v); 424 writeLDIFLine(attrLine, writer, wrapLines, wrapColumn); 425 } 426 } 427 } 428 } 429 } 430 } 431 432 // Make sure there is a blank line after the entry. 433 writer.newLine(); 434 435 return true; 436 } 437 438 private boolean contains(List<Attribute> urlAttrList, ByteString v) 439 { 440 if (urlAttrList != null) 441 { 442 for (Attribute urlAttr : urlAttrList) 443 { 444 for (ByteString urlValue : urlAttr) 445 { 446 if (urlValue.equals(v)) 447 { 448 return true; 449 } 450 } 451 } 452 } 453 return false; 454 } 455}