1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.directory.server.core.schema;
20
21
22 import org.apache.directory.server.constants.ApacheSchemaConstants;
23 import org.apache.directory.server.constants.ServerDNConstants;
24 import org.apache.directory.server.core.entry.DefaultServerAttribute;
25 import org.apache.directory.server.core.entry.DefaultServerEntry;
26 import org.apache.directory.server.core.entry.ServerAttribute;
27 import org.apache.directory.server.core.entry.ServerEntry;
28 import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
29 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
30 import org.apache.directory.server.schema.registries.Registries;
31 import org.apache.directory.shared.ldap.constants.SchemaConstants;
32 import org.apache.directory.shared.ldap.entry.EntryAttribute;
33 import org.apache.directory.shared.ldap.name.LdapDN;
34 import org.apache.directory.shared.ldap.schema.AttributeType;
35 import org.apache.directory.shared.ldap.schema.DITContentRule;
36 import org.apache.directory.shared.ldap.schema.DITStructureRule;
37 import org.apache.directory.shared.ldap.schema.MatchingRule;
38 import org.apache.directory.shared.ldap.schema.MatchingRuleUse;
39 import org.apache.directory.shared.ldap.schema.NameForm;
40 import org.apache.directory.shared.ldap.schema.ObjectClass;
41 import org.apache.directory.shared.ldap.schema.SchemaUtils;
42 import org.apache.directory.shared.ldap.schema.Syntax;
43 import org.apache.directory.shared.ldap.schema.syntax.ComparatorDescription;
44 import org.apache.directory.shared.ldap.schema.syntax.NormalizerDescription;
45 import org.apache.directory.shared.ldap.schema.syntax.SyntaxCheckerDescription;
46
47 import javax.naming.NamingException;
48 import java.util.HashSet;
49 import java.util.Iterator;
50 import java.util.Set;
51
52
53
54
55
56
57
58
59 public class SchemaService
60 {
61 private static final String[] EMPTY_STRING_ARRAY = new String[0];
62 private static final String SCHEMA_TIMESTAMP_ENTRY_DN = "cn=schemaModifications,ou=schema";
63
64
65
66 private ServerEntry schemaSubentry;
67 private final Object lock = new Object();
68
69
70 private Registries registries;
71
72
73 private JdbmPartition schemaPartition;
74
75
76 private SchemaOperationControl schemaControl;
77
78
79
80
81 private LdapDN schemaModificationAttributesDN;
82
83
84
85 public SchemaService( Registries registries, JdbmPartition schemaPartition, SchemaOperationControl schemaControl ) throws NamingException
86 {
87 this.registries = registries;
88 this.schemaPartition = schemaPartition;
89 this.schemaControl = schemaControl;
90
91 schemaModificationAttributesDN = new LdapDN( SCHEMA_TIMESTAMP_ENTRY_DN );
92 schemaModificationAttributesDN.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
93 }
94
95
96 public boolean isSchemaSubentry( String dnString ) throws NamingException
97 {
98 if ( dnString.equalsIgnoreCase( ServerDNConstants.CN_SCHEMA_DN ) ||
99 dnString.equalsIgnoreCase( ServerDNConstants.CN_SCHEMA_DN_NORMALIZED ) )
100 {
101 return true;
102 }
103
104 LdapDN dn = new LdapDN( dnString ).normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
105 return dn.getNormName().equals( ServerDNConstants.CN_SCHEMA_DN_NORMALIZED );
106 }
107
108
109 public Registries getRegistries()
110 {
111 return registries;
112 }
113
114
115 private ServerAttribute generateComparators() throws NamingException
116 {
117 ServerAttribute attr = new DefaultServerAttribute(
118 registries.getAttributeTypeRegistry().lookup( SchemaConstants.COMPARATORS_AT ) );
119
120 Iterator<ComparatorDescription> list = registries.getComparatorRegistry().comparatorDescriptionIterator();
121
122 while ( list.hasNext() )
123 {
124 ComparatorDescription description = list.next();
125 attr.add( SchemaUtils.render( description ).toString() );
126 }
127
128 return attr;
129 }
130
131
132 private ServerAttribute generateNormalizers() throws NamingException
133 {
134 ServerAttribute attr = new DefaultServerAttribute(
135 registries.getAttributeTypeRegistry().lookup( SchemaConstants.NORMALIZERS_AT ) );
136
137 Iterator<NormalizerDescription> list = registries.getNormalizerRegistry().normalizerDescriptionIterator();
138
139 while ( list.hasNext() )
140 {
141 NormalizerDescription normalizer = list.next();
142 attr.add( SchemaUtils.render( normalizer ).toString() );
143 }
144
145 return attr;
146 }
147
148
149 private ServerAttribute generateSyntaxCheckers() throws NamingException
150 {
151 ServerAttribute attr = new DefaultServerAttribute(
152 registries.getAttributeTypeRegistry().lookup( SchemaConstants.SYNTAX_CHECKERS_AT ) );
153
154 Iterator<SyntaxCheckerDescription> list =
155 registries.getSyntaxCheckerRegistry().syntaxCheckerDescriptionIterator();
156
157 while ( list.hasNext() )
158 {
159 SyntaxCheckerDescription syntaxCheckerDescription = list.next();
160 attr.add( SchemaUtils.render( syntaxCheckerDescription ).toString() );
161 }
162
163 return attr;
164 }
165
166
167 private ServerAttribute generateObjectClasses() throws NamingException
168 {
169 ServerAttribute attr = new DefaultServerAttribute(
170 registries.getAttributeTypeRegistry().lookup( SchemaConstants.OBJECT_CLASSES_AT ) );
171
172 Iterator<ObjectClass> list = registries.getObjectClassRegistry().iterator();
173
174 while ( list.hasNext() )
175 {
176 ObjectClass oc = list.next();
177 attr.add( SchemaUtils.render( oc ).toString() );
178 }
179
180 return attr;
181 }
182
183
184 private ServerAttribute generateAttributeTypes() throws NamingException
185 {
186 ServerAttribute attr = new DefaultServerAttribute(
187 registries.getAttributeTypeRegistry().lookup( SchemaConstants.ATTRIBUTE_TYPES_AT ) );
188
189 Iterator<AttributeType> list = registries.getAttributeTypeRegistry().iterator();
190
191 while ( list.hasNext() )
192 {
193 AttributeType at = list.next();
194 attr.add( SchemaUtils.render( at ).toString() );
195 }
196
197 return attr;
198 }
199
200
201 private ServerAttribute generateMatchingRules() throws NamingException
202 {
203 ServerAttribute attr = new DefaultServerAttribute(
204 registries.getAttributeTypeRegistry().lookup( SchemaConstants.MATCHING_RULES_AT ) );
205
206 Iterator<MatchingRule> list = registries.getMatchingRuleRegistry().iterator();
207
208 while ( list.hasNext() )
209 {
210 MatchingRule mr = list.next();
211 attr.add( SchemaUtils.render( mr ).toString() );
212 }
213
214 return attr;
215 }
216
217
218 private ServerAttribute generateMatchingRuleUses() throws NamingException
219 {
220 ServerAttribute attr = new DefaultServerAttribute(
221 registries.getAttributeTypeRegistry().lookup( SchemaConstants.MATCHING_RULE_USE_AT ) );
222
223 Iterator<MatchingRuleUse> list = registries.getMatchingRuleUseRegistry().iterator();
224
225 while ( list.hasNext() )
226 {
227 MatchingRuleUse mru = list.next();
228 attr.add( SchemaUtils.render( mru ).toString() );
229 }
230
231 return attr;
232 }
233
234
235 private ServerAttribute generateSyntaxes() throws NamingException
236 {
237 ServerAttribute attr = new DefaultServerAttribute(
238 registries.getAttributeTypeRegistry().lookup( SchemaConstants.LDAP_SYNTAXES_AT ) );
239
240 Iterator<Syntax> list = registries.getSyntaxRegistry().iterator();
241
242 while ( list.hasNext() )
243 {
244 Syntax syntax = list.next();
245 attr.add( SchemaUtils.render( syntax ).toString() );
246 }
247
248 return attr;
249 }
250
251
252 private ServerAttribute generateDitContextRules() throws NamingException
253 {
254 ServerAttribute attr = new DefaultServerAttribute(
255 registries.getAttributeTypeRegistry().lookup( SchemaConstants.DIT_CONTENT_RULES_AT ) );
256
257 Iterator<DITContentRule> list = registries.getDitContentRuleRegistry().iterator();
258
259 while ( list.hasNext() )
260 {
261 DITContentRule dcr = list.next();
262 attr.add( SchemaUtils.render( dcr ).toString() );
263 }
264
265 return attr;
266 }
267
268
269 private ServerAttribute generateDitStructureRules() throws NamingException
270 {
271 ServerAttribute attr = new DefaultServerAttribute(
272 registries.getAttributeTypeRegistry().lookup( SchemaConstants.DIT_STRUCTURE_RULES_AT ) );
273
274 Iterator<DITStructureRule> list = registries.getDitStructureRuleRegistry().iterator();
275
276 while ( list.hasNext() )
277 {
278 DITStructureRule dsr = list.next();
279 attr.add( SchemaUtils.render( dsr ).toString() );
280 }
281
282 return attr;
283 }
284
285
286 private ServerAttribute generateNameForms() throws NamingException
287 {
288 ServerAttribute attr = new DefaultServerAttribute(
289 registries.getAttributeTypeRegistry().lookup( SchemaConstants.NAME_FORMS_AT ) );
290
291 Iterator<NameForm> list = registries.getNameFormRegistry().iterator();
292
293 while ( list.hasNext() )
294 {
295 NameForm nf = list.next();
296 attr.add( SchemaUtils.render( nf ).toString() );
297 }
298
299 return attr;
300 }
301
302
303 private void generateSchemaSubentry( ServerEntry mods ) throws NamingException
304 {
305 ServerEntry attrs = new DefaultServerEntry( registries, mods.getDn() );
306
307
308 attrs.put( SchemaConstants.OBJECT_CLASS_AT,
309 SchemaConstants.TOP_OC,
310 SchemaConstants.SUBSCHEMA_OC,
311 SchemaConstants.SUBENTRY_OC,
312 ApacheSchemaConstants.APACHE_SUBSCHEMA_OC
313 );
314
315
316 attrs.put( SchemaConstants.CN_AT, "schema" );
317
318
319 attrs.put( generateComparators() );
320 attrs.put( generateNormalizers() );
321 attrs.put( generateSyntaxCheckers() );
322 attrs.put( generateObjectClasses() );
323 attrs.put( generateAttributeTypes() );
324 attrs.put( generateMatchingRules() );
325 attrs.put( generateMatchingRuleUses() );
326 attrs.put( generateSyntaxes() );
327 attrs.put( generateDitContextRules() );
328 attrs.put( generateDitStructureRules() );
329 attrs.put( generateNameForms() );
330 attrs.put( SchemaConstants.SUBTREE_SPECIFICATION_AT, "{}" );
331
332
333
334
335
336
337 AttributeType createTimestampAT = registries.
338 getAttributeTypeRegistry().lookup( SchemaConstants.CREATE_TIMESTAMP_AT );
339 EntryAttribute createTimestamp = mods.get( createTimestampAT );
340 attrs.put( SchemaConstants.CREATE_TIMESTAMP_AT, createTimestamp.get() );
341
342
343 attrs.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN );
344
345
346 AttributeType schemaModifyTimestampAT = registries.
347 getAttributeTypeRegistry().lookup( ApacheSchemaConstants.SCHEMA_MODIFY_TIMESTAMP_AT );
348 EntryAttribute schemaModifyTimestamp = mods.get( schemaModifyTimestampAT );
349 attrs.put( SchemaConstants.MODIFY_TIMESTAMP_AT, schemaModifyTimestamp.get() );
350
351
352 AttributeType schemaModifiersNameAT = registries.
353 getAttributeTypeRegistry().lookup( ApacheSchemaConstants.SCHEMA_MODIFIERS_NAME_AT );
354 EntryAttribute schemaModifiersName = mods.get( schemaModifiersNameAT );
355 attrs.put( SchemaConstants.MODIFIERS_NAME_AT, schemaModifiersName.get() );
356
357
358
359 synchronized ( lock )
360 {
361 schemaSubentry = attrs;
362 }
363 }
364
365
366 private void addAttribute( ServerEntry attrs, String id ) throws NamingException
367 {
368 EntryAttribute attr = schemaSubentry.get( id );
369
370 if ( attr != null )
371 {
372 attrs.put( attr );
373 }
374 }
375
376
377
378
379
380
381
382
383 public ServerEntry getSubschemaEntryImmutable() throws Exception
384 {
385 if ( schemaSubentry == null )
386 {
387 generateSchemaSubentry( schemaPartition.lookup(
388 new LookupOperationContext( null, schemaModificationAttributesDN ) ) );
389 }
390
391 return ( ServerEntry ) schemaSubentry.clone();
392 }
393
394
395
396
397
398
399
400
401 public ServerEntry getSubschemaEntryCloned() throws Exception
402 {
403 if ( schemaSubentry == null )
404 {
405 generateSchemaSubentry( schemaPartition.lookup(
406 new LookupOperationContext( null, schemaModificationAttributesDN ) ) );
407 }
408
409 return ( ServerEntry ) schemaSubentry.clone();
410 }
411
412
413
414
415
416
417
418
419
420
421 public ServerEntry getSubschemaEntry( String[] ids ) throws Exception
422 {
423 if ( ids == null )
424 {
425 ids = EMPTY_STRING_ARRAY;
426 }
427
428 Set<String> setOids = new HashSet<String>();
429 ServerEntry attrs = new DefaultServerEntry( registries, LdapDN.EMPTY_LDAPDN );
430 boolean returnAllOperationalAttributes = false;
431
432 synchronized( lock )
433 {
434
435
436
437
438 ServerEntry mods =
439 schemaPartition.lookup( new LookupOperationContext( null, schemaModificationAttributesDN ) );
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469 generateSchemaSubentry( mods );
470
471
472
473
474
475
476 for ( String id:ids )
477 {
478
479
480 if ( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES.equals( id ) )
481 {
482 returnAllOperationalAttributes = true;
483 }
484 else if ( SchemaConstants.ALL_USER_ATTRIBUTES.equals( id ) )
485 {
486 setOids.add( id );
487 }
488 else
489 {
490 setOids.add( registries.getOidRegistry().getOid( id ) );
491 }
492 }
493
494 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.COMPARATORS_AT_OID ) )
495 {
496 addAttribute( attrs, SchemaConstants.COMPARATORS_AT );
497 }
498
499 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.NORMALIZERS_AT_OID ) )
500 {
501 addAttribute( attrs, SchemaConstants.NORMALIZERS_AT );
502 }
503
504 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.SYNTAX_CHECKERS_AT_OID ) )
505 {
506 addAttribute( attrs, SchemaConstants.SYNTAX_CHECKERS_AT );
507 }
508
509 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.OBJECT_CLASSES_AT_OID ) )
510 {
511 addAttribute( attrs, SchemaConstants.OBJECT_CLASSES_AT );
512 }
513
514 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.ATTRIBUTE_TYPES_AT_OID ) )
515 {
516 addAttribute( attrs, SchemaConstants.ATTRIBUTE_TYPES_AT );
517 }
518
519 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.MATCHING_RULES_AT_OID ) )
520 {
521 addAttribute( attrs, SchemaConstants.MATCHING_RULES_AT );
522 }
523
524 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.MATCHING_RULE_USE_AT_OID ) )
525 {
526 addAttribute( attrs, SchemaConstants.MATCHING_RULE_USE_AT );
527 }
528
529 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.LDAP_SYNTAXES_AT_OID ) )
530 {
531 addAttribute( attrs, SchemaConstants.LDAP_SYNTAXES_AT );
532 }
533
534 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.DIT_CONTENT_RULES_AT_OID ) )
535 {
536 addAttribute( attrs, SchemaConstants.DIT_CONTENT_RULES_AT );
537 }
538
539 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.DIT_STRUCTURE_RULES_AT_OID ) )
540 {
541 addAttribute( attrs, SchemaConstants.DIT_STRUCTURE_RULES_AT );
542 }
543
544 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.NAME_FORMS_AT_OID ) )
545 {
546 addAttribute( attrs, SchemaConstants.NAME_FORMS_AT );
547 }
548
549 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.SUBTREE_SPECIFICATION_AT_OID ) )
550 {
551 addAttribute( attrs, SchemaConstants.SUBTREE_SPECIFICATION_AT );
552 }
553
554 int minSetSize = 0;
555 if ( setOids.contains( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES ) )
556 {
557 minSetSize++;
558 }
559
560 if ( setOids.contains( SchemaConstants.ALL_USER_ATTRIBUTES ) )
561 {
562 minSetSize++;
563 }
564
565 if ( setOids.contains( SchemaConstants.REF_AT_OID ) )
566 {
567 minSetSize++;
568 }
569
570
571 if ( setOids.contains( SchemaConstants.ALL_USER_ATTRIBUTES ) ||
572 setOids.contains( SchemaConstants.OBJECT_CLASS_AT_OID ) ||
573 setOids.size() == minSetSize )
574 {
575 addAttribute( attrs, SchemaConstants.OBJECT_CLASS_AT );
576 }
577
578
579 if ( setOids.contains( SchemaConstants.ALL_USER_ATTRIBUTES ) ||
580 setOids.contains( SchemaConstants.CN_AT_OID ) ||
581 setOids.size() == minSetSize )
582 {
583 addAttribute( attrs, SchemaConstants.CN_AT );
584 }
585
586
587
588
589
590
591 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.CREATE_TIMESTAMP_AT_OID ) )
592 {
593 addAttribute( attrs, SchemaConstants.CREATE_TIMESTAMP_AT );
594 }
595
596 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.CREATORS_NAME_AT_OID ) )
597 {
598 addAttribute( attrs, SchemaConstants.CREATORS_NAME_AT );
599 }
600
601 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.MODIFY_TIMESTAMP_AT_OID ) )
602 {
603 addAttribute( attrs, SchemaConstants.MODIFY_TIMESTAMP_AT );
604 }
605
606 if ( returnAllOperationalAttributes || setOids.contains( SchemaConstants.MODIFIERS_NAME_AT_OID ) )
607 {
608 addAttribute( attrs, SchemaConstants.MODIFIERS_NAME_AT );
609 }
610 }
611
612 return attrs;
613 }
614
615
616 SchemaOperationControl getSchemaControl()
617 {
618 return schemaControl;
619 }
620 }