001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.server.schema.registries;
021
022
023 import java.util.ArrayList;
024 import java.util.HashMap;
025 import java.util.Iterator;
026 import java.util.List;
027 import java.util.Map;
028 import java.util.Properties;
029
030 import org.apache.directory.server.schema.bootstrap.Schema;
031 import org.apache.directory.shared.ldap.schema.AttributeType;
032 import org.apache.directory.shared.ldap.schema.MatchingRule;
033 import org.apache.directory.shared.ldap.schema.ObjectClass;
034 import org.apache.directory.shared.ldap.schema.SchemaObject;
035 import org.apache.directory.shared.ldap.schema.Syntax;
036
037
038 /**
039 * A set of boostrap registries used to fire up the server.
040 *
041 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
042 * @version $Rev: 778529 $
043 */
044 public class DefaultRegistries implements Registries
045 {
046 /** The AttributeType registry */
047 private AttributeTypeRegistry attributeTypeRegistry;
048
049 /** The ObjectClass registry */
050 private DefaultObjectClassRegistry objectClassRegistry;
051
052 private DefaultComparatorRegistry comparatorRegistry;
053 private DefaultDitContentRuleRegistry ditContentRuleRegistry;
054 private DefaultDitStructureRuleRegistry ditStructureRuleRegistry;
055 private DefaultMatchingRuleRegistry matchingRuleRegistry;
056 private DefaultMatchingRuleUseRegistry matchingRuleUseRegistry;
057 private DefaultNameFormRegistry nameFormRegistry;
058 private DefaultNormalizerRegistry normalizerRegistry;
059 private OidRegistry oidRegistry;
060 private DefaultSyntaxCheckerRegistry syntaxCheckerRegistry;
061 private DefaultSyntaxRegistry syntaxRegistry;
062 private Map<String,Schema> loadedByName = new HashMap<String, Schema>();
063 private final SchemaLoader schemaLoader;
064 private final String name;
065
066
067 public DefaultRegistries( String name, SchemaLoader schemaLoader, OidRegistry registry )
068 {
069 this.name = name;
070 this.schemaLoader = schemaLoader;
071
072 this.schemaLoader.setListener( new SchemaLoaderListener() {
073 public void schemaLoaded( Schema schema )
074 {
075 loadedByName.put( schema.getSchemaName(), schema );
076 }
077 });
078
079 oidRegistry = registry;
080 normalizerRegistry = new DefaultNormalizerRegistry();
081 comparatorRegistry = new DefaultComparatorRegistry();
082 syntaxCheckerRegistry = new DefaultSyntaxCheckerRegistry();
083 syntaxRegistry = new DefaultSyntaxRegistry( oidRegistry );
084 matchingRuleRegistry = new DefaultMatchingRuleRegistry( oidRegistry );
085 attributeTypeRegistry = new DefaultAttributeTypeRegistry( oidRegistry );
086 objectClassRegistry = new DefaultObjectClassRegistry( oidRegistry );
087 ditContentRuleRegistry = new DefaultDitContentRuleRegistry( oidRegistry );
088 ditStructureRuleRegistry = new DefaultDitStructureRuleRegistry( oidRegistry );
089 matchingRuleUseRegistry = new DefaultMatchingRuleUseRegistry();
090 nameFormRegistry = new DefaultNameFormRegistry( oidRegistry );
091 }
092
093
094 public String getName()
095 {
096 return name;
097 }
098
099
100 public AttributeTypeRegistry getAttributeTypeRegistry()
101 {
102 return attributeTypeRegistry;
103 }
104
105
106 public ComparatorRegistry getComparatorRegistry()
107 {
108 return comparatorRegistry;
109 }
110
111
112 public DITContentRuleRegistry getDitContentRuleRegistry()
113 {
114 return ditContentRuleRegistry;
115 }
116
117
118 public DITStructureRuleRegistry getDitStructureRuleRegistry()
119 {
120 return ditStructureRuleRegistry;
121 }
122
123
124 public MatchingRuleRegistry getMatchingRuleRegistry()
125 {
126 return matchingRuleRegistry;
127 }
128
129
130 public MatchingRuleUseRegistry getMatchingRuleUseRegistry()
131 {
132 return matchingRuleUseRegistry;
133 }
134
135
136 public NameFormRegistry getNameFormRegistry()
137 {
138 return nameFormRegistry;
139 }
140
141
142 public NormalizerRegistry getNormalizerRegistry()
143 {
144 return normalizerRegistry;
145 }
146
147
148 public ObjectClassRegistry getObjectClassRegistry()
149 {
150 return objectClassRegistry;
151 }
152
153
154 public OidRegistry getOidRegistry()
155 {
156 return oidRegistry;
157 }
158
159
160 public SyntaxCheckerRegistry getSyntaxCheckerRegistry()
161 {
162 return syntaxCheckerRegistry;
163 }
164
165
166 public SyntaxRegistry getSyntaxRegistry()
167 {
168 return syntaxRegistry;
169 }
170
171
172 // ------------------------------------------------------------------------
173 // Code used to sanity check the resolution of entities in registries
174 // ------------------------------------------------------------------------
175
176 /**
177 * Attempts to resolve the dependent schema objects of all entities that
178 * refer to other objects within the registries. Null references will be
179 * handed appropriately.
180 *
181 * @return a list of exceptions encountered while resolving entities
182 */
183 public List<Throwable> checkRefInteg()
184 {
185 ArrayList<Throwable> errors = new ArrayList<Throwable>();
186
187 Iterator<?> list = objectClassRegistry.iterator();
188 while ( list.hasNext() )
189 {
190 ObjectClass oc = ( ObjectClass ) list.next();
191 resolve( oc, errors );
192 }
193
194 list = attributeTypeRegistry.iterator();
195 while ( list.hasNext() )
196 {
197 AttributeType at = ( AttributeType ) list.next();
198 resolve( at, errors );
199 }
200
201 list = matchingRuleRegistry.iterator();
202 while ( list.hasNext() )
203 {
204 MatchingRule mr = ( MatchingRule ) list.next();
205 resolve( mr, errors );
206 }
207
208 list = syntaxRegistry.iterator();
209 while ( list.hasNext() )
210 {
211 Syntax syntax = ( Syntax ) list.next();
212 resolve( syntax, errors );
213 }
214
215 return errors;
216 }
217
218
219 /**
220 * Attempts to resolve the SyntaxChecker associated with a Syntax.
221 *
222 * @param syntax the Syntax to resolve the SyntaxChecker of
223 * @param errors the list of errors to add exceptions to
224 * @return true if it succeeds, false otherwise
225 */
226 private boolean resolve( Syntax syntax, List<Throwable> errors )
227 {
228 if ( syntax == null )
229 {
230 return true;
231 }
232
233 try
234 {
235 syntax.getSyntaxChecker();
236 return true;
237 }
238 catch ( Exception e )
239 {
240 errors.add( e );
241 return false;
242 }
243 }
244
245
246 private boolean resolve( MatchingRule mr, List<Throwable> errors )
247 {
248 boolean isSuccess = true;
249
250 if ( mr == null )
251 {
252 return true;
253 }
254
255 try
256 {
257 if ( mr.getComparator() == null )
258 {
259 String schema = matchingRuleRegistry.getSchemaName( mr.getOid() );
260 errors.add( new NullPointerException( "matchingRule " + mr.getName() + " in schema " + schema
261 + " with OID " + mr.getOid() + " has a null comparator" ) );
262 isSuccess = false;
263 }
264 }
265 catch ( Exception e )
266 {
267 errors.add( e );
268 isSuccess = false;
269 }
270
271 try
272 {
273 if ( mr.getNormalizer() == null )
274 {
275 String schema = matchingRuleRegistry.getSchemaName( mr.getOid() );
276 errors.add( new NullPointerException( "matchingRule " + mr.getName() + " in schema " + schema
277 + " with OID " + mr.getOid() + " has a null normalizer" ) );
278 isSuccess = false;
279 }
280 }
281 catch ( Exception e )
282 {
283 errors.add( e );
284 isSuccess = false;
285 }
286
287 try
288 {
289 isSuccess &= resolve( mr.getSyntax(), errors );
290
291 if ( mr.getSyntax() == null )
292 {
293 String schema = matchingRuleRegistry.getSchemaName( mr.getOid() );
294 errors.add( new NullPointerException( "matchingRule " + mr.getName() + " in schema " + schema
295 + " with OID " + mr.getOid() + " has a null Syntax" ) );
296 isSuccess = false;
297 }
298 }
299 catch ( Exception e )
300 {
301 errors.add( e );
302 isSuccess = false;
303 }
304
305 return isSuccess;
306 }
307
308
309 private boolean resolve( AttributeType at, List<Throwable> errors )
310 {
311 boolean isSuccess = true;
312
313 boolean hasMatchingRule = false;
314
315 if ( at == null )
316 {
317 return true;
318 }
319
320 try
321 {
322 isSuccess &= resolve( at.getSuperior(), errors );
323 }
324 catch ( Exception e )
325 {
326 errors.add( e );
327 isSuccess = false;
328 }
329
330 try
331 {
332 isSuccess &= resolve( at.getEquality(), errors );
333
334 if ( at.getEquality() != null )
335 {
336 hasMatchingRule |= true;
337 }
338 }
339 catch ( Exception e )
340 {
341 errors.add( e );
342 isSuccess = false;
343 }
344
345 try
346 {
347 isSuccess &= resolve( at.getOrdering(), errors );
348
349 if ( at.getOrdering() != null )
350 {
351 hasMatchingRule |= true;
352 }
353 }
354 catch ( Exception e )
355 {
356 errors.add( e );
357 isSuccess = false;
358 }
359
360 try
361 {
362 isSuccess &= resolve( at.getSubstr(), errors );
363
364 if ( at.getSubstr() != null )
365 {
366 hasMatchingRule |= true;
367 }
368 }
369 catch ( Exception e )
370 {
371 errors.add( e );
372 isSuccess = false;
373 }
374
375 try
376 {
377 isSuccess &= resolve( at.getSyntax(), errors );
378
379 if ( at.getSyntax() == null )
380 {
381 String schema = attributeTypeRegistry.getSchemaName( at.getOid() );
382
383 errors.add( new NullPointerException( "attributeType " + at.getName() + " in schema " + schema
384 + " with OID " + at.getOid() + " has a null Syntax" ) );
385
386 isSuccess = false;
387 }
388 }
389 catch ( Exception e )
390 {
391 errors.add( e );
392 isSuccess = false;
393 }
394
395 // try
396 // {
397 // String schema = attributeTypeRegistry.getSchemaName( at.getOid() );
398 // if ( ! hasMatchingRule && at.getSyntax().isHumanReadable() )
399 // {
400 // errors.add( new NullPointerException( "attributeType "
401 // + at.getName() + " in schema " + schema + " with OID "
402 // + at.getOid() + " has a no matchingRules defined" ) );
403 // isSuccess = false;
404 // }
405 // }
406 // catch ( NamingException e )
407 // {
408 // errors.add( e );
409 // isSuccess = false;
410 // }
411
412 return isSuccess;
413 }
414
415
416 private boolean resolve( ObjectClass oc, List<Throwable> errors )
417 {
418 boolean isSuccess = true;
419
420 if ( oc == null )
421 {
422 return true;
423 }
424
425 ObjectClass[] superiors = new org.apache.directory.shared.ldap.schema.ObjectClass[0];
426
427 try
428 {
429 superiors = oc.getSuperClasses();
430 }
431 catch ( Exception e )
432 {
433 superiors = new ObjectClass[0];
434 isSuccess = false;
435 errors.add( e );
436 }
437
438 for ( int ii = 0; ii < superiors.length; ii++ )
439 {
440 isSuccess &= resolve( superiors[ii], errors );
441 }
442
443 AttributeType[] mayList = new org.apache.directory.shared.ldap.schema.AttributeType[0];
444
445 try
446 {
447 mayList = oc.getMayList();
448 }
449 catch ( Exception e )
450 {
451 mayList = new AttributeType[0];
452 isSuccess = false;
453 errors.add( e );
454 }
455
456 for ( int ii = 0; ii < mayList.length; ii++ )
457 {
458 isSuccess &= resolve( mayList[ii], errors );
459 }
460
461 AttributeType[] mustList = new org.apache.directory.shared.ldap.schema.AttributeType[0];
462
463 try
464 {
465 mustList = oc.getMustList();
466 }
467 catch ( Exception e )
468 {
469 mustList = new AttributeType[0];
470 isSuccess = false;
471 errors.add( e );
472 }
473
474 for ( int ii = 0; ii < mustList.length; ii++ )
475 {
476 isSuccess &= resolve( mustList[ii], errors );
477 }
478
479 return isSuccess;
480 }
481
482
483 /**
484 * Alterations to the returned map of schema names to schema objects does not
485 * change the map returned from this method. The returned map is however mutable.
486 */
487 public Map<String, Schema> getLoadedSchemas()
488 {
489 return new HashMap<String,Schema>( loadedByName );
490 }
491
492
493 public void load( String schemaName ) throws Exception
494 {
495 load( schemaName, new Properties() );
496 }
497
498
499 public void load( String schemaName, Properties schemaProperties ) throws Exception
500 {
501 Schema schema = schemaLoader.getSchema( schemaName, schemaProperties );
502
503 if ( schema.isDisabled() )
504 {
505 throw new Exception( "Disabled schemas cannot be loaded into registries." );
506 }
507
508 loadedByName.put( schema.getSchemaName(), schema );
509 schemaLoader.load( schema, this, false );
510 }
511
512
513 public void unload( String schemaName ) throws Exception
514 {
515 disableSchema( ditStructureRuleRegistry, schemaName );
516 disableSchema( ditContentRuleRegistry, schemaName );
517 disableSchema( matchingRuleUseRegistry, schemaName );
518 disableSchema( nameFormRegistry, schemaName );
519 disableSchema( objectClassRegistry, schemaName );
520 disableSchema( attributeTypeRegistry, schemaName );
521 disableSchema( matchingRuleRegistry, schemaName );
522 disableSchema( syntaxRegistry, schemaName );
523
524 normalizerRegistry.unregisterSchemaElements( schemaName );
525 comparatorRegistry.unregisterSchemaElements( schemaName );
526 syntaxCheckerRegistry.unregisterSchemaElements( schemaName );
527 loadedByName.remove( schemaName );
528 }
529
530
531 private void disableSchema( SchemaObjectRegistry registry, String schemaName ) throws Exception
532 {
533 Iterator<? extends SchemaObject> objects = registry.iterator();
534 List<String> unregistered = new ArrayList<String>();
535 while ( objects.hasNext() )
536 {
537 SchemaObject obj = objects.next();
538 if ( obj.getSchema().equalsIgnoreCase( schemaName ) )
539 {
540 unregistered.add( obj.getOid() );
541 }
542 }
543
544 for ( String oid : unregistered )
545 {
546 registry.unregister( oid );
547 }
548 }
549
550
551 public SchemaLoader getSchemaLoader()
552 {
553 return schemaLoader;
554 }
555
556
557 public Schema getSchema( String schemaName )
558 {
559 return this.loadedByName.get( schemaName );
560 }
561
562
563 public void addToLoadedSet( Schema schema )
564 {
565 loadedByName.put( schema.getSchemaName(), schema );
566 }
567
568
569 public void removeFromLoadedSet( String schemaName )
570 {
571 loadedByName.remove( schemaName );
572 }
573 }