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