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.tools;
21  
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.util.HashSet;
26  import java.util.List;
27  import java.util.Set;
28  
29  import javax.naming.directory.Attribute;
30  import javax.naming.directory.Attributes;
31  
32  import jdbm.helper.MRU;
33  import jdbm.recman.BaseRecordManager;
34  import jdbm.recman.CacheRecordManager;
35  
36  import org.apache.commons.cli.CommandLine;
37  import org.apache.commons.cli.Option;
38  import org.apache.commons.cli.Options;
39  import org.apache.directory.server.constants.ServerDNConstants;
40  import org.apache.directory.server.core.DefaultDirectoryService;
41  import org.apache.directory.server.core.DirectoryService;
42  import org.apache.directory.server.core.cursor.Cursor;
43  import org.apache.directory.server.core.entry.ServerEntry;
44  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
45  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmMasterTable;
46  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
47  import org.apache.directory.server.core.schema.PartitionSchemaLoader;
48  import org.apache.directory.server.schema.SerializableComparator;
49  import org.apache.directory.server.schema.bootstrap.ApacheSchema;
50  import org.apache.directory.server.schema.bootstrap.ApachemetaSchema;
51  import org.apache.directory.server.schema.bootstrap.BootstrapSchemaLoader;
52  import org.apache.directory.server.schema.bootstrap.CoreSchema;
53  import org.apache.directory.server.schema.bootstrap.Schema;
54  import org.apache.directory.server.schema.bootstrap.SystemSchema;
55  import org.apache.directory.server.schema.bootstrap.partition.DbFileListing;
56  import org.apache.directory.server.schema.registries.DefaultOidRegistry;
57  import org.apache.directory.server.schema.registries.DefaultRegistries;
58  import org.apache.directory.server.schema.registries.OidRegistry;
59  import org.apache.directory.server.schema.registries.Registries;
60  import org.apache.directory.server.xdbm.Index;
61  import org.apache.directory.server.xdbm.Tuple;
62  import org.apache.directory.shared.ldap.MultiException;
63  import org.apache.directory.shared.ldap.exception.LdapConfigurationException;
64  import org.apache.directory.shared.ldap.exception.LdapNamingException;
65  import org.apache.directory.shared.ldap.message.ResultCodeEnum;
66  import org.apache.directory.shared.ldap.schema.AttributeType;
67  import org.apache.directory.shared.ldap.util.AttributeUtils;
68  
69  
70  /**
71   * Simple tool used to dump the contents of a jdbm based partition.
72   * 
73   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
74   * @version $Rev: 442600 $
75   */
76  public class IndexCommand extends ToolCommand
77  {
78      private Registries bootstrapRegistries = new DefaultRegistries( "bootstrap", new BootstrapSchemaLoader(),
79          new DefaultOidRegistry() );
80  
81  
82      public IndexCommand()
83      {
84          super( "index" );
85      }
86  
87  
88      @SuppressWarnings("unchecked")
89      private Registries loadRegistries() throws Exception
90      {
91          // --------------------------------------------------------------------
92          // Load the bootstrap schemas to start up the schema partition
93          // --------------------------------------------------------------------
94  
95          // setup temporary loader and temp registry 
96          BootstrapSchemaLoader loader = new BootstrapSchemaLoader();
97          OidRegistry oidRegistry = new DefaultOidRegistry();
98          final Registries registries = new DefaultRegistries( "bootstrap", loader, oidRegistry );
99  
100         // load essential bootstrap schemas 
101         Set<Schema> bootstrapSchemas = new HashSet<Schema>();
102         bootstrapSchemas.add( new ApachemetaSchema() );
103         bootstrapSchemas.add( new ApacheSchema() );
104         bootstrapSchemas.add( new CoreSchema() );
105         bootstrapSchemas.add( new SystemSchema() );
106         loader.loadWithDependencies( bootstrapSchemas, registries );
107 
108         // run referential integrity tests
109         List<Throwable> errors = registries.checkRefInteg();
110 
111         if ( !errors.isEmpty() )
112         {
113             MultiException e = new MultiException();
114             for ( Throwable t : errors )
115             {
116                 e.addThrowable( t );
117             }
118             
119             throw e;
120         }
121 
122         SerializableComparator.setRegistry( registries.getComparatorRegistry() );
123 
124         // --------------------------------------------------------------------
125         // Initialize schema partition or bomb out if we cannot find it on disk
126         // --------------------------------------------------------------------
127 
128         // If not present then we need to abort 
129         File schemaDirectory = new File( getLayout().getPartitionsDirectory(), "schema" );
130         if ( !schemaDirectory.exists() )
131         {
132             throw new LdapConfigurationException( "The following schema directory from "
133                 + "the installation layout could not be found:\n\t" + schemaDirectory );
134         }
135 
136         JdbmPartition schemaPartition = new JdbmPartition();
137         schemaPartition.setId( "schema" );
138         schemaPartition.setCacheSize( 1000 );
139 
140         DbFileListing listing;
141         try
142         {
143             listing = new DbFileListing();
144         }
145         catch ( IOException e )
146         {
147             throw new LdapNamingException( "Got IOException while trying to read DBFileListing: " + e.getMessage(),
148                 ResultCodeEnum.OTHER );
149         }
150 
151         Set<Index<?,ServerEntry>> indexedAttributes = new HashSet<Index<?,ServerEntry>>();
152 
153         for ( String attributeId : listing.getIndexedAttributes() )
154         {
155             indexedAttributes.add( new JdbmIndex( attributeId ) );
156         }
157 
158         schemaPartition.setIndexedAttributes( indexedAttributes );
159         schemaPartition.setSuffix( ServerDNConstants.OU_SCHEMA_DN );
160 
161         DirectoryService directoryService = new DefaultDirectoryService();
162         schemaPartition.init( directoryService );
163 
164         // --------------------------------------------------------------------
165         // Initialize schema subsystem and reset registries
166         // --------------------------------------------------------------------
167 
168         PartitionSchemaLoader schemaLoader = new PartitionSchemaLoader( schemaPartition, registries );
169         Registries globalRegistries = new DefaultRegistries( "global", schemaLoader, oidRegistry );
170         schemaLoader.loadEnabled( globalRegistries );
171         SerializableComparator.setRegistry( globalRegistries.getComparatorRegistry() );
172         return globalRegistries;
173     }
174 
175 
176     public void execute( CommandLine cmdline ) throws Exception
177     {
178         getLayout().verifyInstallation();
179         bootstrapRegistries = loadRegistries();
180 
181         String[] partitions = cmdline.getOptionValues( 'p' );
182         String attribute = cmdline.getOptionValue( 'a' );
183 
184         for ( int ii = 0; ii < partitions.length; ii++ )
185         {
186             File partitionDirectory = new File( getLayout().getPartitionsDirectory(), partitions[ii] );
187             buildIndex( partitionDirectory, bootstrapRegistries.getAttributeTypeRegistry().lookup( attribute ) );
188         }
189     }
190 
191 
192     @SuppressWarnings("unchecked")
193     private void buildIndex( File partitionDirectory, AttributeType attributeType ) throws Exception
194     {
195         if ( !partitionDirectory.exists() )
196         {
197             System.err.println( "Partition directory " + partitionDirectory + " does not exist!" );
198             System.exit( 1 );
199         }
200 
201         String path = partitionDirectory.getPath() + File.separator + "master";
202         BaseRecordManager base = new BaseRecordManager( path );
203         base.disableTransactions();
204         CacheRecordManager recMan = new CacheRecordManager( base, new MRU( 1000 ) );
205 
206         JdbmMasterTable<ServerEntry> master = new JdbmMasterTable<ServerEntry>( recMan, bootstrapRegistries );
207         JdbmIndex index = new JdbmIndex();
208         index.setAttributeId( attributeType.getName() );
209         index.setWkDirPath( partitionDirectory );
210         index.setCacheSize( 1000 );
211         index.setNumDupLimit( 1000 );
212         index.init( attributeType, partitionDirectory );
213 
214         Cursor<Tuple<Long,ServerEntry>> list = master.cursor();
215         while ( list.next() )
216         {
217             Tuple<Long,ServerEntry> tuple = list.get();
218             Long id = tuple.getKey();
219             Attributes entry = ( Attributes ) tuple.getValue();
220 
221             Attribute attr = AttributeUtils.getAttribute( entry, attributeType );
222             if ( attr == null )
223             {
224                 continue;
225             }
226 
227             for ( int ii = 0; ii < attr.size(); ii++ )
228             {
229                 index.add( attr.get( ii ), id );
230             }
231         }
232 
233         index.sync();
234     }
235 
236 
237     public Options getOptions()
238     {
239         Options opts = new Options();
240         Option op = null;
241         op = new Option( "p", "partitions", true, "the partitions to add the attribute indices to" );
242         op.setRequired( true );
243         op.setValueSeparator( File.pathSeparatorChar );
244         opts.addOption( op );
245         op = new Option( "a", "attributes", true, "the attribute to index" );
246         op.setRequired( true );
247         op.setValueSeparator( File.pathSeparatorChar );
248         opts.addOption( op );
249         op = new Option( "i", "install-path", true, "path to apacheds installation directory" );
250         op.setRequired( true );
251         opts.addOption( op );
252         return opts;
253     }
254 }