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