1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.ldap.schema.loader;
21
22
23 import java.lang.reflect.Constructor;
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26 import java.security.AccessController;
27 import java.security.PrivilegedAction;
28 import java.util.ArrayList;
29 import java.util.Base64;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Set;
33
34 import org.apache.directory.api.asn1.util.Oid;
35 import org.apache.directory.api.i18n.I18n;
36 import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants;
37 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
38 import org.apache.directory.api.ldap.model.entry.Attribute;
39 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
40 import org.apache.directory.api.ldap.model.entry.Entry;
41 import org.apache.directory.api.ldap.model.entry.Value;
42 import org.apache.directory.api.ldap.model.exception.LdapException;
43 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
44 import org.apache.directory.api.ldap.model.exception.LdapSchemaException;
45 import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
46 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
47 import org.apache.directory.api.ldap.model.schema.AttributeType;
48 import org.apache.directory.api.ldap.model.schema.LdapComparator;
49 import org.apache.directory.api.ldap.model.schema.LdapSyntax;
50 import org.apache.directory.api.ldap.model.schema.LoadableSchemaObject;
51 import org.apache.directory.api.ldap.model.schema.MatchingRule;
52 import org.apache.directory.api.ldap.model.schema.ObjectClass;
53 import org.apache.directory.api.ldap.model.schema.Normalizer;
54 import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum;
55 import org.apache.directory.api.ldap.model.schema.SchemaManager;
56 import org.apache.directory.api.ldap.model.schema.SchemaObject;
57 import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
58 import org.apache.directory.api.ldap.model.schema.SyntaxChecker.SCBuilder;
59 import org.apache.directory.api.ldap.model.schema.UsageEnum;
60 import org.apache.directory.api.ldap.model.schema.parsers.LdapComparatorDescription;
61 import org.apache.directory.api.ldap.model.schema.parsers.NormalizerDescription;
62 import org.apache.directory.api.ldap.model.schema.parsers.SyntaxCheckerDescription;
63 import org.apache.directory.api.ldap.model.schema.registries.DefaultSchema;
64 import org.apache.directory.api.ldap.model.schema.registries.Registries;
65 import org.apache.directory.api.ldap.model.schema.registries.Schema;
66 import org.apache.directory.api.util.StringConstants;
67 import org.apache.directory.api.util.Strings;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71
72
73
74
75
76
77 public class SchemaEntityFactory implements EntityFactory
78 {
79
80 private static final Logger LOG = LoggerFactory.getLogger( SchemaEntityFactory.class );
81
82
83 private static final List<String> EMPTY_LIST = new ArrayList<>();
84
85
86 private static final String[] EMPTY_ARRAY = new String[]
87 {};
88
89
90 private final AttributeClassLoader classLoader;
91
92
93
94
95
96 public SchemaEntityFactory()
97 {
98 this.classLoader = AccessController.doPrivileged( new PrivilegedAction<AttributeClassLoader>()
99 {
100 @Override
101 public AttributeClassLoader run()
102 {
103 return new AttributeClassLoader();
104 }
105 } );
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119 private String getOid( Entry entry, String objectType, boolean strict ) throws LdapInvalidAttributeValueException
120 {
121
122 Attribute mOid = entry.get( MetaSchemaConstants.M_OID_AT );
123
124 if ( mOid == null )
125 {
126 String msg = I18n.err( I18n.ERR_16011_NULL_ATTRIBUTE, objectType, MetaSchemaConstants.M_OID_AT );
127
128 if ( LOG.isWarnEnabled() )
129 {
130 LOG.warn( msg );
131 }
132
133 throw new IllegalArgumentException( msg );
134 }
135
136 String oid = mOid.getString();
137
138 if ( strict && !Oid.isOid( oid ) )
139 {
140 String msg = I18n.err( I18n.ERR_16012_INVALID_COMPARATOR_OID, oid );
141
142 if ( LOG.isWarnEnabled() )
143 {
144 LOG.warn( msg );
145 }
146
147 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
148 }
149
150 return oid;
151 }
152
153
154
155
156
157
158
159
160
161
162
163 private String getOid( SchemaObject description, String objectType ) throws LdapInvalidAttributeValueException
164 {
165
166 String oid = description.getOid();
167
168 if ( oid == null )
169 {
170 String msg = I18n.err( I18n.ERR_16011_NULL_ATTRIBUTE, objectType, MetaSchemaConstants.M_OID_AT );
171
172 if ( LOG.isWarnEnabled() )
173 {
174 LOG.warn( msg );
175 }
176
177 throw new IllegalArgumentException( msg );
178 }
179
180 if ( !Oid.isOid( oid ) )
181 {
182 String msg = I18n.err( I18n.ERR_16012_INVALID_COMPARATOR_OID, oid );
183
184 if ( LOG.isWarnEnabled() )
185 {
186 LOG.warn( msg );
187 }
188
189 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
190 }
191
192 return oid;
193 }
194
195
196
197
198
199
200
201
202 private void checkEntry( Entry entry, String schemaEntity )
203 {
204 if ( entry == null )
205 {
206 String msg = I18n.err( I18n.ERR_16013_NULL_ENTRY, schemaEntity );
207
208 if ( LOG.isWarnEnabled() )
209 {
210 LOG.warn( msg );
211 }
212
213 throw new IllegalArgumentException( msg );
214 }
215 }
216
217
218
219
220
221
222
223
224 private void checkDescription( SchemaObject description, String schemaEntity )
225 {
226 if ( description == null )
227 {
228 String msg = I18n.err( I18n.ERR_16014_NULL_SCHEMA_DESC, schemaEntity );
229
230 if ( LOG.isWarnEnabled() )
231 {
232 LOG.warn( msg );
233 }
234
235 throw new IllegalArgumentException( msg );
236 }
237 }
238
239
240
241
242
243
244
245
246
247
248 private Schema getSchema( String schemaName, Registries registries )
249 {
250 if ( Strings.isEmpty( schemaName ) )
251 {
252 schemaName = MetaSchemaConstants.SCHEMA_OTHER;
253 }
254
255 Schema schema = registries.getLoadedSchema( schemaName );
256
257 if ( schema == null )
258 {
259 String msg = I18n.err( I18n.ERR_16015_NON_EXISTENT_SCHEMA, schemaName );
260 LOG.error( msg );
261 }
262
263 return schema;
264 }
265
266
267
268
269
270 @Override
271 public Schema getSchema( Entry entry ) throws LdapException
272 {
273 String name;
274 String owner;
275 String[] dependencies = EMPTY_ARRAY;
276 boolean isDisabled = false;
277
278 if ( entry == null )
279 {
280 throw new IllegalArgumentException( I18n.err( I18n.ERR_16016_NULL_ENTRY ) );
281 }
282
283 if ( entry.get( SchemaConstants.CN_AT ) == null )
284 {
285 throw new IllegalArgumentException( I18n.err( I18n.ERR_16017_INVALID_CN_AT ) );
286 }
287
288 name = entry.get( SchemaConstants.CN_AT ).getString();
289
290 if ( entry.get( SchemaConstants.CREATORS_NAME_AT ) == null )
291 {
292 throw new IllegalArgumentException( I18n.err( I18n.ERR_16018_INVALID_AT, SchemaConstants.CREATORS_NAME_AT ) );
293 }
294
295 owner = entry.get( SchemaConstants.CREATORS_NAME_AT ).getString();
296
297 if ( entry.get( MetaSchemaConstants.M_DISABLED_AT ) != null )
298 {
299 String value = entry.get( MetaSchemaConstants.M_DISABLED_AT ).getString();
300 value = Strings.upperCase( value );
301 isDisabled = "TRUE".equalsIgnoreCase( value );
302 }
303
304 if ( entry.get( MetaSchemaConstants.M_DEPENDENCIES_AT ) != null )
305 {
306 Set<String> depsSet = new HashSet<>();
307 Attribute depsAttr = entry.get( MetaSchemaConstants.M_DEPENDENCIES_AT );
308
309 for ( Value value : depsAttr )
310 {
311 depsSet.add( value.getString() );
312 }
313
314 dependencies = depsSet.toArray( EMPTY_ARRAY );
315 }
316
317 return new DefaultSchema( null, name, owner, dependencies, isDisabled );
318 }
319
320
321
322
323
324
325
326
327
328
329
330
331 private SyntaxChecker classLoadSyntaxChecker( SchemaManager schemaManager, String oid, String className,
332 Attribute byteCode ) throws LdapException
333 {
334
335 Class<?> clazz;
336 SyntaxChecker syntaxChecker;
337 String byteCodeStr = StringConstants.EMPTY;
338
339 if ( byteCode == null )
340 {
341 try
342 {
343 clazz = Class.forName( className );
344 }
345 catch ( ClassNotFoundException cnfe )
346 {
347 LOG.error( I18n.err( I18n.ERR_16048_CANNOT_FIND_SC_CTOR, className ) );
348 throw new LdapSchemaException( I18n.err( I18n.ERR_16049_CANNOT_FIND_SC_CLASS, cnfe.getMessage() ) );
349 }
350 }
351 else
352 {
353 classLoader.setAttribute( byteCode );
354
355 try
356 {
357 clazz = classLoader.loadClass( className );
358 }
359 catch ( ClassNotFoundException cnfe )
360 {
361 LOG.error( I18n.err( I18n.ERR_16050_CANNOT_LOAD_SC_CTOR, className ) );
362 throw new LdapSchemaException( I18n.err( I18n.ERR_16051_CANNOT_LOAD_SC_CLASS, cnfe.getMessage() ) );
363 }
364
365 byteCodeStr = new String( Base64.getEncoder().encodeToString( byteCode.getBytes() ) );
366 }
367
368
369 try
370 {
371 Method builder = clazz.getMethod( "builder", ( Class<?>[] ) null );
372 syntaxChecker = ( SyntaxChecker ) ( ( SCBuilder ) builder.invoke( null, ( Object[] ) null ) ).setOid( oid ).build();
373 }
374 catch ( NoSuchMethodException nsme )
375 {
376 LOG.error( I18n.err( I18n.ERR_16052_CANNOT_INST_SC_CTOR, className ) );
377 throw new LdapSchemaException( I18n.err( I18n.ERR_16053_CANNOT_INST_SC_CLASS, nsme.getMessage() ) );
378 }
379 catch ( InvocationTargetException | IllegalAccessException e )
380 {
381 LOG.error( I18n.err( I18n.ERR_16054_CANNOT_ACCESS_SC_CTOR, className ) );
382 throw new LdapSchemaException( I18n.err( I18n.ERR_16055_CANNOT_ACCESS_SC_CLASS, e.getMessage() ) );
383 }
384
385
386 syntaxChecker.setBytecode( byteCodeStr );
387 syntaxChecker.setFqcn( className );
388
389
390 syntaxChecker.setSchemaManager( schemaManager );
391
392 return syntaxChecker;
393 }
394
395
396
397
398
399 @Override
400 public SyntaxChecker getSyntaxChecker( SchemaManager schemaManager, Entry entry, Registries targetRegistries,
401 String schemaName ) throws LdapException
402 {
403 checkEntry( entry, SchemaConstants.SYNTAX_CHECKER );
404
405
406 String oid = getOid( entry, SchemaConstants.SYNTAX_CHECKER, schemaManager.isStrict() );
407
408
409 if ( !schemaManager.isSchemaLoaded( schemaName ) )
410 {
411
412 String msg = I18n.err( I18n.ERR_16019_CANNOT_ADD_SC, entry.getDn().getName(), schemaName );
413
414 if ( LOG.isWarnEnabled() )
415 {
416 LOG.warn( msg );
417 }
418
419 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
420 }
421
422 Schema schema = getSchema( schemaName, targetRegistries );
423
424 if ( schema == null )
425 {
426
427 if ( LOG.isInfoEnabled() )
428 {
429 LOG.info( I18n.err( I18n.ERR_16020_CANNOT_ADD_SC_IN_REGISTRY, entry.getDn().getName(), schemaName ) );
430 }
431
432 schema = schemaManager.getLoadedSchema( schemaName );
433 }
434
435
436 String className = getFqcn( entry, SchemaConstants.SYNTAX_CHECKER );
437
438
439 Attribute byteCode = entry.get( MetaSchemaConstants.M_BYTECODE_AT );
440
441 try
442 {
443
444 SyntaxChecker syntaxChecker = classLoadSyntaxChecker( schemaManager, oid, className, byteCode );
445
446
447 setSchemaObjectProperties( syntaxChecker, entry, schema );
448
449
450 return syntaxChecker;
451 }
452 catch ( Exception e )
453 {
454 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, e.getMessage(), e );
455 }
456 }
457
458
459
460
461
462 @Override
463 public SyntaxChecker getSyntaxChecker( SchemaManager schemaManager,
464 SyntaxCheckerDescription syntaxCheckerDescription, Registries targetRegistries, String schemaName )
465 throws LdapException
466 {
467 checkDescription( syntaxCheckerDescription, SchemaConstants.SYNTAX_CHECKER );
468
469
470 String oid = getOid( syntaxCheckerDescription, SchemaConstants.SYNTAX_CHECKER );
471
472
473 Schema schema = getSchema( schemaName, targetRegistries );
474
475 if ( schema == null )
476 {
477
478 String msg = I18n.err( I18n.ERR_16019_CANNOT_ADD_SC, syntaxCheckerDescription.getName(), schemaName );
479
480 if ( LOG.isWarnEnabled() )
481 {
482 LOG.warn( msg );
483 }
484
485 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
486 }
487
488
489 String fqcn = getFqcn( syntaxCheckerDescription, SchemaConstants.SYNTAX_CHECKER );
490
491
492 Attribute byteCode = getByteCode( syntaxCheckerDescription, SchemaConstants.SYNTAX_CHECKER );
493
494
495 SyntaxChecker syntaxChecker = classLoadSyntaxChecker( schemaManager, oid, fqcn, byteCode );
496
497
498 setSchemaObjectProperties( syntaxChecker, syntaxCheckerDescription, schema );
499
500 return syntaxChecker;
501 }
502
503
504
505
506
507
508
509
510
511
512
513
514 private LdapComparator<?> classLoadComparator( SchemaManager schemaManager, String oid, String className,
515 Attribute byteCode ) throws LdapException
516 {
517
518 LdapComparator<?> comparator;
519 Class<?> clazz;
520 String byteCodeStr = StringConstants.EMPTY;
521
522 if ( byteCode == null )
523 {
524 try
525 {
526 clazz = Class.forName( className );
527 }
528 catch ( ClassNotFoundException cnfe )
529 {
530 LOG.error( I18n.err( I18n.ERR_16056_CANNOT_FIND_CMP_CTOR, className ) );
531 throw new LdapSchemaException( I18n.err( I18n.ERR_16057_CANNOT_FIND_CMP_CLASS, cnfe.getMessage() ) );
532 }
533 }
534 else
535 {
536 classLoader.setAttribute( byteCode );
537
538 try
539 {
540 clazz = classLoader.loadClass( className );
541 }
542 catch ( ClassNotFoundException cnfe )
543 {
544 LOG.error( I18n.err( I18n.ERR_16058_CANNOT_LOAD_CMP_CTOR, className ) );
545 throw new LdapSchemaException( I18n.err( I18n.ERR_16059_CANNOT_LOAD_CMP_CLASS, cnfe.getMessage() ) );
546 }
547
548 byteCodeStr = new String( Base64.getEncoder().encodeToString( byteCode.getBytes() ) );
549 }
550
551
552
553 try
554 {
555 Constructor<?> constructor = clazz.getConstructor( new Class[]
556 { String.class } );
557
558 try
559 {
560 comparator = ( LdapComparator<?> ) constructor.newInstance( oid );
561 }
562 catch ( InvocationTargetException ite )
563 {
564 LOG.error( I18n.err( I18n.ERR_16060_CANNOT_INVOKE_CMP_CTOR, className ) );
565 throw new LdapSchemaException( I18n.err( I18n.ERR_16061_CANNOT_INVOKE_CMP_CLASS, ite.getMessage() ) );
566 }
567 catch ( InstantiationException ie )
568 {
569 LOG.error( I18n.err( I18n.ERR_16062_CANNOT_INST_CMP_CTOR_CLASS, className ) );
570 throw new LdapSchemaException( I18n.err( I18n.ERR_16063_CANNOT_INST_CMP_CLASS, ie.getMessage() ) );
571 }
572 catch ( IllegalAccessException ie )
573 {
574 LOG.error( I18n.err( I18n.ERR_16064_CANNOT_ACCESS_CMP_CTOR, className ) );
575 throw new LdapSchemaException( I18n.err( I18n.ERR_16065_CANNOT_ACCESS_CMP_CLASS, ie.getMessage() ) );
576 }
577 }
578 catch ( NoSuchMethodException nsme )
579 {
580
581
582
583 try
584 {
585 clazz.getConstructor();
586 }
587 catch ( NoSuchMethodException nsme2 )
588 {
589 LOG.error( I18n.err( I18n.ERR_16066_CANNOT_FIND_CMP_CTOR_METH_CLASS, className ) );
590 throw new LdapSchemaException( I18n.err( I18n.ERR_16067_CANNOT_FIND_CMP_CTOR_METH, nsme2.getMessage() ) );
591 }
592
593 try
594 {
595 comparator = ( LdapComparator<?> ) clazz.newInstance();
596 }
597 catch ( InstantiationException ie )
598 {
599 LOG.error( I18n.err( I18n.ERR_16062_CANNOT_INST_CMP_CTOR_CLASS, className ) );
600 throw new LdapSchemaException( I18n.err( I18n.ERR_16063_CANNOT_INST_CMP_CLASS, ie.getMessage() ) );
601 }
602 catch ( IllegalAccessException iae )
603 {
604 LOG.error( I18n.err( I18n.ERR_16064_CANNOT_ACCESS_CMP_CTOR, className ) );
605 throw new LdapSchemaException( I18n.err( I18n.ERR_16065_CANNOT_ACCESS_CMP_CLASS, iae.getMessage() ) );
606 }
607
608 if ( !comparator.getOid().equals( oid ) )
609 {
610 String msg = I18n.err( I18n.ERR_16021_DIFFERENT_COMPARATOR_OID, oid, comparator.getOid() );
611 throw new LdapInvalidAttributeValueException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg, nsme );
612 }
613 }
614
615
616 comparator.setBytecode( byteCodeStr );
617 comparator.setFqcn( className );
618
619
620 comparator.setSchemaManager( schemaManager );
621
622 return comparator;
623 }
624
625
626
627
628
629 @Override
630 public LdapComparator<?> getLdapComparator( SchemaManager schemaManager,
631 LdapComparatorDescription comparatorDescription, Registries targetRegistries, String schemaName )
632 throws LdapException
633 {
634 checkDescription( comparatorDescription, SchemaConstants.COMPARATOR );
635
636
637 String oid = getOid( comparatorDescription, SchemaConstants.COMPARATOR );
638
639
640 Schema schema = getSchema( schemaName, targetRegistries );
641
642 if ( schema == null )
643 {
644
645 String msg = I18n.err( I18n.ERR_16022_CANNOT_ADD_CMP, comparatorDescription.getName(), schemaName );
646
647 if ( LOG.isWarnEnabled() )
648 {
649 LOG.warn( msg );
650 }
651
652 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
653 }
654
655
656 String fqcn = getFqcn( comparatorDescription, SchemaConstants.COMPARATOR );
657
658
659 Attribute byteCode = getByteCode( comparatorDescription, SchemaConstants.COMPARATOR );
660
661
662 LdapComparator<?> comparator = classLoadComparator( schemaManager, oid, fqcn, byteCode );
663
664
665 setSchemaObjectProperties( comparator, comparatorDescription, schema );
666
667 return comparator;
668 }
669
670
671
672
673
674 @Override
675 public LdapComparator<?> getLdapComparator( SchemaManager schemaManager, Entry entry, Registries targetRegistries,
676 String schemaName ) throws LdapException
677 {
678 checkEntry( entry, SchemaConstants.COMPARATOR );
679
680
681 String oid = getOid( entry, SchemaConstants.COMPARATOR, schemaManager.isStrict() );
682
683
684 if ( !schemaManager.isSchemaLoaded( schemaName ) )
685 {
686
687 String msg = I18n.err( I18n.ERR_16022_CANNOT_ADD_CMP, entry.getDn().getName(), schemaName );
688
689 if ( LOG.isWarnEnabled() )
690 {
691 LOG.warn( msg );
692 }
693
694 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
695 }
696
697 Schema schema = getSchema( schemaName, targetRegistries );
698
699 if ( schema == null )
700 {
701
702 if ( LOG.isInfoEnabled() )
703 {
704 LOG.info( I18n.err( I18n.ERR_16023_CANNOT_ADD_CMP_IN_REGISTRY, entry.getDn().getName(), schemaName ) );
705 }
706
707 schema = schemaManager.getLoadedSchema( schemaName );
708 }
709
710
711 String fqcn = getFqcn( entry, SchemaConstants.COMPARATOR );
712
713
714 Attribute byteCode = entry.get( MetaSchemaConstants.M_BYTECODE_AT );
715
716 try
717 {
718
719 LdapComparator<?> comparator = classLoadComparator( schemaManager, oid, fqcn, byteCode );
720
721
722 setSchemaObjectProperties( comparator, entry, schema );
723
724
725 return comparator;
726 }
727 catch ( Exception e )
728 {
729 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, e.getMessage(), e );
730 }
731 }
732
733
734
735
736
737
738
739
740
741
742
743
744 private Normalizer classLoadNormalizer( SchemaManager schemaManager, String oid, String className,
745 Attribute byteCode ) throws LdapException
746 {
747
748 Class<?> clazz;
749 Normalizer normalizer;
750 String byteCodeStr = StringConstants.EMPTY;
751
752 if ( byteCode == null )
753 {
754 try
755 {
756 clazz = Class.forName( className );
757 }
758 catch ( ClassNotFoundException cnfe )
759 {
760 LOG.error( I18n.err( I18n.ERR_16068_CANNOT_FIND_NORM_CTOR, className ) );
761 throw new LdapSchemaException( I18n.err( I18n.ERR_16069_CANNOT_FIND_NORM_CLASS, cnfe.getMessage() ) );
762 }
763 }
764 else
765 {
766 classLoader.setAttribute( byteCode );
767
768 try
769 {
770 clazz = classLoader.loadClass( className );
771 }
772 catch ( ClassNotFoundException cnfe )
773 {
774 LOG.error( I18n.err( I18n.ERR_16070_CANNOT_LOAD_NORM_CTOR, className ) );
775 throw new LdapSchemaException( I18n.err( I18n.ERR_16071_CANNOT_LOAD_NORM_CLASS, cnfe.getMessage() ) );
776 }
777
778 byteCodeStr = new String( Base64.getEncoder().encodeToString( byteCode.getBytes() ) );
779 }
780
781
782 try
783 {
784 normalizer = ( Normalizer ) clazz.newInstance();
785 }
786 catch ( InstantiationException ie )
787 {
788 LOG.error( I18n.err( I18n.ERR_16072_CANNOT_INST_NORM_CTOR_CLASS, className ) );
789 throw new LdapSchemaException( I18n.err( I18n.ERR_16073_CANNOT_INST_NORM_CLASS, ie.getMessage() ) );
790 }
791 catch ( IllegalAccessException iae )
792 {
793 LOG.error( I18n.err( I18n.ERR_16074_CANNOT_ACCESS_NORM_CTOR_CLASS, className ) );
794 throw new LdapSchemaException( I18n.err( I18n.ERR_16075_CANNOT_ACCESS_NORM_CTOR, iae.getMessage() ) );
795 }
796
797
798 normalizer.setBytecode( byteCodeStr );
799 normalizer.setFqcn( className );
800
801
802 normalizer.setOid( oid );
803
804
805 normalizer.setSchemaManager( schemaManager );
806
807 return normalizer;
808 }
809
810
811
812
813
814 @Override
815 public Normalizer getNormalizer( SchemaManager schemaManager, NormalizerDescription normalizerDescription,
816 Registries targetRegistries, String schemaName ) throws LdapException
817 {
818 checkDescription( normalizerDescription, SchemaConstants.NORMALIZER );
819
820
821 String oid = getOid( normalizerDescription, SchemaConstants.NORMALIZER );
822
823
824 Schema schema = getSchema( schemaName, targetRegistries );
825
826 if ( schema == null )
827 {
828
829 String msg = I18n.err( I18n.ERR_16024_CANNOT_ADD_NORMALIZER, normalizerDescription.getName(), schemaName );
830
831 if ( LOG.isWarnEnabled() )
832 {
833 LOG.warn( msg );
834 }
835
836 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
837 }
838
839
840 String fqcn = getFqcn( normalizerDescription, SchemaConstants.NORMALIZER );
841
842
843 Attribute byteCode = getByteCode( normalizerDescription, SchemaConstants.NORMALIZER );
844
845
846 Normalizer normalizer = classLoadNormalizer( schemaManager, oid, fqcn, byteCode );
847
848
849 setSchemaObjectProperties( normalizer, normalizerDescription, schema );
850
851 return normalizer;
852 }
853
854
855
856
857
858 @Override
859 public Normalizer getNormalizer( SchemaManager schemaManager, Entry entry, Registries targetRegistries,
860 String schemaName ) throws LdapException
861 {
862 checkEntry( entry, SchemaConstants.NORMALIZER );
863
864
865 String oid = getOid( entry, SchemaConstants.NORMALIZER, schemaManager.isStrict() );
866
867
868 if ( !schemaManager.isSchemaLoaded( schemaName ) )
869 {
870
871 String msg = I18n.err( I18n.ERR_16024_CANNOT_ADD_NORMALIZER, entry.getDn().getName(), schemaName );
872
873 if ( LOG.isWarnEnabled() )
874 {
875 LOG.warn( msg );
876 }
877
878 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
879 }
880
881 Schema schema = getSchema( schemaName, targetRegistries );
882
883 if ( schema == null )
884 {
885
886 if ( LOG.isInfoEnabled() )
887 {
888 LOG.info( I18n.err( I18n.ERR_16025_CANNOT_ADD_NORMALIZER_IN_REGISTRY, entry.getDn().getName(), schemaName ) );
889 }
890
891 schema = schemaManager.getLoadedSchema( schemaName );
892 }
893
894
895 String className = getFqcn( entry, SchemaConstants.NORMALIZER );
896
897
898 Attribute byteCode = entry.get( MetaSchemaConstants.M_BYTECODE_AT );
899
900 try
901 {
902
903 Normalizer normalizer = classLoadNormalizer( schemaManager, oid, className, byteCode );
904
905
906 setSchemaObjectProperties( normalizer, entry, schema );
907
908
909 return normalizer;
910 }
911 catch ( Exception e )
912 {
913 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, e.getMessage(), e );
914 }
915 }
916
917
918
919
920
921
922
923 @Override
924 public LdapSyntax getSyntax( SchemaManager schemaManager, Entry entry, Registries targetRegistries,
925 String schemaName ) throws LdapInvalidAttributeValueException, LdapUnwillingToPerformException
926 {
927 checkEntry( entry, SchemaConstants.SYNTAX );
928
929
930 String oid = getOid( entry, SchemaConstants.SYNTAX, schemaManager.isStrict() );
931
932
933 if ( !schemaManager.isSchemaLoaded( schemaName ) )
934 {
935
936 String msg = I18n.err( I18n.ERR_16026_CANNOT_ADD_SYNTAX, entry.getDn().getName(), schemaName );
937
938 if ( LOG.isWarnEnabled() )
939 {
940 LOG.warn( msg );
941 }
942
943 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
944 }
945
946 Schema schema = getSchema( schemaName, targetRegistries );
947
948 if ( schema == null )
949 {
950
951 if ( LOG.isInfoEnabled() )
952 {
953 LOG.info( I18n.err( I18n.ERR_16027_CANNOT_ADD_SYNTAX_IN_REGISTRY, entry.getDn().getName(), schemaName ) );
954 }
955
956 schema = schemaManager.getLoadedSchema( schemaName );
957 }
958
959
960 LdapSyntax syntax = new LdapSyntax( oid );
961
962
963 setSchemaObjectProperties( syntax, entry, schema );
964
965 return syntax;
966 }
967
968
969
970
971
972
973
974 @Override
975 public MatchingRule getMatchingRule( SchemaManager schemaManager, Entry entry, Registries targetRegistries,
976 String schemaName ) throws LdapUnwillingToPerformException, LdapInvalidAttributeValueException
977 {
978 checkEntry( entry, SchemaConstants.MATCHING_RULE );
979
980
981 String oid = getOid( entry, SchemaConstants.MATCHING_RULE, schemaManager.isStrict() );
982
983
984 if ( !schemaManager.isSchemaLoaded( schemaName ) )
985 {
986
987 String msg = I18n.err( I18n.ERR_16028_CANNOT_ADD_MR, entry.getDn().getName(), schemaName );
988
989 if ( LOG.isWarnEnabled() )
990 {
991 LOG.warn( msg );
992 }
993
994 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
995 }
996
997 Schema schema = getSchema( schemaName, targetRegistries );
998
999 if ( schema == null )
1000 {
1001
1002 if ( LOG.isInfoEnabled() )
1003 {
1004 LOG.info( I18n.err( I18n.ERR_16029_CANNOT_ADD_MR_IN_REGISTRY, entry.getDn().getName(), schemaName ) );
1005 }
1006
1007 schema = schemaManager.getLoadedSchema( schemaName );
1008 }
1009
1010 MatchingRule matchingRule = new MatchingRule( oid );
1011
1012
1013 Attribute mSyntax = entry.get( MetaSchemaConstants.M_SYNTAX_AT );
1014
1015 if ( mSyntax != null )
1016 {
1017 matchingRule.setSyntaxOid( mSyntax.getString() );
1018 }
1019
1020
1021
1022
1023
1024 setSchemaObjectProperties( matchingRule, entry, schema );
1025
1026 return matchingRule;
1027 }
1028
1029
1030
1031
1032
1033
1034
1035
1036 private List<String> getStrings( Attribute attr )
1037 {
1038 if ( attr == null )
1039 {
1040 return EMPTY_LIST;
1041 }
1042
1043 List<String> strings = new ArrayList<>( attr.size() );
1044
1045 for ( Value value : attr )
1046 {
1047 strings.add( value.getString() );
1048 }
1049
1050 return strings;
1051 }
1052
1053
1054
1055
1056
1057 @Override
1058 public ObjectClass getObjectClass( SchemaManager schemaManager, Entry entry, Registries targetRegistries,
1059 String schemaName ) throws LdapException
1060 {
1061 checkEntry( entry, SchemaConstants.OBJECT_CLASS );
1062
1063
1064 String oid = getOid( entry, SchemaConstants.OBJECT_CLASS, schemaManager.isStrict() );
1065
1066
1067 if ( !schemaManager.isSchemaLoaded( schemaName ) )
1068 {
1069
1070 String msg = I18n.err( I18n.ERR_16030_CANNOT_ADD_OC, entry.getDn().getName(), schemaName );
1071
1072 if ( LOG.isWarnEnabled() )
1073 {
1074 LOG.warn( msg );
1075 }
1076
1077 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
1078 }
1079
1080 Schema schema = getSchema( schemaName, targetRegistries );
1081
1082 if ( schema == null )
1083 {
1084
1085 if ( LOG.isInfoEnabled() )
1086 {
1087 LOG.info( I18n.err( I18n.ERR_16031_CANNOT_ADD_OC_IN_REGISTRY, entry.getDn().getName(), schemaName ) );
1088 }
1089
1090 schema = schemaManager.getLoadedSchema( schemaName );
1091 }
1092
1093
1094 ObjectClass oc = new ObjectClass( oid );
1095
1096
1097 Attribute mSuperiors = entry.get( MetaSchemaConstants.M_SUP_OBJECT_CLASS_AT );
1098
1099 if ( mSuperiors != null )
1100 {
1101 oc.setSuperiorOids( getStrings( mSuperiors ) );
1102 }
1103
1104
1105 Attribute mMay = entry.get( MetaSchemaConstants.M_MAY_AT );
1106
1107 if ( mMay != null )
1108 {
1109 oc.setMayAttributeTypeOids( getStrings( mMay ) );
1110 }
1111
1112
1113 Attribute mMust = entry.get( MetaSchemaConstants.M_MUST_AT );
1114
1115 if ( mMust != null )
1116 {
1117 oc.setMustAttributeTypeOids( getStrings( mMust ) );
1118 }
1119
1120
1121 Attribute mTypeObjectClass = entry.get( MetaSchemaConstants.M_TYPE_OBJECT_CLASS_AT );
1122
1123 if ( mTypeObjectClass != null )
1124 {
1125 String type = mTypeObjectClass.getString();
1126 oc.setType( ObjectClassTypeEnum.getClassType( type ) );
1127 }
1128
1129
1130 setSchemaObjectProperties( oc, entry, schema );
1131
1132 return oc;
1133 }
1134
1135
1136
1137
1138
1139
1140
1141 @Override
1142 public AttributeType getAttributeType( SchemaManager schemaManager, Entry entry, Registries targetRegistries,
1143 String schemaName ) throws LdapInvalidAttributeValueException, LdapUnwillingToPerformException
1144 {
1145 checkEntry( entry, SchemaConstants.ATTRIBUTE_TYPE );
1146
1147
1148 String oid = getOid( entry, SchemaConstants.ATTRIBUTE_TYPE, schemaManager.isStrict() );
1149
1150
1151 if ( !schemaManager.isSchemaLoaded( schemaName ) )
1152 {
1153
1154 String msg = I18n.err( I18n.ERR_16032_CANNOT_ADD_AT, entry.getDn().getName(), schemaName );
1155
1156 if ( LOG.isWarnEnabled() )
1157 {
1158 LOG.warn( msg );
1159 }
1160
1161 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
1162 }
1163
1164 Schema schema = getSchema( schemaName, targetRegistries );
1165
1166 if ( schema == null )
1167 {
1168
1169 if ( LOG.isInfoEnabled() )
1170 {
1171 LOG.info( I18n.err( I18n.ERR_16033_CANNOT_ADD_AT_IN_REGISTRY, entry.getDn().getName(), schemaName ) );
1172 }
1173
1174 schema = schemaManager.getLoadedSchema( schemaName );
1175 }
1176
1177
1178 AttributeType attributeType = new AttributeType( oid );
1179
1180 if ( schemaManager.isRelaxed() )
1181 {
1182 attributeType.setRelaxed( true );
1183 }
1184
1185
1186 Attribute mSyntax = entry.get( MetaSchemaConstants.M_SYNTAX_AT );
1187
1188 if ( ( mSyntax != null ) && ( mSyntax.get() != null ) )
1189 {
1190 attributeType.setSyntaxOid( mSyntax.getString() );
1191 }
1192
1193
1194 Attribute mSyntaxLength = entry.get( MetaSchemaConstants.M_LENGTH_AT );
1195
1196 if ( mSyntaxLength != null )
1197 {
1198 attributeType.setSyntaxLength( Integer.parseInt( mSyntaxLength.getString() ) );
1199 }
1200
1201
1202 Attribute mEquality = entry.get( MetaSchemaConstants.M_EQUALITY_AT );
1203
1204 if ( mEquality != null )
1205 {
1206 attributeType.setEqualityOid( mEquality.getString() );
1207 }
1208
1209
1210 Attribute mOrdering = entry.get( MetaSchemaConstants.M_ORDERING_AT );
1211
1212 if ( mOrdering != null )
1213 {
1214 attributeType.setOrderingOid( mOrdering.getString() );
1215 }
1216
1217
1218 Attribute mSubstr = entry.get( MetaSchemaConstants.M_SUBSTR_AT );
1219
1220 if ( mSubstr != null )
1221 {
1222 attributeType.setSubstringOid( mSubstr.getString() );
1223 }
1224
1225 Attribute mSupAttributeType = entry.get( MetaSchemaConstants.M_SUP_ATTRIBUTE_TYPE_AT );
1226
1227
1228 if ( mSupAttributeType != null )
1229 {
1230 attributeType.setSuperiorOid( mSupAttributeType.getString() );
1231 }
1232
1233
1234 Attribute mCollective = entry.get( MetaSchemaConstants.M_COLLECTIVE_AT );
1235
1236 if ( mCollective != null )
1237 {
1238 String val = mCollective.getString();
1239 attributeType.setCollective( "TRUE".equalsIgnoreCase( val ) );
1240 }
1241
1242
1243 Attribute mSingleValued = entry.get( MetaSchemaConstants.M_SINGLE_VALUE_AT );
1244
1245 if ( mSingleValued != null )
1246 {
1247 String val = mSingleValued.getString();
1248 attributeType.setSingleValued( "TRUE".equalsIgnoreCase( val ) );
1249 }
1250
1251
1252 Attribute mNoUserModification = entry.get( MetaSchemaConstants.M_NO_USER_MODIFICATION_AT );
1253
1254 if ( mNoUserModification != null )
1255 {
1256 String val = mNoUserModification.getString();
1257 attributeType.setUserModifiable( !"TRUE".equalsIgnoreCase( val ) );
1258 }
1259
1260
1261 Attribute mUsage = entry.get( MetaSchemaConstants.M_USAGE_AT );
1262
1263 if ( mUsage != null )
1264 {
1265 attributeType.setUsage( UsageEnum.getUsage( mUsage.getString() ) );
1266 }
1267
1268
1269 setSchemaObjectProperties( attributeType, entry, schema );
1270
1271 return attributeType;
1272 }
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283 private String getFqcn( Entry entry, String objectType ) throws LdapInvalidAttributeValueException
1284 {
1285
1286 Attribute mFqcn = entry.get( MetaSchemaConstants.M_FQCN_AT );
1287
1288 if ( mFqcn == null )
1289 {
1290 String msg = I18n.err( I18n.ERR_16034_ENTRY_WITHOUT_VALID_AT, objectType, MetaSchemaConstants.M_FQCN_AT );
1291
1292 if ( LOG.isWarnEnabled() )
1293 {
1294 LOG.warn( msg );
1295 }
1296
1297 throw new IllegalArgumentException( msg );
1298 }
1299
1300 return mFqcn.getString();
1301 }
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311 private String getFqcn( LoadableSchemaObject description, String objectType )
1312 {
1313
1314 String mFqcn = description.getFqcn();
1315
1316 if ( mFqcn == null )
1317 {
1318 String msg = I18n.err( I18n.ERR_16034_ENTRY_WITHOUT_VALID_AT, objectType, MetaSchemaConstants.M_FQCN_AT );
1319
1320 if ( LOG.isWarnEnabled() )
1321 {
1322 LOG.warn( msg );
1323 }
1324
1325 throw new IllegalArgumentException( msg );
1326 }
1327
1328 return mFqcn;
1329 }
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339 private Attribute getByteCode( LoadableSchemaObject description, String objectType )
1340 {
1341 String byteCodeString = description.getBytecode();
1342
1343 if ( byteCodeString == null )
1344 {
1345 String msg = I18n.err( I18n.ERR_16034_ENTRY_WITHOUT_VALID_AT, objectType, MetaSchemaConstants.M_BYTECODE_AT );
1346
1347 if ( LOG.isWarnEnabled() )
1348 {
1349 LOG.warn( msg );
1350 }
1351
1352 throw new IllegalArgumentException( msg );
1353 }
1354
1355 byte[] bytecode = Base64.getDecoder().decode( byteCodeString );
1356
1357 return new DefaultAttribute( MetaSchemaConstants.M_BYTECODE_AT, bytecode );
1358 }
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377 private void setSchemaObjectProperties( SchemaObject schemaObject, Entry entry, Schema schema )
1378 throws LdapInvalidAttributeValueException
1379 {
1380
1381 Attribute mObsolete = entry.get( MetaSchemaConstants.M_OBSOLETE_AT );
1382
1383 if ( mObsolete != null )
1384 {
1385 String val = mObsolete.getString();
1386 schemaObject.setObsolete( "TRUE".equalsIgnoreCase( val ) );
1387 }
1388
1389
1390 Attribute mDescription = entry.get( MetaSchemaConstants.M_DESCRIPTION_AT );
1391
1392 if ( mDescription != null )
1393 {
1394 schemaObject.setDescription( mDescription.getString() );
1395 }
1396
1397
1398 Attribute names = entry.get( MetaSchemaConstants.M_NAME_AT );
1399
1400 if ( names != null )
1401 {
1402 List<String> values = new ArrayList<>();
1403
1404 for ( Value name : names )
1405 {
1406 values.add( name.getString() );
1407 }
1408
1409 schemaObject.setNames( values );
1410 }
1411
1412
1413 Attribute mDisabled = entry.get( MetaSchemaConstants.M_DISABLED_AT );
1414
1415
1416
1417 if ( mDisabled != null )
1418 {
1419 String val = mDisabled.getString();
1420 schemaObject.setEnabled( !"TRUE".equalsIgnoreCase( val ) );
1421 }
1422 else
1423 {
1424 schemaObject.setEnabled( schema.isEnabled() );
1425 }
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439 schemaObject.setSchemaName( schema.getSchemaName() );
1440
1441
1442
1443 Attribute xSchema = entry.get( MetaSchemaConstants.X_SCHEMA_AT );
1444
1445 if ( xSchema != null )
1446 {
1447 String schemaName = xSchema.getString();
1448
1449 if ( !schema.getSchemaName().equalsIgnoreCase( schemaName ) )
1450 {
1451 if ( LOG.isWarnEnabled() )
1452 {
1453 LOG.warn( I18n.msg( I18n.MSG_16011_SCHEMA_XSCHEMA_DIFF, schema.getSchemaName(), schemaName, entry ) );
1454 }
1455 }
1456
1457 schemaObject.addExtension( MetaSchemaConstants.X_SCHEMA_AT, schemaName );
1458 }
1459
1460
1461 Attribute xNotHumanReadable = entry.get( MetaSchemaConstants.X_NOT_HUMAN_READABLE_AT );
1462
1463 if ( xNotHumanReadable != null )
1464 {
1465 String value = xNotHumanReadable.getString();
1466
1467 schemaObject.addExtension( MetaSchemaConstants.X_NOT_HUMAN_READABLE_AT, value );
1468 }
1469
1470
1471 Attribute xReadOnly = entry.get( MetaSchemaConstants.X_READ_ONLY_AT );
1472
1473 if ( xReadOnly != null )
1474 {
1475 String value = xReadOnly.getString();
1476
1477 schemaObject.addExtension( MetaSchemaConstants.X_READ_ONLY_AT, value );
1478 }
1479 }
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496 private void setSchemaObjectProperties( SchemaObject schemaObject, SchemaObject description, Schema schema )
1497 {
1498
1499 schemaObject.setObsolete( description.isObsolete() );
1500
1501
1502 schemaObject.setDescription( description.getDescription() );
1503
1504
1505 schemaObject.setNames( description.getNames() );
1506
1507
1508
1509 schemaObject.setEnabled( schema.isEnabled() );
1510
1511
1512 schemaObject.setSpecification( description.getSpecification() );
1513
1514
1515 schemaObject.setSchemaName( schema.getSchemaName() );
1516
1517
1518 schemaObject.setExtensions( description.getExtensions() );
1519 }
1520 }