001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.ldap.schema.loader; 021 022 023import java.io.File; 024import java.io.IOException; 025import java.io.InputStream; 026import java.net.URL; 027import java.util.ArrayList; 028import java.util.List; 029import java.util.Map; 030import java.util.regex.Pattern; 031 032import org.apache.directory.api.i18n.I18n; 033import org.apache.directory.api.ldap.model.constants.SchemaConstants; 034import org.apache.directory.api.ldap.model.entry.Entry; 035import org.apache.directory.api.ldap.model.exception.LdapException; 036import org.apache.directory.api.ldap.model.ldif.LdifEntry; 037import org.apache.directory.api.ldap.model.ldif.LdifReader; 038import org.apache.directory.api.ldap.model.schema.registries.AbstractSchemaLoader; 039import org.apache.directory.api.ldap.model.schema.registries.Schema; 040import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor; 041import org.apache.directory.api.ldap.schema.extractor.impl.ResourceMap; 042import org.apache.directory.api.util.Strings; 043import org.slf4j.Logger; 044import org.slf4j.LoggerFactory; 045 046 047/** 048 * Loads schema data from LDIF files containing entries representing schema 049 * objects, using the meta schema format. 050 * 051 * This class is used only for tests. 052 * 053 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 054 */ 055public class JarLdifSchemaLoader extends AbstractSchemaLoader 056{ 057 /** 058 * Filesystem path separator pattern, either forward slash or backslash. 059 * java.util.regex.Pattern is immutable so only one instance is needed for all uses. 060 */ 061 private static final String SEPARATOR_PATTERN = "[/\\Q\\\\E]"; 062 063 /** ldif file extension used */ 064 private static final String LDIF_EXT = "ldif"; 065 066 /** static class logger */ 067 private static final Logger LOG = LoggerFactory.getLogger( JarLdifSchemaLoader.class ); 068 069 /** Speedup for DEBUG mode */ 070 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 071 072 /** a map of all the resources in this jar */ 073 private static final Map<String, Boolean> RESOURCE_MAP = ResourceMap.getResources( Pattern 074 .compile( "schema" + SEPARATOR_PATTERN + "ou=schema.*" ) ); 075 076 077 /** 078 * Creates a new LDIF based SchemaLoader. The constructor checks to make 079 * sure the supplied base directory exists and contains a schema.ldif file 080 * and if not complains about it. 081 * 082 * @throws LdapException if the base directory does not exist or does not 083 * a valid schema.ldif file 084 * @throws IOException If we can't load the schema 085 */ 086 public JarLdifSchemaLoader() throws IOException, LdapException 087 { 088 initializeSchemas(); 089 } 090 091 092 private URL getResource( String resource, String msg ) throws IOException 093 { 094 if ( RESOURCE_MAP.get( resource ) ) 095 { 096 return DefaultSchemaLdifExtractor.getUniqueResource( resource, msg ); 097 } 098 else 099 { 100 return new File( resource ).toURI().toURL(); 101 } 102 } 103 104 105 /** 106 * Scans for LDIF files just describing the various schema contained in 107 * the schema repository. 108 * 109 * @throws LdapException 110 */ 111 private void initializeSchemas() throws IOException, LdapException 112 { 113 if ( IS_DEBUG ) 114 { 115 LOG.debug( "Initializing schema" ); 116 } 117 118 Pattern pat = Pattern.compile( "schema" + SEPARATOR_PATTERN + "ou=schema" 119 + SEPARATOR_PATTERN + "cn=[a-z0-9-_]*\\." + LDIF_EXT ); 120 121 for ( String file : RESOURCE_MAP.keySet() ) 122 { 123 if ( pat.matcher( file ).matches() ) 124 { 125 URL resource = getResource( file, "schema LDIF file" ); 126 InputStream in = resource.openStream(); 127 128 try 129 { 130 LdifReader reader = new LdifReader( in ); 131 LdifEntry entry = reader.next(); 132 reader.close(); 133 Schema schema = getSchema( entry.getEntry() ); 134 schemaMap.put( schema.getSchemaName(), schema ); 135 136 if ( IS_DEBUG ) 137 { 138 LOG.debug( "Schema Initialized ... \n{}", schema ); 139 } 140 } 141 catch ( LdapException le ) 142 { 143 LOG.error( I18n.err( I18n.ERR_10003, file ), le ); 144 throw le; 145 } 146 finally 147 { 148 in.close(); 149 } 150 } 151 } 152 } 153 154 155 /** 156 * Utility method to get a regex.Pattern fragment for the path for a schema directory. 157 * 158 * @param schema the schema to get the path for 159 * @return the regex.Pattern fragment for the path for the specified schema directory 160 */ 161 private String getSchemaDirectoryString( Schema schema ) 162 { 163 return "schema" + "/" + "ou=schema" + "/" 164 + "cn=" + Strings.lowerCase( schema.getSchemaName() ) + "/"; 165 } 166 167 168 /** 169 * {@inheritDoc} 170 */ 171 @Override 172 public List<Entry> loadComparators( Schema... schemas ) throws LdapException, IOException 173 { 174 List<Entry> comparatorList = new ArrayList<>(); 175 176 if ( schemas == null ) 177 { 178 return comparatorList; 179 } 180 181 for ( Schema schema : schemas ) 182 { 183 String start = getSchemaDirectoryString( schema ) 184 + SchemaConstants.COMPARATORS_PATH + "/" + "m-oid="; 185 String end = "." + LDIF_EXT; 186 187 for ( String resourcePath : RESOURCE_MAP.keySet() ) 188 { 189 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 190 { 191 URL resource = getResource( resourcePath, "comparator LDIF file" ); 192 LdifReader reader = new LdifReader( resource.openStream() ); 193 LdifEntry entry = reader.next(); 194 reader.close(); 195 196 comparatorList.add( entry.getEntry() ); 197 } 198 } 199 } 200 201 return comparatorList; 202 } 203 204 205 /** 206 * {@inheritDoc} 207 */ 208 @Override 209 public List<Entry> loadSyntaxCheckers( Schema... schemas ) throws LdapException, IOException 210 { 211 List<Entry> syntaxCheckerList = new ArrayList<>(); 212 213 if ( schemas == null ) 214 { 215 return syntaxCheckerList; 216 } 217 218 for ( Schema schema : schemas ) 219 { 220 String start = getSchemaDirectoryString( schema ) 221 + SchemaConstants.SYNTAX_CHECKERS_PATH + "/" + "m-oid="; 222 String end = "." + LDIF_EXT; 223 224 for ( String resourcePath : RESOURCE_MAP.keySet() ) 225 { 226 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 227 { 228 URL resource = getResource( resourcePath, "syntaxChecker LDIF file" ); 229 LdifReader reader = new LdifReader( resource.openStream() ); 230 LdifEntry entry = reader.next(); 231 reader.close(); 232 233 syntaxCheckerList.add( entry.getEntry() ); 234 } 235 } 236 } 237 238 return syntaxCheckerList; 239 } 240 241 242 /** 243 * {@inheritDoc} 244 */ 245 @Override 246 public List<Entry> loadNormalizers( Schema... schemas ) throws LdapException, IOException 247 { 248 List<Entry> normalizerList = new ArrayList<>(); 249 250 if ( schemas == null ) 251 { 252 return normalizerList; 253 } 254 255 for ( Schema schema : schemas ) 256 { 257 String start = getSchemaDirectoryString( schema ) 258 + SchemaConstants.NORMALIZERS_PATH + "/" + "m-oid="; 259 String end = "." + LDIF_EXT; 260 261 for ( String resourcePath : RESOURCE_MAP.keySet() ) 262 { 263 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 264 { 265 URL resource = getResource( resourcePath, "normalizer LDIF file" ); 266 LdifReader reader = new LdifReader( resource.openStream() ); 267 LdifEntry entry = reader.next(); 268 reader.close(); 269 270 normalizerList.add( entry.getEntry() ); 271 } 272 } 273 } 274 275 return normalizerList; 276 } 277 278 279 /** 280 * {@inheritDoc} 281 */ 282 @Override 283 public List<Entry> loadMatchingRules( Schema... schemas ) throws LdapException, IOException 284 { 285 List<Entry> matchingRuleList = new ArrayList<>(); 286 287 if ( schemas == null ) 288 { 289 return matchingRuleList; 290 } 291 292 for ( Schema schema : schemas ) 293 { 294 String start = getSchemaDirectoryString( schema ) 295 + SchemaConstants.MATCHING_RULES_PATH + "/" + "m-oid="; 296 String end = "." + LDIF_EXT; 297 298 for ( String resourcePath : RESOURCE_MAP.keySet() ) 299 { 300 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 301 { 302 URL resource = getResource( resourcePath, "matchingRules LDIF file" ); 303 LdifReader reader = new LdifReader( resource.openStream() ); 304 LdifEntry entry = reader.next(); 305 reader.close(); 306 307 matchingRuleList.add( entry.getEntry() ); 308 } 309 } 310 } 311 312 return matchingRuleList; 313 } 314 315 316 /** 317 * {@inheritDoc} 318 */ 319 @Override 320 public List<Entry> loadSyntaxes( Schema... schemas ) throws LdapException, IOException 321 { 322 List<Entry> syntaxList = new ArrayList<>(); 323 324 if ( schemas == null ) 325 { 326 return syntaxList; 327 } 328 329 for ( Schema schema : schemas ) 330 { 331 String start = getSchemaDirectoryString( schema ) 332 + SchemaConstants.SYNTAXES_PATH + "/" + "m-oid="; 333 String end = "." + LDIF_EXT; 334 335 for ( String resourcePath : RESOURCE_MAP.keySet() ) 336 { 337 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 338 { 339 URL resource = getResource( resourcePath, "syntax LDIF file" ); 340 LdifReader reader = new LdifReader( resource.openStream() ); 341 LdifEntry entry = reader.next(); 342 reader.close(); 343 344 syntaxList.add( entry.getEntry() ); 345 } 346 } 347 } 348 349 return syntaxList; 350 } 351 352 353 /** 354 * {@inheritDoc} 355 */ 356 @Override 357 public List<Entry> loadAttributeTypes( Schema... schemas ) throws LdapException, IOException 358 { 359 List<Entry> attributeTypeList = new ArrayList<>(); 360 361 if ( schemas == null ) 362 { 363 return attributeTypeList; 364 } 365 366 for ( Schema schema : schemas ) 367 { 368 // check that the attributeTypes directory exists for the schema 369 String start = getSchemaDirectoryString( schema ) 370 + SchemaConstants.ATTRIBUTE_TYPES_PATH + "/" + "m-oid="; 371 String end = "." + LDIF_EXT; 372 373 // get list of attributeType LDIF schema files in attributeTypes 374 for ( String resourcePath : RESOURCE_MAP.keySet() ) 375 { 376 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 377 { 378 URL resource = getResource( resourcePath, "attributeType LDIF file" ); 379 LdifReader reader = new LdifReader( resource.openStream() ); 380 LdifEntry entry = reader.next(); 381 reader.close(); 382 383 attributeTypeList.add( entry.getEntry() ); 384 } 385 } 386 } 387 388 return attributeTypeList; 389 } 390 391 392 /** 393 * {@inheritDoc} 394 */ 395 @Override 396 public List<Entry> loadMatchingRuleUses( Schema... schemas ) throws LdapException, IOException 397 { 398 List<Entry> matchingRuleUseList = new ArrayList<>(); 399 400 if ( schemas == null ) 401 { 402 return matchingRuleUseList; 403 } 404 405 for ( Schema schema : schemas ) 406 { 407 String start = getSchemaDirectoryString( schema ) 408 + SchemaConstants.MATCHING_RULE_USE_PATH + "/" + "m-oid="; 409 String end = "." + LDIF_EXT; 410 411 for ( String resourcePath : RESOURCE_MAP.keySet() ) 412 { 413 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 414 { 415 URL resource = getResource( resourcePath, "matchingRuleUse LDIF file" ); 416 LdifReader reader = new LdifReader( resource.openStream() ); 417 LdifEntry entry = reader.next(); 418 reader.close(); 419 420 matchingRuleUseList.add( entry.getEntry() ); 421 } 422 } 423 } 424 425 return matchingRuleUseList; 426 } 427 428 429 /** 430 * {@inheritDoc} 431 */ 432 @Override 433 public List<Entry> loadNameForms( Schema... schemas ) throws LdapException, IOException 434 { 435 List<Entry> nameFormList = new ArrayList<>(); 436 437 if ( schemas == null ) 438 { 439 return nameFormList; 440 } 441 442 for ( Schema schema : schemas ) 443 { 444 String start = getSchemaDirectoryString( schema ) 445 + SchemaConstants.NAME_FORMS_PATH + "/" + "m-oid="; 446 String end = "." + LDIF_EXT; 447 448 for ( String resourcePath : RESOURCE_MAP.keySet() ) 449 { 450 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 451 { 452 URL resource = getResource( resourcePath, "nameForm LDIF file" ); 453 LdifReader reader = new LdifReader( resource.openStream() ); 454 LdifEntry entry = reader.next(); 455 reader.close(); 456 457 nameFormList.add( entry.getEntry() ); 458 } 459 } 460 } 461 462 return nameFormList; 463 } 464 465 466 /** 467 * {@inheritDoc} 468 */ 469 @Override 470 public List<Entry> loadDitContentRules( Schema... schemas ) throws LdapException, IOException 471 { 472 List<Entry> ditContentRulesList = new ArrayList<>(); 473 474 if ( schemas == null ) 475 { 476 return ditContentRulesList; 477 } 478 479 for ( Schema schema : schemas ) 480 { 481 String start = getSchemaDirectoryString( schema ) 482 + SchemaConstants.DIT_CONTENT_RULES_PATH + "/" + "m-oid="; 483 String end = "." + LDIF_EXT; 484 485 for ( String resourcePath : RESOURCE_MAP.keySet() ) 486 { 487 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 488 { 489 URL resource = getResource( resourcePath, "ditContentRule LDIF file" ); 490 LdifReader reader = new LdifReader( resource.openStream() ); 491 LdifEntry entry = reader.next(); 492 reader.close(); 493 494 ditContentRulesList.add( entry.getEntry() ); 495 } 496 } 497 } 498 499 return ditContentRulesList; 500 } 501 502 503 /** 504 * {@inheritDoc} 505 */ 506 @Override 507 public List<Entry> loadDitStructureRules( Schema... schemas ) throws LdapException, IOException 508 { 509 List<Entry> ditStructureRuleList = new ArrayList<>(); 510 511 if ( schemas == null ) 512 { 513 return ditStructureRuleList; 514 } 515 516 for ( Schema schema : schemas ) 517 { 518 String start = getSchemaDirectoryString( schema ) 519 + SchemaConstants.DIT_STRUCTURE_RULES_PATH + "/" + "m-oid="; 520 String end = "." + LDIF_EXT; 521 522 for ( String resourcePath : RESOURCE_MAP.keySet() ) 523 { 524 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 525 { 526 URL resource = getResource( resourcePath, "ditStructureRule LDIF file" ); 527 LdifReader reader = new LdifReader( resource.openStream() ); 528 LdifEntry entry = reader.next(); 529 reader.close(); 530 531 ditStructureRuleList.add( entry.getEntry() ); 532 } 533 } 534 } 535 536 return ditStructureRuleList; 537 } 538 539 540 /** 541 * {@inheritDoc} 542 */ 543 @Override 544 public List<Entry> loadObjectClasses( Schema... schemas ) throws LdapException, IOException 545 { 546 List<Entry> objectClassList = new ArrayList<>(); 547 548 if ( schemas == null ) 549 { 550 return objectClassList; 551 } 552 553 for ( Schema schema : schemas ) 554 { 555 // get objectClasses directory, check if exists, return if not 556 String start = getSchemaDirectoryString( schema ) 557 + SchemaConstants.OBJECT_CLASSES_PATH + "/" + "m-oid="; 558 String end = "." + LDIF_EXT; 559 560 for ( String resourcePath : RESOURCE_MAP.keySet() ) 561 { 562 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 563 { 564 URL resource = getResource( resourcePath, "objectClass LDIF file" ); 565 LdifReader reader = new LdifReader( resource.openStream() ); 566 LdifEntry entry = reader.next(); 567 reader.close(); 568 569 objectClassList.add( entry.getEntry() ); 570 } 571 } 572 } 573 574 return objectClassList; 575 } 576}