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