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