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     */
020    package org.apache.directory.server.xdbm.tools;
021    
022    
023    import java.util.UUID;
024    
025    import org.apache.directory.server.xdbm.ForwardIndexEntry;
026    import org.apache.directory.server.xdbm.Index;
027    import org.apache.directory.server.xdbm.IndexCursor;
028    import org.apache.directory.server.xdbm.IndexEntry;
029    import org.apache.directory.server.xdbm.Store;
030    import org.apache.directory.shared.ldap.constants.SchemaConstants;
031    import org.apache.directory.shared.ldap.csn.CsnFactory;
032    import org.apache.directory.shared.ldap.cursor.Cursor;
033    import org.apache.directory.shared.ldap.entry.DefaultServerEntry;
034    import org.apache.directory.shared.ldap.entry.Entry;
035    import org.apache.directory.shared.ldap.entry.EntryAttribute;
036    import org.apache.directory.shared.ldap.entry.ServerEntry;
037    import org.apache.directory.shared.ldap.entry.client.DefaultClientAttribute;
038    import org.apache.directory.shared.ldap.entry.client.DefaultClientEntry;
039    import org.apache.directory.shared.ldap.name.DN;
040    import org.apache.directory.shared.ldap.schema.SchemaManager;
041    
042    
043    /**
044     * A utility class for loading example LDIF data.
045     *
046     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
047     * @version $Rev$, $Date$
048     */
049    public class StoreUtils
050    {
051        /** CSN factory instance */
052        private static final CsnFactory CSN_FACTORY = new CsnFactory( 0 );
053    
054    
055        /**
056         * Initializes and loads a store with the example data shown in
057         * <a href="http://cwiki.apache.org/confluence/display/DIRxSRVx11/Structure+and+Organization">
058         * Structure and Organization</a>
059         *
060         * TODO might want to make this load an LDIF instead in the future
061         * TODO correct size of spaces in user provided DN
062         * 
063         * @param store the store object to be initialized
064         * @param registries oid registries
065         * @throws Exception on access exceptions
066         */
067        public static void loadExampleData( Store<ServerEntry, Long> store, SchemaManager schemaManager ) throws Exception
068        {
069            store.setSuffixDn( "o=Good Times Co." );
070    
071            DN suffixDn = new DN( "o=Good Times Co." );
072            suffixDn.normalize( schemaManager.getNormalizerMapping() );
073    
074            store.init( schemaManager );
075    
076            // Entry #1
077            DefaultServerEntry entry = new DefaultServerEntry( schemaManager, suffixDn );
078            entry.add( "objectClass", "organization" );
079            entry.add( "o", "Good Times Co." );
080            entry.add( "postalCode", "1" );
081            entry.add( "postOfficeBox", "1" );
082            injectEntryInStore( store, entry );
083    
084            // Entry #2
085            DN dn = new DN( "ou=Sales,o=Good Times Co." );
086            dn.normalize( schemaManager.getNormalizerMapping() );
087            entry = new DefaultServerEntry( schemaManager, dn );
088            entry.add( "objectClass", "top", "organizationalUnit" );
089            entry.add( "ou", "Sales" );
090            entry.add( "postalCode", "1" );
091            entry.add( "postOfficeBox", "1" );
092            injectEntryInStore( store, entry );
093    
094            // Entry #3
095            dn = new DN( "ou=Board of Directors,o=Good Times Co." );
096            dn.normalize( schemaManager.getNormalizerMapping() );
097            entry = new DefaultServerEntry( schemaManager, dn );
098            entry.add( "objectClass", "top", "organizationalUnit" );
099            entry.add( "ou", "Board of Directors" );
100            entry.add( "postalCode", "1" );
101            entry.add( "postOfficeBox", "1" );
102            injectEntryInStore( store, entry );
103    
104            // Entry #4
105            dn = new DN( "ou=Engineering,o=Good Times Co." );
106            dn.normalize( schemaManager.getNormalizerMapping() );
107            entry = new DefaultServerEntry( schemaManager, dn );
108            entry.add( "objectClass", "top", "organizationalUnit" );
109            entry.add( "ou", "Engineering" );
110            entry.add( "postalCode", "2" );
111            entry.add( "postOfficeBox", "2" );
112            injectEntryInStore( store, entry );
113    
114            // Entry #5
115            dn = new DN( "cn=JOhnny WAlkeR,ou=Sales,o=Good Times Co." );
116            dn.normalize( schemaManager.getNormalizerMapping() );
117            entry = new DefaultServerEntry( schemaManager, dn );
118            entry.add( "objectClass", "top", "person", "organizationalPerson" );
119            entry.add( "ou", "Sales" );
120            entry.add( "cn", "JOhnny WAlkeR" );
121            entry.add( "sn", "WAlkeR" );
122            entry.add( "postalCode", "3" );
123            entry.add( "postOfficeBox", "3" );
124            injectEntryInStore( store, entry );
125    
126            // Entry #6
127            dn = new DN( "cn=JIM BEAN,ou=Sales,o=Good Times Co." );
128            dn.normalize( schemaManager.getNormalizerMapping() );
129            entry = new DefaultServerEntry( schemaManager, dn );
130            entry.add( "objectClass", "top", "person", "organizationalPerson" );
131            entry.add( "ou", "Sales" );
132            entry.add( "cn", "JIM BEAN" );
133            entry.add( "surName", "BEAN" );
134            entry.add( "postalCode", "4" );
135            entry.add( "postOfficeBox", "4" );
136            injectEntryInStore( store, entry );
137    
138            // Entry #7
139            dn = new DN( "ou=Apache,ou=Board of Directors,o=Good Times Co." );
140            dn.normalize( schemaManager.getNormalizerMapping() );
141            entry = new DefaultServerEntry( schemaManager, dn );
142            entry.add( "objectClass", "top", "organizationalUnit" );
143            entry.add( "ou", "Apache" );
144            entry.add( "postalCode", "5" );
145            entry.add( "postOfficeBox", "5" );
146            injectEntryInStore( store, entry );
147    
148            // Entry #8
149            dn = new DN( "cn=Jack Daniels,ou=Engineering,o=Good Times Co." );
150            dn.normalize( schemaManager.getNormalizerMapping() );
151            entry = new DefaultServerEntry( schemaManager, dn );
152            entry.add( "objectClass", "top", "person", "organizationalPerson" );
153            entry.add( "ou", "Engineering" );
154            entry.add( "cn", "Jack Daniels" );
155            entry.add( "SN", "Daniels" );
156            entry.add( "postalCode", "6" );
157            entry.add( "postOfficeBox", "6" );
158            injectEntryInStore( store, entry );
159    
160            // aliases -------------
161    
162            // Entry #9
163            dn = new DN( "commonName=Jim Bean,ou=Apache,ou=Board of Directors,o=Good Times Co." );
164            dn.normalize( schemaManager.getNormalizerMapping() );
165            entry = new DefaultServerEntry( schemaManager, dn );
166            entry.add( "objectClass", "top", "alias", "extensibleObject" );
167            entry.add( "ou", "Apache" );
168            entry.add( "commonName", "Jim Bean" );
169            entry.add( "aliasedObjectName", "cn=Jim Bean,ou=Sales,o=Good Times Co." );
170            injectEntryInStore( store, entry );
171    
172            // Entry #10
173            dn = new DN( "commonName=Jim Bean,ou=Board of Directors,o=Good Times Co." );
174            dn.normalize( schemaManager.getNormalizerMapping() );
175            entry = new DefaultServerEntry( schemaManager, dn );
176            entry.add( "objectClass", "top", "alias", "extensibleObject" );
177            entry.add( "commonName", "Jim Bean" );
178            entry.add( "aliasedObjectName", "cn=Jim Bean,ou=Sales,o=Good Times Co." );
179            injectEntryInStore( store, entry );
180    
181            // Entry #11
182            dn = new DN( "2.5.4.3=Johnny Walker,ou=Engineering,o=Good Times Co." );
183            dn.normalize( schemaManager.getNormalizerMapping() );
184            entry = new DefaultServerEntry( schemaManager, dn );
185            entry.add( "objectClass", "top", "alias", "extensibleObject" );
186            entry.add( "ou", "Engineering" );
187            entry.add( "2.5.4.3", "Johnny Walker" );
188            entry.add( "aliasedObjectName", "cn=Johnny Walker,ou=Sales,o=Good Times Co." );
189            injectEntryInStore( store, entry );
190        }
191    
192    
193        /**
194         * This is primarily a convenience method used to extract all the attributes
195         * associated with an entry.
196         *
197         * @param store the store to get the attributes from
198         * @param id the id of the entry to get index information for
199         * @return the index names and values as an Attributes object
200         * @throws Exception if there are failures accessing the underlying store
201         */
202        @SuppressWarnings("unchecked")
203        public Entry getAttributes( Store<Object, Long> store, Long id ) throws Exception
204        {
205            Entry entry = new DefaultClientEntry();
206    
207            // Get the distinguishedName to id mapping
208            entry.put( "_nDn", store.getEntryDn( id ) );
209            entry.put( "_upDn", store.getEntryUpdn( id ) );
210            entry.put( "_parent", Long.toString( store.getParentId( id ) ) );
211    
212            // Get all standard index attribute to value mappings
213            for ( Index index : store.getUserIndices() )
214            {
215                Cursor<ForwardIndexEntry> list = index.reverseCursor();
216                ForwardIndexEntry recordForward = new ForwardIndexEntry();
217                recordForward.setId( id );
218                list.before( recordForward );
219    
220                while ( list.next() )
221                {
222                    IndexEntry rec = list.get();
223                    String val = rec.getValue().toString();
224                    String attrId = index.getAttribute().getName();
225                    EntryAttribute attr = entry.get( attrId );
226    
227                    if ( attr == null )
228                    {
229                        attr = new DefaultClientAttribute( attrId );
230                    }
231    
232                    attr.add( val );
233                    entry.put( attr );
234                }
235            }
236    
237            // Get all existence mappings for this id creating a special key
238            // that looks like so 'existence[attribute]' and the value is set to id
239            IndexCursor<String, Object, Long> list = store.getPresenceIndex().reverseCursor();
240            ForwardIndexEntry recordForward = new ForwardIndexEntry();
241            recordForward.setId( id );
242            list.before( recordForward );
243            StringBuffer val = new StringBuffer();
244    
245            while ( list.next() )
246            {
247                IndexEntry rec = list.get();
248                val.append( "_existence[" );
249                val.append( rec.getValue().toString() );
250                val.append( "]" );
251    
252                String valStr = val.toString();
253                EntryAttribute attr = entry.get( valStr );
254    
255                if ( attr == null )
256                {
257                    attr = new DefaultClientAttribute( valStr );
258                }
259    
260                attr.add( rec.getId().toString() );
261                entry.put( attr );
262                val.setLength( 0 );
263            }
264    
265            // Get all parent child mappings for this entry as the parent using the
266            // key 'child' with many entries following it.
267            IndexCursor<Long, Object, Long> children = store.getOneLevelIndex().forwardCursor();
268            ForwardIndexEntry longRecordForward = new ForwardIndexEntry();
269            recordForward.setId( id );
270            children.before( longRecordForward );
271    
272            EntryAttribute childAttr = new DefaultClientAttribute( "_child" );
273            entry.put( childAttr );
274    
275            while ( children.next() )
276            {
277                IndexEntry rec = children.get();
278                childAttr.add( rec.getId().toString() );
279            }
280    
281            return entry;
282        }
283    
284    
285        /**
286         * 
287         * adds a given <i>ServerEntry</i> to the store after injecting entryCSN and entryUUID operational
288         * attributes
289         *
290         * @param store the store
291         * @param dn the normalized DN
292         * @param entry the server entry
293         * @throws Exception in case of any problems in adding the entry to the store
294         */
295        public static void injectEntryInStore( Store<ServerEntry, Long> store, ServerEntry entry ) throws Exception
296        {
297            entry.add( SchemaConstants.ENTRY_CSN_AT, CSN_FACTORY.newInstance().toString() );
298            entry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
299    
300            store.add( entry );
301        }
302    }