1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.schema;
21
22
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
30 import org.apache.directory.api.ldap.model.entry.Attribute;
31 import org.apache.directory.api.ldap.model.entry.Modification;
32 import org.apache.directory.api.ldap.model.exception.LdapException;
33 import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
34 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
35 import org.apache.directory.api.ldap.model.schema.AttributeType;
36 import org.apache.directory.api.ldap.model.schema.DitContentRule;
37 import org.apache.directory.api.ldap.model.schema.DitStructureRule;
38 import org.apache.directory.api.ldap.model.schema.LdapSyntax;
39 import org.apache.directory.api.ldap.model.schema.MatchingRule;
40 import org.apache.directory.api.ldap.model.schema.MatchingRuleUse;
41 import org.apache.directory.api.ldap.model.schema.NameForm;
42 import org.apache.directory.api.ldap.model.schema.ObjectClass;
43 import org.apache.directory.api.ldap.model.schema.SchemaManager;
44 import org.apache.directory.api.ldap.model.schema.parsers.LdapComparatorDescription;
45 import org.apache.directory.api.ldap.model.schema.parsers.NormalizerDescription;
46 import org.apache.directory.api.ldap.model.schema.parsers.SyntaxCheckerDescription;
47 import org.apache.directory.api.util.Strings;
48 import org.apache.directory.server.core.api.DirectoryService;
49 import org.apache.directory.server.core.api.DnFactory;
50 import org.apache.directory.server.core.api.InterceptorEnum;
51 import org.apache.directory.server.core.api.OperationEnum;
52 import org.apache.directory.server.core.api.interceptor.Interceptor;
53 import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
54 import org.apache.directory.server.core.api.schema.DescriptionParsers;
55 import org.apache.directory.server.i18n.I18n;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59
60
61
62
63
64 public class SchemaSubentryManager
65 {
66
67 private static final Logger LOG = LoggerFactory.getLogger( SchemaSubentryManager.class );
68
69
70 private static final int COMPARATOR_INDEX = 0;
71 private static final int NORMALIZER_INDEX = 1;
72 private static final int SYNTAX_CHECKER_INDEX = 2;
73 private static final int SYNTAX_INDEX = 3;
74 private static final int MATCHING_RULE_INDEX = 4;
75 private static final int ATTRIBUTE_TYPE_INDEX = 5;
76 private static final int OBJECT_CLASS_INDEX = 6;
77 private static final int MATCHING_RULE_USE_INDEX = 7;
78 private static final int DIT_STRUCTURE_RULE_INDEX = 8;
79 private static final int DIT_CONTENT_RULE_INDEX = 9;
80 private static final int NAME_FORM_INDEX = 10;
81
82 private static final Set<String> VALID_OU_VALUES = new HashSet<>();
83
84
85 private final SchemaManager schemaManager;
86
87 private final SchemaSubentryModifier subentryModifier;
88
89
90 private final DescriptionParsers parsers;
91
92
93
94
95
96 private final Map<String, Integer> opAttr2handlerIndex = new HashMap<>( 11 );
97 private static final String CASCADING_ERROR =
98 "Cascading has not yet been implemented: standard operation is in effect.";
99
100 static
101 {
102 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.NORMALIZERS_AT ) );
103 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.COMPARATORS_AT ) );
104 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.SYNTAX_CHECKERS_AT ) );
105 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.SYNTAXES ) );
106 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.MATCHING_RULES_AT ) );
107 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.MATCHING_RULE_USE_AT ) );
108 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.ATTRIBUTE_TYPES_AT ) );
109 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.OBJECT_CLASSES_AT ) );
110 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.NAME_FORMS_AT ) );
111 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.DIT_CONTENT_RULES_AT ) );
112 VALID_OU_VALUES.add( Strings.toLowerCaseAscii( SchemaConstants.DIT_STRUCTURE_RULES_AT ) );
113 }
114
115
116 public SchemaSubentryManager( SchemaManager schemaManager, DnFactory dnFactory )
117 throws LdapException
118 {
119 this.schemaManager = schemaManager;
120 this.subentryModifier = new SchemaSubentryModifier( schemaManager, dnFactory );
121 this.parsers = new DescriptionParsers( schemaManager );
122
123 String comparatorsOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.COMPARATORS_AT );
124 opAttr2handlerIndex.put( comparatorsOid, COMPARATOR_INDEX );
125
126 String normalizersOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.NORMALIZERS_AT );
127 opAttr2handlerIndex.put( normalizersOid, NORMALIZER_INDEX );
128
129 String syntaxCheckersOid = schemaManager.getAttributeTypeRegistry().getOidByName(
130 SchemaConstants.SYNTAX_CHECKERS_AT );
131 opAttr2handlerIndex.put( syntaxCheckersOid, SYNTAX_CHECKER_INDEX );
132
133 String ldapSyntaxesOid = schemaManager.getAttributeTypeRegistry().getOidByName(
134 SchemaConstants.LDAP_SYNTAXES_AT );
135 opAttr2handlerIndex.put( ldapSyntaxesOid, SYNTAX_INDEX );
136
137 String matchingRulesOid = schemaManager.getAttributeTypeRegistry().getOidByName(
138 SchemaConstants.MATCHING_RULES_AT );
139 opAttr2handlerIndex.put( matchingRulesOid, MATCHING_RULE_INDEX );
140
141 String attributeTypesOid = schemaManager.getAttributeTypeRegistry().getOidByName(
142 SchemaConstants.ATTRIBUTE_TYPES_AT );
143 opAttr2handlerIndex.put( attributeTypesOid, ATTRIBUTE_TYPE_INDEX );
144
145 String objectClassesOid = schemaManager.getAttributeTypeRegistry().getOidByName(
146 SchemaConstants.OBJECT_CLASSES_AT );
147 opAttr2handlerIndex.put( objectClassesOid, OBJECT_CLASS_INDEX );
148
149 String matchingRuleUseOid = schemaManager.getAttributeTypeRegistry().getOidByName(
150 SchemaConstants.MATCHING_RULE_USE_AT );
151 opAttr2handlerIndex.put( matchingRuleUseOid, MATCHING_RULE_USE_INDEX );
152
153 String ditStructureRulesOid = schemaManager.getAttributeTypeRegistry().getOidByName(
154 SchemaConstants.DIT_STRUCTURE_RULES_AT );
155 opAttr2handlerIndex.put( ditStructureRulesOid, DIT_STRUCTURE_RULE_INDEX );
156
157 String ditContentRulesOid = schemaManager.getAttributeTypeRegistry().getOidByName(
158 SchemaConstants.DIT_CONTENT_RULES_AT );
159 opAttr2handlerIndex.put( ditContentRulesOid, DIT_CONTENT_RULE_INDEX );
160
161 String nameFormsOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.NAME_FORMS_AT );
162 opAttr2handlerIndex.put( nameFormsOid, NAME_FORM_INDEX );
163 }
164
165
166
167
168
169
170
171
172
173
174
175
176
177 private Interceptor findNextInterceptor( OperationEnum operation, DirectoryService directoryService )
178 {
179 Interceptor interceptor = null;
180
181 List<Interceptor> allInterceptors = directoryService.getInterceptors();
182 List<String> operationInterceptors = directoryService.getInterceptors( operation );
183 int position = 0;
184 String addInterceptor = operationInterceptors.get( position );
185
186 for ( Interceptor inter : allInterceptors )
187 {
188 String interName = inter.getName();
189
190 if ( interName.equals( InterceptorEnum.SCHEMA_INTERCEPTOR.getName() ) )
191 {
192
193 position++;
194
195 if ( position < operationInterceptors.size() )
196 {
197 interceptor = directoryService.getInterceptor( operationInterceptors.get( position ) );
198 }
199
200 break;
201 }
202
203 if ( interName.equals( addInterceptor ) )
204 {
205 position++;
206 addInterceptor = operationInterceptors.get( position );
207 }
208 }
209
210 return interceptor;
211 }
212
213
214
215
216
217 private int findPosition( OperationEnum operation, Interceptor interceptor, DirectoryService directoryService )
218 {
219 int position = 1;
220
221 List<String> interceptors = directoryService.getInterceptors( operation );
222
223 String interceptorName = interceptor.getName();
224
225 for ( String name : interceptors )
226 {
227 if ( name.equals( interceptorName ) )
228 {
229 break;
230 }
231
232 position++;
233 }
234
235 return position;
236 }
237
238
239
240
241
242
243
244
245
246 public void modifySchemaSubentry( ModifyOperationContext modifyContext, boolean doCascadeModify )
247 throws LdapException
248 {
249 DirectoryService directoryService = modifyContext.getSession().getDirectoryService();
250
251
252
253
254 Interceptor nextAdd = findNextInterceptor( OperationEnum.ADD, directoryService );
255 int positionAdd = findPosition( OperationEnum.ADD, nextAdd, directoryService );
256 Interceptor nextDelete = findNextInterceptor( OperationEnum.DELETE, directoryService );
257 int positionDelete = findPosition( OperationEnum.DELETE, nextDelete, directoryService );
258
259 for ( Modification mod : modifyContext.getModItems() )
260 {
261 String opAttrOid = schemaManager.getAttributeTypeRegistry().getOidByName( mod.getAttribute().getId() );
262
263 Attribute serverAttribute = mod.getAttribute();
264
265 switch ( mod.getOperation() )
266 {
267 case ADD_ATTRIBUTE:
268 modifyAddOperation( nextAdd, positionAdd, modifyContext, opAttrOid, serverAttribute,
269 doCascadeModify );
270 break;
271
272 case REMOVE_ATTRIBUTE:
273 modifyRemoveOperation( nextDelete, positionDelete, modifyContext, opAttrOid, serverAttribute );
274 break;
275
276 case REPLACE_ATTRIBUTE:
277
278 if ( directoryService.getAtProvider().getEntryCSN().equals( serverAttribute.getAttributeType() ) )
279 {
280 break;
281 }
282
283 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
284 I18n.err( I18n.ERR_283 ) );
285
286 default:
287 throw new IllegalStateException( I18n.err( I18n.ERR_284, mod.getOperation() ) );
288 }
289 }
290 }
291
292
293
294
295
296
297
298
299
300
301
302 private void modifyRemoveOperation( Interceptor nextInterceptor, int position,
303 ModifyOperationContext modifyContext, String opAttrOid,
304 Attribute mods ) throws LdapException
305 {
306 int index = opAttr2handlerIndex.get( opAttrOid );
307
308 switch ( index )
309 {
310 case COMPARATOR_INDEX :
311 LdapComparatorDescription[] comparatorDescriptions = parsers.parseComparators( mods );
312
313 for ( LdapComparatorDescription comparatorDescription : comparatorDescriptions )
314 {
315 subentryModifier.delete( nextInterceptor, position, modifyContext, comparatorDescription );
316 }
317
318 break;
319
320 case NORMALIZER_INDEX :
321 NormalizerDescription[] normalizerDescriptions = parsers.parseNormalizers( mods );
322
323 for ( NormalizerDescription normalizerDescription : normalizerDescriptions )
324 {
325 subentryModifier.delete( nextInterceptor, position, modifyContext, normalizerDescription );
326 }
327
328 break;
329
330 case SYNTAX_CHECKER_INDEX :
331 SyntaxCheckerDescription[] syntaxCheckerDescriptions = parsers.parseSyntaxCheckers( mods );
332
333 for ( SyntaxCheckerDescription syntaxCheckerDescription : syntaxCheckerDescriptions )
334 {
335 subentryModifier.delete( nextInterceptor, position, modifyContext, syntaxCheckerDescription );
336 }
337
338 break;
339
340 case SYNTAX_INDEX :
341 LdapSyntax[] syntaxes = parsers.parseLdapSyntaxes( mods );
342
343 for ( LdapSyntax syntax : syntaxes )
344 {
345 subentryModifier.deleteSchemaObject( nextInterceptor, position, modifyContext, syntax );
346 }
347
348 break;
349
350 case MATCHING_RULE_INDEX :
351 MatchingRule[] mrs = parsers.parseMatchingRules( mods );
352
353 for ( MatchingRule mr : mrs )
354 {
355 subentryModifier.deleteSchemaObject( nextInterceptor, position, modifyContext, mr );
356 }
357
358 break;
359
360 case ATTRIBUTE_TYPE_INDEX :
361 AttributeType[] ats = parsers.parseAttributeTypes( mods );
362
363 for ( AttributeType at : ats )
364 {
365 subentryModifier.deleteSchemaObject( nextInterceptor, position, modifyContext, at );
366 }
367
368 break;
369
370 case OBJECT_CLASS_INDEX :
371 ObjectClass[] ocs = parsers.parseObjectClasses( mods );
372
373 for ( ObjectClass oc : ocs )
374 {
375 subentryModifier.deleteSchemaObject( nextInterceptor, position, modifyContext, oc );
376 }
377
378 break;
379
380 case MATCHING_RULE_USE_INDEX :
381 MatchingRuleUse[] mrus = parsers.parseMatchingRuleUses( mods );
382
383 for ( MatchingRuleUse mru : mrus )
384 {
385 subentryModifier.deleteSchemaObject( nextInterceptor, position, modifyContext, mru );
386 }
387
388 break;
389
390 case DIT_STRUCTURE_RULE_INDEX :
391 DitStructureRule[] dsrs = parsers.parseDitStructureRules( mods );
392
393 for ( DitStructureRule dsr : dsrs )
394 {
395 subentryModifier.deleteSchemaObject( nextInterceptor, position, modifyContext, dsr );
396 }
397
398 break;
399
400 case DIT_CONTENT_RULE_INDEX :
401 DitContentRule[] dcrs = parsers.parseDitContentRules( mods );
402
403 for ( DitContentRule dcr : dcrs )
404 {
405 subentryModifier.deleteSchemaObject( nextInterceptor, position, modifyContext, dcr );
406 }
407
408 break;
409
410 case NAME_FORM_INDEX :
411 NameForm[] nfs = parsers.parseNameForms( mods );
412
413 for ( NameForm nf : nfs )
414 {
415 subentryModifier.deleteSchemaObject( nextInterceptor, position, modifyContext, nf );
416 }
417
418 break;
419
420 default:
421 throw new IllegalStateException( I18n.err( I18n.ERR_285, index ) );
422 }
423 }
424
425
426
427
428
429
430
431
432
433
434
435
436 private void modifyAddOperation( Interceptor nextInterceptor, int position, ModifyOperationContext modifyContext,
437 String opAttrOid,
438 Attribute mods, boolean doCascadeModify ) throws LdapException
439 {
440 if ( doCascadeModify )
441 {
442 LOG.error( CASCADING_ERROR );
443 }
444
445 int index = opAttr2handlerIndex.get( opAttrOid );
446
447 switch ( index )
448 {
449 case COMPARATOR_INDEX :
450 LdapComparatorDescription[] comparatorDescriptions = parsers.parseComparators( mods );
451
452 for ( LdapComparatorDescription comparatorDescription : comparatorDescriptions )
453 {
454 subentryModifier.add( nextInterceptor, position, modifyContext, comparatorDescription );
455 }
456
457 break;
458
459 case NORMALIZER_INDEX :
460 NormalizerDescription[] normalizerDescriptions = parsers.parseNormalizers( mods );
461
462 for ( NormalizerDescription normalizerDescription : normalizerDescriptions )
463 {
464 subentryModifier.add( nextInterceptor, position, modifyContext, normalizerDescription );
465 }
466
467 break;
468
469 case SYNTAX_CHECKER_INDEX :
470 SyntaxCheckerDescription[] syntaxCheckerDescriptions = parsers.parseSyntaxCheckers( mods );
471
472 for ( SyntaxCheckerDescription syntaxCheckerDescription : syntaxCheckerDescriptions )
473 {
474 subentryModifier.add( nextInterceptor, position, modifyContext, syntaxCheckerDescription );
475 }
476
477 break;
478
479 case SYNTAX_INDEX :
480 LdapSyntax[] syntaxes = parsers.parseLdapSyntaxes( mods );
481
482 for ( LdapSyntax syntax : syntaxes )
483 {
484 subentryModifier.addSchemaObject( nextInterceptor, position, modifyContext, syntax );
485 }
486
487 break;
488
489 case MATCHING_RULE_INDEX :
490 MatchingRule[] mrs = parsers.parseMatchingRules( mods );
491
492 for ( MatchingRule mr : mrs )
493 {
494 subentryModifier.addSchemaObject( nextInterceptor, position, modifyContext, mr );
495 }
496
497 break;
498
499 case ATTRIBUTE_TYPE_INDEX :
500 AttributeType[] ats = parsers.parseAttributeTypes( mods );
501
502 for ( AttributeType at : ats )
503 {
504 subentryModifier.addSchemaObject( nextInterceptor, position, modifyContext, at );
505 }
506
507 break;
508
509 case OBJECT_CLASS_INDEX :
510 ObjectClass[] ocs = parsers.parseObjectClasses( mods );
511
512 for ( ObjectClass oc : ocs )
513 {
514 subentryModifier.addSchemaObject( nextInterceptor, position, modifyContext, oc );
515 }
516
517 break;
518
519 case MATCHING_RULE_USE_INDEX :
520 MatchingRuleUse[] mrus = parsers.parseMatchingRuleUses( mods );
521
522 for ( MatchingRuleUse mru : mrus )
523 {
524 subentryModifier.addSchemaObject( nextInterceptor, position, modifyContext, mru );
525 }
526
527 break;
528
529 case DIT_STRUCTURE_RULE_INDEX :
530 DitStructureRule[] dsrs = parsers.parseDitStructureRules( mods );
531
532 for ( DitStructureRule dsr : dsrs )
533 {
534 subentryModifier.addSchemaObject( nextInterceptor, position, modifyContext, dsr );
535 }
536
537 break;
538
539 case DIT_CONTENT_RULE_INDEX :
540 DitContentRule[] dcrs = parsers.parseDitContentRules( mods );
541
542 for ( DitContentRule dcr : dcrs )
543 {
544 subentryModifier.addSchemaObject( nextInterceptor, position, modifyContext, dcr );
545 }
546
547 break;
548
549 case NAME_FORM_INDEX :
550 NameForm[] nfs = parsers.parseNameForms( mods );
551
552 for ( NameForm nf : nfs )
553 {
554 subentryModifier.addSchemaObject( nextInterceptor, position, modifyContext, nf );
555 }
556
557 break;
558
559 default:
560 throw new IllegalStateException( I18n.err( I18n.ERR_285, index ) );
561 }
562 }
563 }