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