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    protected void doInit() throws LdapException
088    {
089        if ( !initialized )
090        {
091            // Initializing the wrapped partition
092            super.doInit();
093
094            // Load LDIF entries
095            loadLdifEntries();
096        }
097    }
098
099
100    /**
101     * Loads the LDIF entries from the input stream.
102     * 
103     * @throws Exception
104     */
105    private void loadLdifEntries() throws LdapException
106    {
107        if ( inputStream != null )
108        {
109            // Initializing the reader and the entry iterator
110            try ( LdifReader reader = new LdifReader( inputStream ) )
111            {
112                Iterator<LdifEntry> itr = reader.iterator();
113    
114                // Exiting if there's no entry
115                if ( !itr.hasNext() )
116                {
117                    return;
118                }
119    
120                // Getting the context entry
121                LdifEntry ldifEntry = itr.next();
122                Entry contextEntry = new DefaultEntry( schemaManager, ldifEntry.getEntry() );
123    
124                // Checking the context entry
125                if ( suffixDn.equals( contextEntry.getDn() ) )
126                {
127                    addMandatoryOpAt( contextEntry );
128    
129                    super.add( new AddOperationContext( null, contextEntry ) );
130                }
131                else
132                {
133                    throw new LdapException( "The given LDIF file doesn't contain the context entry" );
134                }
135    
136                // Iterating on all entries
137                while ( itr.hasNext() )
138                {
139                    Entry entry = new DefaultEntry( schemaManager, itr.next().getEntry() );
140                    addMandatoryOpAt( entry );
141    
142                    super.add( new AddOperationContext( null, entry ) );
143                }
144            }
145            catch ( IOException ioe )
146            {
147                throw new LdapOtherException( ioe.getMessage(), ioe );
148            }
149        }
150    }
151
152
153    /**
154     * Adds the CSN and UUID attributes to the entry if they are not present.
155     */
156    private void addMandatoryOpAt( Entry entry ) throws LdapException
157    {
158        // entryCSN
159        if ( entry.get( SchemaConstants.ENTRY_CSN_AT ) == null )
160        {
161            entry.add( SchemaConstants.ENTRY_CSN_AT, defaultCSNFactory.newInstance().toString() );
162        }
163
164        // entryUUID
165        if ( entry.get( SchemaConstants.ENTRY_UUID_AT ) == null )
166        {
167            String uuid = UUID.randomUUID().toString();
168            entry.add( SchemaConstants.ENTRY_UUID_AT, uuid );
169        }
170    }
171
172
173    //---------------------------------------------------------------------------------------------
174    // Operations
175    //---------------------------------------------------------------------------------------------
176    /**
177     * {@inheritDoc}
178     */
179    @Override
180    public void add( AddOperationContext arg0 ) throws LdapException
181    {
182        // Does nothing (Read-Only)
183    }
184
185
186    /**
187     * {@inheritDoc}
188     */
189    @Override
190    public Entry delete( PartitionTxn partitionTxn, String id ) throws LdapException
191    {
192        // Does nothing (Read-Only)
193        return null;
194    }
195
196
197    /**
198     * {@inheritDoc}
199     */
200    @Override
201    public Entry delete( DeleteOperationContext deleteContext ) throws LdapException
202    {
203        // Does nothing (Read-Only)
204        return null;
205    }
206
207
208    /**
209     * {@inheritDoc}
210     */
211    @Override
212    public void modify( ModifyOperationContext arg0 ) throws LdapException
213    {
214        // Does nothing (Read-Only)
215    }
216
217
218    /**
219     * {@inheritDoc}
220     */
221    @Override
222    public void move( MoveOperationContext arg0 ) throws LdapException
223    {
224        // Does nothing (Read-Only)
225    }
226
227
228    /**
229     * {@inheritDoc}
230     */
231    @Override
232    public void moveAndRename( MoveAndRenameOperationContext arg0 ) throws LdapException
233    {
234        // Does nothing (Read-Only)
235    }
236
237
238    /**
239     * {@inheritDoc}
240     */
241    @Override
242    public void rename( RenameOperationContext arg0 ) throws LdapException
243    {
244        // Does nothing (Read-Only)
245    }
246}