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