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 * https://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 */ 020package org.apache.directory.api.ldap.schema.loader; 021 022 023import java.lang.reflect.Constructor; 024import java.lang.reflect.InvocationTargetException; 025import java.lang.reflect.Method; 026import java.security.AccessController; 027import java.security.PrivilegedAction; 028import java.util.ArrayList; 029import java.util.HashSet; 030import java.util.List; 031import java.util.Set; 032 033import org.apache.directory.api.asn1.util.Oid; 034import org.apache.directory.api.i18n.I18n; 035import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants; 036import org.apache.directory.api.ldap.model.constants.SchemaConstants; 037import org.apache.directory.api.ldap.model.entry.Attribute; 038import org.apache.directory.api.ldap.model.entry.DefaultAttribute; 039import org.apache.directory.api.ldap.model.entry.Entry; 040import org.apache.directory.api.ldap.model.entry.Value; 041import org.apache.directory.api.ldap.model.exception.LdapException; 042import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException; 043import org.apache.directory.api.ldap.model.exception.LdapSchemaException; 044import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException; 045import org.apache.directory.api.ldap.model.message.ResultCodeEnum; 046import org.apache.directory.api.ldap.model.schema.AttributeType; 047import org.apache.directory.api.ldap.model.schema.LdapComparator; 048import org.apache.directory.api.ldap.model.schema.LdapSyntax; 049import org.apache.directory.api.ldap.model.schema.LoadableSchemaObject; 050import org.apache.directory.api.ldap.model.schema.MatchingRule; 051import org.apache.directory.api.ldap.model.schema.ObjectClass; 052import org.apache.directory.api.ldap.model.schema.Normalizer; 053import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum; 054import org.apache.directory.api.ldap.model.schema.SchemaManager; 055import org.apache.directory.api.ldap.model.schema.SchemaObject; 056import org.apache.directory.api.ldap.model.schema.SyntaxChecker; 057import org.apache.directory.api.ldap.model.schema.SyntaxChecker.SCBuilder; 058import org.apache.directory.api.ldap.model.schema.UsageEnum; 059import org.apache.directory.api.ldap.model.schema.parsers.LdapComparatorDescription; 060import org.apache.directory.api.ldap.model.schema.parsers.NormalizerDescription; 061import org.apache.directory.api.ldap.model.schema.parsers.SyntaxCheckerDescription; 062import org.apache.directory.api.ldap.model.schema.registries.DefaultSchema; 063import org.apache.directory.api.ldap.model.schema.registries.Registries; 064import org.apache.directory.api.ldap.model.schema.registries.Schema; 065import org.apache.directory.api.util.Base64; 066import org.apache.directory.api.util.StringConstants; 067import org.apache.directory.api.util.Strings; 068import org.slf4j.Logger; 069import org.slf4j.LoggerFactory; 070 071 072/** 073 * Showing how it's done ... 074 * 075 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 076 */ 077public class SchemaEntityFactory implements EntityFactory 078{ 079 /** Slf4j logger */ 080 private static final Logger LOG = LoggerFactory.getLogger( SchemaEntityFactory.class ); 081 082 /** The empty string list. */ 083 private static final List<String> EMPTY_LIST = new ArrayList<>(); 084 085 /** The empty string array. */ 086 private static final String[] EMPTY_ARRAY = new String[] 087 {}; 088 089 /** A special ClassLoader that loads a class from the bytecode attribute */ 090 private final AttributeClassLoader classLoader; 091 092 093 /** 094 * Instantiates a new schema entity factory. 095 */ 096 public SchemaEntityFactory() 097 { 098 this.classLoader = AccessController.doPrivileged( new PrivilegedAction<AttributeClassLoader>() 099 { 100 @Override 101 public AttributeClassLoader run() 102 { 103 return new AttributeClassLoader(); 104 } 105 } ); 106 } 107 108 109 /** 110 * Get an OID from an entry. Handles the bad cases (null OID, 111 * not a valid OID, ...) 112 * 113 * @param entry The entry to process 114 * @param objectType The type of processed SchemaObject 115 * @param strict If we want a strict control of the OID 116 * @return The found OID 117 * @throws LdapInvalidAttributeValueException If the OID is not valid 118 */ 119 private String getOid( Entry entry, String objectType, boolean strict ) throws LdapInvalidAttributeValueException 120 { 121 // The OID 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 * Get an OID from an entry. Handles the bad cases (null OID, 156 * not a valid OID, ...) 157 * 158 * @param description The schemaObject description 159 * @param objectType The type of SchemaObject being processed 160 * @return The found OID 161 * @throws LdapInvalidAttributeValueException If the OID is invalid 162 */ 163 private String getOid( SchemaObject description, String objectType ) throws LdapInvalidAttributeValueException 164 { 165 // The OID 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 * Check that the Entry is not null 198 * 199 * @param entry The entry to check 200 * @param schemaEntity The message to log if the entry is invalid 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 * Check that the Description is not null 220 * 221 * @param description description entry to check 222 * @param schemaEntity The message to log if the description is invalid 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 * Get the schema from its name. Return the Other reference if there 242 * is no schema name. Throws a NPE if the schema is not loaded. 243 * 244 * @param schemaName The schema name to fetch 245 * @param registries The registries where we get the schema from 246 * @return the found Schema 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 * {@inheritDoc} 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 * Class load a SyntaxChecker instance 323 * 324 * @param schemaManager The SchemaManager 325 * @param oid The SyntaxChecker OID 326 * @param className The class name associated with the SyntaxChecker 327 * @param byteCode The SyntaxChecker class bytecode 328 * @return The loaded SyntaxChecker 329 * @throws LdapException If the SyntaxChecker cannot be loaded 330 */ 331 private SyntaxChecker classLoadSyntaxChecker( SchemaManager schemaManager, String oid, String className, 332 Attribute byteCode ) throws LdapException 333 { 334 // Try to class load the syntaxChecker 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.encode( byteCode.getBytes() ) ); 366 } 367 368 // Create the syntaxChecker instance 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 // Update the common fields 386 syntaxChecker.setBytecode( byteCodeStr ); 387 syntaxChecker.setFqcn( className ); 388 389 // Inject the SchemaManager for the comparator who needs it 390 syntaxChecker.setSchemaManager( schemaManager ); 391 392 return syntaxChecker; 393 } 394 395 396 /** 397 * {@inheritDoc} 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 // The SyntaxChecker OID 406 String oid = getOid( entry, SchemaConstants.SYNTAX_CHECKER, schemaManager.isStrict() ); 407 408 // Get the schema 409 if ( !schemaManager.isSchemaLoaded( schemaName ) ) 410 { 411 // The schema is not loaded. We can't create the requested Normalizer 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 // The schema is disabled. We still have to update the backend 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 // The FQCN 436 String className = getFqcn( entry, SchemaConstants.SYNTAX_CHECKER ); 437 438 // The ByteCode 439 Attribute byteCode = entry.get( MetaSchemaConstants.M_BYTECODE_AT ); 440 441 try 442 { 443 // Class load the syntaxChecker 444 SyntaxChecker syntaxChecker = classLoadSyntaxChecker( schemaManager, oid, className, byteCode ); 445 446 // Update the common fields 447 setSchemaObjectProperties( syntaxChecker, entry, schema ); 448 449 // return the resulting syntaxChecker 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 * {@inheritDoc} 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 // The Comparator OID 470 String oid = getOid( syntaxCheckerDescription, SchemaConstants.SYNTAX_CHECKER ); 471 472 // Get the schema 473 Schema schema = getSchema( schemaName, targetRegistries ); 474 475 if ( schema == null ) 476 { 477 // The schema is not loaded. We can't create the requested SyntaxChecker 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 // The FQCN 489 String fqcn = getFqcn( syntaxCheckerDescription, SchemaConstants.SYNTAX_CHECKER ); 490 491 // get the byteCode 492 Attribute byteCode = getByteCode( syntaxCheckerDescription, SchemaConstants.SYNTAX_CHECKER ); 493 494 // Class load the SyntaxChecker 495 SyntaxChecker syntaxChecker = classLoadSyntaxChecker( schemaManager, oid, fqcn, byteCode ); 496 497 // Update the common fields 498 setSchemaObjectProperties( syntaxChecker, syntaxCheckerDescription, schema ); 499 500 return syntaxChecker; 501 } 502 503 504 /** 505 * Class load a comparator instances 506 * 507 * @param schemaManager The SchemaManager 508 * @param oid The comparator OID 509 * @param className The class name associated with the comparator 510 * @param byteCode The comparator class bytecode 511 * @return The loaded comparator 512 * @throws LdapException If the comparator cannot be loaded 513 */ 514 private LdapComparator<?> classLoadComparator( SchemaManager schemaManager, String oid, String className, 515 Attribute byteCode ) throws LdapException 516 { 517 // Try to class load the comparator 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.encode( byteCode.getBytes() ) ); 549 } 550 551 // Create the comparator instance. Either we have a no argument constructor, 552 // or we have one which takes an OID. Lets try the one with an OID argument first 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 // Ok, let's try with the constructor without argument. 581 // In this case, we will have to check that the OID is the same than 582 // the one we got in the Comparator entry 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 // Update the loadable fields 616 comparator.setBytecode( byteCodeStr ); 617 comparator.setFqcn( className ); 618 619 // Inject the SchemaManager for the comparator who needs it 620 comparator.setSchemaManager( schemaManager ); 621 622 return comparator; 623 } 624 625 626 /** 627 * {@inheritDoc} 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 // The Comparator OID 637 String oid = getOid( comparatorDescription, SchemaConstants.COMPARATOR ); 638 639 // Get the schema 640 Schema schema = getSchema( schemaName, targetRegistries ); 641 642 if ( schema == null ) 643 { 644 // The schema is not loaded. We can't create the requested Comparator 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 // The FQCN 656 String fqcn = getFqcn( comparatorDescription, SchemaConstants.COMPARATOR ); 657 658 // get the byteCode 659 Attribute byteCode = getByteCode( comparatorDescription, SchemaConstants.COMPARATOR ); 660 661 // Class load the comparator 662 LdapComparator<?> comparator = classLoadComparator( schemaManager, oid, fqcn, byteCode ); 663 664 // Update the common fields 665 setSchemaObjectProperties( comparator, comparatorDescription, schema ); 666 667 return comparator; 668 } 669 670 671 /** 672 * {@inheritDoc} 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 // The Comparator OID 681 String oid = getOid( entry, SchemaConstants.COMPARATOR, schemaManager.isStrict() ); 682 683 // Get the schema 684 if ( !schemaManager.isSchemaLoaded( schemaName ) ) 685 { 686 // The schema is not loaded. We can't create the requested Comparator 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 // The schema is disabled. We still have to update the backend 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 // The FQCN 711 String fqcn = getFqcn( entry, SchemaConstants.COMPARATOR ); 712 713 // The ByteCode 714 Attribute byteCode = entry.get( MetaSchemaConstants.M_BYTECODE_AT ); 715 716 try 717 { 718 // Class load the comparator 719 LdapComparator<?> comparator = classLoadComparator( schemaManager, oid, fqcn, byteCode ); 720 721 // Update the common fields 722 setSchemaObjectProperties( comparator, entry, schema ); 723 724 // return the resulting comparator 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 * Class load a normalizer instances 736 * 737 * @param schemaManager The SchemaManager 738 * @param oid The normalizer OID 739 * @param className The class name associated with the normalizer 740 * @param byteCode The normalizer class bytecode 741 * @return The loaded normalizer 742 * @throws LdapException If the normalizer cannot be loaded 743 */ 744 private Normalizer classLoadNormalizer( SchemaManager schemaManager, String oid, String className, 745 Attribute byteCode ) throws LdapException 746 { 747 // Try to class load the normalizer 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.encode( byteCode.getBytes() ) ); 779 } 780 781 // Create the normalizer instance 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 // Update the common fields 798 normalizer.setBytecode( byteCodeStr ); 799 normalizer.setFqcn( className ); 800 801 // Inject the new OID, as the loaded normalizer might have its own 802 normalizer.setOid( oid ); 803 804 // Inject the SchemaManager for the normalizer who needs it 805 normalizer.setSchemaManager( schemaManager ); 806 807 return normalizer; 808 } 809 810 811 /** 812 * {@inheritDoc} 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 // The Comparator OID 821 String oid = getOid( normalizerDescription, SchemaConstants.NORMALIZER ); 822 823 // Get the schema 824 Schema schema = getSchema( schemaName, targetRegistries ); 825 826 if ( schema == null ) 827 { 828 // The schema is not loaded. We can't create the requested Normalizer 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 // The FQCN 840 String fqcn = getFqcn( normalizerDescription, SchemaConstants.NORMALIZER ); 841 842 // get the byteCode 843 Attribute byteCode = getByteCode( normalizerDescription, SchemaConstants.NORMALIZER ); 844 845 // Class load the normalizer 846 Normalizer normalizer = classLoadNormalizer( schemaManager, oid, fqcn, byteCode ); 847 848 // Update the common fields 849 setSchemaObjectProperties( normalizer, normalizerDescription, schema ); 850 851 return normalizer; 852 } 853 854 855 /** 856 * {@inheritDoc} 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 // The Normalizer OID 865 String oid = getOid( entry, SchemaConstants.NORMALIZER, schemaManager.isStrict() ); 866 867 // Get the schema 868 if ( !schemaManager.isSchemaLoaded( schemaName ) ) 869 { 870 // The schema is not loaded. We can't create the requested Normalizer 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 // The schema is disabled. We still have to update the backend 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 // The FQCN 895 String className = getFqcn( entry, SchemaConstants.NORMALIZER ); 896 897 // The ByteCode 898 Attribute byteCode = entry.get( MetaSchemaConstants.M_BYTECODE_AT ); 899 900 try 901 { 902 // Class load the Normalizer 903 Normalizer normalizer = classLoadNormalizer( schemaManager, oid, className, byteCode ); 904 905 // Update the common fields 906 setSchemaObjectProperties( normalizer, entry, schema ); 907 908 // return the resulting Normalizer 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 * {@inheritDoc} 920 * @throws LdapInvalidAttributeValueException If the Syntax does not exist 921 * @throws LdapUnwillingToPerformException If the schema is not loaded 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 // The Syntax OID 930 String oid = getOid( entry, SchemaConstants.SYNTAX, schemaManager.isStrict() ); 931 932 // Get the schema 933 if ( !schemaManager.isSchemaLoaded( schemaName ) ) 934 { 935 // The schema is not loaded. We can't create the requested Syntax 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 // The schema is disabled. We still have to update the backend 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 // Create the new LdapSyntax instance 960 LdapSyntax syntax = new LdapSyntax( oid ); 961 962 // Common properties 963 setSchemaObjectProperties( syntax, entry, schema ); 964 965 return syntax; 966 } 967 968 969 /** 970 * {@inheritDoc} 971 * @throws LdapInvalidAttributeValueException If the MatchingRule does not exist 972 * @throws LdapUnwillingToPerformException If the schema is not loaded 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 // The MatchingRule OID 981 String oid = getOid( entry, SchemaConstants.MATCHING_RULE, schemaManager.isStrict() ); 982 983 // Get the schema 984 if ( !schemaManager.isSchemaLoaded( schemaName ) ) 985 { 986 // The schema is not loaded. We can't create the requested MatchingRule 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 // The schema is disabled. We still have to update the backend 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 // The syntax field 1013 Attribute mSyntax = entry.get( MetaSchemaConstants.M_SYNTAX_AT ); 1014 1015 if ( mSyntax != null ) 1016 { 1017 matchingRule.setSyntaxOid( mSyntax.getString() ); 1018 } 1019 1020 // The normalizer and comparator fields will be updated when we will 1021 // apply the registry 1022 1023 // Common properties 1024 setSchemaObjectProperties( matchingRule, entry, schema ); 1025 1026 return matchingRule; 1027 } 1028 1029 1030 /** 1031 * Create a list of string from a multivalued attribute's values 1032 * 1033 * @param attr The Attribute to read 1034 * @return The list of values as Strings 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 * {@inheritDoc} 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 // The ObjectClass OID 1064 String oid = getOid( entry, SchemaConstants.OBJECT_CLASS, schemaManager.isStrict() ); 1065 1066 // Get the schema 1067 if ( !schemaManager.isSchemaLoaded( schemaName ) ) 1068 { 1069 // The schema is not loaded. We can't create the requested ObjectClass 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 // The schema is disabled. We still have to update the backend 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 // Create the ObjectClass instance 1094 ObjectClass oc = new ObjectClass( oid ); 1095 1096 // The Sup field 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 // The May field 1105 Attribute mMay = entry.get( MetaSchemaConstants.M_MAY_AT ); 1106 1107 if ( mMay != null ) 1108 { 1109 oc.setMayAttributeTypeOids( getStrings( mMay ) ); 1110 } 1111 1112 // The Must field 1113 Attribute mMust = entry.get( MetaSchemaConstants.M_MUST_AT ); 1114 1115 if ( mMust != null ) 1116 { 1117 oc.setMustAttributeTypeOids( getStrings( mMust ) ); 1118 } 1119 1120 // The objectClassType field 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 // Common properties 1130 setSchemaObjectProperties( oc, entry, schema ); 1131 1132 return oc; 1133 } 1134 1135 1136 /** 1137 * {@inheritDoc} 1138 * @throws LdapInvalidAttributeValueException If the AttributeType does not exist 1139 * @throws LdapUnwillingToPerformException If the schema is not loaded 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 // The AttributeType OID 1148 String oid = getOid( entry, SchemaConstants.ATTRIBUTE_TYPE, schemaManager.isStrict() ); 1149 1150 // Get the schema 1151 if ( !schemaManager.isSchemaLoaded( schemaName ) ) 1152 { 1153 // The schema is not loaded, this is an error 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 // The schema is disabled. We still have to update the backend 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 // Create the new AttributeType 1178 AttributeType attributeType = new AttributeType( oid ); 1179 1180 if ( schemaManager.isRelaxed() ) 1181 { 1182 attributeType.setRelaxed( true ); 1183 } 1184 1185 // Syntax 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 // Syntax Length 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 // Equality 1202 Attribute mEquality = entry.get( MetaSchemaConstants.M_EQUALITY_AT ); 1203 1204 if ( mEquality != null ) 1205 { 1206 attributeType.setEqualityOid( mEquality.getString() ); 1207 } 1208 1209 // Ordering 1210 Attribute mOrdering = entry.get( MetaSchemaConstants.M_ORDERING_AT ); 1211 1212 if ( mOrdering != null ) 1213 { 1214 attributeType.setOrderingOid( mOrdering.getString() ); 1215 } 1216 1217 // Substr 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 // Sup 1228 if ( mSupAttributeType != null ) 1229 { 1230 attributeType.setSuperiorOid( mSupAttributeType.getString() ); 1231 } 1232 1233 // isCollective 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 // isSingleValued 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 // isReadOnly 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 // Usage 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 // Common properties 1269 setSchemaObjectProperties( attributeType, entry, schema ); 1270 1271 return attributeType; 1272 } 1273 1274 1275 /** 1276 * Process the FQCN attribute 1277 * 1278 * @param entry The entry to read 1279 * @param objectType The type of schema object 1280 * @return The schema object FQCN 1281 * @throws LdapInvalidAttributeValueException If the attribute does not contain a valid value 1282 */ 1283 private String getFqcn( Entry entry, String objectType ) throws LdapInvalidAttributeValueException 1284 { 1285 // The FQCN 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 * Process the FQCN attribute 1306 * 1307 * @param description The Schema Object description 1308 * @param objectType The SchemaObject type 1309 * @return The SchemaObject FQCN 1310 */ 1311 private String getFqcn( LoadableSchemaObject description, String objectType ) 1312 { 1313 // The FQCN 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 * Process the ByteCode attribute 1334 * 1335 * @param description The SchemaObject description 1336 * @param objectType The SchemaObject type 1337 * @return The Attribute containing the byteCode 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.decode( byteCodeString.toCharArray() ); 1356 1357 return new DefaultAttribute( MetaSchemaConstants.M_BYTECODE_AT, bytecode ); 1358 } 1359 1360 1361 /** 1362 * Process the common attributes to all SchemaObjects : 1363 * - obsolete 1364 * - description 1365 * - names 1366 * - schemaName 1367 * - specification (if any) 1368 * - extensions 1369 * - isReadOnly 1370 * - isEnabled 1371 * 1372 * @param schemaObject The SchemaObject to set 1373 * @param entry The entry containing the SchemaObject properties 1374 * @param schema the updated Schema 1375 * @throws LdapInvalidAttributeValueException If some of the properties are invalid 1376 */ 1377 private void setSchemaObjectProperties( SchemaObject schemaObject, Entry entry, Schema schema ) 1378 throws LdapInvalidAttributeValueException 1379 { 1380 // The isObsolete field 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 // The description field 1390 Attribute mDescription = entry.get( MetaSchemaConstants.M_DESCRIPTION_AT ); 1391 1392 if ( mDescription != null ) 1393 { 1394 schemaObject.setDescription( mDescription.getString() ); 1395 } 1396 1397 // The names field 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 // The isEnabled field 1413 Attribute mDisabled = entry.get( MetaSchemaConstants.M_DISABLED_AT ); 1414 1415 // If the SchemaObject has an explicit m-disabled attribute, then use it. 1416 // Otherwise, inherit it from the schema 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 // The specification field 1428 /* 1429 * TODO : create the M_SPECIFICATION_AT 1430 EntryAttribute mSpecification = entry.get( MetaSchemaConstants.M_SPECIFICATION_AT ); 1431 1432 if ( mSpecification != null ) 1433 { 1434 so.setSpecification( mSpecification.getString() ); 1435 } 1436 */ 1437 1438 // The schemaName field 1439 schemaObject.setSchemaName( schema.getSchemaName() ); 1440 1441 // The extensions fields 1442 // X-SCHEMA 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 // X-NOT-HUMAN-READABLE 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 // X-READ-ONLY 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 * Process the common attributes to all SchemaObjects : 1484 * - obsolete 1485 * - description 1486 * - names 1487 * - schemaName 1488 * - specification (if any) 1489 * - extensions 1490 * - isEnabled 1491 * 1492 * @param schemaObject The SchemaObject to set 1493 * @param description The SchemaObjetc description 1494 * @param schema the updated Schema 1495 */ 1496 private void setSchemaObjectProperties( SchemaObject schemaObject, SchemaObject description, Schema schema ) 1497 { 1498 // The isObsolete field 1499 schemaObject.setObsolete( description.isObsolete() ); 1500 1501 // The description field 1502 schemaObject.setDescription( description.getDescription() ); 1503 1504 // The names field 1505 schemaObject.setNames( description.getNames() ); 1506 1507 // The isEnabled field. Has the description does not hold a 1508 // Disable field, we will inherit from the schema enable field 1509 schemaObject.setEnabled( schema.isEnabled() ); 1510 1511 // The specification field 1512 schemaObject.setSpecification( description.getSpecification() ); 1513 1514 // The schemaName field 1515 schemaObject.setSchemaName( schema.getSchemaName() ); 1516 1517 // The extensions field 1518 schemaObject.setExtensions( description.getExtensions() ); 1519 } 1520}