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 */ 020package org.apache.directory.server.config; 021 022 023import java.io.File; 024import java.util.UUID; 025 026import org.apache.directory.api.ldap.model.constants.SchemaConstants; 027import org.apache.directory.api.ldap.model.csn.CsnFactory; 028import org.apache.directory.api.ldap.model.entry.Entry; 029import org.apache.directory.api.ldap.model.exception.LdapException; 030import org.apache.directory.api.ldap.model.ldif.LdifReader; 031import org.apache.directory.api.ldap.model.name.Dn; 032import org.apache.directory.api.ldap.model.schema.SchemaManager; 033import org.apache.directory.api.util.DateUtils; 034import org.apache.directory.api.util.TimeProvider; 035import org.apache.directory.server.constants.ServerDNConstants; 036import org.apache.directory.server.core.api.DnFactory; 037import org.apache.directory.server.core.api.InstanceLayout; 038import org.apache.directory.server.core.api.interceptor.context.AddOperationContext; 039import org.apache.directory.server.core.api.partition.PartitionTxn; 040import org.apache.directory.server.core.partition.ldif.LdifPartition; 041import org.slf4j.Logger; 042import org.slf4j.LoggerFactory; 043 044 045/** 046 * Tool for initializing the configuration patition. 047 * 048 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 049 */ 050public class ConfigPartitionInitializer 051{ 052 /** A logger for this class */ 053 private static final Logger LOG = LoggerFactory.getLogger( ConfigPartitionInitializer.class ); 054 055 private SchemaManager schemaManager; 056 057 private InstanceLayout instanceLayout; 058 059 private DnFactory dnFactory; 060 061 062 /** 063 * Creates a new instance of ConfigPartitionHelper. 064 * 065 * @param instanceLayout the instance layout where the configuration partition lives in 066 * @param dnFactory the DN factory 067 * @param cacheService the cache service 068 * @param schemaManager the schema manager 069 */ 070 public ConfigPartitionInitializer( InstanceLayout instanceLayout, DnFactory dnFactory, 071 SchemaManager schemaManager ) 072 { 073 this.instanceLayout = instanceLayout; 074 this.dnFactory = dnFactory; 075 this.schemaManager = schemaManager; 076 } 077 078 079 /** 080 * Initializes the configuration partition. If no configuration partition exists the default 081 * configuration is extracted. If the old single-file configuration exists it is migrated 082 * to new multi-file LDIF partition. 083 * 084 * @return the initialized configuration partition 085 * @throws Exception If we can't initialize the configuration partition 086 */ 087 public LdifPartition initConfigPartition() throws Exception 088 { 089 LdifPartition configPartition = new LdifPartition( schemaManager, dnFactory ); 090 configPartition.setId( "config" ); 091 configPartition.setPartitionPath( instanceLayout.getConfDirectory().toURI() ); 092 configPartition.setSuffixDn( new Dn( schemaManager, "ou=config" ) ); 093 configPartition.setSchemaManager( schemaManager ); 094 095 File newConfigDir = new File( instanceLayout.getConfDirectory(), configPartition.getSuffixDn().getName() ); 096 097 File oldConfFile = new File( instanceLayout.getConfDirectory(), LdifConfigExtractor.LDIF_CONFIG_FILE ); 098 099 boolean migrate = false; 100 101 File tempConfFile = null; 102 103 if ( oldConfFile.exists() ) 104 { 105 if ( newConfigDir.exists() ) 106 { 107 // conflict, which one to choose 108 String msg = "Conflict in selecting configuration source, both " + LdifConfigExtractor.LDIF_CONFIG_FILE 109 + " and " + newConfigDir.getName() + " exist" + " delete either one of them and restart the server"; 110 LOG.warn( msg ); 111 throw new IllegalStateException( msg ); 112 } 113 114 migrate = true; 115 } 116 else if ( !newConfigDir.exists() ) 117 { 118 String file = LdifConfigExtractor.extractSingleFileConfig( instanceLayout.getConfDirectory(), 119 LdifConfigExtractor.LDIF_CONFIG_FILE, true ); 120 tempConfFile = new File( file ); 121 } 122 123 LdifReader reader = null; 124 125 if ( migrate ) 126 { 127 LOG.info( "Old config partition detected, converting to multiple LDIF file configuration model" ); 128 reader = new LdifReader( oldConfFile, schemaManager ); 129 } 130 else if ( tempConfFile != null ) 131 { 132 LOG.info( "Creating default configuration" ); 133 reader = new LdifReader( tempConfFile, schemaManager ); 134 } 135 136 if ( reader != null ) 137 { 138 // sometimes user may have forgotten to delete ou=config.ldif after deleting ou=config folder 139 File residue = new File( instanceLayout.getConfDirectory(), "ou=config.ldif" ); 140 if ( residue.exists() ) 141 { 142 residue.delete(); 143 } 144 145 // just for the sake of above check the initialization part is kept here 146 // and in the below else block 147 configPartition.initialize(); 148 149 CsnFactory csnFactory = new CsnFactory( 0 ); 150 151 while ( reader.hasNext() ) 152 { 153 Entry entry = reader.next().getEntry(); 154 155 // add the mandatory attributes 156 if ( !entry.containsAttribute( SchemaConstants.ENTRY_UUID_AT ) ) 157 { 158 String uuid = UUID.randomUUID().toString(); 159 entry.add( SchemaConstants.ENTRY_UUID_AT, uuid ); 160 } 161 162 if ( !entry.containsAttribute( SchemaConstants.ENTRY_CSN_AT ) ) 163 { 164 entry.removeAttributes( SchemaConstants.ENTRY_CSN_AT ); 165 entry.add( SchemaConstants.ENTRY_CSN_AT, csnFactory.newInstance().toString() ); 166 } 167 168 if ( !entry.containsAttribute( SchemaConstants.CREATORS_NAME_AT ) ) 169 { 170 entry.add( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN ); 171 } 172 173 if ( !entry.containsAttribute( SchemaConstants.CREATE_TIMESTAMP_AT ) ) 174 { 175 entry.add( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( TimeProvider.DEFAULT ) ); 176 } 177 178 AddOperationContext addContext = new AddOperationContext( null, entry ); 179 addContext.setPartition( configPartition ); 180 PartitionTxn partitionTxn = null; 181 182 try 183 { 184 partitionTxn = configPartition.beginWriteTransaction(); 185 addContext.setTransaction( partitionTxn ); 186 configPartition.add( addContext ); 187 partitionTxn.commit(); 188 } 189 catch ( LdapException le ) 190 { 191 partitionTxn.abort(); 192 193 throw le; 194 } 195 } 196 197 reader.close(); 198 199 if ( migrate ) 200 { 201 oldConfFile.renameTo( new File( oldConfFile.getAbsolutePath() + "_migrated" ) ); 202 } 203 else 204 { 205 tempConfFile.delete(); 206 } 207 } 208 else 209 { 210 configPartition.initialize(); 211 } 212 213 return configPartition; 214 } 215 216}