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.IOException;
024import java.io.InputStream;
025import java.util.Iterator;
026import java.util.UUID;
027
028import org.apache.directory.api.ldap.model.constants.SchemaConstants;
029import org.apache.directory.api.ldap.model.entry.DefaultEntry;
030import org.apache.directory.api.ldap.model.entry.Entry;
031import org.apache.directory.api.ldap.model.exception.LdapException;
032import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
033import org.apache.directory.api.ldap.model.exception.LdapOtherException;
034import org.apache.directory.api.ldap.model.ldif.LdifEntry;
035import org.apache.directory.api.ldap.model.ldif.LdifReader;
036import org.apache.directory.api.ldap.model.name.Dn;
037import org.apache.directory.api.ldap.model.schema.SchemaManager;
038import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
039import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
040import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
041import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
042import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
043import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
044import org.apache.directory.server.core.api.partition.PartitionTxn;
045import org.apache.directory.server.core.partition.ldif.AbstractLdifPartition;
046
047
048/**
049 * This class implements a read-only configuration partition.
050 *
051 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
052 */
053public class ReadOnlyConfigurationPartition extends AbstractLdifPartition
054{
055    /** The input stream */
056    private InputStream inputStream;
057
058
059    /**
060     * Creates a new instance of ReadOnlyConfigurationPartition.
061     *
062     * @param inputStream
063     *      the input stream
064     * @param schemaManager
065     *      the schema manager
066     */
067    public ReadOnlyConfigurationPartition( InputStream inputStream, SchemaManager schemaManager )
068    {
069        super( schemaManager );
070        this.inputStream = inputStream;
071        id = "config";
072
073        try
074        {
075            suffixDn = new Dn( schemaManager, "ou=config" );
076        }
077        catch ( LdapInvalidDnException lide )
078        {
079            // Nothing to do
080        }
081    }
082
083
084    /**
085     * {@inheritDoc}
086     */
087    @Override
088    protected void doInit() throws LdapException
089    {
090        if ( !initialized )
091        {
092            // Initializing the wrapped partition
093            super.doInit();
094
095            // Load LDIF entries
096            loadLdifEntries();
097        }
098    }
099
100
101    /**
102     * Loads the LDIF entries from the input stream.
103     * 
104     * @throws Exception
105     */
106    private void loadLdifEntries() throws LdapException
107    {
108        if ( inputStream != null )
109        {
110            // Initializing the reader and the entry iterator
111            try ( LdifReader reader = new LdifReader( inputStream ) )
112            {
113                Iterator<LdifEntry> itr = reader.iterator();
114    
115                // Exiting if there's no entry
116                if ( !itr.hasNext() )
117                {
118                    return;
119                }
120    
121                // Getting the context entry
122                LdifEntry ldifEntry = itr.next();
123                Entry contextEntry = new DefaultEntry( schemaManager, ldifEntry.getEntry() );
124    
125                // Checking the context entry
126                if ( suffixDn.equals( contextEntry.getDn() ) )
127                {
128                    addMandatoryOpAt( contextEntry );
129    
130                    super.add( new AddOperationContext( null, contextEntry ) );
131                }
132                else
133                {
134                    throw new LdapException( "The given LDIF file doesn't contain the context entry" );
135                }
136    
137                // Iterating on all entries
138                while ( itr.hasNext() )
139                {
140                    Entry entry = new DefaultEntry( schemaManager, itr.next().getEntry() );
141                    addMandatoryOpAt( entry );
142    
143                    super.add( new AddOperationContext( null, entry ) );
144                }
145            }
146            catch ( IOException ioe )
147            {
148                throw new LdapOtherException( ioe.getMessage(), ioe );
149            }
150        }
151    }
152
153
154    /**
155     * Adds the CSN and UUID attributes to the entry if they are not present.
156     */
157    private void addMandatoryOpAt( Entry entry ) throws LdapException
158    {
159        // entryCSN
160        if ( entry.get( SchemaConstants.ENTRY_CSN_AT ) == null )
161        {
162            entry.add( SchemaConstants.ENTRY_CSN_AT, defaultCSNFactory.newInstance().toString() );
163        }
164
165        // entryUUID
166        if ( entry.get( SchemaConstants.ENTRY_UUID_AT ) == null )
167        {
168            String uuid = UUID.randomUUID().toString();
169            entry.add( SchemaConstants.ENTRY_UUID_AT, uuid );
170        }
171    }
172
173
174    //---------------------------------------------------------------------------------------------
175    // Operations
176    //---------------------------------------------------------------------------------------------
177    /**
178     * {@inheritDoc}
179     */
180    @Override
181    public void add( AddOperationContext arg0 ) throws LdapException
182    {
183        // Does nothing (Read-Only)
184    }
185
186
187    /**
188     * {@inheritDoc}
189     */
190    @Override
191    public Entry delete( PartitionTxn partitionTxn, String id ) throws LdapException
192    {
193        // Does nothing (Read-Only)
194        return null;
195    }
196
197
198    /**
199     * {@inheritDoc}
200     */
201    @Override
202    public Entry delete( DeleteOperationContext deleteContext ) throws LdapException
203    {
204        // Does nothing (Read-Only)
205        return null;
206    }
207
208
209    /**
210     * {@inheritDoc}
211     */
212    @Override
213    public void modify( ModifyOperationContext arg0 ) throws LdapException
214    {
215        // Does nothing (Read-Only)
216    }
217
218
219    /**
220     * {@inheritDoc}
221     */
222    @Override
223    public void move( MoveOperationContext arg0 ) throws LdapException
224    {
225        // Does nothing (Read-Only)
226    }
227
228
229    /**
230     * {@inheritDoc}
231     */
232    @Override
233    public void moveAndRename( MoveAndRenameOperationContext arg0 ) throws LdapException
234    {
235        // Does nothing (Read-Only)
236    }
237
238
239    /**
240     * {@inheritDoc}
241     */
242    @Override
243    public void rename( RenameOperationContext arg0 ) throws LdapException
244    {
245        // Does nothing (Read-Only)
246    }
247}