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