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 }