View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.api.ldap.schema.loader;
21  
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.net.URL;
27  import java.util.ArrayList;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.regex.Pattern;
31  
32  import org.apache.directory.api.i18n.I18n;
33  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
34  import org.apache.directory.api.ldap.model.entry.Entry;
35  import org.apache.directory.api.ldap.model.exception.LdapException;
36  import org.apache.directory.api.ldap.model.ldif.LdifEntry;
37  import org.apache.directory.api.ldap.model.ldif.LdifReader;
38  import org.apache.directory.api.ldap.model.schema.registries.AbstractSchemaLoader;
39  import org.apache.directory.api.ldap.model.schema.registries.Schema;
40  import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
41  import org.apache.directory.api.ldap.schema.extractor.impl.ResourceMap;
42  import org.apache.directory.api.util.Strings;
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  
47  /**
48   * Loads schema data from LDIF files containing entries representing schema
49   * objects, using the meta schema format.
50   * 
51   * This class is used only for tests.
52   *
53   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
54   */
55  public class JarLdifSchemaLoader extends AbstractSchemaLoader
56  {
57      /**
58       * Filesystem path separator pattern, either forward slash or backslash.
59       * java.util.regex.Pattern is immutable so only one instance is needed for all uses.
60       */
61      private static final String SEPARATOR_PATTERN = "[/\\Q\\\\E]";
62  
63      /** ldif file extension used */
64      private static final String LDIF_EXT = "ldif";
65  
66      /** static class logger */
67      private static final Logger LOG = LoggerFactory.getLogger( JarLdifSchemaLoader.class );
68  
69      /** Speedup for DEBUG mode */
70      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
71  
72      /** a map of all the resources in this jar */
73      private static final Map<String, Boolean> RESOURCE_MAP = ResourceMap.getResources( Pattern
74          .compile( "schema" + SEPARATOR_PATTERN + "ou=schema.*" ) );
75  
76  
77      /**
78       * Creates a new LDIF based SchemaLoader. The constructor checks to make
79       * sure the supplied base directory exists and contains a schema.ldif file
80       * and if not complains about it.
81       *
82       * @throws LdapException if the base directory does not exist or does not
83       * a valid schema.ldif file
84       * @throws IOException If we can't load the schema
85       */
86      public JarLdifSchemaLoader() throws IOException, LdapException
87      {
88          initializeSchemas();
89      }
90  
91  
92      private URL getResource( String resource, String msg ) throws IOException
93      {
94          if ( RESOURCE_MAP.get( resource ) )
95          {
96              return DefaultSchemaLdifExtractor.getUniqueResource( resource, msg );
97          }
98          else
99          {
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 }