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.server.core.bootstrap.plugin;
21  
22  
23  import java.io.File;
24  import java.io.FileWriter;
25  import java.io.IOException;
26  import java.io.PrintWriter;
27  import java.net.MalformedURLException;
28  import java.net.URL;
29  import java.net.URLClassLoader;
30  import java.util.ArrayList;
31  import java.util.Arrays;
32  import java.util.HashMap;
33  import java.util.HashSet;
34  import java.util.Iterator;
35  import java.util.List;
36  import java.util.Map;
37  import java.util.Set;
38  
39  import javax.naming.NamingException;
40  
41  import org.apache.directory.server.constants.ApacheSchemaConstants;
42  import org.apache.directory.server.constants.MetaSchemaConstants;
43  import org.apache.directory.server.constants.ServerDNConstants;
44  import org.apache.directory.server.core.entry.DefaultServerAttribute;
45  import org.apache.directory.server.core.entry.DefaultServerEntry;
46  import org.apache.directory.server.core.entry.ServerEntry;
47  import org.apache.directory.server.core.entry.ServerModification;
48  import org.apache.directory.server.xdbm.Index;
49  import org.apache.directory.server.xdbm.IndexNotFoundException;
50  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
51  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmStore;
52  import org.apache.directory.server.schema.SerializableComparator;
53  import org.apache.directory.server.schema.bootstrap.ApacheSchema;
54  import org.apache.directory.server.schema.bootstrap.ApachemetaSchema;
55  import org.apache.directory.server.schema.bootstrap.BootstrapSchema;
56  import org.apache.directory.server.schema.bootstrap.BootstrapSchemaLoader;
57  import org.apache.directory.server.schema.bootstrap.CoreSchema;
58  import org.apache.directory.server.schema.bootstrap.Schema;
59  import org.apache.directory.server.schema.bootstrap.SystemSchema;
60  import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
61  import org.apache.directory.server.schema.registries.ComparatorRegistry;
62  import org.apache.directory.server.schema.registries.DefaultOidRegistry;
63  import org.apache.directory.server.schema.registries.DefaultRegistries;
64  import org.apache.directory.server.schema.registries.MatchingRuleRegistry;
65  import org.apache.directory.server.schema.registries.NormalizerRegistry;
66  import org.apache.directory.server.schema.registries.ObjectClassRegistry;
67  import org.apache.directory.server.schema.registries.Registries;
68  import org.apache.directory.server.schema.registries.SyntaxCheckerRegistry;
69  import org.apache.directory.server.schema.registries.SyntaxRegistry;
70  import org.apache.directory.server.utils.AttributesFactory;
71  import org.apache.directory.shared.ldap.constants.SchemaConstants;
72  import org.apache.directory.shared.ldap.entry.Modification;
73  import org.apache.directory.shared.ldap.entry.ModificationOperation;
74  import org.apache.directory.shared.ldap.name.LdapDN;
75  import org.apache.directory.shared.ldap.schema.AttributeType;
76  import org.apache.directory.shared.ldap.schema.MatchingRule;
77  import org.apache.directory.shared.ldap.schema.ObjectClass;
78  import org.apache.directory.shared.ldap.schema.SchemaObject;
79  import org.apache.directory.shared.ldap.schema.Syntax;
80  import org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker;
81  import org.apache.directory.shared.ldap.util.DateUtils;
82  import org.apache.maven.plugin.AbstractMojo;
83  import org.apache.maven.plugin.MojoExecutionException;
84  import org.apache.maven.plugin.MojoFailureException;
85  import org.codehaus.plexus.util.FileUtils;
86  
87  
88  /**
89   * A plugin used to pre-load meta schema entries into the schema partition.
90   *
91   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
92   * @version $Rev$
93   * @goal load
94   * @description creates and pre-loads ApacheDS schema partition
95   * @phase compile
96   * @requiresDependencyResolution compile
97   */
98  public class BootstrapPlugin extends AbstractMojo
99  {
100     private static final String ADMIN_NORM_NAME = "0.9.2342.19200300.100.1.1=admin,2.5.4.11=system";
101 
102     /**
103      * The classpath elements of the project being tested.
104      *
105      * @parameter expression="${project.compileClasspathElements}"
106      * @required
107      * @readonly
108      */
109     private List<String> classpathElements;
110 
111     /**
112      * The package to put the db file entry listing info as well as the partition.
113      *
114      * @parameter expression="org.apache.directory.server.schema.bootstrap.partition"
115      */
116     private String outputPackage;
117 
118     /**
119      * The file name to use for the package listing.
120      *
121      * @parameter expression="DBFILES"
122      */
123     private String listingFileName;
124 
125     /**
126      * The target directory into which the plugin generates schema partion files
127      * within the specified outputPackage.
128      *
129      * @parameter expression="target/classes"
130      */
131     private File outputDirectory;
132 
133     /**
134      * The name of the set of bootstrap schemas to load into the registries
135      * and ultimately into the schema partition being built.
136      *
137      * @parameter
138      */
139     private String[] bootstrapSchemaClasses;
140 
141     /**
142      * The set of disabled schema names.
143      *
144      * @parameter
145      */
146     private String[] disabledSchemas;
147 
148     /**
149      * The names of Attributes to index.
150      *
151      * @parameter
152      */
153     private String[] indexedAttributes;
154 
155     /**
156      * Factory used to create attributes objects from schema entities.
157      */
158     private AttributesFactory attributesFactory = new AttributesFactory();
159 
160     /**
161      * Registries of objects used to load the schema partition.
162      */
163     private Registries registries;
164 
165     /**
166      * The store to load schema entities into.
167      */
168     private JdbmStore store = new JdbmStore();
169 
170     /**
171      * Map of schemas by name
172      */
173     private Map<String, Schema> schemas = new HashMap<String, Schema>();
174 
175 
176     /**
177      * Loads a bunch of bootstrap classes into memory then adds them to a new
178      * schema partition within the target area.  The db files for this partition
179      * are then packaged into the jar by the jar plugin.
180      */
181     public void execute() throws MojoExecutionException, MojoFailureException
182     {
183         File packageDirectory = new File( outputDirectory, outputPackage.replace( '.', File.separatorChar ) );
184 
185         if ( !packageDirectory.exists() )
186         {
187             packageDirectory.mkdirs();
188         }
189 
190         // delete output directory if it exists
191         File schemaDirectory = new File( packageDirectory, "schema" );
192 
193         if ( schemaDirectory.exists() )
194         {
195             try
196             {
197                 FileUtils.forceDelete( schemaDirectory );
198             }
199             catch ( IOException e )
200             {
201                 throw new MojoFailureException( "Failed to delete old schema partition folder "
202                     + schemaDirectory.getAbsolutePath() + ": " + e.getMessage() );
203             }
204         }
205 
206         initializeSchemas();
207 
208         try
209         {
210             initializePartition( schemaDirectory );
211         }
212         catch ( Exception ne )
213         {
214             throw new MojoFailureException( "Failed to initialize the root partition :" + ne.getMessage() );
215         }
216 
217         try
218         {
219             LdapDN dn = new LdapDN( SchemaConstants.OU_AT + "=schema" );
220             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
221 
222             if ( !hasEntry( dn ) )
223             {
224                 ServerEntry entry = new DefaultServerEntry( registries, dn );
225                 entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC );
226                 entry.get( SchemaConstants.OBJECT_CLASS_AT ).add( SchemaConstants.ORGANIZATIONAL_UNIT_OC );
227                 entry.put( SchemaConstants.OU_AT, "schema" );
228                 store.add( dn, entry );
229             }
230 
231             createSchemasAndContainers();
232 
233             addSyntaxCheckers();
234             addSyntaxes();
235             addNormalizers();
236             addComparators();
237             addMatchingRules();
238             addAttributeTypes();
239             addObjectClasses();
240 
241             if ( disabledSchemas != null && disabledSchemas.length > 0 )
242             {
243                 getLog().info( "------------------------------------------------------------------------" );
244                 getLog().info( "Disabling schemas:" );
245                 getLog().info( "------------------------------------------------------------------------" );
246                 getLog().info( "" );
247 
248                 for ( String disabledSchema : disabledSchemas )
249                 {
250                     disableSchema( disabledSchema );
251                     getLog().info( "\t\t o " + disabledSchema );
252                 }
253 
254                 getLog().info( "" );
255                 getLog().info( "------------------------------------------------------------------------" );
256             }
257 
258             createSchemaModificationAttributesEntry();
259         }
260         catch ( Exception e )
261         {
262             throw new MojoFailureException( "Failed to add syntaxCheckers to partition: " + e.getMessage() );
263         }
264 
265         try
266         {
267             store.sync();
268         }
269         catch ( Exception e )
270         {
271             e.printStackTrace();
272         }
273 
274         // ------------------------------------------------------------------
275         // Create db file listing and place it into the right package on disk
276         // ------------------------------------------------------------------
277 
278         File listingFile = new File( packageDirectory, listingFileName );
279         PrintWriter out = null;
280         try
281         {
282             out = new PrintWriter( new FileWriter( listingFile ) );
283             out.print( getDbFileListing().toString() );
284             out.flush();
285         }
286         catch ( IOException e )
287         {
288             throw new MojoFailureException( "Failed to write file: " + e.getMessage() );
289         }
290         catch ( IndexNotFoundException e )
291         {
292             // never really thrown
293             e.printStackTrace();
294         }
295         finally
296         {
297             if ( out != null )
298             {
299                 out.close();
300             }
301         }
302     }
303 
304     private static final String[] OTHER_SCHEMA_DEPENDENCIES = new String[]
305         { "system", "core", "apache", "apachemeta" };
306 
307 
308     private void createSchemasAndContainers() throws Exception
309     {
310         Map<String, Schema> schemaMap = this.registries.getLoadedSchemas();
311 
312         for ( Schema schema : schemaMap.values() )
313         {
314             createSchemaAndContainers( schema );
315         }
316 
317         Schema other = new Schema()
318         {
319             public String[] getDependencies()
320             {
321                 return OTHER_SCHEMA_DEPENDENCIES;
322             }
323 
324 
325             public String getOwner()
326             {
327                 return "uid=admin,ou=system";
328             }
329 
330 
331             public String getSchemaName()
332             {
333                 return "other";
334             }
335 
336 
337             public boolean isDisabled()
338             {
339                 return false;
340             }
341         };
342 
343         createSchemaAndContainers( other );
344     }
345 
346 
347     private void createSchemaAndContainers( Schema schema ) throws Exception
348     {
349         LdapDN dn = new LdapDN( SchemaConstants.CN_AT + "=" + schema.getSchemaName() + "," + SchemaConstants.OU_AT
350             + "=schema" );
351         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
352 
353         if ( hasEntry( dn ) )
354         {
355             return;
356         }
357 
358         ServerEntry entry = attributesFactory.getAttributes( schema, registries );
359         entry.setDn( dn );
360         store.add( dn, entry );
361 
362         dn = ( LdapDN ) dn.clone();
363 
364         dn.add( SchemaConstants.OU_AT + "=comparators" );
365         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
366         checkCreateContainer( dn );
367 
368         dn.remove( dn.size() - 1 );
369         dn.add( SchemaConstants.OU_AT + "=normalizers" );
370         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
371         checkCreateContainer( dn );
372 
373         dn.remove( dn.size() - 1 );
374         dn.add( SchemaConstants.OU_AT + "=syntaxCheckers" );
375         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
376         checkCreateContainer( dn );
377 
378         dn.remove( dn.size() - 1 );
379         dn.add( SchemaConstants.OU_AT + "=syntaxes" );
380         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
381         checkCreateContainer( dn );
382 
383         dn.remove( dn.size() - 1 );
384         dn.add( SchemaConstants.OU_AT + "=matchingRules" );
385         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
386         checkCreateContainer( dn );
387 
388         dn.remove( dn.size() - 1 );
389         dn.add( SchemaConstants.OU_AT + "=attributeTypes" );
390         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
391         checkCreateContainer( dn );
392 
393         dn.remove( dn.size() - 1 );
394         dn.add( SchemaConstants.OU_AT + "=objectClasses" );
395         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
396         checkCreateContainer( dn );
397 
398         dn.remove( dn.size() - 1 );
399         dn.add( SchemaConstants.OU_AT + "=nameForms" );
400         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
401         checkCreateContainer( dn );
402 
403         dn.remove( dn.size() - 1 );
404         dn.add( SchemaConstants.OU_AT + "=ditStructureRules" );
405         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
406         checkCreateContainer( dn );
407 
408         dn.remove( dn.size() - 1 );
409         dn.add( SchemaConstants.OU_AT + "=ditContentRules" );
410         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
411         checkCreateContainer( dn );
412 
413         dn.remove( dn.size() - 1 );
414         dn.add( SchemaConstants.OU_AT + "=matchingRuleUse" );
415         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
416         checkCreateContainer( dn );
417     }
418 
419 
420     private void addAttributeTypes() throws Exception
421     {
422         getLog().info( "------------------------------------------------------------------------" );
423         getLog().info( " Adding attributeTypes:" );
424         getLog().info( "------------------------------------------------------------------------" );
425         getLog().info( "" );
426 
427         AttributeTypeRegistry attributeTypeRegistry = registries.getAttributeTypeRegistry();
428 
429         Iterator<AttributeType> ii = attributeTypeRegistry.iterator();
430 
431         while ( ii.hasNext() )
432         {
433             AttributeType at = ii.next();
434             String schemaName = attributeTypeRegistry.getSchemaName( at.getOid() );
435             Schema schema = registries.getLoadedSchemas().get( schemaName );
436             getLog().info( "\t\t o [" + schemaName + "] - " + getNameOrNumericoid( at ) );
437             LdapDN dn = checkCreateSchema( schemaName );
438             dn.add( SchemaConstants.OU_AT + "=attributeTypes" );
439             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
440             checkCreateContainer( dn );
441             ServerEntry entry = attributesFactory.getAttributes( at, schema, registries );
442             dn.add( MetaSchemaConstants.M_OID_AT + "=" + at.getOid() );
443             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
444             entry.setDn( dn );
445             store.add( dn, entry );
446         }
447 
448         getLog().info( "" );
449     }
450 
451 
452     private void addObjectClasses() throws Exception
453     {
454         getLog().info( "------------------------------------------------------------------------" );
455         getLog().info( " Adding objectClasses:" );
456         getLog().info( "------------------------------------------------------------------------" );
457         getLog().info( "" );
458 
459         ObjectClassRegistry objectClassRegistry = registries.getObjectClassRegistry();
460         Iterator<ObjectClass> ii = objectClassRegistry.iterator();
461 
462         while ( ii.hasNext() )
463         {
464             ObjectClass oc = ii.next();
465             String schemaName = objectClassRegistry.getSchemaName( oc.getOid() );
466             Schema schema = registries.getLoadedSchemas().get( schemaName );
467             getLog().info( "\t\t o [" + schemaName + "] - " + getNameOrNumericoid( oc ) );
468             LdapDN dn = checkCreateSchema( schemaName );
469             dn.add( SchemaConstants.OU_AT + "=objectClasses" );
470             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
471             checkCreateContainer( dn );
472             ServerEntry entry = attributesFactory.getAttributes( oc, schema, registries );
473             dn.add( MetaSchemaConstants.M_OID_AT + "=" + oc.getOid() );
474             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
475             entry.setDn( dn );
476             store.add( dn, entry );
477         }
478 
479         getLog().info( "" );
480     }
481 
482 
483     private void addMatchingRules() throws Exception
484     {
485         getLog().info( "------------------------------------------------------------------------" );
486         getLog().info( " Adding matchingRules:" );
487         getLog().info( "------------------------------------------------------------------------" );
488         getLog().info( "" );
489 
490         MatchingRuleRegistry matchingRuleRegistry = registries.getMatchingRuleRegistry();
491         Iterator<MatchingRule> ii = matchingRuleRegistry.iterator();
492 
493         while ( ii.hasNext() )
494         {
495             MatchingRule mr = ii.next();
496             String schemaName = matchingRuleRegistry.getSchemaName( mr.getOid() );
497             Schema schema = registries.getLoadedSchemas().get( schemaName );
498             getLog().info( "\t\t o [" + schemaName + "] - " + getNameOrNumericoid( mr ) );
499             LdapDN dn = checkCreateSchema( schemaName );
500             dn.add( SchemaConstants.OU_AT + "=matchingRules" );
501             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
502             checkCreateContainer( dn );
503             ServerEntry entry = attributesFactory.getAttributes( mr, schema, registries );
504             dn.add( MetaSchemaConstants.M_OID_AT + "=" + mr.getOid() );
505             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
506             entry.setDn( dn );
507             store.add( dn, entry );
508         }
509 
510         getLog().info( "" );
511     }
512 
513 
514     private void addComparators() throws Exception
515     {
516         getLog().info( "------------------------------------------------------------------------" );
517         getLog().info( " Adding comparators:" );
518         getLog().info( "------------------------------------------------------------------------" );
519         getLog().info( "" );
520 
521         ComparatorRegistry comparatorRegistry = registries.getComparatorRegistry();
522         Iterator<String> ii = comparatorRegistry.oidIterator();
523 
524         while ( ii.hasNext() )
525         {
526             String oid = ii.next();
527             String schemaName = comparatorRegistry.getSchemaName( oid );
528             Schema schema = registries.getLoadedSchemas().get( schemaName );
529             getLog().info( "\t\t o [" + schemaName + "] - " + oid );
530             LdapDN dn = checkCreateSchema( schemaName );
531             dn.add( SchemaConstants.OU_AT + "=comparators" );
532             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
533             checkCreateContainer( dn );
534             ServerEntry entry = attributesFactory.getAttributes( oid, comparatorRegistry.lookup( oid ), schema,
535                 registries );
536             dn.add( MetaSchemaConstants.M_OID_AT + "=" + oid );
537             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
538             entry.setDn( dn );
539             store.add( dn, entry );
540         }
541         getLog().info( "" );
542     }
543 
544 
545     private void addNormalizers() throws Exception
546     {
547         getLog().info( "------------------------------------------------------------------------" );
548         getLog().info( " Adding normalizers:" );
549         getLog().info( "------------------------------------------------------------------------" );
550         getLog().info( "" );
551 
552         NormalizerRegistry normalizerRegistry = registries.getNormalizerRegistry();
553         Iterator<String> ii = normalizerRegistry.oidIterator();
554 
555         while ( ii.hasNext() )
556         {
557             String oid = ii.next();
558             String schemaName = normalizerRegistry.getSchemaName( oid );
559             Schema schema = registries.getLoadedSchemas().get( schemaName );
560             getLog().info( "\t\t o [" + schemaName + "] - " + oid );
561             LdapDN dn = checkCreateSchema( schemaName );
562             dn.add( SchemaConstants.OU_AT + "=normalizers" );
563             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
564             checkCreateContainer( dn );
565             ServerEntry entry = attributesFactory.getAttributes( oid, normalizerRegistry.lookup( oid ), schema,
566                 registries );
567             dn.add( MetaSchemaConstants.M_OID_AT + "=" + oid );
568             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
569             entry.setDn( dn );
570             store.add( dn, entry );
571         }
572 
573         getLog().info( "" );
574     }
575 
576 
577     private void addSyntaxes() throws Exception
578     {
579         getLog().info( "------------------------------------------------------------------------" );
580         getLog().info( " Adding syntaxes:" );
581         getLog().info( "------------------------------------------------------------------------" );
582         getLog().info( "" );
583 
584         SyntaxRegistry syntaxRegistry = registries.getSyntaxRegistry();
585         Iterator<Syntax> ii = syntaxRegistry.iterator();
586 
587         while ( ii.hasNext() )
588         {
589             Syntax syntax = ii.next();
590             getLog().info( "\t\t o [" + syntax.getSchema() + "] - " + getNameOrNumericoid( syntax ) );
591             LdapDN dn = checkCreateSchema( syntax.getSchema() );
592             Schema schema = registries.getLoadedSchemas().get( syntax.getSchema() );
593             dn.add( SchemaConstants.OU_AT + "=syntaxes" );
594             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
595             checkCreateContainer( dn );
596             ServerEntry entry = attributesFactory.getAttributes( syntax, schema, registries );
597             dn.add( MetaSchemaConstants.M_OID_AT + "=" + syntax.getOid() );
598             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
599             entry.setDn( dn );
600             store.add( dn, entry );
601         }
602         getLog().info( "" );
603     }
604 
605 
606     private void addSyntaxCheckers() throws Exception
607     {
608         getLog().info( "------------------------------------------------------------------------" );
609         getLog().info( " Adding syntaxCheckers:" );
610         getLog().info( "------------------------------------------------------------------------" );
611         getLog().info( "" );
612 
613         SyntaxCheckerRegistry syntaxCheckerRegistry = registries.getSyntaxCheckerRegistry();
614         Iterator<SyntaxChecker> ii = syntaxCheckerRegistry.iterator();
615 
616         while ( ii.hasNext() )
617         {
618             SyntaxChecker syntaxChecker = ii.next();
619             String schemaName = syntaxCheckerRegistry.getSchemaName( syntaxChecker.getSyntaxOid() );
620             Schema schema = registries.getLoadedSchemas().get( schemaName );
621             getLog().info( "\t\t o [" + schemaName + "] - " + syntaxChecker.getSyntaxOid() );
622             LdapDN dn = checkCreateSchema( schemaName );
623             dn.add( SchemaConstants.OU_AT + "=syntaxCheckers" );
624             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
625             checkCreateContainer( dn );
626             ServerEntry entry = attributesFactory.getAttributes( syntaxChecker, schema, registries );
627             dn.add( MetaSchemaConstants.M_OID_AT + "=" + syntaxChecker.getSyntaxOid() );
628             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
629             entry.setDn( dn );
630             store.add( dn, entry );
631         }
632 
633         getLog().info( "" );
634     }
635 
636 
637     /**
638      * Creates the configuration and initializes the partition so we can start
639      * adding entries into it.
640      *
641      * @param workingDirectory the working directory for partition resources
642      * @throws Exception when the partition cannot be fired up
643      */
644     private void initializePartition( File workingDirectory ) throws Exception
645     {
646         store.setCacheSize( 1000 );
647         store.setName( "schema" );
648         store.setSuffixDn( SchemaConstants.OU_AT + "=schema" );
649         store.setSyncOnWrite( false );
650         store.setWorkingDirectory( workingDirectory );
651 
652         // add the indices
653         Set<JdbmIndex> userIndices = new HashSet<JdbmIndex>();
654 
655         for ( String indexedAttribute : indexedAttributes )
656         {
657             JdbmIndex index = new JdbmIndex();
658             index.setAttributeId( indexedAttribute );
659             userIndices.add( index );
660         }
661 
662         store.setUserIndices( userIndices );
663 
664         try
665         {
666             store.init( this.registries );
667             LdapDN dn = new LdapDN( ServerDNConstants.OU_SCHEMA_DN );
668             dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
669             ServerEntry rootEntry = new DefaultServerEntry( registries, dn );
670             rootEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, 
671                 SchemaConstants.ORGANIZATIONAL_UNIT_OC );
672             rootEntry.put( SchemaConstants.OU_AT, "schema" );
673             store.add( dn, rootEntry );
674         }
675         catch ( Exception e )
676         {
677             throw new MojoFailureException( "Failed to initialize parition: " + e.getMessage() );
678         }
679     }
680 
681 
682     /**
683      * Creates the special schemaModificationsAttribute entry used to
684      * store the modification attributes for the schema.  The current
685      * time is used to create the initial values for the attributes in
686      * this entry.
687      * 
688      * @throws NamingException if there is a failure to add the entry 
689      */
690     private void createSchemaModificationAttributesEntry() throws Exception
691     {
692         ServerEntry entry = new DefaultServerEntry( registries );
693         entry.put( SchemaConstants.OBJECT_CLASS_AT, ApacheSchemaConstants.SCHEMA_MODIFICATION_ATTRIBUTES_OC,
694             SchemaConstants.TOP_OC );
695 
696         entry.put( ApacheSchemaConstants.SCHEMA_MODIFIERS_NAME_AT, ADMIN_NORM_NAME );
697         entry.put( SchemaConstants.MODIFIERS_NAME_AT, ADMIN_NORM_NAME );
698         entry.put( SchemaConstants.CREATORS_NAME_AT, ADMIN_NORM_NAME );
699 
700         entry.put( ApacheSchemaConstants.SCHEMA_MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
701         entry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
702         entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
703 
704         entry.put( SchemaConstants.CN_AT, "schemaModifications" );
705         entry.put( ApacheSchemaConstants.SUBSCHEMA_SUBENTRY_NAME_AT, "cn=schema" );
706 
707         LdapDN normName = new LdapDN( "cn=schemaModifications,ou=schema" );
708         normName.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
709         entry.setDn( normName );
710         store.add( normName, entry );
711     }
712 
713 
714     /**
715      * Loads all the bootstrap schemas into the registries in preparation for
716      * loading them into the schema partition.
717      *
718      * @throws MojoFailureException when the schema cannot be initialized
719      */
720     private void initializeSchemas() throws MojoFailureException
721     {
722         // -------------------------------------------------------------------
723         // load the bootstrap schemas to pre-load into the partition
724         // -------------------------------------------------------------------
725 
726         // always include these core bootstrap schemas
727         BootstrapSchema schema = new SystemSchema();
728         schemas.put( schema.getSchemaName(), schema );
729 
730         schema = new ApacheSchema();
731         schemas.put( schema.getSchemaName(), schema );
732 
733         schema = new ApachemetaSchema();
734         schemas.put( schema.getSchemaName(), schema );
735 
736         schema = new CoreSchema();
737         schemas.put( schema.getSchemaName(), schema );
738 
739         getLog().info( "------------------------------------------------------------------------" );
740         getLog().info( "Found bootstrap schemas: " );
741         getLog().info( "------------------------------------------------------------------------" );
742         getLog().info( "" );
743 
744         // start loading other schemas from the plugin's configuration section
745         ClassLoader parent = getClass().getClassLoader();
746         URL[] urls = new URL[classpathElements.size()];
747         int i = 0;
748 
749         for ( String classpathElement : classpathElements )
750         {
751             try
752             {
753                 urls[i++] = new File( classpathElement ).toURI().toURL();
754             }
755             catch ( MalformedURLException e )
756             {
757                 throw ( MojoFailureException ) new MojoFailureException( "Could not construct classloader: " )
758                     .initCause( e );
759             }
760         }
761 
762         ClassLoader cl = new URLClassLoader( urls, parent );
763 
764         for ( String bootstrapSchemaClass : bootstrapSchemaClasses )
765         {
766             try
767             {
768                 Class<?> schemaClass = cl.loadClass( bootstrapSchemaClass );
769                 schema = ( BootstrapSchema ) schemaClass.newInstance();
770                 schemas.put( schema.getSchemaName(), schema );
771             }
772             catch ( ClassNotFoundException e )
773             {
774                 getLog().info( "ClassLoader " + getClass().getClassLoader() );
775                 getLog()
776                     .info(
777                         "ClassLoader URLs: "
778                             + Arrays.asList( ( ( URLClassLoader ) getClass().getClassLoader() ).getURLs() ) );
779                 e.printStackTrace();
780                 throw new MojoFailureException( "Could not find BootstrapSchema class: "
781                     + bootstrapSchemaClass );
782             }
783             catch ( InstantiationException e )
784             {
785                 e.printStackTrace();
786                 throw new MojoFailureException( "Could not instantiate BootstrapSchema class: "
787                     + bootstrapSchemaClass );
788             }
789             catch ( IllegalAccessException e )
790             {
791                 e.printStackTrace();
792                 throw new MojoFailureException( "Could not instantiate BootstrapSchema class due to security: "
793                     + bootstrapSchemaClass );
794             }
795 
796             getLog().info( "\t" + bootstrapSchemaClass );
797         }
798 
799         getLog().info( "" );
800 
801         BootstrapSchemaLoader loader = new BootstrapSchemaLoader( cl );
802         registries = new DefaultRegistries( "bootstrap", loader, new DefaultOidRegistry() );
803 
804         try
805         {
806             loader.loadWithDependencies( schemas.values(), registries );
807         }
808         catch ( Exception e )
809         {
810             e.printStackTrace();
811             throw new MojoFailureException( "Failed to load bootstrap registries with schemas: " + e.getMessage() );
812         }
813 
814         SerializableComparator.setRegistry( registries.getComparatorRegistry() );
815     }
816 
817 
818     private void checkCreateContainer( LdapDN dn ) throws Exception
819     {
820         LdapDN clonedDn = ( LdapDN ) dn.clone();
821 
822         if ( hasEntry( clonedDn ) )
823         {
824             return;
825         }
826 
827         ServerEntry entry = new DefaultServerEntry( registries, clonedDn );
828         entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, SchemaConstants.ORGANIZATIONAL_UNIT_OC );
829         entry.put( SchemaConstants.OU_AT, ( String ) clonedDn.getRdn().getValue() );
830         store.add( clonedDn, entry );
831     }
832 
833 
834     private LdapDN checkCreateSchema( String schemaName ) throws Exception
835     {
836         Schema schema = schemas.get( schemaName );
837         LdapDN dn = new LdapDN( SchemaConstants.CN_AT + "=" + schemaName + "," + SchemaConstants.OU_AT + "=schema" );
838         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
839 
840         if ( hasEntry( dn ) )
841         {
842             return dn;
843         }
844 
845         ServerEntry entry = attributesFactory.getAttributes( schema, registries );
846         entry.setDn( dn );
847         store.add( dn, entry );
848         return dn;
849     }
850 
851 
852     private void disableSchema( String schemaName ) throws Exception
853     {
854         LdapDN dn = new LdapDN( SchemaConstants.CN_AT + "=" + schemaName + "," + SchemaConstants.OU_AT + "=schema" );
855         dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
856 
857         Modification mod = new ServerModification( ModificationOperation.ADD_ATTRIBUTE, new DefaultServerAttribute(
858             MetaSchemaConstants.M_DISABLED_AT, registries.getAttributeTypeRegistry().lookup(
859                 MetaSchemaConstants.M_DISABLED_AT ), "TRUE" ) );
860 
861         List<Modification> mods = new ArrayList<Modification>();
862         mods.add( mod );
863         store.modify( dn, mods );
864     }
865 
866 
867     private String getNameOrNumericoid( SchemaObject object )
868     {
869         // first try to use userfriendly name if we can
870         if ( object.getName() != null )
871         {
872             return object.getName();
873         }
874 
875         return object.getOid();
876     }
877 
878 
879     private boolean hasEntry( LdapDN dn ) throws Exception
880     {
881         Long id = store.getEntryId( dn.toNormName() );
882 
883         return ( id != null );
884     }
885 
886 
887     private StringBuffer getDbFileListing() throws IndexNotFoundException
888     {
889         StringBuffer buf = new StringBuffer();
890         buf.append( "schema/master.db\n" );
891 
892         Iterator<String> systemIndices = store.systemIndices();
893 
894         while ( systemIndices.hasNext() )
895         {
896             Index index = store.getSystemIndex( systemIndices.next() );
897             buf.append( "schema/" );
898             buf.append( index.getAttribute().getName() );
899             buf.append( ".db\n" );
900         }
901 
902         buf.append( "[USER INDICES]\n" );
903 
904         for ( String indexedAttribute : indexedAttributes )
905         {
906             buf.append( "schema/" );
907             buf.append( indexedAttribute );
908             buf.append( ".db\n" );
909         }
910 
911         return buf;
912     }
913 }