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.schema.registries;
21  
22  
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Properties;
29  
30  import org.apache.directory.server.schema.bootstrap.Schema;
31  import org.apache.directory.shared.ldap.schema.AttributeType;
32  import org.apache.directory.shared.ldap.schema.MatchingRule;
33  import org.apache.directory.shared.ldap.schema.ObjectClass;
34  import org.apache.directory.shared.ldap.schema.SchemaObject;
35  import org.apache.directory.shared.ldap.schema.Syntax;
36  
37  
38  /**
39   * A set of boostrap registries used to fire up the server.
40   *
41   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
42   * @version $Rev: 658888 $
43   */
44  public class DefaultRegistries implements Registries
45  {
46      private DefaultAttributeTypeRegistry attributeTypeRegistry;
47      private DefaultComparatorRegistry comparatorRegistry;
48      private DefaultDitContentRuleRegistry ditContentRuleRegistry;
49      private DefaultDitStructureRuleRegistry ditStructureRuleRegistry;
50      private DefaultMatchingRuleRegistry matchingRuleRegistry;
51      private DefaultMatchingRuleUseRegistry matchingRuleUseRegistry;
52      private DefaultNameFormRegistry nameFormRegistry;
53      private DefaultNormalizerRegistry normalizerRegistry;
54      private DefaultObjectClassRegistry objectClassRegistry;
55      private OidRegistry oidRegistry;
56      private DefaultSyntaxCheckerRegistry syntaxCheckerRegistry;
57      private DefaultSyntaxRegistry syntaxRegistry;
58      private Map<String,Schema> loadedByName = new HashMap<String, Schema>();
59      private final SchemaLoader schemaLoader;
60      private final String name;
61  
62  
63      public DefaultRegistries( String name, SchemaLoader schemaLoader, OidRegistry registry )
64      {
65          this.name = name;
66          this.schemaLoader = schemaLoader;
67          this.schemaLoader.setListener( new SchemaLoaderListener() {
68              public void schemaLoaded( Schema schema )
69              {
70                  loadedByName.put( schema.getSchemaName(), schema );
71              }
72          });
73          oidRegistry = registry;
74          normalizerRegistry = new DefaultNormalizerRegistry();
75          comparatorRegistry = new DefaultComparatorRegistry();
76          syntaxCheckerRegistry = new DefaultSyntaxCheckerRegistry();
77          syntaxRegistry = new DefaultSyntaxRegistry( oidRegistry );
78          matchingRuleRegistry = new DefaultMatchingRuleRegistry( oidRegistry );
79          attributeTypeRegistry = new DefaultAttributeTypeRegistry( oidRegistry );
80          objectClassRegistry = new DefaultObjectClassRegistry( oidRegistry );
81          ditContentRuleRegistry = new DefaultDitContentRuleRegistry( oidRegistry );
82          ditStructureRuleRegistry = new DefaultDitStructureRuleRegistry( oidRegistry );
83          matchingRuleUseRegistry = new DefaultMatchingRuleUseRegistry();
84          nameFormRegistry = new DefaultNameFormRegistry( oidRegistry );
85      }
86  
87  
88      public String getName()
89      {
90          return name;
91      }
92      
93      
94      public AttributeTypeRegistry getAttributeTypeRegistry()
95      {
96          return attributeTypeRegistry;
97      }
98  
99  
100     public ComparatorRegistry getComparatorRegistry()
101     {
102         return comparatorRegistry;
103     }
104 
105 
106     public DITContentRuleRegistry getDitContentRuleRegistry()
107     {
108         return ditContentRuleRegistry;
109     }
110 
111 
112     public DITStructureRuleRegistry getDitStructureRuleRegistry()
113     {
114         return ditStructureRuleRegistry;
115     }
116 
117 
118     public MatchingRuleRegistry getMatchingRuleRegistry()
119     {
120         return matchingRuleRegistry;
121     }
122 
123 
124     public MatchingRuleUseRegistry getMatchingRuleUseRegistry()
125     {
126         return matchingRuleUseRegistry;
127     }
128 
129 
130     public NameFormRegistry getNameFormRegistry()
131     {
132         return nameFormRegistry;
133     }
134 
135 
136     public NormalizerRegistry getNormalizerRegistry()
137     {
138         return normalizerRegistry;
139     }
140 
141 
142     public ObjectClassRegistry getObjectClassRegistry()
143     {
144         return objectClassRegistry;
145     }
146 
147 
148     public OidRegistry getOidRegistry()
149     {
150         return oidRegistry;
151     }
152 
153 
154     public SyntaxCheckerRegistry getSyntaxCheckerRegistry()
155     {
156         return syntaxCheckerRegistry;
157     }
158 
159 
160     public SyntaxRegistry getSyntaxRegistry()
161     {
162         return syntaxRegistry;
163     }
164 
165 
166     // ------------------------------------------------------------------------
167     // Code used to sanity check the resolution of entities in registries
168     // ------------------------------------------------------------------------
169 
170     /**
171      * Attempts to resolve the dependent schema objects of all entities that
172      * refer to other objects within the registries.  Null references will be
173      * handed appropriately.
174      *
175      * @return a list of exceptions encountered while resolving entities
176      */
177     public List<Throwable> checkRefInteg()
178     {
179         ArrayList<Throwable> errors = new ArrayList<Throwable>();
180 
181         Iterator list = objectClassRegistry.iterator();
182         while ( list.hasNext() )
183         {
184             ObjectClass oc = ( ObjectClass ) list.next();
185             resolve( oc, errors );
186         }
187 
188         list = attributeTypeRegistry.list();
189         while ( list.hasNext() )
190         {
191             AttributeType at = ( AttributeType ) list.next();
192             resolve( at, errors );
193         }
194 
195         list = matchingRuleRegistry.iterator();
196         while ( list.hasNext() )
197         {
198             MatchingRule mr = ( MatchingRule ) list.next();
199             resolve( mr, errors );
200         }
201 
202         list = syntaxRegistry.iterator();
203         while ( list.hasNext() )
204         {
205             Syntax syntax = ( Syntax ) list.next();
206             resolve( syntax, errors );
207         }
208 
209         return errors;
210     }
211 
212 
213     /**
214      * Attempts to resolve the SyntaxChecker associated with a Syntax.
215      *
216      * @param syntax the Syntax to resolve the SyntaxChecker of
217      * @param errors the list of errors to add exceptions to
218      * @return true if it succeeds, false otherwise
219      */
220     private boolean resolve( Syntax syntax, List<Throwable> errors )
221     {
222         if ( syntax == null )
223         {
224             return true;
225         }
226 
227         try
228         {
229             syntax.getSyntaxChecker();
230             return true;
231         }
232         catch ( Exception e )
233         {
234             errors.add( e );
235             return false;
236         }
237     }
238 
239 
240     private boolean resolve( MatchingRule mr, List<Throwable> errors )
241     {
242         boolean isSuccess = true;
243 
244         if ( mr == null )
245         {
246             return true;
247         }
248 
249         try
250         {
251             if ( mr.getComparator() == null )
252             {
253                 String schema = matchingRuleRegistry.getSchemaName( mr.getOid() );
254                 errors.add( new NullPointerException( "matchingRule " + mr.getName() + " in schema " + schema
255                     + " with OID " + mr.getOid() + " has a null comparator" ) );
256                 isSuccess = false;
257             }
258         }
259         catch ( Exception e )
260         {
261             errors.add( e );
262             isSuccess = false;
263         }
264 
265         try
266         {
267             if ( mr.getNormalizer() == null )
268             {
269                 String schema = matchingRuleRegistry.getSchemaName( mr.getOid() );
270                 errors.add( new NullPointerException( "matchingRule " + mr.getName() + " in schema " + schema
271                     + " with OID " + mr.getOid() + " has a null normalizer" ) );
272                 isSuccess = false;
273             }
274         }
275         catch ( Exception e )
276         {
277             errors.add( e );
278             isSuccess = false;
279         }
280 
281         try
282         {
283             isSuccess &= resolve( mr.getSyntax(), errors );
284 
285             if ( mr.getSyntax() == null )
286             {
287                 String schema = matchingRuleRegistry.getSchemaName( mr.getOid() );
288                 errors.add( new NullPointerException( "matchingRule " + mr.getName() + " in schema " + schema
289                     + " with OID " + mr.getOid() + " has a null Syntax" ) );
290                 isSuccess = false;
291             }
292         }
293         catch ( Exception e )
294         {
295             errors.add( e );
296             isSuccess = false;
297         }
298 
299         return isSuccess;
300     }
301 
302 
303     private boolean resolve( AttributeType at, List<Throwable> errors )
304     {
305         boolean isSuccess = true;
306 
307         boolean hasMatchingRule = false;
308 
309         if ( at == null )
310         {
311             return true;
312         }
313 
314         try
315         {
316             isSuccess &= resolve( at.getSuperior(), errors );
317         }
318         catch ( Exception e )
319         {
320             errors.add( e );
321             isSuccess = false;
322         }
323 
324         try
325         {
326             isSuccess &= resolve( at.getEquality(), errors );
327 
328             if ( at.getEquality() != null )
329             {
330                 hasMatchingRule |= true;
331             }
332         }
333         catch ( Exception e )
334         {
335             errors.add( e );
336             isSuccess = false;
337         }
338 
339         try
340         {
341             isSuccess &= resolve( at.getOrdering(), errors );
342 
343             if ( at.getOrdering() != null )
344             {
345                 hasMatchingRule |= true;
346             }
347         }
348         catch ( Exception e )
349         {
350             errors.add( e );
351             isSuccess = false;
352         }
353 
354         try
355         {
356             isSuccess &= resolve( at.getSubstr(), errors );
357 
358             if ( at.getSubstr() != null )
359             {
360                 hasMatchingRule |= true;
361             }
362         }
363         catch ( Exception e )
364         {
365             errors.add( e );
366             isSuccess = false;
367         }
368 
369         try
370         {
371             isSuccess &= resolve( at.getSyntax(), errors );
372 
373             if ( at.getSyntax() == null )
374             {
375                 String schema = attributeTypeRegistry.getSchemaName( at.getOid() );
376 
377                 errors.add( new NullPointerException( "attributeType " + at.getName() + " in schema " + schema
378                     + " with OID " + at.getOid() + " has a null Syntax" ) );
379 
380                 isSuccess = false;
381             }
382         }
383         catch ( Exception e )
384         {
385             errors.add( e );
386             isSuccess = false;
387         }
388 
389         //        try
390         //        {
391         //            String schema = attributeTypeRegistry.getSchemaName( at.getOid() );
392         //            if ( ! hasMatchingRule && at.getSyntax().isHumanReadable() )
393         //            {
394         //                errors.add( new NullPointerException( "attributeType "
395         //                        + at.getName() + " in schema " + schema + " with OID "
396         //                        + at.getOid() + " has a no matchingRules defined" ) );
397         //                isSuccess = false;
398         //            }
399         //        }
400         //        catch ( NamingException e )
401         //        {
402         //            errors.add( e );
403         //            isSuccess = false;
404         //        }
405 
406         return isSuccess;
407     }
408 
409 
410     private boolean resolve( ObjectClass oc, List<Throwable> errors )
411     {
412         boolean isSuccess = true;
413 
414         if ( oc == null )
415         {
416             return true;
417         }
418 
419         ObjectClass[] superiors = new org.apache.directory.shared.ldap.schema.ObjectClass[0];
420 
421         try
422         {
423             superiors = oc.getSuperClasses();
424         }
425         catch ( Exception e )
426         {
427             superiors = new ObjectClass[0];
428             isSuccess = false;
429             errors.add( e );
430         }
431 
432         for ( int ii = 0; ii < superiors.length; ii++ )
433         {
434             isSuccess &= resolve( superiors[ii], errors );
435         }
436 
437         AttributeType[] mayList = new org.apache.directory.shared.ldap.schema.AttributeType[0];
438 
439         try
440         {
441             mayList = oc.getMayList();
442         }
443         catch ( Exception e )
444         {
445             mayList = new AttributeType[0];
446             isSuccess = false;
447             errors.add( e );
448         }
449 
450         for ( int ii = 0; ii < mayList.length; ii++ )
451         {
452             isSuccess &= resolve( mayList[ii], errors );
453         }
454 
455         AttributeType[] mustList = new org.apache.directory.shared.ldap.schema.AttributeType[0];
456 
457         try
458         {
459             mustList = oc.getMustList();
460         }
461         catch ( Exception e )
462         {
463             mustList = new AttributeType[0];
464             isSuccess = false;
465             errors.add( e );
466         }
467 
468         for ( int ii = 0; ii < mustList.length; ii++ )
469         {
470             isSuccess &= resolve( mustList[ii], errors );
471         }
472 
473         return isSuccess;
474     }
475 
476     
477     /**
478      * Alterations to the returned map of schema names to schema objects does not 
479      * change the map returned from this method.  The returned map is however mutable.
480      */
481     public Map<String, Schema> getLoadedSchemas()
482     {
483         return new HashMap<String,Schema>( loadedByName );
484     }
485 
486 
487     public void load( String schemaName ) throws Exception
488     {
489         load( schemaName, new Properties() );
490     }
491 
492 
493     public void load( String schemaName, Properties schemaProperties ) throws Exception
494     {
495         Schema schema = schemaLoader.getSchema( schemaName, schemaProperties );
496         
497         if ( schema.isDisabled() )
498         {
499             throw new Exception( "Disabled schemas cannot be loaded into registries." );
500         }
501         
502         loadedByName.put( schema.getSchemaName(), schema );
503         schemaLoader.load( schema, this, false );
504     }
505     
506     
507     public void unload( String schemaName ) throws Exception
508     {
509         disableSchema( ditStructureRuleRegistry, schemaName );
510         disableSchema( ditContentRuleRegistry, schemaName );
511         disableSchema( matchingRuleUseRegistry, schemaName );
512         disableSchema( nameFormRegistry, schemaName );
513         disableSchema( objectClassRegistry, schemaName );
514         disableSchema( attributeTypeRegistry, schemaName );
515         disableSchema( matchingRuleRegistry, schemaName );
516         disableSchema( syntaxRegistry, schemaName );
517 
518         normalizerRegistry.unregisterSchemaElements( schemaName );
519         comparatorRegistry.unregisterSchemaElements( schemaName );
520         syntaxCheckerRegistry.unregisterSchemaElements( schemaName );
521         loadedByName.remove( schemaName );
522     }
523 
524 
525     private void disableSchema( SchemaObjectRegistry registry, String schemaName ) throws Exception
526     {
527         Iterator<? extends SchemaObject> objects = registry.iterator();
528         List<String> unregistered = new ArrayList<String>();
529         while ( objects.hasNext() )
530         {
531             SchemaObject obj = objects.next();
532             if ( obj.getSchema().equalsIgnoreCase( schemaName ) )
533             {
534                 unregistered.add( obj.getOid() );
535             }
536         }
537         
538         for ( String oid : unregistered )
539         {
540             registry.unregister( oid );
541         }
542     }
543     
544 
545     public SchemaLoader setSchemaLoader()
546     {
547         return schemaLoader;
548     }
549 
550 
551     public Schema getSchema( String schemaName )
552     {
553         return this.loadedByName.get( schemaName );
554     }
555 
556 
557     public void addToLoadedSet( Schema schema )
558     {
559         loadedByName.put( schema.getSchemaName(), schema );
560     }
561 
562 
563     public void removeFromLoadedSet( String schemaName )
564     {
565         loadedByName.remove( schemaName );
566     }
567 }