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    package org.apache.directory.server.core.factory;
020    
021    
022    import java.io.File;
023    import java.util.List;
024    
025    import org.apache.commons.io.FileUtils;
026    import org.apache.directory.server.constants.ServerDNConstants;
027    import org.apache.directory.server.core.DefaultDirectoryService;
028    import org.apache.directory.server.core.DirectoryService;
029    import org.apache.directory.server.core.partition.Partition;
030    import org.apache.directory.server.core.partition.ldif.LdifPartition;
031    import org.apache.directory.server.core.schema.SchemaPartition;
032    import org.apache.directory.server.i18n.I18n;
033    import org.apache.directory.shared.ldap.constants.SchemaConstants;
034    import org.apache.directory.shared.ldap.schema.SchemaManager;
035    import org.apache.directory.shared.ldap.schema.ldif.extractor.SchemaLdifExtractor;
036    import org.apache.directory.shared.ldap.schema.ldif.extractor.impl.DefaultSchemaLdifExtractor;
037    import org.apache.directory.shared.ldap.schema.loader.ldif.LdifSchemaLoader;
038    import org.apache.directory.shared.ldap.schema.manager.impl.DefaultSchemaManager;
039    import org.apache.directory.shared.ldap.schema.registries.SchemaLoader;
040    import org.apache.directory.shared.ldap.util.ExceptionUtils;
041    import org.slf4j.Logger;
042    import org.slf4j.LoggerFactory;
043    
044    
045    /**
046     * A Default factory for DirectoryService.
047     *
048     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
049     * @version $Rev$, $Date$
050     */
051    public class DefaultDirectoryServiceFactory implements DirectoryServiceFactory
052    {
053        /** A logger for this class */
054        private static final Logger LOG = LoggerFactory.getLogger( DefaultDirectoryServiceFactory.class );
055    
056        /**
057         * The default factory returns stock instances of a directory
058         * service with smart defaults
059         */
060        public static final DirectoryServiceFactory DEFAULT = new DefaultDirectoryServiceFactory();
061    
062        /** The directory service. */
063        private DirectoryService directoryService;
064    
065        /** The partition factory. */
066        private PartitionFactory partitionFactory;
067    
068    
069        /* default access */DefaultDirectoryServiceFactory()
070        {
071            try
072            {
073                // creating the instance here so that
074                // we we can set some properties like accesscontrol, anon access
075                // before starting up the service
076                directoryService = new DefaultDirectoryService();
077            }
078            catch ( Exception e )
079            {
080                throw new RuntimeException( e );
081            }
082    
083            try
084            {
085                String typeName = System.getProperty( "apacheds.partition.factory" );
086                if ( typeName != null )
087                {
088                    Class<? extends PartitionFactory> type = ( Class<? extends PartitionFactory> ) Class.forName( typeName );
089                    partitionFactory = type.newInstance();
090                }
091                else
092                {
093                    partitionFactory = new JdbmPartitionFactory();
094                }
095            }
096            catch ( Exception e )
097            {
098                LOG.error( "Error instantiating custom partiton factory", e );
099                throw new RuntimeException( e );
100            }
101        }
102    
103    
104        /**
105         * {@inheritDoc}
106         */
107        public void init( String name ) throws Exception
108        {
109            if ( directoryService != null && directoryService.isStarted() )
110            {
111                return;
112            }
113    
114            build( name );
115        }
116    
117    
118        /**
119         * Build the working directory
120         */
121        private void buildWorkingDirectory( String name )
122        {
123            String workingDirectory = System.getProperty( "workingDirectory" );
124    
125            if ( workingDirectory == null )
126            {
127                workingDirectory = System.getProperty( "java.io.tmpdir" ) + "/server-work-" + name;
128            }
129    
130            directoryService.setWorkingDirectory( new File( workingDirectory ) );
131        }
132    
133    
134        /**
135         * Inits the schema and schema partition.
136         */
137        private void initSchema() throws Exception
138        {
139            SchemaPartition schemaPartition = directoryService.getSchemaService().getSchemaPartition();
140    
141            // Init the LdifPartition
142            LdifPartition ldifPartition = new LdifPartition();
143            String workingDirectory = directoryService.getWorkingDirectory().getPath();
144            ldifPartition.setWorkingDirectory( workingDirectory + "/schema" );
145    
146            // Extract the schema on disk (a brand new one) and load the registries
147            File schemaRepository = new File( workingDirectory, "schema" );
148            SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
149            extractor.extractOrCopy();
150    
151            schemaPartition.setWrappedPartition( ldifPartition );
152    
153            SchemaLoader loader = new LdifSchemaLoader( schemaRepository );
154            SchemaManager schemaManager = new DefaultSchemaManager( loader );
155            directoryService.setSchemaManager( schemaManager );
156    
157            // We have to load the schema now, otherwise we won't be able
158            // to initialize the Partitions, as we won't be able to parse 
159            // and normalize their suffix DN
160            schemaManager.loadAllEnabled();
161    
162            schemaPartition.setSchemaManager( schemaManager );
163    
164            List<Throwable> errors = schemaManager.getErrors();
165    
166            if ( errors.size() != 0 )
167            {
168                throw new Exception( I18n.err( I18n.ERR_317, ExceptionUtils.printErrors( errors ) ) );
169            }
170        }
171    
172    
173        /**
174         * Inits the system partition.
175         * 
176         * @throws Exception the exception
177         */
178        private void initSystemPartition() throws Exception
179        {
180            // change the working directory to something that is unique
181            // on the system and somewhere either under target directory
182            // or somewhere in a temp area of the machine.
183    
184            // Inject the System Partition
185            Partition systemPartition = partitionFactory.createPartition( "system", ServerDNConstants.SYSTEM_DN, 500,
186                new File( directoryService.getWorkingDirectory(), "system" ) );
187            systemPartition.setSchemaManager( directoryService.getSchemaManager() );
188    
189            partitionFactory.addIndex( systemPartition, SchemaConstants.OBJECT_CLASS_AT, 100 );
190    
191            directoryService.setSystemPartition( systemPartition );
192        }
193    
194    
195        /**
196         * Builds the directory server instance.
197         * 
198         * @param name the instance name
199         */
200        private void build( String name ) throws Exception
201        {
202            directoryService.setInstanceId( name );
203            buildWorkingDirectory( name );
204    
205            // Erase the working directory to be sure that we don't have some
206            // remaining data from a previous run
207            String workingDirectoryPath = directoryService.getWorkingDirectory().getPath();
208            File workingDirectory = new File( workingDirectoryPath );
209            FileUtils.deleteDirectory( workingDirectory );
210    
211            // Init the service now
212            initSchema();
213            initSystemPartition();
214    
215            directoryService.startup();
216        }
217    
218    
219        /**
220         * {@inheritDoc}
221         */
222        public DirectoryService getDirectoryService() throws Exception
223        {
224            return directoryService;
225        }
226    
227    
228        /**
229         * {@inheritDoc}
230         */
231        public PartitionFactory getPartitionFactory() throws Exception
232        {
233            return partitionFactory;
234        }
235    }