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  
21  package org.apache.directory.api.ldap.schema.loader;
22  
23  
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.net.URL;
27  import java.nio.file.Files;
28  import java.nio.file.Paths;
29  import java.util.ArrayList;
30  import java.util.HashMap;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.regex.Pattern;
34  
35  import org.apache.directory.api.ldap.model.entry.Entry;
36  import org.apache.directory.api.ldap.model.exception.LdapException;
37  import org.apache.directory.api.ldap.model.ldif.LdifEntry;
38  import org.apache.directory.api.ldap.model.ldif.LdifReader;
39  import org.apache.directory.api.ldap.model.schema.registries.AbstractSchemaLoader;
40  import org.apache.directory.api.ldap.model.schema.registries.Schema;
41  import org.slf4j.Logger;
42  import org.slf4j.LoggerFactory;
43  
44  
45  /**
46   * A schema loader based on a single monolithic ldif file containing all the schema partition elements
47   * 
48   * Performs better than any other existing LDIF schema loaders. NOT DOCUMENTED atm
49   * 
50   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
51   */
52  public class SingleLdifSchemaLoader extends AbstractSchemaLoader
53  {
54      /** 
55       * Pattern for start of schema Dn.
56       * java.util.regex.Pattern is immutable so only one instance is needed for all uses.
57       */
58      private static final Pattern SCHEMA_START_PATTERN = Pattern
59          .compile( "cn\\s*=\\s*[a-z0-9-_]*\\s*,\\s*ou\\s*=\\s*schema" );
60  
61      /** The logger. */
62      private static final Logger LOG = LoggerFactory.getLogger( SingleLdifSchemaLoader.class );
63  
64      /** The schema object Rdn attribute types. */
65      private String[] schemaObjectTypeRdns = new String[]
66          { "attributetypes", "comparators", "ditContentRules", "ditStructureRules", "matchingRules", "matchingRuleUse",
67              "nameForms", "normalizers", "objectClasses", "syntaxes", "syntaxCheckers" };
68  
69      /** The map containing ... */
70      private Map<String, Map<String, List<Entry>>> scObjEntryMap = new HashMap<String, Map<String, List<Entry>>>();
71  
72  
73      /**
74       * Instantiates a new single LDIF schema loader.
75       */
76      public SingleLdifSchemaLoader()
77      {
78          try
79          {
80              URL resource = getClass().getClassLoader().getResource( "schema-all.ldif" );
81  
82              LOG.debug( "URL of the all schema ldif file {}", resource );
83  
84              for ( String s : schemaObjectTypeRdns )
85              {
86                  scObjEntryMap.put( s, new HashMap<String, List<Entry>>() );
87              }
88  
89              InputStream in = resource.openStream();
90  
91              initializeSchemas( in );
92          }
93          catch ( LdapException | IOException e )
94          {
95              throw new RuntimeException( e );
96          }
97      }
98  
99      
100     /**
101      * Instantiates a new single LDIF schema loader.
102      * 
103      * @param schemaFile The Schema to load
104      */
105     public SingleLdifSchemaLoader( String schemaFile )
106     {
107         try
108         {
109             for ( String s : schemaObjectTypeRdns )
110             {
111                 scObjEntryMap.put( s, new HashMap<String, List<Entry>>() );
112             }
113 
114             InputStream in = Files.newInputStream( Paths.get( schemaFile ) );
115 
116             initializeSchemas( in );
117         }
118         catch ( LdapException | IOException e )
119         {
120             throw new RuntimeException( e );
121         }
122     }
123 
124     
125     /**
126      * Instantiates a new single LDIF schema loader.
127      * 
128      * @param schemaUrl The URL of the schema to load
129      */
130     public SingleLdifSchemaLoader( URL schemaUrl )
131     {
132         try
133         {
134             for ( String s : schemaObjectTypeRdns )
135             {
136                 scObjEntryMap.put( s, new HashMap<String, List<Entry>>() );
137             }
138 
139             InputStream in = schemaUrl.openStream();
140 
141             initializeSchemas( in );
142         }
143         catch ( LdapException | IOException e )
144         {
145             throw new RuntimeException( e );
146         }
147     }
148 
149 
150     /**
151      * Initialize the Schema object from a Single LDIF file
152      */
153     private void initializeSchemas( InputStream in ) throws LdapException, IOException
154     {
155         try ( LdifReader ldifReader = new LdifReader( in ) )
156         {
157             Schema currentSchema = null;
158     
159             while ( ldifReader.hasNext() )
160             {
161                 LdifEntry ldifEntry = ldifReader.next();
162                 String dn = ldifEntry.getDn().getName();
163                 
164                 if ( SCHEMA_START_PATTERN.matcher( dn ).matches() )
165                 {
166                     Schema schema = getSchema( ldifEntry.getEntry() );
167                     schemaMap.put( schema.getSchemaName(), schema );
168                     currentSchema = schema;
169                 }
170                 else
171                 {
172                     loadSchemaObject( currentSchema.getSchemaName(), ldifEntry );
173                 }
174             }
175         }
176     }
177 
178 
179     /**
180      * Load all the schemaObjects
181      */
182     private void loadSchemaObject( String schemaName, LdifEntry ldifEntry ) throws LdapException
183     {
184         for ( String scObjTypeRdn : schemaObjectTypeRdns )
185         {
186             Pattern regex = Pattern.compile( "m-oid\\s*=\\s*[0-9\\.]*\\s*" + ",\\s*ou\\s*=\\s*" + scObjTypeRdn
187                 + "\\s*,\\s*cn\\s*=\\s*" + schemaName
188                 + "\\s*,\\s*ou=schema\\s*", Pattern.CASE_INSENSITIVE );
189 
190             String dn = ldifEntry.getDn().getName();
191 
192             if ( regex.matcher( dn ).matches() )
193             {
194                 Map<String, List<Entry>> m = scObjEntryMap.get( scObjTypeRdn );
195                 List<Entry> entryList = m.get( schemaName );
196                 
197                 if ( entryList == null )
198                 {
199                     entryList = new ArrayList<Entry>();
200                     entryList.add( ldifEntry.getEntry() );
201                     m.put( schemaName, entryList );
202                 }
203                 else
204                 {
205                     entryList.add( ldifEntry.getEntry() );
206                 }
207 
208                 break;
209             }
210         }
211     }
212 
213 
214     private List<Entry> loadSchemaObjects( String schemaObjectType, Schema... schemas ) throws LdapException,
215         IOException
216     {
217         Map<String, List<Entry>> m = scObjEntryMap.get( schemaObjectType );
218         List<Entry> atList = new ArrayList<Entry>();
219 
220         for ( Schema s : schemas )
221         {
222             List<Entry> preLoaded = m.get( s.getSchemaName() );
223             
224             if ( preLoaded != null )
225             {
226                 atList.addAll( preLoaded );
227             }
228         }
229 
230         return atList;
231     }
232 
233 
234     /**
235      * {@inheritDoc}
236      */
237     public List<Entry> loadAttributeTypes( Schema... schemas ) throws LdapException, IOException
238     {
239         return loadSchemaObjects( "attributetypes", schemas );
240     }
241 
242 
243     /**
244      * {@inheritDoc}
245      */
246     public List<Entry> loadComparators( Schema... schemas ) throws LdapException, IOException
247     {
248         return loadSchemaObjects( "comparators", schemas );
249     }
250 
251 
252     /**
253      * {@inheritDoc}
254      */
255     public List<Entry> loadDitContentRules( Schema... schemas ) throws LdapException, IOException
256     {
257         return loadSchemaObjects( "ditContentRules", schemas );
258     }
259 
260 
261     /**
262      * {@inheritDoc}
263      */
264     public List<Entry> loadDitStructureRules( Schema... schemas ) throws LdapException, IOException
265     {
266         return loadSchemaObjects( "ditStructureRules", schemas );
267     }
268 
269 
270     /**
271      * {@inheritDoc}
272      */
273     public List<Entry> loadMatchingRules( Schema... schemas ) throws LdapException, IOException
274     {
275         return loadSchemaObjects( "matchingRules", schemas );
276     }
277 
278 
279     /**
280      * {@inheritDoc}
281      */
282     public List<Entry> loadMatchingRuleUses( Schema... schemas ) throws LdapException, IOException
283     {
284         return loadSchemaObjects( "matchingRuleUse", schemas );
285     }
286 
287 
288     /**
289      * {@inheritDoc}
290      */
291     public List<Entry> loadNameForms( Schema... schemas ) throws LdapException, IOException
292     {
293         return loadSchemaObjects( "nameForms", schemas );
294     }
295 
296 
297     /**
298      * {@inheritDoc}
299      */
300     public List<Entry> loadNormalizers( Schema... schemas ) throws LdapException, IOException
301     {
302         return loadSchemaObjects( "normalizers", schemas );
303     }
304 
305 
306     /**
307      * {@inheritDoc}
308      */
309     public List<Entry> loadObjectClasses( Schema... schemas ) throws LdapException, IOException
310     {
311         return loadSchemaObjects( "objectClasses", schemas );
312     }
313 
314 
315     /**
316      * {@inheritDoc}
317      */
318     public List<Entry> loadSyntaxes( Schema... schemas ) throws LdapException, IOException
319     {
320         return loadSchemaObjects( "syntaxes", schemas );
321     }
322 
323 
324     /**
325      * {@inheritDoc}
326      */
327     public List<Entry> loadSyntaxCheckers( Schema... schemas ) throws LdapException, IOException
328     {
329         return loadSchemaObjects( "syntaxCheckers", schemas );
330     }
331 
332 }
333 
334 class SchemaMarker
335 {
336     /** The start marker. */
337     private int start;
338 
339     /** The end marker. */
340     private int end;
341 
342 
343     SchemaMarker( int start )
344     {
345         this.start = start;
346     }
347 
348 
349     public void setEnd( int end )
350     {
351         this.end = end;
352     }
353 
354 
355     public int getStart()
356     {
357         return start;
358     }
359 
360 
361     public int getEnd()
362     {
363         return end;
364     }
365 }