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-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017package org.opends.server.tools.makeldif; 018 019import static org.opends.messages.ToolMessages.*; 020import static org.opends.server.util.StaticUtils.*; 021 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.List; 025import java.util.Map; 026 027import org.forgerock.i18n.LocalizableMessage; 028import org.forgerock.opendj.ldap.ByteString; 029import org.forgerock.opendj.ldap.DN; 030import org.forgerock.opendj.ldap.schema.AttributeType; 031import org.forgerock.opendj.ldap.schema.CoreSchema; 032import org.opends.server.types.Attribute; 033import org.opends.server.types.Entry; 034 035/** 036 * This class defines a branch that should be included in the resulting LDIF. A 037 * branch may or may not have subordinate entries. 038 */ 039public class Branch 040{ 041 /** The DN for this branch entry. */ 042 private final DN branchDN; 043 /** 044 * The number of entries that should be created below this branch for each 045 * subordinate template. 046 */ 047 private int[] numEntriesPerTemplate; 048 /** The names of the subordinate templates for this branch. */ 049 private String[] subordinateTemplateNames; 050 /** The set of subordinate templates for this branch. */ 051 private Template[] subordinateTemplates; 052 /** The set of template lines that correspond to the RDN components. */ 053 private final TemplateLine[] rdnLines; 054 /** The set of extra lines that should be included in this branch entry. */ 055 private TemplateLine[] extraLines; 056 057 058 059 /** 060 * Creates a new branch with the provided information. 061 * 062 * @param templateFile The template file in which this branch appears. 063 * @param branchDN The DN for this branch entry. 064 */ 065 public Branch(TemplateFile templateFile, DN branchDN) 066 { 067 this(templateFile, branchDN, new String[0], new int[0], 068 new TemplateLine[0]); 069 } 070 071 072 073 /** 074 * Creates a new branch with the provided information. 075 * 076 * @param templateFile The template file in which this branch 077 * appears. 078 * @param branchDN The DN for this branch entry. 079 * @param subordinateTemplateNames The names of the subordinate templates 080 * used to generate entries below this 081 * branch. 082 * @param numEntriesPerTemplate The number of entries that should be 083 * created below this branch for each 084 * subordinate template. 085 * @param extraLines The set of extra lines that should be 086 * included in this branch entry. 087 */ 088 private Branch(TemplateFile templateFile, DN branchDN, 089 String[] subordinateTemplateNames, int[] numEntriesPerTemplate, 090 TemplateLine[] extraLines) 091 { 092 this.branchDN = branchDN; 093 this.subordinateTemplateNames = subordinateTemplateNames; 094 this.numEntriesPerTemplate = numEntriesPerTemplate; 095 this.extraLines = extraLines; 096 097 subordinateTemplates = null; 098 099 100 // Get the RDN template lines based just on the entry DN. 101 Entry entry = createEntry(branchDN); 102 103 ArrayList<LocalizableMessage> warnings = new ArrayList<>(); 104 ArrayList<TemplateLine> lineList = new ArrayList<>(); 105 106 for (String ocName : entry.getObjectClasses().values()) 107 { 108 try 109 { 110 String[] valueStrings = new String[] { ocName }; 111 Tag[] tags = new Tag[1]; 112 tags[0] = new StaticTextTag(); 113 tags[0].initializeForBranch(templateFile, this, valueStrings, 0, warnings); 114 115 lineList.add(new TemplateLine(CoreSchema.getObjectClassAttributeType(), 0, tags)); 116 } 117 catch (Exception e) 118 { 119 // This should never happen. 120 e.printStackTrace(); 121 } 122 } 123 124 for (List<Attribute> attrList : entry.getUserAttributes().values()) 125 { 126 for (Attribute a : attrList) 127 { 128 for (ByteString v : a) 129 { 130 try 131 { 132 String[] valueStrings = new String[] { v.toString() }; 133 Tag[] tags = new Tag[] { new StaticTextTag() }; 134 tags[0].initializeForBranch(templateFile, this, valueStrings, 0, warnings); 135 lineList.add(new TemplateLine(a.getAttributeDescription().getAttributeType(), 0, tags)); 136 } 137 catch (Exception e) 138 { 139 // This should never happen. 140 e.printStackTrace(); 141 } 142 } 143 } 144 } 145 146 for (List<Attribute> attrList : entry.getOperationalAttributes().values()) 147 { 148 for (Attribute a : attrList) 149 { 150 for (ByteString v : a) 151 { 152 try 153 { 154 String[] valueStrings = new String[] { v.toString() }; 155 Tag[] tags = new Tag[] { new StaticTextTag() }; 156 tags[0].initializeForBranch(templateFile, this, valueStrings, 0, warnings); 157 lineList.add(new TemplateLine(a.getAttributeDescription().getAttributeType(), 0, tags)); 158 } 159 catch (Exception e) 160 { 161 // This should never happen. 162 e.printStackTrace(); 163 } 164 } 165 } 166 } 167 168 rdnLines = new TemplateLine[lineList.size()]; 169 lineList.toArray(rdnLines); 170 } 171 172 173 174 /** 175 * Performs any necessary processing to ensure that the branch initialization 176 * is completed. In particular, it should make sure that all referenced 177 * subordinate templates actually exist in the template file. 178 * 179 * @param templates The set of templates defined in the template file. 180 * 181 * @throws MakeLDIFException If any of the subordinate templates are not 182 * defined in the template file. 183 */ 184 public void completeBranchInitialization(Map<String,Template> templates) 185 throws MakeLDIFException 186 { 187 if (subordinateTemplateNames == null) 188 { 189 subordinateTemplateNames = new String[0]; 190 subordinateTemplates = new Template[0]; 191 } 192 else 193 { 194 subordinateTemplates = new Template[subordinateTemplateNames.length]; 195 for (int i=0; i < subordinateTemplates.length; i++) 196 { 197 subordinateTemplates[i] = 198 templates.get(toLowerCase(subordinateTemplateNames[i])); 199 if (subordinateTemplates[i] == null) 200 { 201 throw new MakeLDIFException(ERR_MAKELDIF_UNDEFINED_BRANCH_SUBORDINATE.get( 202 branchDN, subordinateTemplateNames[i])); 203 } 204 } 205 } 206 } 207 208 209 210 /** 211 * Retrieves the DN for this branch entry. 212 * 213 * @return The DN for this branch entry. 214 */ 215 public DN getBranchDN() 216 { 217 return branchDN; 218 } 219 220 221 222 /** 223 * Retrieves the names of the subordinate templates for this branch. 224 * 225 * @return The names of the subordinate templates for this branch. 226 */ 227 public String[] getSubordinateTemplateNames() 228 { 229 return subordinateTemplateNames; 230 } 231 232 233 234 /** 235 * Retrieves the set of subordinate templates used to generate entries below 236 * this branch. Note that the subordinate templates will not be available 237 * until the <CODE>completeBranchInitialization</CODE> method has been called. 238 * 239 * @return The set of subordinate templates used to generate entries below 240 * this branch. 241 */ 242 public Template[] getSubordinateTemplates() 243 { 244 return subordinateTemplates; 245 } 246 247 248 249 /** 250 * Retrieves the number of entries that should be created below this branch 251 * for each subordinate template. 252 * 253 * @return The number of entries that should be created below this branch for 254 * each subordinate template. 255 */ 256 public int[] getNumEntriesPerTemplate() 257 { 258 return numEntriesPerTemplate; 259 } 260 261 262 263 /** 264 * Adds a new subordinate template to this branch. Note that this should not 265 * be used after <CODE>completeBranchInitialization</CODE> has been called. 266 * 267 * @param name The name of the template to use to generate the 268 * entries. 269 * @param numEntries The number of entries to create based on the template. 270 */ 271 public void addSubordinateTemplate(String name, int numEntries) 272 { 273 String[] newNames = new String[subordinateTemplateNames.length+1]; 274 int[] newCounts = new int[numEntriesPerTemplate.length+1]; 275 276 System.arraycopy(subordinateTemplateNames, 0, newNames, 0, 277 subordinateTemplateNames.length); 278 System.arraycopy(numEntriesPerTemplate, 0, newCounts, 0, 279 numEntriesPerTemplate.length); 280 281 newNames[subordinateTemplateNames.length] = name; 282 newCounts[numEntriesPerTemplate.length] = numEntries; 283 284 subordinateTemplateNames = newNames; 285 numEntriesPerTemplate = newCounts; 286 } 287 288 289 290 /** 291 * Retrieves the set of extra lines that should be included in this branch 292 * entry. 293 * 294 * @return The set of extra lines that should be included in this branch 295 * entry. 296 */ 297 public TemplateLine[] getExtraLines() 298 { 299 return extraLines; 300 } 301 302 303 304 /** 305 * Adds the provided template line to the set of extra lines for this branch. 306 * 307 * @param line The line to add to the set of extra lines for this branch. 308 */ 309 public void addExtraLine(TemplateLine line) 310 { 311 TemplateLine[] newExtraLines = new TemplateLine[extraLines.length+1]; 312 System.arraycopy(extraLines, 0, newExtraLines, 0, extraLines.length); 313 newExtraLines[extraLines.length] = line; 314 315 extraLines = newExtraLines; 316 } 317 318 319 320 /** 321 * Indicates whether this branch contains a reference to the specified 322 * attribute type, either in the RDN components of the DN or in the extra 323 * lines. 324 * 325 * @param attributeType The attribute type for which to make the 326 * determination. 327 * 328 * @return <CODE>true</CODE> if the branch does contain the specified 329 * attribute type, or <CODE>false</CODE> if it does not. 330 */ 331 public boolean hasAttribute(AttributeType attributeType) 332 { 333 if (branchDN.rdn().hasAttributeType(attributeType)) 334 { 335 return true; 336 } 337 338 for (TemplateLine l : extraLines) 339 { 340 if (l.getAttributeType().equals(attributeType)) 341 { 342 return true; 343 } 344 } 345 346 return false; 347 } 348 349 350 351 /** 352 * Writes the entry for this branch, as well as all appropriate subordinate 353 * entries. 354 * 355 * @param entryWriter The entry writer to which the entries should be 356 * written. 357 * 358 * @return The result that indicates whether processing should continue. 359 * 360 * @throws IOException If a problem occurs while attempting to write to the 361 * LDIF writer. 362 * 363 * @throws MakeLDIFException If some other problem occurs. 364 */ 365 public TagResult writeEntries(EntryWriter entryWriter) 366 throws IOException, MakeLDIFException 367 { 368 // Create a new template entry and populate it based on the RDN attributes 369 // and extra lines. 370 TemplateEntry entry = new TemplateEntry(this); 371 372 for (TemplateLine l : rdnLines) 373 { 374 TagResult r = l.generateLine(entry); 375 if (!r.keepProcessingEntry() 376 || !r.keepProcessingParent() 377 || !r.keepProcessingTemplateFile()) 378 { 379 return r; 380 } 381 } 382 383 for (TemplateLine l : extraLines) 384 { 385 TagResult r = l.generateLine(entry); 386 if (!r.keepProcessingEntry() 387 || !r.keepProcessingParent() 388 || !r.keepProcessingTemplateFile()) 389 { 390 return r; 391 } 392 } 393 394 if (! entryWriter.writeEntry(entry)) 395 { 396 return TagResult.STOP_PROCESSING; 397 } 398 399 400 for (int i=0; i < subordinateTemplates.length; i++) 401 { 402 TagResult r = 403 subordinateTemplates[i].writeEntries(entryWriter, branchDN, 404 numEntriesPerTemplate[i]); 405 if (!r.keepProcessingParent() 406 || !r.keepProcessingTemplateFile()) 407 { 408 if (r.keepProcessingTemplateFile()) 409 { 410 // We don't want to propagate a "stop processing parent" all the way 411 // up the chain. 412 return TagResult.SUCCESS_RESULT; 413 } 414 415 return r; 416 } 417 } 418 419 return TagResult.SUCCESS_RESULT; 420 } 421} 422