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.config;
21  
22  
23  import java.io.File;
24  import java.util.UUID;
25  
26  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
27  import org.apache.directory.api.ldap.model.csn.CsnFactory;
28  import org.apache.directory.api.ldap.model.entry.Entry;
29  import org.apache.directory.api.ldap.model.exception.LdapException;
30  import org.apache.directory.api.ldap.model.ldif.LdifReader;
31  import org.apache.directory.api.ldap.model.name.Dn;
32  import org.apache.directory.api.ldap.model.schema.SchemaManager;
33  import org.apache.directory.api.util.DateUtils;
34  import org.apache.directory.api.util.TimeProvider;
35  import org.apache.directory.server.constants.ServerDNConstants;
36  import org.apache.directory.server.core.api.DnFactory;
37  import org.apache.directory.server.core.api.InstanceLayout;
38  import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
39  import org.apache.directory.server.core.api.partition.PartitionTxn;
40  import org.apache.directory.server.core.partition.ldif.LdifPartition;
41  import org.slf4j.Logger;
42  import org.slf4j.LoggerFactory;
43  
44  
45  /**
46   * Tool for initializing the configuration patition.
47   *
48   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
49   */
50  public class ConfigPartitionInitializer
51  {
52      /** A logger for this class */
53      private static final Logger LOG = LoggerFactory.getLogger( ConfigPartitionInitializer.class );
54  
55      private SchemaManager schemaManager;
56  
57      private InstanceLayout instanceLayout;
58  
59      private DnFactory dnFactory;
60  
61  
62      /**
63       * Creates a new instance of ConfigPartitionHelper.
64       *
65       * @param instanceLayout the instance layout where the configuration partition lives in
66       * @param dnFactory the DN factory
67       * @param cacheService the cache service
68       * @param schemaManager the schema manager
69       */
70      public ConfigPartitionInitializer( InstanceLayout instanceLayout, DnFactory dnFactory,
71          SchemaManager schemaManager )
72      {
73          this.instanceLayout = instanceLayout;
74          this.dnFactory = dnFactory;
75          this.schemaManager = schemaManager;
76      }
77  
78  
79      /**
80       * Initializes the configuration partition. If no configuration partition exists the default
81       * configuration is extracted. If the old single-file configuration exists it is migrated 
82       * to new multi-file LDIF partition. 
83       *
84       * @return the initialized configuration partition
85       * @throws Exception If we can't initialize the configuration partition
86       */
87      public LdifPartition initConfigPartition() throws Exception
88      {
89          LdifPartitionn/ldif/LdifPartition.html#LdifPartition">LdifPartition configPartition = new LdifPartition( schemaManager, dnFactory );
90          configPartition.setId( "config" );
91          configPartition.setPartitionPath( instanceLayout.getConfDirectory().toURI() );
92          configPartition.setSuffixDn( new Dn( schemaManager, "ou=config" ) );
93          configPartition.setSchemaManager( schemaManager );
94  
95          File newConfigDir = new File( instanceLayout.getConfDirectory(), configPartition.getSuffixDn().getName() );
96  
97          File oldConfFile = new File( instanceLayout.getConfDirectory(), LdifConfigExtractor.LDIF_CONFIG_FILE );
98  
99          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                 AddOperationContextceptor/context/AddOperationContext.html#AddOperationContext">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 }