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