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 /** a map of all the resources in this jar */ 070 private static final Map<String, Boolean> RESOURCE_MAP = ResourceMap.getResources( Pattern 071 .compile( "schema" + SEPARATOR_PATTERN + "ou=schema.*" ) ); 072 073 074 /** 075 * Creates a new LDIF based SchemaLoader. The constructor checks to make 076 * sure the supplied base directory exists and contains a schema.ldif file 077 * and if not complains about it. 078 * 079 * @throws LdapException if the base directory does not exist or does not 080 * a valid schema.ldif file 081 * @throws IOException If we can't load the schema 082 */ 083 public JarLdifSchemaLoader() throws IOException, LdapException 084 { 085 initializeSchemas(); 086 } 087 088 089 private URL getResource( String resource, String msg ) throws IOException 090 { 091 if ( RESOURCE_MAP.get( resource ) ) 092 { 093 return DefaultSchemaLdifExtractor.getUniqueResource( resource, msg ); 094 } 095 else 096 { 097 return new File( resource ).toURI().toURL(); 098 } 099 } 100 101 102 /** 103 * Scans for LDIF files just describing the various schema contained in 104 * the schema repository. 105 * 106 * @throws LdapException If the schema can't be initialized 107 * @throws IOException If the file cannot be read 108 */ 109 private void initializeSchemas() throws IOException, LdapException 110 { 111 if ( LOG.isDebugEnabled() ) 112 { 113 LOG.debug( I18n.msg( I18n.MSG_16006_INITIALIZING_SCHEMA ) ); 114 } 115 116 Pattern pat = Pattern.compile( "schema" + SEPARATOR_PATTERN + "ou=schema" 117 + SEPARATOR_PATTERN + "cn=[a-z0-9-_]*\\." + LDIF_EXT ); 118 119 for ( String file : RESOURCE_MAP.keySet() ) 120 { 121 if ( pat.matcher( file ).matches() ) 122 { 123 URL resource = getResource( file, "schema LDIF file" ); 124 125 try ( InputStream in = resource.openStream() ) 126 { 127 try ( LdifReader reader = new LdifReader( in ) ) 128 { 129 LdifEntry entry = reader.next(); 130 Schema schema = getSchema( entry.getEntry() ); 131 schemaMap.put( schema.getSchemaName(), schema ); 132 133 if ( LOG.isDebugEnabled() ) 134 { 135 LOG.debug( I18n.msg( I18n.MSG_16007_SCHEMA_INITIALIZED, schema ) ); 136 } 137 } 138 } 139 catch ( LdapException le ) 140 { 141 LOG.error( I18n.err( I18n.ERR_16009_LDIF_LOAD_FAIL, file ), le ); 142 throw le; 143 } 144 } 145 } 146 } 147 148 149 /** 150 * Utility method to get a regex.Pattern fragment for the path for a schema directory. 151 * 152 * @param schema the schema to get the path for 153 * @return the regex.Pattern fragment for the path for the specified schema directory 154 */ 155 private String getSchemaDirectoryString( Schema schema ) 156 { 157 return "schema" + "/" + "ou=schema" + "/" 158 + "cn=" + Strings.lowerCase( schema.getSchemaName() ) + "/"; 159 } 160 161 162 /** 163 * {@inheritDoc} 164 */ 165 @Override 166 public List<Entry> loadComparators( Schema... schemas ) throws LdapException, IOException 167 { 168 List<Entry> comparatorList = new ArrayList<>(); 169 170 if ( schemas == null ) 171 { 172 return comparatorList; 173 } 174 175 for ( Schema schema : schemas ) 176 { 177 String start = getSchemaDirectoryString( schema ) 178 + SchemaConstants.COMPARATORS_PATH + "/" + "m-oid="; 179 String end = "." + LDIF_EXT; 180 181 for ( String resourcePath : RESOURCE_MAP.keySet() ) 182 { 183 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 184 { 185 URL resource = getResource( resourcePath, "comparator LDIF file" ); 186 LdifReader reader = new LdifReader( resource.openStream() ); 187 LdifEntry entry = reader.next(); 188 reader.close(); 189 190 comparatorList.add( entry.getEntry() ); 191 } 192 } 193 } 194 195 return comparatorList; 196 } 197 198 199 /** 200 * {@inheritDoc} 201 */ 202 @Override 203 public List<Entry> loadSyntaxCheckers( Schema... schemas ) throws LdapException, IOException 204 { 205 List<Entry> syntaxCheckerList = new ArrayList<>(); 206 207 if ( schemas == null ) 208 { 209 return syntaxCheckerList; 210 } 211 212 for ( Schema schema : schemas ) 213 { 214 String start = getSchemaDirectoryString( schema ) 215 + SchemaConstants.SYNTAX_CHECKERS_PATH + "/" + "m-oid="; 216 String end = "." + LDIF_EXT; 217 218 for ( String resourcePath : RESOURCE_MAP.keySet() ) 219 { 220 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 221 { 222 URL resource = getResource( resourcePath, "syntaxChecker LDIF file" ); 223 LdifReader reader = new LdifReader( resource.openStream() ); 224 LdifEntry entry = reader.next(); 225 reader.close(); 226 227 syntaxCheckerList.add( entry.getEntry() ); 228 } 229 } 230 } 231 232 return syntaxCheckerList; 233 } 234 235 236 /** 237 * {@inheritDoc} 238 */ 239 @Override 240 public List<Entry> loadNormalizers( Schema... schemas ) throws LdapException, IOException 241 { 242 List<Entry> normalizerList = new ArrayList<>(); 243 244 if ( schemas == null ) 245 { 246 return normalizerList; 247 } 248 249 for ( Schema schema : schemas ) 250 { 251 String start = getSchemaDirectoryString( schema ) 252 + SchemaConstants.NORMALIZERS_PATH + "/" + "m-oid="; 253 String end = "." + LDIF_EXT; 254 255 for ( String resourcePath : RESOURCE_MAP.keySet() ) 256 { 257 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 258 { 259 URL resource = getResource( resourcePath, "normalizer LDIF file" ); 260 LdifReader reader = new LdifReader( resource.openStream() ); 261 LdifEntry entry = reader.next(); 262 reader.close(); 263 264 normalizerList.add( entry.getEntry() ); 265 } 266 } 267 } 268 269 return normalizerList; 270 } 271 272 273 /** 274 * {@inheritDoc} 275 */ 276 @Override 277 public List<Entry> loadMatchingRules( Schema... schemas ) throws LdapException, IOException 278 { 279 List<Entry> matchingRuleList = new ArrayList<>(); 280 281 if ( schemas == null ) 282 { 283 return matchingRuleList; 284 } 285 286 for ( Schema schema : schemas ) 287 { 288 String start = getSchemaDirectoryString( schema ) 289 + SchemaConstants.MATCHING_RULES_PATH + "/" + "m-oid="; 290 String end = "." + LDIF_EXT; 291 292 for ( String resourcePath : RESOURCE_MAP.keySet() ) 293 { 294 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 295 { 296 URL resource = getResource( resourcePath, "matchingRules LDIF file" ); 297 LdifReader reader = new LdifReader( resource.openStream() ); 298 LdifEntry entry = reader.next(); 299 reader.close(); 300 301 matchingRuleList.add( entry.getEntry() ); 302 } 303 } 304 } 305 306 return matchingRuleList; 307 } 308 309 310 /** 311 * {@inheritDoc} 312 */ 313 @Override 314 public List<Entry> loadSyntaxes( Schema... schemas ) throws LdapException, IOException 315 { 316 List<Entry> syntaxList = new ArrayList<>(); 317 318 if ( schemas == null ) 319 { 320 return syntaxList; 321 } 322 323 for ( Schema schema : schemas ) 324 { 325 String start = getSchemaDirectoryString( schema ) 326 + SchemaConstants.SYNTAXES_PATH + "/" + "m-oid="; 327 String end = "." + LDIF_EXT; 328 329 for ( String resourcePath : RESOURCE_MAP.keySet() ) 330 { 331 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 332 { 333 URL resource = getResource( resourcePath, "syntax LDIF file" ); 334 LdifReader reader = new LdifReader( resource.openStream() ); 335 LdifEntry entry = reader.next(); 336 reader.close(); 337 338 syntaxList.add( entry.getEntry() ); 339 } 340 } 341 } 342 343 return syntaxList; 344 } 345 346 347 /** 348 * {@inheritDoc} 349 */ 350 @Override 351 public List<Entry> loadAttributeTypes( Schema... schemas ) throws LdapException, IOException 352 { 353 List<Entry> attributeTypeList = new ArrayList<>(); 354 355 if ( schemas == null ) 356 { 357 return attributeTypeList; 358 } 359 360 for ( Schema schema : schemas ) 361 { 362 // check that the attributeTypes directory exists for the schema 363 String start = getSchemaDirectoryString( schema ) 364 + SchemaConstants.ATTRIBUTE_TYPES_PATH + "/" + "m-oid="; 365 String end = "." + LDIF_EXT; 366 367 // get list of attributeType LDIF schema files in attributeTypes 368 for ( String resourcePath : RESOURCE_MAP.keySet() ) 369 { 370 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 371 { 372 URL resource = getResource( resourcePath, "attributeType LDIF file" ); 373 LdifReader reader = new LdifReader( resource.openStream() ); 374 LdifEntry entry = reader.next(); 375 reader.close(); 376 377 attributeTypeList.add( entry.getEntry() ); 378 } 379 } 380 } 381 382 return attributeTypeList; 383 } 384 385 386 /** 387 * {@inheritDoc} 388 */ 389 @Override 390 public List<Entry> loadMatchingRuleUses( Schema... schemas ) throws LdapException, IOException 391 { 392 List<Entry> matchingRuleUseList = new ArrayList<>(); 393 394 if ( schemas == null ) 395 { 396 return matchingRuleUseList; 397 } 398 399 for ( Schema schema : schemas ) 400 { 401 String start = getSchemaDirectoryString( schema ) 402 + SchemaConstants.MATCHING_RULE_USE_PATH + "/" + "m-oid="; 403 String end = "." + LDIF_EXT; 404 405 for ( String resourcePath : RESOURCE_MAP.keySet() ) 406 { 407 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 408 { 409 URL resource = getResource( resourcePath, "matchingRuleUse LDIF file" ); 410 LdifReader reader = new LdifReader( resource.openStream() ); 411 LdifEntry entry = reader.next(); 412 reader.close(); 413 414 matchingRuleUseList.add( entry.getEntry() ); 415 } 416 } 417 } 418 419 return matchingRuleUseList; 420 } 421 422 423 /** 424 * {@inheritDoc} 425 */ 426 @Override 427 public List<Entry> loadNameForms( Schema... schemas ) throws LdapException, IOException 428 { 429 List<Entry> nameFormList = new ArrayList<>(); 430 431 if ( schemas == null ) 432 { 433 return nameFormList; 434 } 435 436 for ( Schema schema : schemas ) 437 { 438 String start = getSchemaDirectoryString( schema ) 439 + SchemaConstants.NAME_FORMS_PATH + "/" + "m-oid="; 440 String end = "." + LDIF_EXT; 441 442 for ( String resourcePath : RESOURCE_MAP.keySet() ) 443 { 444 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 445 { 446 URL resource = getResource( resourcePath, "nameForm LDIF file" ); 447 LdifReader reader = new LdifReader( resource.openStream() ); 448 LdifEntry entry = reader.next(); 449 reader.close(); 450 451 nameFormList.add( entry.getEntry() ); 452 } 453 } 454 } 455 456 return nameFormList; 457 } 458 459 460 /** 461 * {@inheritDoc} 462 */ 463 @Override 464 public List<Entry> loadDitContentRules( Schema... schemas ) throws LdapException, IOException 465 { 466 List<Entry> ditContentRulesList = new ArrayList<>(); 467 468 if ( schemas == null ) 469 { 470 return ditContentRulesList; 471 } 472 473 for ( Schema schema : schemas ) 474 { 475 String start = getSchemaDirectoryString( schema ) 476 + SchemaConstants.DIT_CONTENT_RULES_PATH + "/" + "m-oid="; 477 String end = "." + LDIF_EXT; 478 479 for ( String resourcePath : RESOURCE_MAP.keySet() ) 480 { 481 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 482 { 483 URL resource = getResource( resourcePath, "ditContentRule LDIF file" ); 484 LdifReader reader = new LdifReader( resource.openStream() ); 485 LdifEntry entry = reader.next(); 486 reader.close(); 487 488 ditContentRulesList.add( entry.getEntry() ); 489 } 490 } 491 } 492 493 return ditContentRulesList; 494 } 495 496 497 /** 498 * {@inheritDoc} 499 */ 500 @Override 501 public List<Entry> loadDitStructureRules( Schema... schemas ) throws LdapException, IOException 502 { 503 List<Entry> ditStructureRuleList = new ArrayList<>(); 504 505 if ( schemas == null ) 506 { 507 return ditStructureRuleList; 508 } 509 510 for ( Schema schema : schemas ) 511 { 512 String start = getSchemaDirectoryString( schema ) 513 + SchemaConstants.DIT_STRUCTURE_RULES_PATH + "/" + "m-oid="; 514 String end = "." + LDIF_EXT; 515 516 for ( String resourcePath : RESOURCE_MAP.keySet() ) 517 { 518 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 519 { 520 URL resource = getResource( resourcePath, "ditStructureRule LDIF file" ); 521 LdifReader reader = new LdifReader( resource.openStream() ); 522 LdifEntry entry = reader.next(); 523 reader.close(); 524 525 ditStructureRuleList.add( entry.getEntry() ); 526 } 527 } 528 } 529 530 return ditStructureRuleList; 531 } 532 533 534 /** 535 * {@inheritDoc} 536 */ 537 @Override 538 public List<Entry> loadObjectClasses( Schema... schemas ) throws LdapException, IOException 539 { 540 List<Entry> objectClassList = new ArrayList<>(); 541 542 if ( schemas == null ) 543 { 544 return objectClassList; 545 } 546 547 for ( Schema schema : schemas ) 548 { 549 // get objectClasses directory, check if exists, return if not 550 String start = getSchemaDirectoryString( schema ) 551 + SchemaConstants.OBJECT_CLASSES_PATH + "/" + "m-oid="; 552 String end = "." + LDIF_EXT; 553 554 for ( String resourcePath : RESOURCE_MAP.keySet() ) 555 { 556 if ( resourcePath.startsWith( start ) && resourcePath.endsWith( end ) ) 557 { 558 URL resource = getResource( resourcePath, "objectClass LDIF file" ); 559 LdifReader reader = new LdifReader( resource.openStream() ); 560 LdifEntry entry = reader.next(); 561 reader.close(); 562 563 objectClassList.add( entry.getEntry() ); 564 } 565 } 566 } 567 568 return objectClassList; 569 } 570}