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