001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.server.core.partition.ldif; 021 022 023 import java.io.File; 024 import java.io.FileFilter; 025 import java.io.FileWriter; 026 import java.io.IOException; 027 import java.util.Iterator; 028 import java.util.List; 029 import java.util.UUID; 030 031 import org.apache.directory.server.core.entry.ClonedServerEntry; 032 import org.apache.directory.server.core.interceptor.context.AddOperationContext; 033 import org.apache.directory.server.core.interceptor.context.BindOperationContext; 034 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext; 035 import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext; 036 import org.apache.directory.server.core.interceptor.context.MoveOperationContext; 037 import org.apache.directory.server.core.interceptor.context.RenameOperationContext; 038 import org.apache.directory.server.core.interceptor.context.UnbindOperationContext; 039 import org.apache.directory.server.core.partition.Partition; 040 import org.apache.directory.server.core.partition.avl.AvlPartition; 041 import org.apache.directory.server.core.partition.impl.btree.BTreePartition; 042 import org.apache.directory.server.i18n.I18n; 043 import org.apache.directory.server.xdbm.Index; 044 import org.apache.directory.server.xdbm.IndexCursor; 045 import org.apache.directory.server.xdbm.IndexEntry; 046 import org.apache.directory.shared.ldap.constants.SchemaConstants; 047 import org.apache.directory.shared.ldap.csn.CsnFactory; 048 import org.apache.directory.shared.ldap.entry.DefaultServerEntry; 049 import org.apache.directory.shared.ldap.entry.Entry; 050 import org.apache.directory.shared.ldap.entry.ServerEntry; 051 import org.apache.directory.shared.ldap.exception.LdapException; 052 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException; 053 import org.apache.directory.shared.ldap.ldif.LdapLdifException; 054 import org.apache.directory.shared.ldap.ldif.LdifEntry; 055 import org.apache.directory.shared.ldap.ldif.LdifReader; 056 import org.apache.directory.shared.ldap.ldif.LdifUtils; 057 import org.apache.directory.shared.ldap.name.AVA; 058 import org.apache.directory.shared.ldap.name.DN; 059 import org.apache.directory.shared.ldap.name.RDN; 060 import org.apache.directory.shared.ldap.schema.AttributeType; 061 import org.apache.directory.shared.ldap.schema.SchemaManager; 062 import org.apache.directory.shared.ldap.util.StringTools; 063 import org.apache.directory.shared.ldap.util.SystemUtils; 064 import org.slf4j.Logger; 065 import org.slf4j.LoggerFactory; 066 067 068 /** 069 * A LDIF based partition. Data are stored on disk as LDIF, following this organisation : 070 * <li> each entry is associated with a file, postfixed with LDIF 071 * <li> each entry having at least one child will have a directory created using its name. 072 * The root is the partition's suffix. 073 * <br> 074 * So for instance, we may have on disk : 075 * <pre> 076 * /ou=example,ou=system.ldif 077 * /ou=example,ou=system/ 078 * | 079 * +--> cn=test.ldif 080 * cn=test/ 081 * | 082 * +--> cn=another test.ldif 083 * ... 084 * </pre> 085 * <br><br> 086 * In this exemple, the partition's suffix is <b>ou=example,ou=system</b>. 087 * <br> 088 * 089 * @org.apache.xbean.XBean 090 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 091 * @version $Rev$, $Date$ 092 */ 093 public class LdifPartition extends BTreePartition<Long> 094 { 095 /** A logger for this class */ 096 private static Logger LOG = LoggerFactory.getLogger( LdifPartition.class ); 097 098 /** The directory into which the partition is stored */ 099 private String workingDirectory; 100 101 /** The directory into which the entries are stored */ 102 private File suffixDirectory; 103 104 /** Flags used for the getFile() method */ 105 private static final boolean CREATE = Boolean.TRUE; 106 private static final boolean DELETE = Boolean.FALSE; 107 108 private int ldifScanInterval; 109 110 /** A filter used to pick all the directories */ 111 private FileFilter dirFilter = new FileFilter() 112 { 113 public boolean accept( File dir ) 114 { 115 return dir.isDirectory(); 116 } 117 }; 118 119 /** A filter used to pick all the ldif entries */ 120 private FileFilter entryFilter = new FileFilter() 121 { 122 public boolean accept( File dir ) 123 { 124 if ( dir.getName().endsWith( CONF_FILE_EXTN ) ) 125 { 126 return dir.isFile(); 127 } 128 else 129 { 130 return false; 131 } 132 } 133 }; 134 135 /** The extension used for LDIF entry files */ 136 private static final String CONF_FILE_EXTN = ".ldif"; 137 138 /** We use a partition to manage searches on this partition */ 139 private AvlPartition wrappedPartition; 140 141 /** A default CSN factory */ 142 private static CsnFactory defaultCSNFactory; 143 144 145 /** 146 * Creates a new instance of LdifPartition. 147 */ 148 public LdifPartition() 149 { 150 wrappedPartition = new AvlPartition(); 151 } 152 153 154 /** 155 * {@inheritDoc} 156 */ 157 protected void doInit() throws Exception 158 { 159 // Initialize the AvlPartition 160 wrappedPartition.setId( id ); 161 wrappedPartition.setSuffix( suffix.getName() ); 162 wrappedPartition.setSchemaManager( schemaManager ); 163 wrappedPartition.initialize(); 164 165 // Create the CsnFactory with a invalid ReplicaId 166 // @TODO : inject a correct ReplicaId 167 defaultCSNFactory = new CsnFactory( 0 ); 168 169 this.searchEngine = wrappedPartition.getSearchEngine(); 170 171 LOG.debug( "id is : {}", wrappedPartition.getId() ); 172 173 // Initialize the suffixDirectory : it's a composition 174 // of the workingDirectory followed by the suffix 175 if ( ( suffix == null ) || ( suffix.isEmpty() ) ) 176 { 177 String msg = I18n.err( I18n.ERR_150 ); 178 LOG.error( msg ); 179 throw new LdapInvalidDnException( msg ); 180 } 181 182 if ( !suffix.isNormalized() ) 183 { 184 suffix.normalize( schemaManager.getNormalizerMapping() ); 185 } 186 187 String suffixDirName = getFileName( suffix ); 188 suffixDirectory = new File( workingDirectory, suffixDirName ); 189 190 // Create the context entry now, if it does not exists, or load the 191 // existing entries 192 if ( suffixDirectory.exists() ) 193 { 194 loadEntries( new File( workingDirectory ) ); 195 } 196 else 197 { 198 // The partition directory does not exist, we have to create it, including parent directories 199 try 200 { 201 suffixDirectory.mkdirs(); 202 } 203 catch ( SecurityException se ) 204 { 205 String msg = I18n.err( I18n.ERR_151, suffixDirectory.getAbsolutePath(), se.getLocalizedMessage() ); 206 LOG.error( msg ); 207 throw se; 208 } 209 210 // And create the context entry too 211 File contextEntryFile = new File( suffixDirectory + CONF_FILE_EXTN ); 212 213 LOG.info( "ldif file doesn't exist {}, creating it.", contextEntryFile.getAbsolutePath() ); 214 215 if ( contextEntry == null ) 216 { 217 if ( contextEntryFile.exists() ) 218 { 219 LdifReader reader = new LdifReader( contextEntryFile ); 220 contextEntry = new DefaultServerEntry( schemaManager, reader.next().getEntry() ); 221 reader.close(); 222 } 223 else 224 { 225 // No context entry and no LDIF file exists. 226 // Skip initialization of context entry here, it will be added later. 227 return; 228 } 229 } 230 231 if ( contextEntry.get( SchemaConstants.ENTRY_CSN_AT ) == null ) 232 { 233 contextEntry.add( SchemaConstants.ENTRY_CSN_AT, defaultCSNFactory.newInstance().toString() ); 234 } 235 236 if ( contextEntry.get( SchemaConstants.ENTRY_UUID_AT ) == null ) 237 { 238 String uuid = UUID.randomUUID().toString(); 239 contextEntry.add( SchemaConstants.ENTRY_UUID_AT, uuid ); 240 } 241 242 FileWriter fw = new FileWriter( contextEntryFile ); 243 fw.write( LdifUtils.convertEntryToLdif( contextEntry ) ); 244 fw.close(); 245 246 // And add this entry to the underlying partition 247 wrappedPartition.getStore().add( contextEntry ); 248 } 249 } 250 251 252 //------------------------------------------------------------------------- 253 // Operations 254 //------------------------------------------------------------------------- 255 /** 256 * {@inheritDoc} 257 */ 258 @Override 259 public void add( AddOperationContext addContext ) throws Exception 260 { 261 wrappedPartition.add( addContext ); 262 add( addContext.getEntry() ); 263 } 264 265 266 /** 267 * {@inheritDoc} 268 */ 269 public void bind( BindOperationContext bindContext ) throws Exception 270 { 271 wrappedPartition.bind( bindContext ); 272 } 273 274 275 /** 276 * {@inheritDoc} 277 */ 278 @Override 279 public void delete( Long id ) throws Exception 280 { 281 ServerEntry entry = lookup( id ); 282 283 wrappedPartition.delete( id ); 284 285 if ( entry != null ) 286 { 287 File ldifFile = getFile( entry.getDn(), DELETE ); 288 289 boolean deleted = deleteFile( ldifFile ); 290 291 LOG.debug( "deleted file {} {}", ldifFile.getAbsoluteFile(), deleted ); 292 293 // Delete the parent if there is no more children 294 File parentFile = ldifFile.getParentFile(); 295 296 if ( parentFile.listFiles().length == 0 ) 297 { 298 deleteFile( parentFile ); 299 300 LOG.debug( "deleted file {} {}", parentFile.getAbsoluteFile(), deleted ); 301 } 302 303 } 304 305 } 306 307 308 /** 309 * {@inheritDoc} 310 */ 311 @Override 312 public void modify( ModifyOperationContext modifyContext ) throws Exception 313 { 314 Long id = getEntryId( modifyContext.getDn().getNormName() ); 315 316 wrappedPartition.modify( id, modifyContext.getModItems() ); 317 318 // Get the modified entry and store it in the context for post usage 319 ClonedServerEntry modifiedEntry = lookup( id ); 320 modifyContext.setAlteredEntry( modifiedEntry ); 321 322 // just overwrite the existing file 323 DN dn = modifyContext.getDn(); 324 325 // And write it back on disk 326 FileWriter fw = new FileWriter( getFile( dn, DELETE ) ); 327 fw.write( LdifUtils.convertEntryToLdif( modifiedEntry ) ); 328 fw.close(); 329 } 330 331 332 /** 333 * {@inheritDoc} 334 */ 335 @Override 336 public void move( MoveOperationContext moveContext ) throws Exception 337 { 338 DN oldDn = moveContext.getDn(); 339 Long id = getEntryId( oldDn.getNormName() ); 340 341 wrappedPartition.move( moveContext ); 342 343 // Get the modified entry 344 ClonedServerEntry modifiedEntry = lookup( id ); 345 346 entryMoved( oldDn, modifiedEntry, id ); 347 } 348 349 350 /** 351 * {@inheritDoc} 352 */ 353 @Override 354 public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws Exception 355 { 356 DN oldDn = moveAndRenameContext.getDn(); 357 Long id = getEntryId( oldDn.getNormName() ); 358 359 wrappedPartition.moveAndRename( moveAndRenameContext ); 360 361 // Get the modified entry and store it in the context for post usage 362 ClonedServerEntry modifiedEntry = lookup( id ); 363 moveAndRenameContext.setAlteredEntry( modifiedEntry ); 364 365 entryMoved( oldDn, modifiedEntry, id ); 366 } 367 368 369 /** 370 * {@inheritDoc} 371 */ 372 @Override 373 public void rename( RenameOperationContext renameContext ) throws Exception 374 { 375 DN oldDn = renameContext.getDn(); 376 Long id = getEntryId( oldDn.getNormName() ); 377 378 // Create the new entry 379 wrappedPartition.rename( renameContext ); 380 381 // Get the modified entry and store it in the context for post usage 382 ClonedServerEntry modifiedEntry = lookup( id ); 383 renameContext.setAlteredEntry( modifiedEntry ); 384 385 // Now move the potential children for the old entry 386 // and remove the old entry 387 entryMoved( oldDn, modifiedEntry, id ); 388 } 389 390 391 /** 392 * rewrites the moved entry and its associated children 393 * Note that instead of moving and updating the existing files on disk 394 * this method gets the moved entry and its children and writes the LDIF files 395 * 396 * @param oldEntryDn the moved entry's old DN 397 * @param entryId the moved entry's master table ID 398 * @param deleteOldEntry a flag to tell whether to delete the old entry files 399 * @throws Exception 400 */ 401 private void entryMoved( DN oldEntryDn, Entry modifiedEntry, Long entryIdOld ) throws Exception 402 { 403 // First, add the new entry 404 add( modifiedEntry ); 405 406 // Then, if there are some children, move then to the new place 407 IndexCursor<Long, ServerEntry, Long> cursor = getSubLevelIndex().forwardCursor( entryIdOld ); 408 409 while ( cursor.next() ) 410 { 411 IndexEntry<Long, ServerEntry, Long> entry = cursor.get(); 412 413 // except the parent entry add the rest of entries 414 if ( entry.getId() != entryIdOld ) 415 { 416 add( wrappedPartition.lookup( entry.getId() ) ); 417 } 418 } 419 420 cursor.close(); 421 422 // And delete the old entry's LDIF file 423 File file = getFile( oldEntryDn, DELETE ); 424 boolean deleted = deleteFile( file ); 425 LOG.warn( "move operation: deleted file {} {}", file.getAbsoluteFile(), deleted ); 426 427 // and the associated directory ( the file's name's minus ".ldif") 428 String dirName = file.getAbsolutePath(); 429 dirName = dirName.substring( 0, dirName.indexOf( CONF_FILE_EXTN ) ); 430 deleted = deleteFile( new File( dirName ) ); 431 LOG.warn( "move operation: deleted dir {} {}", dirName, deleted ); 432 } 433 434 435 /** 436 * loads the configuration into the DIT from the file system 437 * Note that it assumes the presence of a directory with the partition suffix's upname 438 * under the partition's base dir 439 * 440 * for ex. if 'config' is the partition's id and 'ou=config' is its suffix it looks for the dir with the path 441 * 442 * <directory-service-working-dir>/config/ou=config 443 * e.x example.com/config/ou=config 444 * 445 * NOTE: this dir setup is just to ease the testing of this partition, this needs to be 446 * replaced with some kind of bootstrapping the default config from a jar file and 447 * write to the FS in LDIF format 448 * 449 * @throws Exception 450 */ 451 private void loadEntries( File entryDir ) throws Exception 452 { 453 LOG.debug( "Processing dir {}", entryDir.getName() ); 454 455 // First, load the entries 456 File[] entries = entryDir.listFiles( entryFilter ); 457 458 if ( ( entries != null ) && ( entries.length != 0 ) ) 459 { 460 LdifReader ldifReader = new LdifReader(); 461 462 for ( File entry : entries ) 463 { 464 LOG.debug( "parsing ldif file {}", entry.getName() ); 465 List<LdifEntry> ldifEntries = ldifReader.parseLdifFile( entry.getAbsolutePath() ); 466 ldifReader.close(); 467 468 if ( ( ldifEntries != null ) && !ldifEntries.isEmpty() ) 469 { 470 // this ldif will have only one entry 471 LdifEntry ldifEntry = ldifEntries.get( 0 ); 472 LOG.debug( "Adding entry {}", ldifEntry ); 473 474 ServerEntry serverEntry = new DefaultServerEntry( schemaManager, ldifEntry.getEntry() ); 475 476 if ( !serverEntry.containsAttribute( SchemaConstants.ENTRY_CSN_AT ) ) 477 { 478 serverEntry.put( SchemaConstants.ENTRY_CSN_AT, defaultCSNFactory.newInstance().toString() ); 479 } 480 481 if ( !serverEntry.containsAttribute( SchemaConstants.ENTRY_UUID_AT ) ) 482 { 483 serverEntry.put( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() ); 484 } 485 486 // call add on the wrapped partition not on the self 487 wrappedPartition.getStore().add( serverEntry ); 488 } 489 } 490 491 } 492 else 493 { 494 // If we don't have ldif files, we won't have sub-directories 495 return; 496 } 497 498 // Second, recurse on the sub directories 499 File[] dirs = entryDir.listFiles( dirFilter ); 500 501 if ( ( dirs != null ) && ( dirs.length != 0 ) ) 502 { 503 for ( File f : dirs ) 504 { 505 loadEntries( f ); 506 } 507 } 508 } 509 510 511 /** 512 * Create the file name from the entry DN. 513 */ 514 private File getFile( DN entryDn, boolean create ) throws LdapException 515 { 516 StringBuilder filePath = new StringBuilder(); 517 filePath.append( suffixDirectory ).append( File.separator ); 518 519 DN baseDn = ( DN ) entryDn.getSuffix( suffix.size() ); 520 521 for ( int i = 0; i < baseDn.size() - 1; i++ ) 522 { 523 String rdnFileName = getFileName( baseDn.getRdn( i ) ); 524 525 filePath.append( rdnFileName ).append( File.separator ); 526 } 527 528 String rdnFileName = getFileName( entryDn.getRdn() ) + CONF_FILE_EXTN; 529 String parentDir = filePath.toString(); 530 531 File dir = new File( parentDir ); 532 533 if ( !dir.exists() && create ) 534 { 535 // We have to create the entry if it does not have a parent 536 dir.mkdir(); 537 } 538 539 File ldifFile = new File( parentDir + rdnFileName ); 540 541 if ( ldifFile.exists() && create ) 542 { 543 // The entry already exists 544 throw new LdapException( I18n.err( I18n.ERR_633 ) ); 545 } 546 547 return ldifFile; 548 } 549 550 551 /** 552 * Compute the real name based on the RDN, assuming that depending on the underlying 553 * OS, some characters are not allowed. 554 * 555 * We don't allow filename which length is > 255 chars. 556 */ 557 private String getFileName( RDN rdn ) throws LdapException 558 { 559 String fileName = ""; 560 561 Iterator<AVA> iterator = rdn.iterator(); 562 while ( iterator.hasNext() ) 563 { 564 AVA ava = iterator.next(); 565 566 // First, get the AT name, or OID 567 String normAT = ava.getNormType(); 568 AttributeType at = schemaManager.lookupAttributeTypeRegistry( normAT ); 569 570 String atName = at.getName(); 571 572 // Now, get the normalized value 573 String normValue = ava.getNormValue().getString(); 574 575 fileName += atName + "=" + normValue; 576 577 if ( iterator.hasNext() ) 578 { 579 fileName += "+"; 580 } 581 } 582 583 return getOSFileName( fileName ); 584 } 585 586 587 /** 588 * Compute the real name based on the DN, assuming that depending on the underlying 589 * OS, some characters are not allowed. 590 * 591 * We don't allow filename which length is > 255 chars. 592 */ 593 private String getFileName( DN dn ) throws LdapException 594 { 595 StringBuilder sb = new StringBuilder(); 596 boolean isFirst = true; 597 598 for ( RDN rdn : dn.getRdns() ) 599 { 600 // First, get the AT name, or OID 601 String normAT = rdn.getAtav().getNormType(); 602 AttributeType at = schemaManager.lookupAttributeTypeRegistry( normAT ); 603 604 String atName = at.getName(); 605 606 // Now, get the normalized value 607 String normValue = rdn.getAtav().getNormValue().getString(); 608 609 if ( isFirst ) 610 { 611 isFirst = false; 612 } 613 else 614 { 615 sb.append( "," ); 616 } 617 618 sb.append( atName ).append( "=" ).append( normValue ); 619 } 620 621 return getOSFileName( sb.toString() ); 622 } 623 624 625 /** 626 * Get a OS compatible file name 627 */ 628 private String getOSFileName( String fileName ) 629 { 630 if ( SystemUtils.IS_OS_WINDOWS ) 631 { 632 // On Windows, we escape '/', '<', '>', '\', '|', '"', ':', '+', ' ', '[', ']', 633 // '*', [0x00-0x1F], '?' 634 StringBuilder sb = new StringBuilder(); 635 636 for ( char c : fileName.toCharArray() ) 637 { 638 switch ( c ) 639 { 640 case 0x00: 641 case 0x01: 642 case 0x02: 643 case 0x03: 644 case 0x04: 645 case 0x05: 646 case 0x06: 647 case 0x07: 648 case 0x08: 649 case 0x09: 650 case 0x0A: 651 case 0x0B: 652 case 0x0C: 653 case 0x0D: 654 case 0x0E: 655 case 0x0F: 656 case 0x10: 657 case 0x11: 658 case 0x12: 659 case 0x13: 660 case 0x14: 661 case 0x15: 662 case 0x16: 663 case 0x17: 664 case 0x18: 665 case 0x19: 666 case 0x1A: 667 case 0x1B: 668 case 0x1C: 669 case 0x1D: 670 case 0x1E: 671 case 0x1F: 672 sb.append( "\\" ).append( StringTools.dumpHex( ( byte ) ( c >> 4 ) ) ).append( 673 StringTools.dumpHex( ( byte ) ( c & 0x04 ) ) ); 674 break; 675 676 case '/': 677 case '\\': 678 case '<': 679 case '>': 680 case '|': 681 case '"': 682 case ':': 683 case '+': 684 case ' ': 685 case '[': 686 case ']': 687 case '*': 688 case '?': 689 sb.append( '\\' ).append( c ); 690 break; 691 692 default: 693 sb.append( c ); 694 break; 695 } 696 } 697 698 return sb.toString().toLowerCase(); 699 } 700 else 701 { 702 // On linux, just escape '/' and null 703 StringBuilder sb = new StringBuilder(); 704 705 for ( char c : fileName.toCharArray() ) 706 { 707 switch ( c ) 708 { 709 case '/': 710 sb.append( "\\/" ); 711 break; 712 713 case '\0': 714 sb.append( "\\00" ); 715 break; 716 717 default: 718 sb.append( c ); 719 break; 720 } 721 } 722 723 return sb.toString().toLowerCase(); 724 } 725 } 726 727 728 /** 729 * Write the new entry on disk. It does not exist, as this ha sbeen checked 730 * by the ExceptionInterceptor. 731 */ 732 private void add( Entry entry ) throws Exception 733 { 734 FileWriter fw = new FileWriter( getFile( entry.getDn(), CREATE ) ); 735 fw.write( LdifUtils.convertEntryToLdif( entry ) ); 736 fw.close(); 737 } 738 739 740 /** 741 * Recursively delete an entry and all of its children. If the entry is a directory, 742 * then get into it, call the same method on each of the contained files, 743 * and delete the directory. 744 */ 745 private boolean deleteFile( File file ) 746 { 747 if ( file.isDirectory() ) 748 { 749 File[] files = file.listFiles(); 750 751 // Process the contained files 752 for ( File f : files ) 753 { 754 deleteFile( f ); 755 } 756 757 // then delete the directory itself 758 return file.delete(); 759 } 760 else 761 { 762 return file.delete(); 763 } 764 } 765 766 767 @Override 768 public void addIndexOn( Index<? extends Object, ServerEntry, Long> index ) throws Exception 769 { 770 wrappedPartition.addIndexOn( index ); 771 } 772 773 774 @Override 775 public int count() throws Exception 776 { 777 return wrappedPartition.count(); 778 } 779 780 781 @Override 782 protected void doDestroy() throws Exception 783 { 784 wrappedPartition.destroy(); 785 } 786 787 788 @Override 789 public Index<String, ServerEntry, Long> getAliasIndex() 790 { 791 return wrappedPartition.getAliasIndex(); 792 } 793 794 795 @Override 796 public int getChildCount( Long id ) throws Exception 797 { 798 return wrappedPartition.getChildCount( id ); 799 } 800 801 802 @Override 803 public String getEntryDn( Long id ) throws Exception 804 { 805 return wrappedPartition.getEntryDn( id ); 806 } 807 808 809 @Override 810 public Long getEntryId( String dn ) throws Exception 811 { 812 return wrappedPartition.getEntryId( dn ); 813 } 814 815 816 @Override 817 public String getEntryUpdn( Long id ) throws Exception 818 { 819 return wrappedPartition.getEntryUpdn( id ); 820 } 821 822 823 @Override 824 public String getEntryUpdn( String dn ) throws Exception 825 { 826 return wrappedPartition.getEntryUpdn( dn ); 827 } 828 829 830 @Override 831 public Index<String, ServerEntry, Long> getNdnIndex() 832 { 833 return wrappedPartition.getNdnIndex(); 834 } 835 836 837 @Override 838 public Index<Long, ServerEntry, Long> getOneAliasIndex() 839 { 840 return wrappedPartition.getOneAliasIndex(); 841 } 842 843 844 @Override 845 public Index<Long, ServerEntry, Long> getOneLevelIndex() 846 { 847 return wrappedPartition.getOneLevelIndex(); 848 } 849 850 851 @Override 852 public Long getParentId( Long childId ) throws Exception 853 { 854 return wrappedPartition.getParentId( childId ); 855 } 856 857 858 @Override 859 public Long getParentId( String dn ) throws Exception 860 { 861 return wrappedPartition.getParentId( dn ); 862 } 863 864 865 @Override 866 public Index<String, ServerEntry, Long> getPresenceIndex() 867 { 868 return wrappedPartition.getPresenceIndex(); 869 } 870 871 872 @Override 873 public String getProperty( String propertyName ) throws Exception 874 { 875 return wrappedPartition.getProperty( propertyName ); 876 } 877 878 879 @Override 880 public Index<Long, ServerEntry, Long> getSubAliasIndex() 881 { 882 return wrappedPartition.getSubAliasIndex(); 883 } 884 885 886 @Override 887 public Index<Long, ServerEntry, Long> getSubLevelIndex() 888 { 889 return wrappedPartition.getSubLevelIndex(); 890 } 891 892 893 @Override 894 public Index<?, ServerEntry, Long> getSystemIndex( String id ) throws Exception 895 { 896 return wrappedPartition.getSystemIndex( id ); 897 } 898 899 900 @Override 901 public Iterator<String> getSystemIndices() 902 { 903 return wrappedPartition.getSystemIndices(); 904 } 905 906 907 @Override 908 public Index<String, ServerEntry, Long> getUpdnIndex() 909 { 910 return wrappedPartition.getUpdnIndex(); 911 } 912 913 914 @Override 915 public Index<? extends Object, ServerEntry, Long> getUserIndex( String id ) throws Exception 916 { 917 return wrappedPartition.getUserIndex( id ); 918 } 919 920 921 @Override 922 public Iterator<String> getUserIndices() 923 { 924 return wrappedPartition.getUserIndices(); 925 } 926 927 928 @Override 929 public boolean hasSystemIndexOn( String id ) throws Exception 930 { 931 return wrappedPartition.hasSystemIndexOn( id ); 932 } 933 934 935 @Override 936 public boolean hasUserIndexOn( String id ) throws Exception 937 { 938 return wrappedPartition.hasUserIndexOn( id ); 939 } 940 941 942 @Override 943 public boolean isInitialized() 944 { 945 return wrappedPartition != null && wrappedPartition.isInitialized(); 946 } 947 948 949 @Override 950 public IndexCursor<Long, ServerEntry, Long> list( Long id ) throws Exception 951 { 952 return wrappedPartition.list( id ); 953 } 954 955 956 @Override 957 public ClonedServerEntry lookup( Long id ) throws Exception 958 { 959 return wrappedPartition.lookup( id ); 960 } 961 962 963 @Override 964 public void setAliasIndexOn( Index<String, ServerEntry, Long> index ) throws Exception 965 { 966 wrappedPartition.setAliasIndexOn( index ); 967 } 968 969 970 @Override 971 public void setNdnIndexOn( Index<String, ServerEntry, Long> index ) throws Exception 972 { 973 wrappedPartition.setNdnIndexOn( index ); 974 } 975 976 977 @Override 978 public void setOneAliasIndexOn( Index<Long, ServerEntry, Long> index ) throws Exception 979 { 980 wrappedPartition.setOneAliasIndexOn( index ); 981 } 982 983 984 @Override 985 public void setOneLevelIndexOn( Index<Long, ServerEntry, Long> index ) throws Exception 986 { 987 wrappedPartition.setOneLevelIndexOn( index ); 988 } 989 990 991 @Override 992 public void setPresenceIndexOn( Index<String, ServerEntry, Long> index ) throws Exception 993 { 994 wrappedPartition.setPresenceIndexOn( index ); 995 } 996 997 998 @Override 999 public void setProperty( String propertyName, String propertyValue ) throws Exception 1000 { 1001 wrappedPartition.setProperty( propertyName, propertyValue ); 1002 } 1003 1004 1005 @Override 1006 public void setSchemaManager( SchemaManager schemaManager ) 1007 { 1008 super.setSchemaManager( schemaManager ); 1009 } 1010 1011 1012 @Override 1013 public void setSubAliasIndexOn( Index<Long, ServerEntry, Long> index ) throws Exception 1014 { 1015 wrappedPartition.setSubAliasIndexOn( index ); 1016 } 1017 1018 1019 @Override 1020 public void setUpdnIndexOn( Index<String, ServerEntry, Long> index ) throws Exception 1021 { 1022 wrappedPartition.setUpdnIndexOn( index ); 1023 } 1024 1025 1026 @Override 1027 public void sync() throws Exception 1028 { 1029 wrappedPartition.sync(); 1030 //TODO implement the File I/O here to push the update to entries to the corresponding LDIF file 1031 } 1032 1033 1034 public void unbind( UnbindOperationContext unbindContext ) throws Exception 1035 { 1036 wrappedPartition.unbind( unbindContext ); 1037 } 1038 1039 1040 @Override 1041 public String getId() 1042 { 1043 // TODO Auto-generated method stub 1044 return super.getId(); 1045 } 1046 1047 1048 @Override 1049 public void setId( String id ) 1050 { 1051 super.setId( id ); 1052 wrappedPartition.setId( id ); 1053 } 1054 1055 1056 @Override 1057 public void setSuffix( String suffix ) throws LdapInvalidDnException 1058 { 1059 super.setSuffix( suffix ); 1060 wrappedPartition.setSuffix( suffix ); 1061 } 1062 1063 1064 /** 1065 * the interval at which the config directory containing LDIF files 1066 * should be scanned, default value is 10 min 1067 * 1068 * @param ldifScanInterval the scan interval time in minutes 1069 */ 1070 public void setLdifScanInterval( int ldifScanInterval ) 1071 { 1072 this.ldifScanInterval = ldifScanInterval; 1073 } 1074 1075 1076 /** 1077 * @return the workingDirectory 1078 */ 1079 public String getWorkingDirectory() 1080 { 1081 return workingDirectory; 1082 } 1083 1084 1085 /** 1086 * @param workingDirectory the workingDirectory to set 1087 */ 1088 public void setWorkingDirectory( String workingDirectory ) 1089 { 1090 this.workingDirectory = workingDirectory; 1091 } 1092 1093 1094 /** 1095 * @return the contextEntry 1096 */ 1097 public Entry getContextEntry() 1098 { 1099 return contextEntry; 1100 } 1101 1102 1103 /** 1104 * @param contextEntry the contextEntry to set 1105 */ 1106 public void setContextEntry( String contextEntry ) throws LdapLdifException 1107 { 1108 LdifReader ldifReader = new LdifReader(); 1109 List<LdifEntry> entries = ldifReader.parseLdif( contextEntry ); 1110 1111 try 1112 { 1113 ldifReader.close(); 1114 } 1115 catch ( IOException ioe ) 1116 { 1117 // What can we do here ??? 1118 } 1119 1120 this.contextEntry = new DefaultServerEntry( schemaManager, entries.get( 0 ).getEntry() ); 1121 } 1122 1123 1124 /** 1125 * @return the wrappedPartition 1126 */ 1127 public Partition getWrappedPartition() 1128 { 1129 return wrappedPartition; 1130 } 1131 1132 1133 /** 1134 * @param wrappedPartition the wrappedPartition to set 1135 */ 1136 public void setWrappedPartition( AvlPartition wrappedPartition ) 1137 { 1138 this.wrappedPartition = wrappedPartition; 1139 } 1140 }