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