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.schemaloader;
021
022
023import java.io.File;
024import java.io.FileNotFoundException;
025import java.io.FilenameFilter;
026import java.io.IOException;
027import java.util.ArrayList;
028import java.util.List;
029
030import org.apache.directory.api.i18n.I18n;
031import org.apache.directory.api.ldap.model.constants.SchemaConstants;
032import org.apache.directory.api.ldap.model.entry.Entry;
033import org.apache.directory.api.ldap.model.exception.LdapException;
034import org.apache.directory.api.ldap.model.ldif.LdifEntry;
035import org.apache.directory.api.ldap.model.ldif.LdifReader;
036import org.apache.directory.api.ldap.model.schema.registries.AbstractSchemaLoader;
037import org.apache.directory.api.ldap.model.schema.registries.Schema;
038import org.apache.directory.api.util.Strings;
039import org.slf4j.Logger;
040import org.slf4j.LoggerFactory;
041
042
043/**
044 * Loads schema data from LDIF files containing entries representing schema
045 * objects, using the meta schema format.
046 *
047 * This class is used only for tests.
048 * 
049 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
050 */
051public class LdifSchemaLoader extends AbstractSchemaLoader
052{
053    /** ldif file extension used */
054    private static final String LDIF_EXT = "ldif";
055
056    /** ou=schema LDIF file name */
057    private static final String OU_SCHEMA_LDIF = "ou=schema." + LDIF_EXT;
058
059    /** static class logger */
060    private static final Logger LOG = LoggerFactory.getLogger( LdifSchemaLoader.class );
061
062    /** Speedup for DEBUG mode */
063    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
064
065    /** directory containing the schema LDIF file for ou=schema */
066    private final File baseDirectory;
067
068    /** a filter for listing all the LDIF files within a directory */
069    private final FilenameFilter ldifFilter = new FilenameFilter()
070    {
071        public boolean accept( File file, String name )
072        {
073            return name.endsWith( LDIF_EXT );
074        }
075    };
076
077
078    /**
079     * Creates a new LDIF based SchemaLoader. The constructor checks to make
080     * sure the supplied base directory exists and contains a schema.ldif file
081     * and if not complains about it.
082     *
083     * @param baseDirectory the schema LDIF base directory
084     * @throws Exception if the base directory does not exist or does not
085     * a valid schema.ldif file
086     */
087    public LdifSchemaLoader( File baseDirectory ) throws Exception
088    {
089        this.baseDirectory = baseDirectory;
090
091        if ( !baseDirectory.exists() )
092        {
093            String msg = "Provided baseDirectory '" + baseDirectory.getAbsolutePath() + "' does not exist.";
094            LOG.error( msg );
095            throw new IllegalArgumentException( msg );
096        }
097
098        File schemaLdif = new File( baseDirectory, OU_SCHEMA_LDIF );
099
100        if ( !schemaLdif.exists() )
101        {
102            String msg = I18n.err( I18n.ERR_10004, schemaLdif.getAbsolutePath() );
103            LOG.error( msg );
104            throw new FileNotFoundException( msg );
105        }
106
107        if ( IS_DEBUG )
108        {
109            LOG.debug( "Using '{}' as the base schema load directory.", baseDirectory );
110        }
111
112        initializeSchemas();
113    }
114
115
116    /**
117     * Scans for LDIF files just describing the various schema contained in
118     * the schema repository.
119     *
120     * @throws Exception
121     */
122    private void initializeSchemas() throws Exception
123    {
124        if ( IS_DEBUG )
125        {
126            LOG.debug( "Initializing schema" );
127        }
128
129        File schemaDirectory = new File( baseDirectory, SchemaConstants.OU_SCHEMA );
130        String[] ldifFiles = schemaDirectory.list( ldifFilter );
131
132        for ( String ldifFile : ldifFiles )
133        {
134            File file = new File( schemaDirectory, ldifFile );
135
136            try
137            {
138                LdifReader reader = new LdifReader( file );
139                LdifEntry entry = reader.next();
140                reader.close();
141                Schema schema = getSchema( entry.getEntry() );
142
143                if ( schema == null )
144                {
145                    // The entry was not a schema, skip it
146                    continue;
147                }
148
149                schemaMap.put( schema.getSchemaName(), schema );
150
151                if ( IS_DEBUG )
152                {
153                    LOG.debug( "Schema Initialized ... \n{}", schema );
154                }
155            }
156            catch ( Exception e )
157            {
158                LOG.error( I18n.err( I18n.ERR_10003, ldifFile ), e );
159                throw e;
160            }
161        }
162    }
163
164
165    /**
166     * Utility method to get the file for a schema directory.
167     *
168     * @param schema the schema to get the file for
169     * @return the file for the specific schema directory
170     */
171    private File getSchemaDirectory( Schema schema )
172    {
173        return new File( new File( baseDirectory, SchemaConstants.OU_SCHEMA ), "cn="
174            + Strings.lowerCase( schema.getSchemaName() ) );
175    }
176
177
178    /**
179     * {@inheritDoc}
180     */
181    public List<Entry> loadComparators( Schema... schemas ) throws LdapException, IOException
182    {
183        List<Entry> comparatorList = new ArrayList<Entry>();
184
185        if ( schemas == null )
186        {
187            return comparatorList;
188        }
189
190        for ( Schema schema : schemas )
191        {
192            File comparatorsDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.COMPARATORS_PATH );
193
194            if ( !comparatorsDirectory.exists() )
195            {
196                return comparatorList;
197            }
198
199            File[] comparators = comparatorsDirectory.listFiles( ldifFilter );
200
201            for ( File ldifFile : comparators )
202            {
203                LdifReader reader = new LdifReader( ldifFile );
204                LdifEntry entry = reader.next();
205                reader.close();
206
207                comparatorList.add( entry.getEntry() );
208            }
209        }
210
211        return comparatorList;
212    }
213
214
215    /**
216     * {@inheritDoc}
217     */
218    public List<Entry> loadSyntaxCheckers( Schema... schemas ) throws LdapException, IOException
219    {
220        List<Entry> syntaxCheckerList = new ArrayList<Entry>();
221
222        if ( schemas == null )
223        {
224            return syntaxCheckerList;
225        }
226
227        for ( Schema schema : schemas )
228        {
229            File syntaxCheckersDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.SYNTAX_CHECKERS_PATH );
230
231            if ( !syntaxCheckersDirectory.exists() )
232            {
233                return syntaxCheckerList;
234            }
235
236            File[] syntaxCheckerFiles = syntaxCheckersDirectory.listFiles( ldifFilter );
237
238            for ( File ldifFile : syntaxCheckerFiles )
239            {
240                LdifReader reader = new LdifReader( ldifFile );
241                LdifEntry entry = reader.next();
242                reader.close();
243
244                syntaxCheckerList.add( entry.getEntry() );
245            }
246        }
247
248        return syntaxCheckerList;
249    }
250
251
252    /**
253     * {@inheritDoc}
254     */
255    public List<Entry> loadNormalizers( Schema... schemas ) throws LdapException, IOException
256    {
257        List<Entry> normalizerList = new ArrayList<Entry>();
258
259        if ( schemas == null )
260        {
261            return normalizerList;
262        }
263
264        for ( Schema schema : schemas )
265        {
266            File normalizersDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.NORMALIZERS_PATH );
267
268            if ( !normalizersDirectory.exists() )
269            {
270                return normalizerList;
271            }
272
273            File[] normalizerFiles = normalizersDirectory.listFiles( ldifFilter );
274
275            for ( File ldifFile : normalizerFiles )
276            {
277                LdifReader reader = new LdifReader( ldifFile );
278                LdifEntry entry = reader.next();
279                reader.close();
280
281                normalizerList.add( entry.getEntry() );
282            }
283        }
284
285        return normalizerList;
286    }
287
288
289    /**
290     * {@inheritDoc}
291     */
292    public List<Entry> loadMatchingRules( Schema... schemas ) throws LdapException, IOException
293    {
294        List<Entry> matchingRuleList = new ArrayList<Entry>();
295
296        if ( schemas == null )
297        {
298            return matchingRuleList;
299        }
300
301        for ( Schema schema : schemas )
302        {
303            File matchingRulesDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.MATCHING_RULES_PATH );
304
305            if ( !matchingRulesDirectory.exists() )
306            {
307                return matchingRuleList;
308            }
309
310            File[] matchingRuleFiles = matchingRulesDirectory.listFiles( ldifFilter );
311
312            for ( File ldifFile : matchingRuleFiles )
313            {
314                LdifReader reader = new LdifReader( ldifFile );
315                LdifEntry entry = reader.next();
316                reader.close();
317
318                matchingRuleList.add( entry.getEntry() );
319            }
320        }
321
322        return matchingRuleList;
323    }
324
325
326    /**
327     * {@inheritDoc}
328     */
329    public List<Entry> loadSyntaxes( Schema... schemas ) throws LdapException, IOException
330    {
331        List<Entry> syntaxList = new ArrayList<Entry>();
332
333        if ( schemas == null )
334        {
335            return syntaxList;
336        }
337
338        for ( Schema schema : schemas )
339        {
340            File syntaxesDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.SYNTAXES_PATH );
341
342            if ( !syntaxesDirectory.exists() )
343            {
344                return syntaxList;
345            }
346
347            File[] syntaxFiles = syntaxesDirectory.listFiles( ldifFilter );
348
349            for ( File ldifFile : syntaxFiles )
350            {
351                LdifReader reader = new LdifReader( ldifFile );
352                LdifEntry entry = reader.next();
353                reader.close();
354
355                syntaxList.add( entry.getEntry() );
356            }
357        }
358
359        return syntaxList;
360    }
361
362
363    /**
364     * {@inheritDoc}
365     */
366    public List<Entry> loadAttributeTypes( Schema... schemas ) throws LdapException, IOException
367    {
368        List<Entry> attributeTypeList = new ArrayList<Entry>();
369
370        if ( schemas == null )
371        {
372            return attributeTypeList;
373        }
374
375        for ( Schema schema : schemas )
376        {
377            // check that the attributeTypes directory exists for the schema
378            File attributeTypesDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.ATTRIBUTE_TYPES_PATH );
379
380            if ( !attributeTypesDirectory.exists() )
381            {
382                return attributeTypeList;
383            }
384
385            // get list of attributeType LDIF schema files in attributeTypes
386            File[] attributeTypeFiles = attributeTypesDirectory.listFiles( ldifFilter );
387
388            for ( File ldifFile : attributeTypeFiles )
389            {
390                LdifReader reader = new LdifReader( ldifFile );
391                LdifEntry entry = reader.next();
392                reader.close();
393
394                attributeTypeList.add( entry.getEntry() );
395            }
396        }
397
398        return attributeTypeList;
399    }
400
401
402    /**
403     * {@inheritDoc}
404     */
405    public List<Entry> loadMatchingRuleUses( Schema... schemas ) throws LdapException, IOException
406    {
407        List<Entry> matchingRuleUseList = new ArrayList<Entry>();
408
409        if ( schemas == null )
410        {
411            return matchingRuleUseList;
412        }
413
414        for ( Schema schema : schemas )
415        {
416            File matchingRuleUsesDirectory = new File( getSchemaDirectory( schema ),
417                SchemaConstants.MATCHING_RULE_USE_PATH );
418
419            if ( !matchingRuleUsesDirectory.exists() )
420            {
421                return matchingRuleUseList;
422            }
423
424            File[] matchingRuleUseFiles = matchingRuleUsesDirectory.listFiles( ldifFilter );
425
426            for ( File ldifFile : matchingRuleUseFiles )
427            {
428                LdifReader reader = new LdifReader( ldifFile );
429                LdifEntry entry = reader.next();
430                reader.close();
431
432                matchingRuleUseList.add( entry.getEntry() );
433            }
434        }
435
436        return matchingRuleUseList;
437    }
438
439
440    /**
441     * {@inheritDoc}
442     */
443    public List<Entry> loadNameForms( Schema... schemas ) throws LdapException, IOException
444    {
445        List<Entry> nameFormList = new ArrayList<Entry>();
446
447        if ( schemas == null )
448        {
449            return nameFormList;
450        }
451
452        for ( Schema schema : schemas )
453        {
454            File nameFormsDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.NAME_FORMS_PATH );
455
456            if ( !nameFormsDirectory.exists() )
457            {
458                return nameFormList;
459            }
460
461            File[] nameFormFiles = nameFormsDirectory.listFiles( ldifFilter );
462
463            for ( File ldifFile : nameFormFiles )
464            {
465                LdifReader reader = new LdifReader( ldifFile );
466                LdifEntry entry = reader.next();
467                reader.close();
468
469                nameFormList.add( entry.getEntry() );
470            }
471        }
472
473        return nameFormList;
474    }
475
476
477    /**
478     * {@inheritDoc}
479     */
480    public List<Entry> loadDitContentRules( Schema... schemas ) throws LdapException, IOException
481    {
482        List<Entry> ditContentRuleList = new ArrayList<Entry>();
483
484        if ( schemas == null )
485        {
486            return ditContentRuleList;
487        }
488
489        for ( Schema schema : schemas )
490        {
491            File ditContentRulesDirectory = new File( getSchemaDirectory( schema ),
492                SchemaConstants.DIT_CONTENT_RULES_PATH );
493
494            if ( !ditContentRulesDirectory.exists() )
495            {
496                return ditContentRuleList;
497            }
498
499            File[] ditContentRuleFiles = ditContentRulesDirectory.listFiles( ldifFilter );
500
501            for ( File ldifFile : ditContentRuleFiles )
502            {
503                LdifReader reader = new LdifReader( ldifFile );
504                LdifEntry entry = reader.next();
505                reader.close();
506
507                ditContentRuleList.add( entry.getEntry() );
508            }
509        }
510
511        return ditContentRuleList;
512    }
513
514
515    /**
516     * {@inheritDoc}
517     */
518    public List<Entry> loadDitStructureRules( Schema... schemas ) throws LdapException, IOException
519    {
520        List<Entry> ditStructureRuleList = new ArrayList<Entry>();
521
522        if ( schemas == null )
523        {
524            return ditStructureRuleList;
525        }
526
527        for ( Schema schema : schemas )
528        {
529            File ditStructureRulesDirectory = new File( getSchemaDirectory( schema ),
530                SchemaConstants.DIT_STRUCTURE_RULES_PATH );
531
532            if ( !ditStructureRulesDirectory.exists() )
533            {
534                return ditStructureRuleList;
535            }
536
537            File[] ditStructureRuleFiles = ditStructureRulesDirectory.listFiles( ldifFilter );
538
539            for ( File ldifFile : ditStructureRuleFiles )
540            {
541                LdifReader reader = new LdifReader( ldifFile );
542                LdifEntry entry = reader.next();
543                reader.close();
544
545                ditStructureRuleList.add( entry.getEntry() );
546            }
547        }
548
549        return ditStructureRuleList;
550    }
551
552
553    /**
554     * {@inheritDoc}
555     */
556    public List<Entry> loadObjectClasses( Schema... schemas ) throws LdapException, IOException
557    {
558        List<Entry> objectClassList = new ArrayList<Entry>();
559
560        if ( schemas == null )
561        {
562            return objectClassList;
563        }
564
565        for ( Schema schema : schemas )
566        {
567            // get objectClasses directory, check if exists, return if not
568            File objectClassesDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.OBJECT_CLASSES_PATH );
569
570            if ( !objectClassesDirectory.exists() )
571            {
572                return objectClassList;
573            }
574
575            // get list of objectClass LDIF files from directory and load
576            File[] objectClassFiles = objectClassesDirectory.listFiles( ldifFilter );
577
578            for ( File ldifFile : objectClassFiles )
579            {
580                LdifReader reader = new LdifReader( ldifFile );
581                LdifEntry entry = reader.next();
582                reader.close();
583
584                objectClassList.add( entry.getEntry() );
585            }
586        }
587
588        return objectClassList;
589    }
590}