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