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
021package org.apache.directory.ldap.client.api;
022
023
024import java.io.IOException;
025import java.text.ParseException;
026import java.util.ArrayList;
027import java.util.List;
028import java.util.Set;
029
030import org.apache.directory.api.i18n.I18n;
031import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants;
032import org.apache.directory.api.ldap.model.constants.SchemaConstants;
033import org.apache.directory.api.ldap.model.entry.Attribute;
034import org.apache.directory.api.ldap.model.entry.DefaultEntry;
035import org.apache.directory.api.ldap.model.entry.Entry;
036import org.apache.directory.api.ldap.model.entry.Value;
037import org.apache.directory.api.ldap.model.exception.LdapException;
038import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
039import org.apache.directory.api.ldap.model.name.Dn;
040import org.apache.directory.api.ldap.model.schema.AttributeType;
041import org.apache.directory.api.ldap.model.schema.AttributesFactory;
042import org.apache.directory.api.ldap.model.schema.DitContentRule;
043import org.apache.directory.api.ldap.model.schema.DitStructureRule;
044import org.apache.directory.api.ldap.model.schema.LdapSyntax;
045import org.apache.directory.api.ldap.model.schema.MatchingRule;
046import org.apache.directory.api.ldap.model.schema.MatchingRuleUse;
047import org.apache.directory.api.ldap.model.schema.NameForm;
048import org.apache.directory.api.ldap.model.schema.ObjectClass;
049import org.apache.directory.api.ldap.model.schema.SchemaObject;
050import org.apache.directory.api.ldap.model.schema.SchemaObjectWrapper;
051import org.apache.directory.api.ldap.model.schema.parsers.AttributeTypeDescriptionSchemaParser;
052import org.apache.directory.api.ldap.model.schema.parsers.DitContentRuleDescriptionSchemaParser;
053import org.apache.directory.api.ldap.model.schema.parsers.DitStructureRuleDescriptionSchemaParser;
054import org.apache.directory.api.ldap.model.schema.parsers.LdapComparatorDescription;
055import org.apache.directory.api.ldap.model.schema.parsers.LdapComparatorDescriptionSchemaParser;
056import org.apache.directory.api.ldap.model.schema.parsers.LdapSyntaxDescriptionSchemaParser;
057import org.apache.directory.api.ldap.model.schema.parsers.MatchingRuleDescriptionSchemaParser;
058import org.apache.directory.api.ldap.model.schema.parsers.MatchingRuleUseDescriptionSchemaParser;
059import org.apache.directory.api.ldap.model.schema.parsers.NameFormDescriptionSchemaParser;
060import org.apache.directory.api.ldap.model.schema.parsers.NormalizerDescription;
061import org.apache.directory.api.ldap.model.schema.parsers.NormalizerDescriptionSchemaParser;
062import org.apache.directory.api.ldap.model.schema.parsers.ObjectClassDescriptionSchemaParser;
063import org.apache.directory.api.ldap.model.schema.parsers.SyntaxCheckerDescription;
064import org.apache.directory.api.ldap.model.schema.parsers.SyntaxCheckerDescriptionSchemaParser;
065import org.apache.directory.api.ldap.model.schema.registries.AbstractSchemaLoader;
066import org.apache.directory.api.ldap.model.schema.registries.DefaultSchema;
067import org.apache.directory.api.ldap.model.schema.registries.Schema;
068import org.apache.directory.api.util.Base64;
069import org.apache.directory.api.util.Strings;
070import org.apache.directory.ldap.client.api.exception.InvalidConnectionException;
071import org.slf4j.Logger;
072import org.slf4j.LoggerFactory;
073
074
075/**
076 * A schema loader which uses LdapConnection to load schema from a ApacheDS serveur
077 *
078 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
079 */
080public class DefaultSchemaLoader extends AbstractSchemaLoader
081{
082    private static final String DEFAULT_APACHEDS_VENDOR_NAME = "Apache Software Foundation";
083
084    /** the logger */
085    private static final Logger LOG = LoggerFactory.getLogger( DefaultSchemaLoader.class );
086
087    /** the connection to the ldap server */
088    private LdapConnection connection;
089
090    /** the subschemaSubentry DN */
091    private Dn subschemaSubentryDn;
092
093    /** The SubschemaSubentry descriptions parsers */
094    private static final AttributeTypeDescriptionSchemaParser AT_DESCR_SCHEMA_PARSER = new AttributeTypeDescriptionSchemaParser();
095    private static final DitStructureRuleDescriptionSchemaParser DSR_DESCR_SCHEMA_PARSER = new DitStructureRuleDescriptionSchemaParser();
096    private static final DitContentRuleDescriptionSchemaParser DCR_DESCR_SCHEMA_PARSER = new DitContentRuleDescriptionSchemaParser();
097    private static final MatchingRuleDescriptionSchemaParser MR_DESCR_SCHEMA_PARSER = new MatchingRuleDescriptionSchemaParser();
098    private static final MatchingRuleUseDescriptionSchemaParser MRU_DESCR_SCHEMA_PARSER = new MatchingRuleUseDescriptionSchemaParser();
099    private static final NameFormDescriptionSchemaParser NF_DESCR_SCHEMA_PARSER = new NameFormDescriptionSchemaParser();
100    private static final ObjectClassDescriptionSchemaParser OC_DESCR_SCHEMA_PARSER = new ObjectClassDescriptionSchemaParser();
101    private static final LdapSyntaxDescriptionSchemaParser LS_DESCR_SCHEMA_PARSER = new LdapSyntaxDescriptionSchemaParser();
102
103    private static final LdapComparatorDescriptionSchemaParser C_DESCR_SCHEMA_PARSER = new LdapComparatorDescriptionSchemaParser();
104    private static final NormalizerDescriptionSchemaParser N_DESCR_SCHEMA_PARSER = new NormalizerDescriptionSchemaParser();
105    private static final SyntaxCheckerDescriptionSchemaParser SC_DESCR_SCHEMA_PARSER = new SyntaxCheckerDescriptionSchemaParser();
106
107
108    /**
109     * Creates a new instance of DefaultSchemaLoader.
110     *
111     * @param connection the LDAP connection
112     * @throws LdapException if the connection is not authenticated or if there are any problems
113     *                   while loading the schema entries
114     */
115    public DefaultSchemaLoader( LdapConnection connection ) throws LdapException
116    {
117        this( connection, false );
118    }
119
120
121    /**
122     * Creates a new instance of DefaultSchemaLoader.
123     *
124     * @param connection the LDAP connection
125     * @param relaxed initial setting for the relaxed mode
126     * @throws LdapException if the connection is not authenticated or if there are any problems
127     *                   while loading the schema entries
128     */
129    public DefaultSchemaLoader( LdapConnection connection, boolean relaxed ) throws LdapException
130    {
131        if ( connection == null )
132        {
133            throw new InvalidConnectionException( I18n.err( I18n.ERR_04104_NULL_CONNECTION_CANNOT_CONNECT ) );
134        }
135
136        this.connection = connection;
137        setRelaxed( relaxed );
138        setQuirksMode( relaxed );
139
140        // Flagging if the connection was already connected
141        boolean wasConnected = connection.isConnected();
142
143        try
144        {
145            // Connecting (if needed)
146            if ( !wasConnected )
147            {
148                connection.connect();
149            }
150
151            // Getting the subschemaSubentry DN from the rootDSE
152            Entry rootDse = connection.lookup( Dn.ROOT_DSE, SchemaConstants.SUBSCHEMA_SUBENTRY_AT,
153                SchemaConstants.VENDOR_NAME_AT );
154
155            if ( rootDse != null )
156            {
157                // Checking if this is an ApacheDS server
158                if ( isApacheDs( rootDse ) )
159                {
160                    // Getting the subSchemaSubEntry attribute
161                    Attribute subschemaSubentryAttribute = rootDse.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT );
162
163                    if ( ( subschemaSubentryAttribute != null ) && ( subschemaSubentryAttribute.size() > 0 ) )
164                    {
165                        subschemaSubentryDn = new Dn( connection.getSchemaManager(),
166                            subschemaSubentryAttribute.getString() );
167
168                        loadSchemas();
169                    }
170                }
171                else
172                {
173                    try
174                    {
175                        // No matter what, first try to search the schema from the rootDSE
176                        // Getting the subSchemaSubEntry attribute
177                        Attribute subschemaSubentryAttribute = rootDse.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT );
178
179                        if ( ( subschemaSubentryAttribute != null ) && ( subschemaSubentryAttribute.size() > 0 ) )
180                        {
181                            subschemaSubentryDn = new Dn( connection.getSchemaManager(),
182                                subschemaSubentryAttribute.getString() );
183
184                            loadSchemas();
185                        }
186                    }
187                    catch ( LdapException le )
188                    {
189                        // TODO : if we can't read the schema from the rootDSE, just try to read the 
190                        // schema from cn=schema
191                        throw le;
192                    }
193                }
194            }
195        }
196        finally
197        {
198            // Checking if the connection needs to be closed
199            if ( ( !wasConnected ) && ( connection.isConnected() ) )
200            {
201                try
202                {
203                    connection.close();
204                }
205                catch ( IOException e )
206                {
207                    throw new LdapException( e );
208                }
209            }
210        }
211    }
212
213
214    /**
215     * Creates a new instance of NetworkSchemaLoader.
216     *
217     * @param connection the LDAP connection
218     * @param subschemaSubentryDn The SubschemaSubentry
219     * @throws LdapException if the connection is not authenticated or if there are any problems
220     *                   while loading the schema entries
221     */
222    public DefaultSchemaLoader( LdapConnection connection, Dn subschemaSubentryDn ) throws LdapException
223    {
224        if ( !connection.isAuthenticated() )
225        {
226            throw new IllegalArgumentException( I18n.err( I18n.ERR_04105_CONNECTION_NOT_AUTHENTICATED ) );
227        }
228
229        this.connection = connection;
230        this.subschemaSubentryDn = subschemaSubentryDn;
231
232        loadSchemas();
233    }
234
235
236    /**
237     * Indicates if the given Root DSE corresponds to an ApacheDS server.
238     *
239     * @param rootDse the Root DSE
240     * @return <code>true</code> if this is an ApacheDS server,
241     *         <code>false</code> if not.
242     * @throws LdapInvalidAttributeValueException If the vendorName attribute contains an invalid value 
243     */
244    private boolean isApacheDs( Entry rootDse ) throws LdapInvalidAttributeValueException
245    {
246        if ( rootDse != null )
247        {
248            Attribute vendorNameAttribute = rootDse.get( SchemaConstants.VENDOR_NAME_AT );
249
250            if ( ( vendorNameAttribute != null ) && vendorNameAttribute.size() == 1 )
251            {
252                return DEFAULT_APACHEDS_VENDOR_NAME.equalsIgnoreCase( vendorNameAttribute.getString() );
253            }
254        }
255
256        return false;
257    }
258
259
260    /**
261     * Load all the schemas.
262     * 
263     * @throws LdapException If one schema can't be loaded
264     */
265    private void loadSchemas() throws LdapException
266    {
267        if ( LOG.isDebugEnabled() )
268        {
269            LOG.debug( I18n.msg( I18n.MSG_04160_INITIALIZING_SCHEMAS ) );
270        }
271
272        // Load all the elements from the SubschemaSubentry
273        Entry subschemaSubentry = connection.lookup( subschemaSubentryDn,
274            SchemaConstants.ATTRIBUTE_TYPES_AT,
275            SchemaConstants.COMPARATORS_AT,
276            SchemaConstants.DIT_CONTENT_RULES_AT,
277            SchemaConstants.DIT_STRUCTURE_RULES_AT,
278            SchemaConstants.LDAP_SYNTAXES_AT,
279            SchemaConstants.MATCHING_RULES_AT,
280            SchemaConstants.MATCHING_RULE_USE_AT,
281            SchemaConstants.NAME_FORMS_AT,
282            SchemaConstants.NORMALIZERS_AT,
283            SchemaConstants.OBJECT_CLASSES_AT,
284            SchemaConstants.SYNTAX_CHECKERS_AT
285            );
286
287        // Load all the AT
288        Attribute attributeTypes = subschemaSubentry.get( SchemaConstants.ATTRIBUTE_TYPES_AT );
289        loadAttributeTypes( attributeTypes );
290
291        // Load all the C
292        Attribute comparators = subschemaSubentry.get( SchemaConstants.COMPARATORS_AT );
293        loadComparators( comparators );
294
295        // Load all the DCR
296        Attribute ditContentRules = subschemaSubentry.get( SchemaConstants.DIT_CONTENT_RULES_AT );
297        loadDitContentRules( ditContentRules );
298
299        // Load all the DSR
300        Attribute ditStructureRules = subschemaSubentry.get( SchemaConstants.DIT_STRUCTURE_RULES_AT );
301        loadDitStructureRules( ditStructureRules );
302
303        // Load all the LS
304        Attribute ldapSytaxes = subschemaSubentry.get( SchemaConstants.LDAP_SYNTAXES_AT );
305        loadLdapSyntaxes( ldapSytaxes );
306
307        // Load all the MR
308        Attribute matchingRules = subschemaSubentry.get( SchemaConstants.MATCHING_RULES_AT );
309        loadMatchingRules( matchingRules );
310
311        // Load all the MRU
312        Attribute matchingRuleUse = subschemaSubentry.get( SchemaConstants.MATCHING_RULE_USE_AT );
313        loadMatchingRuleUses( matchingRuleUse );
314
315        // Load all the N
316        Attribute normalizers = subschemaSubentry.get( SchemaConstants.NORMALIZERS_AT );
317        loadNormalizers( normalizers );
318
319        // Load all the NF
320        Attribute nameForms = subschemaSubentry.get( SchemaConstants.NAME_FORMS_AT );
321        loadNameForms( nameForms );
322
323        // Load all the OC
324        Attribute objectClasses = subschemaSubentry.get( SchemaConstants.OBJECT_CLASSES_AT );
325        loadObjectClasses( objectClasses );
326
327        // Load all the SC
328        Attribute syntaxCheckers = subschemaSubentry.get( SchemaConstants.SYNTAX_CHECKERS_AT );
329        loadSyntaxCheckers( syntaxCheckers );
330    }
331
332
333    private void loadAttributeTypes( Attribute attributeTypes ) throws LdapException
334    {
335        if ( attributeTypes == null )
336        {
337            return;
338        }
339
340        for ( Value value : attributeTypes )
341        {
342            String desc = value.getString();
343
344            try
345            {
346                AttributeType attributeType = AT_DESCR_SCHEMA_PARSER.parse( desc );
347
348                updateSchemas( attributeType );
349            }
350            catch ( ParseException pe )
351            {
352                throw new LdapException( pe );
353            }
354        }
355    }
356
357
358    private void loadComparators( Attribute comparators ) throws LdapException
359    {
360        if ( comparators == null )
361        {
362            return;
363        }
364
365        for ( Value value : comparators )
366        {
367            String desc = value.getString();
368
369            try
370            {
371                LdapComparatorDescription comparator = C_DESCR_SCHEMA_PARSER.parse( desc );
372
373                updateSchemas( comparator );
374            }
375            catch ( ParseException pe )
376            {
377                throw new LdapException( pe );
378            }
379        }
380    }
381
382
383    private void loadDitContentRules( Attribute ditContentRules ) throws LdapException
384    {
385        if ( ditContentRules == null )
386        {
387            return;
388        }
389
390        for ( Value value : ditContentRules )
391        {
392            String desc = value.getString();
393
394            try
395            {
396                DitContentRule ditContentRule = DCR_DESCR_SCHEMA_PARSER.parse( desc );
397
398                updateSchemas( ditContentRule );
399            }
400            catch ( ParseException pe )
401            {
402                throw new LdapException( pe );
403            }
404        }
405    }
406
407
408    private void loadDitStructureRules( Attribute ditStructureRules ) throws LdapException
409    {
410        if ( ditStructureRules == null )
411        {
412            return;
413        }
414
415        for ( Value value : ditStructureRules )
416        {
417            String desc = value.getString();
418
419            try
420            {
421                DitStructureRule ditStructureRule = DSR_DESCR_SCHEMA_PARSER.parse( desc );
422
423                updateSchemas( ditStructureRule );
424            }
425            catch ( ParseException pe )
426            {
427                throw new LdapException( pe );
428            }
429        }
430    }
431
432
433    private void loadLdapSyntaxes( Attribute ldapSyntaxes ) throws LdapException
434    {
435        if ( ldapSyntaxes == null )
436        {
437            return;
438        }
439
440        for ( Value value : ldapSyntaxes )
441        {
442            String desc = value.getString();
443
444            try
445            {
446                LdapSyntax ldapSyntax = LS_DESCR_SCHEMA_PARSER.parse( desc );
447
448                updateSchemas( ldapSyntax );
449            }
450            catch ( ParseException pe )
451            {
452                throw new LdapException( pe );
453            }
454        }
455    }
456
457
458    private void loadMatchingRules( Attribute matchingRules ) throws LdapException
459    {
460        if ( matchingRules == null )
461        {
462            return;
463        }
464
465        for ( Value value : matchingRules )
466        {
467            String desc = value.getString();
468
469            try
470            {
471                MatchingRule matchingRule = MR_DESCR_SCHEMA_PARSER.parse( desc );
472
473                updateSchemas( matchingRule );
474            }
475            catch ( ParseException pe )
476            {
477                throw new LdapException( pe );
478            }
479        }
480    }
481
482
483    private void loadMatchingRuleUses( Attribute matchingRuleUses ) throws LdapException
484    {
485        if ( matchingRuleUses == null )
486        {
487            return;
488        }
489
490        for ( Value value : matchingRuleUses )
491        {
492            String desc = value.getString();
493
494            try
495            {
496                MatchingRuleUse matchingRuleUse = MRU_DESCR_SCHEMA_PARSER.parse( desc );
497
498                updateSchemas( matchingRuleUse );
499            }
500            catch ( ParseException pe )
501            {
502                throw new LdapException( pe );
503            }
504        }
505    }
506
507
508    private void loadNameForms( Attribute nameForms ) throws LdapException
509    {
510        if ( nameForms == null )
511        {
512            return;
513        }
514
515        for ( Value value : nameForms )
516        {
517            String desc = value.getString();
518
519            try
520            {
521                NameForm nameForm = NF_DESCR_SCHEMA_PARSER.parse( desc );
522
523                updateSchemas( nameForm );
524            }
525            catch ( ParseException pe )
526            {
527                throw new LdapException( pe );
528            }
529        }
530    }
531
532
533    private void loadNormalizers( Attribute normalizers ) throws LdapException
534    {
535        if ( normalizers == null )
536        {
537            return;
538        }
539
540        for ( Value value : normalizers )
541        {
542            String desc = value.getString();
543
544            try
545            {
546                NormalizerDescription normalizer = N_DESCR_SCHEMA_PARSER.parse( desc );
547
548                updateSchemas( normalizer );
549            }
550            catch ( ParseException pe )
551            {
552                throw new LdapException( pe );
553            }
554        }
555    }
556
557
558    private void loadObjectClasses( Attribute objectClasses ) throws LdapException
559    {
560        if ( objectClasses == null )
561        {
562            return;
563        }
564
565        for ( Value value : objectClasses )
566        {
567            String desc = value.getString();
568
569            try
570            {
571                ObjectClass objectClass = OC_DESCR_SCHEMA_PARSER.parse( desc );
572
573                updateSchemas( objectClass );
574            }
575            catch ( ParseException pe )
576            {
577                throw new LdapException( pe );
578            }
579        }
580    }
581
582
583    private void loadSyntaxCheckers( Attribute syntaxCheckers ) throws LdapException
584    {
585        if ( syntaxCheckers == null )
586        {
587            return;
588        }
589
590        for ( Value value : syntaxCheckers )
591        {
592            String desc = value.getString();
593
594            try
595            {
596                SyntaxCheckerDescription syntaxChecker = SC_DESCR_SCHEMA_PARSER.parse( desc );
597
598                updateSchemas( syntaxChecker );
599            }
600            catch ( ParseException pe )
601            {
602                throw new LdapException( pe );
603            }
604        }
605    }
606
607
608    private void updateSchemas( SchemaObject schemaObject )
609    {
610        String schemaName = schemaObject.getSchemaName();
611        Schema schema;
612
613        if ( Strings.isEmpty( schemaName ) || "null".equals( schemaName ) )
614        {
615            schemaName = "default";
616            schema = schemaMap.get( schemaName );
617        }
618        else
619        {
620            schema = schemaMap.get( schemaName );
621        }
622
623        if ( schema == null )
624        {
625            schema = new DefaultSchema( this, schemaName );
626
627            schemaMap.put( schemaName, schema );
628        }
629
630        schema.getContent().add( new SchemaObjectWrapper( schemaObject ) );
631
632    }
633
634
635    /**
636     * {@inheritDoc}
637     */
638    @Override
639    public List<Entry> loadAttributeTypes( Schema... schemas ) throws LdapException, IOException
640    {
641        List<Entry> attributeTypeEntries = new ArrayList<>();
642
643        if ( schemas == null )
644        {
645            return attributeTypeEntries;
646        }
647
648        AttributesFactory factory = new AttributesFactory();
649
650        for ( Schema schema : schemas )
651        {
652            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
653
654            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
655            {
656                SchemaObject schemaObject = schemaObjectWrapper.get();
657
658                if ( schemaObject instanceof AttributeType )
659                {
660                    AttributeType attributeType = ( AttributeType ) schemaObject;
661
662                    Entry attributeTypeEntry = factory.convert( attributeType, schema, null );
663
664                    attributeTypeEntries.add( attributeTypeEntry );
665                }
666            }
667        }
668
669        return attributeTypeEntries;
670    }
671
672
673    /**
674     * {@inheritDoc}
675     */
676    @Override
677    public List<Entry> loadComparators( Schema... schemas ) throws LdapException, IOException
678    {
679        List<Entry> comparatorEntries = new ArrayList<>();
680
681        if ( schemas == null )
682        {
683            return comparatorEntries;
684        }
685
686        for ( Schema schema : schemas )
687        {
688            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
689
690            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
691            {
692                SchemaObject schemaObject = schemaObjectWrapper.get();
693
694                if ( schemaObject instanceof LdapComparatorDescription )
695                {
696                    LdapComparatorDescription ldapComparatorDescription = ( LdapComparatorDescription ) schemaObject;
697                    Entry lcEntry = getEntry( ldapComparatorDescription );
698
699                    comparatorEntries.add( lcEntry );
700                }
701            }
702        }
703
704        return comparatorEntries;
705    }
706
707
708    /**
709     * {@inheritDoc}
710     */
711    @Override
712    public List<Entry> loadDitContentRules( Schema... schemas ) throws LdapException, IOException
713    {
714        List<Entry> ditContentRuleEntries = new ArrayList<>();
715
716        if ( schemas == null )
717        {
718            return ditContentRuleEntries;
719        }
720
721        AttributesFactory factory = new AttributesFactory();
722
723        for ( Schema schema : schemas )
724        {
725            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
726
727            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
728            {
729                SchemaObject schemaObject = schemaObjectWrapper.get();
730
731                if ( schemaObject instanceof DitContentRule )
732                {
733                    DitContentRule ditContentRule = ( DitContentRule ) schemaObject;
734
735                    Entry ditContentRuleEntry = factory.convert( ditContentRule, schema, null );
736
737                    ditContentRuleEntries.add( ditContentRuleEntry );
738                }
739            }
740        }
741
742        return ditContentRuleEntries;
743    }
744
745
746    /**
747     * {@inheritDoc}
748     */
749    @Override
750    public List<Entry> loadDitStructureRules( Schema... schemas ) throws LdapException, IOException
751    {
752        List<Entry> ditStructureRuleEntries = new ArrayList<>();
753
754        if ( schemas == null )
755        {
756            return ditStructureRuleEntries;
757        }
758
759        AttributesFactory factory = new AttributesFactory();
760
761        for ( Schema schema : schemas )
762        {
763            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
764
765            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
766            {
767                SchemaObject schemaObject = schemaObjectWrapper.get();
768
769                if ( schemaObject instanceof DitStructureRule )
770                {
771                    DitStructureRule ditStructureRule = ( DitStructureRule ) schemaObject;
772
773                    Entry ditStructureRuleEntry = factory.convert( ditStructureRule, schema, null );
774
775                    ditStructureRuleEntries.add( ditStructureRuleEntry );
776                }
777            }
778        }
779
780        return ditStructureRuleEntries;
781    }
782
783
784    /**
785     * {@inheritDoc}
786     */
787    @Override
788    public List<Entry> loadMatchingRuleUses( Schema... schemas ) throws LdapException, IOException
789    {
790        List<Entry> matchingRuleUseEntries = new ArrayList<>();
791
792        if ( schemas == null )
793        {
794            return matchingRuleUseEntries;
795        }
796
797        AttributesFactory factory = new AttributesFactory();
798
799        for ( Schema schema : schemas )
800        {
801            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
802
803            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
804            {
805                SchemaObject schemaObject = schemaObjectWrapper.get();
806
807                if ( schemaObject instanceof MatchingRuleUse )
808                {
809                    MatchingRuleUse matchingRuleUse = ( MatchingRuleUse ) schemaObject;
810
811                    Entry matchingRuleUseEntry = factory.convert( matchingRuleUse, schema, null );
812
813                    matchingRuleUseEntries.add( matchingRuleUseEntry );
814                }
815            }
816        }
817
818        return matchingRuleUseEntries;
819    }
820
821
822    /**
823     * {@inheritDoc}
824     */
825    @Override
826    public List<Entry> loadMatchingRules( Schema... schemas ) throws LdapException, IOException
827    {
828        List<Entry> matchingRuleEntries = new ArrayList<>();
829
830        if ( schemas == null )
831        {
832            return matchingRuleEntries;
833        }
834
835        AttributesFactory factory = new AttributesFactory();
836
837        for ( Schema schema : schemas )
838        {
839            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
840
841            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
842            {
843                SchemaObject schemaObject = schemaObjectWrapper.get();
844
845                if ( schemaObject instanceof MatchingRule )
846                {
847                    MatchingRule matchingRule = ( MatchingRule ) schemaObject;
848
849                    Entry matchingRuleEntry = factory.convert( matchingRule, schema, null );
850
851                    matchingRuleEntries.add( matchingRuleEntry );
852                }
853            }
854        }
855
856        return matchingRuleEntries;
857    }
858
859
860    /**
861     * {@inheritDoc}
862     */
863    @Override
864    public List<Entry> loadNameForms( Schema... schemas ) throws LdapException, IOException
865    {
866        List<Entry> nameFormEntries = new ArrayList<>();
867
868        if ( schemas == null )
869        {
870            return nameFormEntries;
871        }
872
873        AttributesFactory factory = new AttributesFactory();
874
875        for ( Schema schema : schemas )
876        {
877            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
878
879            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
880            {
881                SchemaObject schemaObject = schemaObjectWrapper.get();
882
883                if ( schemaObject instanceof NameForm )
884                {
885                    NameForm nameForm = ( NameForm ) schemaObject;
886
887                    Entry nameFormEntry = factory.convert( nameForm, schema, null );
888
889                    nameFormEntries.add( nameFormEntry );
890                }
891            }
892        }
893
894        return nameFormEntries;
895    }
896
897
898    /**
899     * {@inheritDoc}
900     */
901    @Override
902    public List<Entry> loadNormalizers( Schema... schemas ) throws LdapException, IOException
903    {
904        List<Entry> normalizerEntries = new ArrayList<>();
905
906        if ( schemas == null )
907        {
908            return normalizerEntries;
909        }
910
911        for ( Schema schema : schemas )
912        {
913            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
914
915            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
916            {
917                SchemaObject schemaObject = schemaObjectWrapper.get();
918
919                if ( schemaObject instanceof NormalizerDescription )
920                {
921                    NormalizerDescription normalizerDescription = ( NormalizerDescription ) schemaObject;
922                    Entry normalizerEntry = getEntry( normalizerDescription );
923
924                    normalizerEntries.add( normalizerEntry );
925                }
926            }
927        }
928
929        return normalizerEntries;
930    }
931
932
933    /**
934     * {@inheritDoc}
935     */
936    @Override
937    public List<Entry> loadObjectClasses( Schema... schemas ) throws LdapException, IOException
938    {
939        List<Entry> objectClassEntries = new ArrayList<>();
940
941        if ( schemas == null )
942        {
943            return objectClassEntries;
944        }
945
946        AttributesFactory factory = new AttributesFactory();
947
948        for ( Schema schema : schemas )
949        {
950            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
951
952            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
953            {
954                SchemaObject schemaObject = schemaObjectWrapper.get();
955
956                if ( schemaObject instanceof ObjectClass )
957                {
958                    ObjectClass objectClass = ( ObjectClass ) schemaObject;
959
960                    Entry objectClassEntry = factory.convert( objectClass, schema, null );
961
962                    objectClassEntries.add( objectClassEntry );
963                }
964            }
965        }
966
967        return objectClassEntries;
968    }
969
970
971    /**
972     * {@inheritDoc}
973     */
974    @Override
975    public List<Entry> loadSyntaxCheckers( Schema... schemas ) throws LdapException, IOException
976    {
977        List<Entry> syntaxCheckerEntries = new ArrayList<>();
978
979        if ( schemas == null )
980        {
981            return syntaxCheckerEntries;
982        }
983
984        for ( Schema schema : schemas )
985        {
986            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
987
988            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
989            {
990                SchemaObject schemaObject = schemaObjectWrapper.get();
991
992                if ( schemaObject instanceof SyntaxCheckerDescription )
993                {
994                    SyntaxCheckerDescription syntaxCheckerDescription = ( SyntaxCheckerDescription ) schemaObject;
995                    Entry syntaxCheckerEntry = getEntry( syntaxCheckerDescription );
996
997                    syntaxCheckerEntries.add( syntaxCheckerEntry );
998                }
999            }
1000        }
1001
1002        return syntaxCheckerEntries;
1003    }
1004
1005
1006    /**
1007     * {@inheritDoc}
1008     */
1009    @Override
1010    public List<Entry> loadSyntaxes( Schema... schemas ) throws LdapException, IOException
1011    {
1012        List<Entry> syntaxEntries = new ArrayList<>();
1013
1014        if ( schemas == null )
1015        {
1016            return syntaxEntries;
1017        }
1018
1019        AttributesFactory factory = new AttributesFactory();
1020
1021        for ( Schema schema : schemas )
1022        {
1023            Set<SchemaObjectWrapper> schemaObjectWrappers = schema.getContent();
1024
1025            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjectWrappers )
1026            {
1027                SchemaObject schemaObject = schemaObjectWrapper.get();
1028
1029                if ( schemaObject instanceof LdapSyntax )
1030                {
1031                    LdapSyntax ldapSyntax = ( LdapSyntax ) schemaObject;
1032
1033                    Entry ldapSyntaxEntry = factory.convert( ldapSyntax, schema, null );
1034
1035                    syntaxEntries.add( ldapSyntaxEntry );
1036                }
1037            }
1038        }
1039
1040        return syntaxEntries;
1041    }
1042
1043
1044    private Entry getEntry( LdapComparatorDescription comparatorDescription )
1045    {
1046        Entry entry = new DefaultEntry();
1047
1048        entry.put( SchemaConstants.OBJECT_CLASS_AT,
1049            SchemaConstants.TOP_OC,
1050            MetaSchemaConstants.META_TOP_OC,
1051            MetaSchemaConstants.META_COMPARATOR_OC );
1052
1053        entry.put( MetaSchemaConstants.M_OID_AT, comparatorDescription.getOid() );
1054        entry.put( MetaSchemaConstants.M_FQCN_AT, comparatorDescription.getFqcn() );
1055
1056        if ( comparatorDescription.getBytecode() != null )
1057        {
1058            entry.put( MetaSchemaConstants.M_BYTECODE_AT,
1059                Base64.decode( comparatorDescription.getBytecode().toCharArray() ) );
1060        }
1061
1062        if ( comparatorDescription.getDescription() != null )
1063        {
1064            entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, comparatorDescription.getDescription() );
1065        }
1066
1067        return entry;
1068    }
1069
1070
1071    private Entry getEntry( SyntaxCheckerDescription syntaxCheckerDescription )
1072    {
1073        Entry entry = new DefaultEntry();
1074
1075        entry.put( SchemaConstants.OBJECT_CLASS_AT,
1076            SchemaConstants.TOP_OC,
1077            MetaSchemaConstants.META_TOP_OC,
1078            MetaSchemaConstants.META_SYNTAX_CHECKER_OC );
1079
1080        entry.put( MetaSchemaConstants.M_OID_AT, syntaxCheckerDescription.getOid() );
1081        entry.put( MetaSchemaConstants.M_FQCN_AT, syntaxCheckerDescription.getFqcn() );
1082
1083        if ( syntaxCheckerDescription.getBytecode() != null )
1084        {
1085            entry.put( MetaSchemaConstants.M_BYTECODE_AT,
1086                Base64.decode( syntaxCheckerDescription.getBytecode().toCharArray() ) );
1087        }
1088
1089        if ( syntaxCheckerDescription.getDescription() != null )
1090        {
1091            entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, syntaxCheckerDescription.getDescription() );
1092        }
1093
1094        return entry;
1095    }
1096
1097
1098    private Entry getEntry( NormalizerDescription normalizerDescription )
1099    {
1100        Entry entry = new DefaultEntry();
1101
1102        entry.put( SchemaConstants.OBJECT_CLASS_AT,
1103            SchemaConstants.TOP_OC,
1104            MetaSchemaConstants.META_TOP_OC,
1105            MetaSchemaConstants.META_NORMALIZER_OC );
1106
1107        entry.put( MetaSchemaConstants.M_OID_AT, normalizerDescription.getOid() );
1108        entry.put( MetaSchemaConstants.M_FQCN_AT, normalizerDescription.getFqcn() );
1109
1110        if ( normalizerDescription.getBytecode() != null )
1111        {
1112            entry.put( MetaSchemaConstants.M_BYTECODE_AT,
1113                Base64.decode( normalizerDescription.getBytecode().toCharArray() ) );
1114        }
1115
1116        if ( normalizerDescription.getDescription() != null )
1117        {
1118            entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, normalizerDescription.getDescription() );
1119        }
1120
1121        return entry;
1122    }
1123
1124
1125    /**
1126     * Sets the quirks mode for all the internal parsers.
1127     *
1128     * If enabled the parser accepts non-numeric OIDs and some
1129     * special characters in descriptions.
1130     *
1131     * @param enabled the new quirks mode
1132     */
1133    public void setQuirksMode( boolean enabled )
1134    {
1135        AT_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1136        C_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1137        DCR_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1138        DSR_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1139        LS_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1140        MR_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1141        MRU_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1142        N_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1143        NF_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1144        OC_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1145        SC_DESCR_SCHEMA_PARSER.setQuirksMode( enabled );
1146    }
1147}