View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.core.schema;
21  
22  
23  import java.util.ArrayList;
24  import java.util.LinkedList;
25  import java.util.Collection;
26  import java.util.Comparator;
27  import java.util.HashMap;
28  import java.util.HashSet;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Properties;
33  import java.util.Set;
34  import java.util.Stack;
35  
36  import javax.naming.NamingException;
37  
38  import org.apache.directory.server.constants.MetaSchemaConstants;
39  import org.apache.directory.server.core.entry.ClonedServerEntry;
40  import org.apache.directory.server.core.entry.ServerEntry;
41  import org.apache.directory.server.core.filtering.EntryFilteringCursor;
42  import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
43  import org.apache.directory.server.core.interceptor.context.ListOperationContext;
44  import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
45  import org.apache.directory.server.core.partition.Partition;
46  import org.apache.directory.server.schema.bootstrap.Schema;
47  import org.apache.directory.server.schema.registries.AbstractSchemaLoader;
48  import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
49  import org.apache.directory.server.schema.registries.Registries;
50  import org.apache.directory.server.schema.registries.SchemaLoader;
51  import org.apache.directory.shared.ldap.constants.SchemaConstants;
52  import org.apache.directory.shared.ldap.entry.EntryAttribute;
53  import org.apache.directory.shared.ldap.entry.Value;
54  import org.apache.directory.shared.ldap.name.LdapDN;
55  import org.apache.directory.shared.ldap.schema.AttributeType;
56  import org.apache.directory.shared.ldap.schema.Normalizer;
57  import org.apache.directory.shared.ldap.schema.ObjectClass;
58  import org.apache.directory.shared.ldap.schema.Syntax;
59  import org.apache.directory.shared.ldap.schema.MatchingRule;
60  import org.apache.directory.shared.ldap.schema.syntax.ComparatorDescription;
61  import org.apache.directory.shared.ldap.schema.syntax.NormalizerDescription;
62  import org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker;
63  import org.apache.directory.shared.ldap.schema.syntax.SyntaxCheckerDescription;
64  import org.apache.directory.shared.ldap.util.Base64;
65      
66  import org.slf4j.Logger;
67  import org.slf4j.LoggerFactory;
68  
69  
70  /**
71   * A class that loads schemas from a partition.
72   *
73   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
74   * @version $Rev$
75   */
76  public class PartitionSchemaLoader extends AbstractSchemaLoader
77  {
78      /** static class logger */
79      private static final Logger LOG = LoggerFactory.getLogger( PartitionSchemaLoader.class );
80  
81      private final SchemaPartitionDao dao;
82      private SchemaEntityFactory factory;
83      private Partition partition;
84      
85      /** The attributeType registry */
86      private AttributeTypeRegistry atRegistry;
87      
88      private final AttributeType mOidAT;
89      private final AttributeType mNameAT;
90      private final AttributeType cnAT;
91      private final AttributeType byteCodeAT;
92      private final AttributeType descAT;
93      private final AttributeType fqcnAT;
94  
95      private static Map<String, LdapDN> staticAttributeTypeDNs = new HashMap<String, LdapDN>();
96      private static Map<String, LdapDN> staticMatchingRulesDNs = new HashMap<String, LdapDN>();
97      private static Map<String, LdapDN> staticObjectClassesDNs = new HashMap<String, LdapDN>();
98      private static Map<String, LdapDN> staticComparatorsDNs = new HashMap<String, LdapDN>();
99      private static Map<String, LdapDN> staticNormalizersDNs = new HashMap<String, LdapDN>();
100     private static Map<String, LdapDN> staticSyntaxCheckersDNs = new HashMap<String, LdapDN>();
101     private static Map<String, LdapDN> staticSyntaxesDNs = new HashMap<String, LdapDN>();
102     
103     
104     public PartitionSchemaLoader( Partition partition, Registries registries ) throws Exception
105     {
106         this.factory = new SchemaEntityFactory( registries );
107         this.partition = partition;
108         atRegistry = registries.getAttributeTypeRegistry();
109         
110         dao = new SchemaPartitionDao( this.partition, registries );
111         mOidAT = atRegistry.lookup( MetaSchemaConstants.M_OID_AT );
112         mNameAT = atRegistry.lookup( MetaSchemaConstants.M_NAME_AT );
113         cnAT = atRegistry.lookup( SchemaConstants.CN_AT );
114         byteCodeAT = atRegistry.lookup( MetaSchemaConstants.M_BYTECODE_AT );
115         descAT = atRegistry.lookup( MetaSchemaConstants.M_DESCRIPTION_AT );
116         fqcnAT = atRegistry.lookup( MetaSchemaConstants.M_FQCN_AT );
117         
118         initStaticDNs( "system" );
119         initStaticDNs( "core" );
120         initStaticDNs( "apache" );
121         initStaticDNs( "apachemeta" );
122         initStaticDNs( "other" );
123         initStaticDNs( "collective" );
124         initStaticDNs( "java" );
125         initStaticDNs( "cosine" );
126         initStaticDNs( "inetorgperson" );
127     }
128     
129     
130     private void initStaticDNs( String schemaName ) throws Exception
131     {
132         
133         // Initialize AttributeType Dns
134         LdapDN dn = new LdapDN( "ou=attributeTypes,cn=" + schemaName + ",ou=schema" );
135         dn.normalize( atRegistry.getNormalizerMapping() );
136         staticAttributeTypeDNs.put( schemaName, dn );
137 
138         // Initialize ObjectClasses Dns
139         dn = new LdapDN( "ou=objectClasses,cn=" + schemaName + ",ou=schema" );
140         dn.normalize( atRegistry.getNormalizerMapping() );
141         staticObjectClassesDNs.put( schemaName, dn );
142 
143         // Initialize MatchingRules Dns
144         dn = new LdapDN( "ou=matchingRules,cn=" + schemaName + ",ou=schema" );
145         dn.normalize( atRegistry.getNormalizerMapping() );
146         staticMatchingRulesDNs.put( schemaName, dn );
147 
148         // Initialize Comparators Dns
149         dn = new LdapDN( "ou=comparators,cn=" + schemaName + ",ou=schema" );
150         dn.normalize( atRegistry.getNormalizerMapping() );
151         staticComparatorsDNs.put( schemaName, dn );
152         
153         // Initialize Normalizers Dns
154         dn = new LdapDN( "ou=normalizers,cn=" + schemaName + ",ou=schema" );
155         dn.normalize( atRegistry.getNormalizerMapping() );
156         staticNormalizersDNs.put( schemaName, dn );
157 
158         // Initialize SyntaxCheckers Dns
159         dn = new LdapDN( "ou=syntaxCheckers,cn=" + schemaName + ",ou=schema" );
160         dn.normalize( atRegistry.getNormalizerMapping() );
161         staticSyntaxCheckersDNs.put( schemaName, dn );
162 
163         // Initialize Syntaxes Dns
164         dn = new LdapDN( "ou=syntaxes,cn=" + schemaName + ",ou=schema" );
165         dn.normalize( atRegistry.getNormalizerMapping() );
166         staticSyntaxesDNs.put( schemaName, dn );
167 
168     }
169     
170     /**
171      * Utility method to load all enabled schemas into this registry.
172      * 
173      * @param targetRegistries
174      * @throws NamingException
175      */
176     public void loadEnabled( Registries targetRegistries ) throws Exception
177     {
178         /* 
179          * We need to load all names and oids into the oid registry regardless of
180          * the entity being in an enabled schema.  This is necessary because we 
181          * search for values in the schema partition that represent matchingRules
182          * and other entities that are not loaded.  While searching these values
183          * in disabled schemas normalizers will attempt to equate names with oids
184          * and if there is an unrecognized value by a normalizer then the search 
185          * will fail.
186          * 
187          * For example there is a NameOrNumericOidNormalizer that will reduce a 
188          * numeric OID or a non-numeric OID to it's numeric form using the OID 
189          * registry.  While searching the schema partition for attributeTypes we
190          * might find values of matchingRules in the m-ordering, m-equality, and
191          * m-substr attributes of metaAttributeType definitions.  Now if an entry
192          * references a matchingRule that has not been loaded then the 
193          * NameOrNumericOidNormalizer will bomb out when it tries to resolve 
194          * names of matchingRules in unloaded schemas to OID values using the 
195          * OID registry.  To prevent this we need to load all the OID's in advance
196          * regardless of whether they are used or not.
197          */
198         EntryFilteringCursor cursor = dao.listAllNames();
199         
200         while ( cursor.next() )
201         {
202             ServerEntry entry = cursor.get();
203             String oid = entry.get( mOidAT ).getString();
204             EntryAttribute names = entry.get( mNameAT );
205             targetRegistries.getOidRegistry().register( oid, oid );
206             
207             for ( Value<?> value:names )
208             {
209                 targetRegistries.getOidRegistry().register( ( String ) value.get(), oid );
210             }
211         }
212         
213         cursor.close();
214         
215         
216         Map<String, Schema> allSchemaMap = getSchemas();
217         Set<Schema> enabledSchemaSet = new HashSet<Schema>();
218 
219         for ( Schema schema: allSchemaMap.values() )
220         {
221             if ( ! schema.isDisabled() )
222             {
223                 LOG.debug( "will attempt to load enabled schema: {}", schema.getSchemaName() );
224                     
225                 enabledSchemaSet.add( schema );
226             }
227             else
228             {
229                 LOG.debug( "will NOT attempt to load disabled schema: {}", schema.getSchemaName() );
230             }
231         }
232 
233         loadWithDependencies( enabledSchemaSet, targetRegistries );
234     }
235     
236     
237     /**
238      * Lists the names of the schemas that depend on the schema name provided.
239      * 
240      * @param schemaName the name of the schema to find dependents for
241      * @return a set of schemas (String names) that depend on the schema
242      * @throws NamingException if there are problems searching the schema partition
243      */
244     public Set<String> listDependentSchemaNames( String schemaName ) throws Exception
245     {
246         Set<String> dependees = new HashSet<String>();
247         Set<ServerEntry> results = dao.listSchemaDependents( schemaName );
248         
249         if ( results.isEmpty() )
250         {
251             return dependees;
252         }
253         
254         for ( ServerEntry sr: results )
255         {
256             EntryAttribute cn = sr.get( cnAT );
257             dependees.add( cn.getString() );
258         }
259         
260         return dependees;
261     }
262 
263     
264     /**
265      * Lists the names of the enabled schemas that depend on the schema name 
266      * provided.
267      * 
268      * @param schemaName the name of the schema to find dependents for
269      * @return a set of enabled schemas (String names) that depend on the schema
270      * @throws NamingException if there are problems searching the schema partition
271      */
272     public Set<String> listEnabledDependentSchemaNames( String schemaName ) throws Exception
273     {
274         Set<String> dependees = new HashSet<String>();
275         Set<ServerEntry> results = dao.listEnabledSchemaDependents( schemaName );
276         
277         if ( results.isEmpty() )
278         {
279             return dependees;
280         }
281         
282         for ( ServerEntry sr: results )
283         {
284             EntryAttribute cn = sr.get( cnAT );
285             dependees.add( cn.getString() );
286         }
287         
288         return dependees;
289     }
290 
291     
292     public Map<String,Schema> getSchemas() throws Exception
293     {
294         return dao.getSchemas();
295     }
296 
297     
298     public Set<String> getSchemaNames() throws Exception
299     {
300         return dao.getSchemaNames();
301     }
302     
303     
304     public Schema getSchema( String schemaName ) throws Exception
305     {
306         return dao.getSchema( schemaName );
307     }
308 
309 
310     public Schema getSchema( String schemaName, Properties schemaProperties ) throws Exception
311     {
312         return getSchema( schemaName );
313     }
314 
315 
316     public final void loadWithDependencies( Collection<Schema> schemas, Registries targetRegistries ) throws Exception
317     {
318         HashMap<String,Schema> notLoaded = new HashMap<String,Schema>();
319 
320         for ( Schema schema : schemas )
321         {
322             notLoaded.put( schema.getSchemaName(), schema );
323         }
324 
325         Iterator<Schema> list = notLoaded.values().iterator();
326         while ( list.hasNext() )
327         {
328             Schema schema = list.next();
329             loadDepsFirst( schema, new Stack<String>(), notLoaded, schema, targetRegistries, null );
330             list = notLoaded.values().iterator();
331         }
332     }
333 
334     /**
335      * {@link SchemaLoader#load(Schema, Registries, boolean)}
336      */
337     public final void load( Schema schema, Registries targetRegistries, boolean isDepLoad ) throws Exception
338     {
339         // if we're loading a dependency and it has not been enabled on 
340         // disk then enable it on disk before we proceed to load it
341         if ( schema.isDisabled() && isDepLoad )
342         {
343             dao.enableSchema( schema.getSchemaName() );
344         }
345         
346         if ( targetRegistries.getLoadedSchemas().containsKey( schema.getSchemaName() ) )
347         {
348             LOG.debug( "schema {} already seems to be loaded", schema.getSchemaName() );
349             return;
350         }
351         
352         LOG.debug( "loading {} schema ...", schema.getSchemaName() );
353         
354         loadComparators( schema, targetRegistries );
355         loadNormalizers( schema, targetRegistries );
356         loadSyntaxCheckers( schema, targetRegistries );
357         loadSyntaxes( schema, targetRegistries );
358         loadMatchingRules( schema, targetRegistries );
359         loadAttributeTypes( schema, targetRegistries );
360         loadObjectClasses( schema, targetRegistries );
361         loadMatchingRuleUses( schema, targetRegistries );
362         loadDitContentRules( schema, targetRegistries );
363         loadNameForms( schema, targetRegistries );
364         
365         // order does matter here so some special trickery is needed
366         // we cannot load a DSR before the DSRs it depends on are loaded?
367         // TODO need ot confirm this ( or we must make the class for this and use deferred 
368         // resolution until everything is available?
369         
370         loadDitStructureRules( schema, targetRegistries );
371         
372         
373         notifyListenerOrRegistries( schema, targetRegistries );
374     }
375 
376     
377     private void loadMatchingRuleUses( Schema schema, Registries targetRegistries )
378     {
379         // TODO Auto-generated method stub
380     }
381 
382 
383     private void loadDitStructureRules( Schema schema, Registries targetRegistries )
384     {
385         // TODO Auto-generated method stub
386     }
387 
388 
389     private void loadNameForms( Schema schema, Registries targetRegistries )
390     {
391         // TODO Auto-generated method stub
392     }
393 
394 
395     private void loadDitContentRules( Schema schema, Registries targetRegistries )
396     {
397         // TODO Auto-generated method stub
398     }
399 
400 
401     private void loadObjectClasses( Schema schema, Registries targetRegistries ) throws Exception
402     {
403         /**
404          * Sometimes search may return child objectClasses before their superiors have
405          * been registered like with attributeTypes.  To prevent this from bombing out
406          * the loader we will defer the registration of elements until later.
407          */
408         LinkedList<ObjectClass> deferred = new LinkedList<ObjectClass>();
409 
410         LdapDN dn = staticObjectClassesDNs.get( schema.getSchemaName() );
411         
412         if ( dn == null )
413         {
414             dn = new LdapDN( "ou=objectClasses,cn=" + schema.getSchemaName() + ",ou=schema" );
415             dn.normalize( atRegistry.getNormalizerMapping() );
416             staticObjectClassesDNs.put( schema.getSchemaName(), dn );
417         }
418         
419         if ( ! partition.hasEntry( new EntryOperationContext( null, dn ) ) )
420         {
421             return;
422         }
423         
424         LOG.debug( "{} schema: loading objectClasses", schema.getSchemaName() );
425         
426         EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
427         
428         while ( list.next() )
429         {
430             ClonedServerEntry result = list.get();
431             LdapDN resultDN = result.getDn();
432             resultDN.normalize( atRegistry.getNormalizerMapping() );
433             ClonedServerEntry attrs = lookupPartition( resultDN );
434             ObjectClass oc = factory.getObjectClass( attrs, targetRegistries, schema.getSchemaName() );
435             
436             try
437             {
438                 targetRegistries.getObjectClassRegistry().register( oc );
439             }
440             catch ( Exception ne )
441             {
442                 deferred.add( oc );
443             }
444         }
445         
446         LOG.debug( "Deferred queue size = {}", deferred.size() );
447         if ( LOG.isDebugEnabled() )
448         {
449             StringBuffer buf = new StringBuffer();
450             buf.append( "Deferred queue contains: " );
451             
452             for ( ObjectClass extra : deferred )
453             {
454                 buf.append( extra.getName() );
455                 buf.append( '[' );
456                 buf.append( extra.getOid() );
457                 buf.append( "]" );
458                 buf.append( "\n" );
459             }
460         }
461         
462         int lastCount = deferred.size();
463         while ( ! deferred.isEmpty() )
464         {
465             LOG.debug( "Deferred queue size = {}", deferred.size() );
466             ObjectClass oc = deferred.removeFirst();
467             Exception lastException = null;
468             
469             try
470             {
471                 targetRegistries.getObjectClassRegistry().register( oc );
472             }
473             catch ( Exception ne )
474             {
475                 deferred.addLast( oc );
476                 lastException = ne;
477             }
478             
479             // if we shrank the deferred list we're doing good and can continue
480             if ( deferred.size() < lastCount )
481             {
482                 lastCount = deferred.size();
483             }
484             else
485             {
486                 StringBuffer buf = new StringBuffer();
487                 buf.append( "A cycle must exist somewhere within the objectClasses of the " );
488                 buf.append( schema.getSchemaName() );
489                 buf.append( " schema.  We cannot seem to register the following objectClasses:\n" );
490                 
491                 for ( ObjectClass extra : deferred )
492                 {
493                     buf.append( extra.getName() );
494                     buf.append( '[' );
495                     buf.append( extra.getOid() );
496                     buf.append( "]" );
497                     buf.append( "\n" );
498                 }
499                 
500                 NamingException ne = new NamingException( buf.toString() );
501                 ne.setRootCause( lastException );
502             }
503         }
504     }
505 
506 
507     private void loadAttributeTypes( Schema schema, Registries targetRegistries ) throws Exception
508     {
509         LinkedList<AttributeType> deferred = new LinkedList<AttributeType>();
510         
511         LdapDN dn = staticAttributeTypeDNs.get( schema.getSchemaName() );
512         
513         if ( dn == null )
514         {
515             dn = new LdapDN( "ou=attributeTypes,cn=" + schema.getSchemaName() + ",ou=schema" );
516             dn.normalize( atRegistry.getNormalizerMapping() );
517             staticAttributeTypeDNs.put( schema.getSchemaName(), dn );
518         }
519         
520         if ( ! partition.hasEntry( new EntryOperationContext( null, dn ) ) )
521         {
522             return;
523         }
524         
525         LOG.debug( "{} schema: loading attributeTypes", schema.getSchemaName() );
526         
527         EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
528         
529         while ( list.next() )
530         {
531             ServerEntry result = list.get();
532             LdapDN resultDN = result.getDn();
533             resultDN.normalize( atRegistry.getNormalizerMapping() );
534             ServerEntry attrs = lookupPartition( resultDN );
535             AttributeType at = factory.getAttributeType( attrs, targetRegistries, schema.getSchemaName() );
536             try
537             {
538                 targetRegistries.getAttributeTypeRegistry().register( at );
539             }
540             catch ( Exception ne )
541             {
542                 deferred.add( at );
543             }
544         }
545 
546         LOG.debug( "Deferred queue size = {}", deferred.size() );
547         if ( LOG.isDebugEnabled() )
548         {
549             StringBuffer buf = new StringBuffer();
550             buf.append( "Deferred queue contains: " );
551             
552             for ( AttributeType extra : deferred )
553             {
554                 buf.append( extra.getName() );
555                 buf.append( '[' );
556                 buf.append( extra.getOid() );
557                 buf.append( "]" );
558                 buf.append( "\n" );
559             }
560         }
561         
562         int lastCount = deferred.size();
563         while ( ! deferred.isEmpty() )
564         {
565             LOG.debug( "Deferred queue size = {}", deferred.size() );
566             AttributeType at = deferred.removeFirst();
567             Exception lastException = null;
568             
569             try
570             {
571                 targetRegistries.getAttributeTypeRegistry().register( at );
572             }
573             catch ( Exception ne )
574             {
575                 deferred.addLast( at );
576                 lastException = ne;
577             }
578             
579             // if we shrank the deferred list we're doing good and can continue
580             if ( deferred.size() < lastCount )
581             {
582                 lastCount = deferred.size();
583             }
584             else
585             {
586                 StringBuffer buf = new StringBuffer();
587                 buf.append( "A cycle must exist somewhere within the attributeTypes of the " );
588                 buf.append( schema.getSchemaName() );
589                 buf.append( " schema.  We cannot seem to register the following attributeTypes:\n" );
590                 
591                 for ( AttributeType extra : deferred )
592                 {
593                     buf.append( extra.getName() );
594                     buf.append( '[' );
595                     buf.append( extra.getOid() );
596                     buf.append( "]" );
597                     buf.append( "\n" );
598                 }
599                 
600                 NamingException ne = new NamingException( buf.toString() );
601                 ne.setRootCause( lastException );
602             }
603         }
604     }
605 
606 
607     private void loadMatchingRules( Schema schema, Registries targetRegistries ) throws Exception
608     {
609         LdapDN dn = staticMatchingRulesDNs.get( schema.getSchemaName() );
610         
611         if ( dn == null )
612         {
613             dn = new LdapDN( "ou=matchingRules,cn=" + schema.getSchemaName() + ",ou=schema" );
614             dn.normalize( atRegistry.getNormalizerMapping() );
615             staticMatchingRulesDNs.put( schema.getSchemaName(), dn );
616         }
617         
618         if ( ! partition.hasEntry( new EntryOperationContext( null, dn ) ) )
619         {
620             return;
621         }
622         
623         LOG.debug( "{} schema: loading matchingRules", schema.getSchemaName() );
624         
625         EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
626         
627         while ( list.next() )
628         {
629             ServerEntry result = list.get();
630             LdapDN resultDN = result.getDn();
631             resultDN.normalize( atRegistry.getNormalizerMapping() );
632             ServerEntry attrs = lookupPartition( resultDN );
633             MatchingRule mrule = factory.getMatchingRule( attrs, targetRegistries, schema.getSchemaName() );
634             targetRegistries.getMatchingRuleRegistry().register( mrule );
635 
636         }
637     }
638 
639 
640     private void loadSyntaxes( Schema schema, Registries targetRegistries ) throws Exception
641     {
642         LdapDN dn = staticSyntaxesDNs.get( schema.getSchemaName() );
643         
644         if ( dn == null )
645         {
646             dn = new LdapDN( "ou=syntaxes,cn=" + schema.getSchemaName() + ",ou=schema" );
647             dn.normalize( atRegistry.getNormalizerMapping() );
648             staticSyntaxesDNs.put( schema.getSchemaName(), dn );
649         }
650         
651         if ( ! partition.hasEntry( new EntryOperationContext( null, dn ) ) )
652         {
653             return;
654         }
655         
656         LOG.debug( "{} schema: loading syntaxes", schema.getSchemaName() );
657         
658         EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
659         
660         while ( list.next() )
661         {
662             ServerEntry result = list.get();
663             LdapDN resultDN = result.getDn();
664             resultDN.normalize( atRegistry.getNormalizerMapping() );
665             ServerEntry attrs = lookupPartition( resultDN );
666             Syntax syntax = factory.getSyntax( attrs, targetRegistries, schema.getSchemaName() );
667             targetRegistries.getSyntaxRegistry().register( syntax );
668         }
669     }
670 
671 
672     private void loadSyntaxCheckers( Schema schema, Registries targetRegistries ) throws Exception
673     {
674         LdapDN dn = staticSyntaxCheckersDNs.get( schema.getSchemaName() );
675         
676         if ( dn == null )
677         {
678             dn = new LdapDN( "ou=syntaxCheckers,cn=" + schema.getSchemaName() + ",ou=schema" );
679             dn.normalize( atRegistry.getNormalizerMapping() );
680             staticSyntaxCheckersDNs.put( schema.getSchemaName(), dn );
681         }
682         
683         if ( ! partition.hasEntry( new EntryOperationContext( null, dn ) ) )
684         {
685             return;
686         }
687         
688         LOG.debug( "{} schema: loading syntaxCheckers", schema.getSchemaName() );
689         
690         EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
691         
692         while ( list.next() )
693         {
694             ServerEntry result = list.get();
695             LdapDN resultDN = result.getDn();
696             resultDN.normalize( atRegistry.getNormalizerMapping() );
697             ServerEntry attrs = lookupPartition( resultDN );
698             SyntaxChecker sc = factory.getSyntaxChecker( attrs, targetRegistries );
699             SyntaxCheckerDescription syntaxCheckerDescription = 
700                 getSyntaxCheckerDescription( schema.getSchemaName(), attrs );
701             targetRegistries.getSyntaxCheckerRegistry().register( syntaxCheckerDescription, sc );
702         }
703     }
704 
705 
706     private void loadNormalizers( Schema schema, Registries targetRegistries ) throws Exception
707     {
708         LdapDN dn = staticNormalizersDNs.get( schema.getSchemaName() );
709         
710         if ( dn == null )
711         {
712             dn = new LdapDN( "ou=normalizers,cn=" + schema.getSchemaName() + ",ou=schema" );
713             dn.normalize( atRegistry.getNormalizerMapping() );
714             staticNormalizersDNs.put( schema.getSchemaName(), dn );
715         }
716         
717         if ( ! partition.hasEntry( new EntryOperationContext( null, dn ) ) )
718         {
719             return;
720         }
721         
722         LOG.debug( "{} schema: loading normalizers", schema.getSchemaName() );
723         
724         EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
725         
726         while ( list.next() )
727         {
728             ClonedServerEntry result = list.get();
729             LdapDN resultDN = result.getDn();
730             resultDN.normalize( atRegistry.getNormalizerMapping() );
731             ServerEntry attrs = lookupPartition( resultDN );
732             Normalizer normalizer = factory.getNormalizer( attrs, targetRegistries );
733             NormalizerDescription normalizerDescription = getNormalizerDescription( schema.getSchemaName(), attrs );
734             targetRegistries.getNormalizerRegistry().register( normalizerDescription, normalizer );
735         }
736     }
737 
738 
739     private String getOid( ServerEntry entry ) throws Exception
740     {
741         EntryAttribute oid = entry.get( mOidAT );
742         
743         if ( oid == null )
744         {
745             return null;
746         }
747         
748         return oid.getString();
749     }
750 
751     
752     private NormalizerDescription getNormalizerDescription( String schemaName, ServerEntry entry ) throws Exception
753     {
754         NormalizerDescription description = new NormalizerDescription();
755         description.setNumericOid( getOid( entry ) );
756         List<String> values = new ArrayList<String>();
757         values.add( schemaName );
758         description.addExtension( MetaSchemaConstants.X_SCHEMA, values );
759         description.setFqcn( entry.get( fqcnAT ).getString() );
760         
761         EntryAttribute desc = entry.get( descAT );
762         if ( desc != null && desc.size() > 0 )
763         {
764             description.setDescription( desc.getString() );
765         }
766         
767         EntryAttribute bytecode = entry.get( byteCodeAT );
768         
769         if ( bytecode != null && bytecode.size() > 0 )
770         {
771             byte[] bytes = bytecode.getBytes();
772             description.setBytecode( new String( Base64.encode( bytes ) ) );
773         }
774 
775         return description;
776     }
777 
778     
779     private ClonedServerEntry lookupPartition( LdapDN dn ) throws Exception
780     {
781         return partition.lookup( new LookupOperationContext( null, dn ) );
782     }
783     
784     
785     @SuppressWarnings("unchecked")
786     private void loadComparators( Schema schema, Registries targetRegistries ) throws Exception
787     {
788         LdapDN dn = staticComparatorsDNs.get( schema.getSchemaName() );
789         
790         if ( dn == null )
791         {
792             dn = new LdapDN( "ou=comparators,cn=" + schema.getSchemaName() + ",ou=schema" );
793             dn.normalize( atRegistry.getNormalizerMapping() );
794             staticComparatorsDNs.put( schema.getSchemaName(), dn );
795         }
796 
797         if ( ! partition.hasEntry( new EntryOperationContext( null, dn ) ) )
798         {
799             return;
800         }
801         
802         LOG.debug( "{} schema: loading comparators", schema.getSchemaName() );
803         
804         EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
805         
806         while ( list.next() )
807         {
808             ClonedServerEntry result = list.get();
809             LdapDN resultDN = result.getDn();
810             resultDN.normalize( atRegistry.getNormalizerMapping() );
811             ClonedServerEntry attrs = lookupPartition( resultDN );
812             Comparator comparator = factory.getComparator( attrs, targetRegistries );
813             ComparatorDescription comparatorDescription = getComparatorDescription( schema.getSchemaName(), attrs );
814             targetRegistries.getComparatorRegistry().register( comparatorDescription, comparator );
815         }
816     }
817 
818 
819     private ComparatorDescription getComparatorDescription( String schemaName, ServerEntry entry ) throws Exception
820     {
821         ComparatorDescription description = new ComparatorDescription();
822         description.setNumericOid( getOid( entry ) );
823         List<String> values = new ArrayList<String>();
824         values.add( schemaName );
825         description.addExtension( MetaSchemaConstants.X_SCHEMA, values );
826         description.setFqcn( entry.get( fqcnAT ).getString() );
827         
828         EntryAttribute desc = entry.get( descAT );
829         
830         if ( desc != null && desc.size() > 0 )
831         {
832             description.setDescription( desc.getString() );
833         }
834         
835         EntryAttribute bytecode = entry.get( byteCodeAT );
836         
837         if ( bytecode != null && bytecode.size() > 0 )
838         {
839             byte[] bytes = bytecode.getBytes();
840             description.setBytecode( new String( Base64.encode( bytes ) ) );
841         }
842 
843         return description;
844     }
845 
846     
847     private SyntaxCheckerDescription getSyntaxCheckerDescription( String schemaName, ServerEntry entry ) 
848         throws Exception
849     {
850         SyntaxCheckerDescription description = new SyntaxCheckerDescription();
851         description.setNumericOid( getOid( entry ) );
852         List<String> values = new ArrayList<String>();
853         values.add( schemaName );
854         description.addExtension( MetaSchemaConstants.X_SCHEMA, values );
855         description.setFqcn( entry.get( fqcnAT ).getString() );
856         
857         EntryAttribute desc = entry.get( descAT );
858         
859         if ( desc != null && desc.size() > 0 )
860         {
861             description.setDescription( desc.getString() );
862         }
863         
864         EntryAttribute bytecode = entry.get( byteCodeAT );
865         
866         if ( bytecode != null && bytecode.size() > 0 )
867         {
868             byte[] bytes = bytecode.getBytes();
869             description.setBytecode( new String( Base64.encode( bytes ) ) );
870         }
871 
872         return description;
873     }
874 
875     
876     public void loadWithDependencies( Schema schema, Registries registries ) throws Exception
877     {
878         HashMap<String,Schema> notLoaded = new HashMap<String,Schema>();
879         notLoaded.put( schema.getSchemaName(), schema );                        
880         Properties props = new Properties();
881         loadDepsFirst( schema, new Stack<String>(), notLoaded, schema, registries, props );
882     }
883 }