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 */ 019package org.apache.directory.server.core.factory; 020 021 022import java.io.File; 023import java.io.IOException; 024import java.util.List; 025 026import org.apache.directory.api.ldap.model.constants.SchemaConstants; 027import org.apache.directory.api.ldap.model.schema.LdapComparator; 028import org.apache.directory.api.ldap.model.schema.SchemaManager; 029import org.apache.directory.api.ldap.model.schema.comparators.NormalizingComparator; 030import org.apache.directory.api.ldap.model.schema.registries.ComparatorRegistry; 031import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader; 032import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor; 033import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor; 034import org.apache.directory.api.ldap.schema.loader.LdifSchemaLoader; 035import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager; 036import org.apache.directory.api.util.FileUtils; 037import org.apache.directory.api.util.exception.Exceptions; 038import org.apache.directory.server.constants.ServerDNConstants; 039import org.apache.directory.server.core.DefaultDirectoryService; 040import org.apache.directory.server.core.api.DirectoryService; 041import org.apache.directory.server.core.api.InstanceLayout; 042import org.apache.directory.server.core.api.partition.Partition; 043import org.apache.directory.server.core.api.schema.SchemaPartition; 044import org.apache.directory.server.core.partition.ldif.LdifPartition; 045import org.apache.directory.server.i18n.I18n; 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048 049 050/** 051 * A Default factory for DirectoryService. 052 * 053 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 054 */ 055public class DefaultDirectoryServiceFactory implements DirectoryServiceFactory 056{ 057 /** A logger for this class */ 058 private static final Logger LOG = LoggerFactory.getLogger( DefaultDirectoryServiceFactory.class ); 059 060 /** The directory service. */ 061 private DirectoryService directoryService; 062 063 /** The partition factory. */ 064 private PartitionFactory partitionFactory; 065 066 067 public DefaultDirectoryServiceFactory() 068 { 069 try 070 { 071 // creating the instance here so that 072 // we we can set some properties like accesscontrol, anon access 073 // before starting up the service 074 directoryService = new DefaultDirectoryService(); 075 076 // no need to register a shutdown hook during tests because this 077 // starts a lot of threads and slows down test execution 078 directoryService.setShutdownHookEnabled( false ); 079 } 080 catch ( Exception e ) 081 { 082 throw new RuntimeException( e ); 083 } 084 085 try 086 { 087 String typeName = System.getProperty( "apacheds.partition.factory" ); 088 089 if ( typeName != null ) 090 { 091 Class<? extends PartitionFactory> type = ( Class<? extends PartitionFactory> ) Class.forName( typeName ); 092 partitionFactory = type.newInstance(); 093 } 094 else 095 { 096 partitionFactory = new JdbmPartitionFactory(); 097 } 098 } 099 catch ( Exception e ) 100 { 101 LOG.error( "Error instantiating custom partiton factory", e ); 102 throw new RuntimeException( e ); 103 } 104 } 105 106 107 public DefaultDirectoryServiceFactory( DirectoryService directoryService, PartitionFactory partitionFactory ) 108 { 109 this.directoryService = directoryService; 110 this.partitionFactory = partitionFactory; 111 } 112 113 114 /** 115 * {@inheritDoc} 116 */ 117 public void init( String name ) throws Exception 118 { 119 if ( ( directoryService != null ) && directoryService.isStarted() ) 120 { 121 return; 122 } 123 124 build( name ); 125 } 126 127 128 /** 129 * Build the working directory 130 */ 131 private void buildInstanceDirectory( String name ) throws IOException 132 { 133 String instanceDirectory = System.getProperty( "workingDirectory" ); 134 135 if ( instanceDirectory == null ) 136 { 137 instanceDirectory = System.getProperty( "java.io.tmpdir" ) + "/server-work-" + name; 138 } 139 140 InstanceLayout instanceLayout = new InstanceLayout( instanceDirectory ); 141 142 if ( instanceLayout.getInstanceDirectory().exists() ) 143 { 144 try 145 { 146 FileUtils.deleteDirectory( instanceLayout.getInstanceDirectory() ); 147 } 148 catch ( IOException e ) 149 { 150 LOG.error( "couldn't delete the instance directory before initializing the DirectoryService", e ); 151 } 152 } 153 154 directoryService.setInstanceLayout( instanceLayout ); 155 } 156 157 158 /** 159 * Inits the schema and schema partition. 160 */ 161 private void initSchema() throws Exception 162 { 163 File workingDirectory = directoryService.getInstanceLayout().getPartitionsDirectory(); 164 165 // Extract the schema on disk (a brand new one) and load the registries 166 File schemaRepository = new File( workingDirectory, "schema" ); 167 SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( workingDirectory ); 168 169 try 170 { 171 extractor.extractOrCopy(); 172 } 173 catch ( IOException ioe ) 174 { 175 // The schema has already been extracted, bypass 176 } 177 178 SchemaLoader loader = new LdifSchemaLoader( schemaRepository ); 179 SchemaManager schemaManager = new DefaultSchemaManager( loader ); 180 181 // We have to load the schema now, otherwise we won't be able 182 // to initialize the Partitions, as we won't be able to parse 183 // and normalize their suffix Dn 184 schemaManager.loadAllEnabled(); 185 186 // Tell all the normalizer comparators that they should not normalize anything 187 ComparatorRegistry comparatorRegistry = schemaManager.getComparatorRegistry(); 188 189 for ( LdapComparator<?> comparator : comparatorRegistry ) 190 { 191 if ( comparator instanceof NormalizingComparator ) 192 { 193 ( ( NormalizingComparator ) comparator ).setOnServer(); 194 } 195 } 196 197 directoryService.setSchemaManager( schemaManager ); 198 199 // Init the LdifPartition 200 LdifPartition ldifPartition = new LdifPartition( schemaManager, directoryService.getDnFactory() ); 201 ldifPartition.setPartitionPath( new File( workingDirectory, "schema" ).toURI() ); 202 SchemaPartition schemaPartition = new SchemaPartition( schemaManager ); 203 schemaPartition.setWrappedPartition( ldifPartition ); 204 directoryService.setSchemaPartition( schemaPartition ); 205 206 List<Throwable> errors = schemaManager.getErrors(); 207 208 if ( !errors.isEmpty() ) 209 { 210 throw new Exception( I18n.err( I18n.ERR_317, Exceptions.printErrors( errors ) ) ); 211 } 212 } 213 214 215 /** 216 * Inits the system partition. 217 * 218 * @throws Exception the exception 219 */ 220 private void initSystemPartition() throws Exception 221 { 222 // change the working directory to something that is unique 223 // on the system and somewhere either under target directory 224 // or somewhere in a temp area of the machine. 225 226 // Inject the System Partition 227 Partition systemPartition = partitionFactory.createPartition( directoryService.getSchemaManager(), 228 directoryService.getDnFactory(), 229 "system", ServerDNConstants.SYSTEM_DN, 500, 230 new File( directoryService.getInstanceLayout().getPartitionsDirectory(), "system" ) ); 231 systemPartition.setSchemaManager( directoryService.getSchemaManager() ); 232 233 partitionFactory.addIndex( systemPartition, SchemaConstants.OBJECT_CLASS_AT, 100 ); 234 235 directoryService.setSystemPartition( systemPartition ); 236 } 237 238 239 /** 240 * Builds the directory server instance. 241 * 242 * @param name the instance name 243 */ 244 private void build( String name ) throws Exception 245 { 246 directoryService.setInstanceId( name ); 247 buildInstanceDirectory( name ); 248 249 // Init the service now 250 initSchema(); 251 initSystemPartition(); 252 253 directoryService.startup(); 254 } 255 256 257 /** 258 * {@inheritDoc} 259 */ 260 public DirectoryService getDirectoryService() throws Exception 261 { 262 return directoryService; 263 } 264 265 266 /** 267 * {@inheritDoc} 268 */ 269 public PartitionFactory getPartitionFactory() throws Exception 270 { 271 return partitionFactory; 272 } 273}