1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.tools;
21
22
23 import java.io.File;
24 import java.io.FileWriter;
25 import java.io.IOException;
26 import java.io.PrintWriter;
27 import java.util.ArrayList;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Set;
31
32 import javax.naming.NamingEnumeration;
33 import javax.naming.directory.Attribute;
34 import javax.naming.directory.Attributes;
35
36 import jdbm.helper.MRU;
37 import jdbm.recman.BaseRecordManager;
38 import jdbm.recman.CacheRecordManager;
39
40 import org.apache.commons.cli.CommandLine;
41 import org.apache.commons.cli.Option;
42 import org.apache.commons.cli.Options;
43 import org.apache.directory.server.constants.ServerDNConstants;
44 import org.apache.directory.server.core.DefaultDirectoryService;
45 import org.apache.directory.server.core.DirectoryService;
46 import org.apache.directory.server.core.cursor.Cursor;
47 import org.apache.directory.server.core.entry.ServerEntry;
48 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
49 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmMasterTable;
50 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
51 import org.apache.directory.server.core.schema.PartitionSchemaLoader;
52 import org.apache.directory.server.schema.SerializableComparator;
53 import org.apache.directory.server.schema.bootstrap.ApacheSchema;
54 import org.apache.directory.server.schema.bootstrap.ApachemetaSchema;
55 import org.apache.directory.server.schema.bootstrap.BootstrapSchemaLoader;
56 import org.apache.directory.server.schema.bootstrap.CoreSchema;
57 import org.apache.directory.server.schema.bootstrap.Schema;
58 import org.apache.directory.server.schema.bootstrap.SystemSchema;
59 import org.apache.directory.server.schema.bootstrap.partition.DbFileListing;
60 import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
61 import org.apache.directory.server.schema.registries.DefaultOidRegistry;
62 import org.apache.directory.server.schema.registries.DefaultRegistries;
63 import org.apache.directory.server.schema.registries.OidRegistry;
64 import org.apache.directory.server.schema.registries.Registries;
65 import org.apache.directory.server.xdbm.Index;
66 import org.apache.directory.server.xdbm.Tuple;
67 import org.apache.directory.shared.ldap.MultiException;
68 import org.apache.directory.shared.ldap.exception.LdapConfigurationException;
69 import org.apache.directory.shared.ldap.exception.LdapNamingException;
70 import org.apache.directory.shared.ldap.ldif.LdifUtils;
71 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
72 import org.apache.directory.shared.ldap.schema.AttributeType;
73 import org.apache.directory.shared.ldap.schema.UsageEnum;
74 import org.apache.directory.shared.ldap.util.Base64;
75
76
77
78
79
80
81
82
83 public class DumpCommand extends ToolCommand
84 {
85 private Registries bootstrapRegistries = new DefaultRegistries( "bootstrap", new BootstrapSchemaLoader(),
86 new DefaultOidRegistry() );
87 private Set exclusions = new HashSet();
88 private boolean includeOperational = false;
89
90
91 public DumpCommand()
92 {
93 super( "dump" );
94 }
95
96
97 private Registries loadRegistries() throws Exception
98 {
99
100
101
102
103
104 BootstrapSchemaLoader loader = new BootstrapSchemaLoader();
105 OidRegistry oidRegistry = new DefaultOidRegistry();
106 final Registries registries = new DefaultRegistries( "bootstrap", loader, oidRegistry );
107
108
109 Set<Schema> bootstrapSchemas = new HashSet<Schema>();
110 bootstrapSchemas.add( new ApachemetaSchema() );
111 bootstrapSchemas.add( new ApacheSchema() );
112 bootstrapSchemas.add( new CoreSchema() );
113 bootstrapSchemas.add( new SystemSchema() );
114 loader.loadWithDependencies( bootstrapSchemas, registries );
115
116
117 List<Throwable> errors = registries.checkRefInteg();
118
119 if ( !errors.isEmpty() )
120 {
121 MultiException e = new MultiException();
122 for ( Throwable t : errors )
123 {
124 e.addThrowable( t );
125 }
126
127 throw e;
128 }
129
130 SerializableComparator.setRegistry( registries.getComparatorRegistry() );
131
132
133
134
135
136
137 File schemaDirectory = new File( getLayout().getPartitionsDirectory(), "schema" );
138 if ( !schemaDirectory.exists() )
139 {
140 throw new LdapConfigurationException( "The following schema directory from "
141 + "the installation layout could not be found:\n\t" + schemaDirectory );
142 }
143
144 JdbmPartition schemaPartition = new JdbmPartition();
145 schemaPartition.setId( "schema" );
146 schemaPartition.setCacheSize( 1000 );
147
148 DbFileListing listing;
149 try
150 {
151 listing = new DbFileListing();
152 }
153 catch ( IOException e )
154 {
155 throw new LdapNamingException( "Got IOException while trying to read DBFileListing: " + e.getMessage(),
156 ResultCodeEnum.OTHER );
157 }
158
159 Set<Index<?,ServerEntry>> indexedAttributes = new HashSet<Index<?,ServerEntry>>();
160
161 for ( String attributeId : listing.getIndexedAttributes() )
162 {
163 indexedAttributes.add( new JdbmIndex( attributeId ) );
164 }
165
166 schemaPartition.setIndexedAttributes( indexedAttributes );
167 schemaPartition.setSuffix( ServerDNConstants.OU_SCHEMA_DN );
168
169 DirectoryService directoryService = new DefaultDirectoryService();
170 schemaPartition.init( directoryService );
171
172
173
174
175
176 PartitionSchemaLoader schemaLoader = new PartitionSchemaLoader( schemaPartition, registries );
177 Registries globalRegistries = new DefaultRegistries( "global", schemaLoader, oidRegistry );
178 schemaLoader.loadEnabled( globalRegistries );
179 SerializableComparator.setRegistry( globalRegistries.getComparatorRegistry() );
180 return globalRegistries;
181 }
182
183
184 public void execute( CommandLine cmdline ) throws Exception
185 {
186 getLayout().verifyInstallation();
187 bootstrapRegistries = loadRegistries();
188
189 includeOperational = cmdline.hasOption( 'o' );
190 String[] partitions = cmdline.getOptionValues( 'p' );
191 String outputFile = cmdline.getOptionValue( 'f' );
192 PrintWriter out = null;
193
194 String[] excludedAttributes = cmdline.getOptionValues( 'e' );
195 if ( excludedAttributes != null )
196 {
197 AttributeTypeRegistry registry = bootstrapRegistries.getAttributeTypeRegistry();
198 for ( int ii = 0; ii < excludedAttributes.length; ii++ )
199 {
200 AttributeType type = registry.lookup( excludedAttributes[ii] );
201 exclusions.add( type.getName() );
202 }
203 }
204
205 if ( outputFile == null )
206 {
207 out = new PrintWriter( System.out );
208 }
209 else
210 {
211 out = new PrintWriter( new FileWriter( outputFile ) );
212 }
213
214 for ( int ii = 0; ii < partitions.length; ii++ )
215 {
216 File partitionDirectory = new File( getLayout().getPartitionsDirectory(), partitions[ii] );
217 out.println( "\n\n" );
218 dump( partitionDirectory, out );
219 }
220 }
221
222
223 private void dump( File partitionDirectory, PrintWriter out ) throws Exception
224 {
225 if ( !partitionDirectory.exists() )
226 {
227 System.err.println( "Partition directory " + partitionDirectory + " does not exist!" );
228 System.exit( 1 );
229 }
230
231 out.println( "# ========================================================================" );
232 out.println( "# ApacheDS Tools Version: " + getVersion() );
233 out.println( "# Partition Directory: " + partitionDirectory );
234 out.println( "# ========================================================================\n\n" );
235
236 String path = partitionDirectory.getPath() + File.separator + "master";
237 BaseRecordManager base = new BaseRecordManager( path );
238 base.disableTransactions();
239 CacheRecordManager recMan = new CacheRecordManager( base, new MRU( 1000 ) );
240
241 JdbmMasterTable<ServerEntry> master = new JdbmMasterTable<ServerEntry>( recMan, bootstrapRegistries );
242 AttributeType attributeType = bootstrapRegistries.getAttributeTypeRegistry().lookup( "apacheUpdn" );
243 JdbmIndex idIndex = new JdbmIndex();
244 idIndex.setAttributeId( attributeType.getName() );
245 idIndex.setWkDirPath( partitionDirectory );
246 idIndex.setCacheSize( 1000 );
247 idIndex.setNumDupLimit( 1000 );
248 idIndex.init( attributeType, partitionDirectory );
249
250 out.println( "#---------------------" );
251 Cursor<Tuple<Long,ServerEntry>> list = master.cursor();
252 StringBuffer buf = new StringBuffer();
253 while ( list.next() )
254 {
255 Tuple<Long,ServerEntry> tuple = list.get();
256 Long id = tuple.getKey();
257 String dn = ( String ) idIndex.reverseLookup( id );
258 Attributes entry = ( Attributes ) tuple.getValue();
259
260 filterAttributes( dn, entry );
261
262 buf.append( "# Entry: " ).append( id ).append( "\n#---------------------\n\n" );
263 if ( !LdifUtils.isLDIFSafe( dn ) )
264 {
265
266
267 buf.append( "dn:: " ).append( new String( Base64.encode( dn.getBytes() ) ) );
268 }
269 else
270 {
271 buf.append( "dn: " ).append( dn );
272 }
273 buf.append( "\n" ).append( LdifUtils.convertToLdif( entry ) );
274 if ( list.next() )
275 {
276 buf.append( "\n\n#---------------------\n" );
277 }
278 out.print( buf.toString() );
279 out.flush();
280 buf.setLength( 0 );
281 }
282 }
283
284
285 private void filterAttributes( String dn, Attributes entry ) throws Exception
286 {
287 List toRemove = new ArrayList();
288 AttributeTypeRegistry registry = bootstrapRegistries.getAttributeTypeRegistry();
289 NamingEnumeration attrs = entry.getAll();
290 while ( attrs.hasMore() )
291 {
292 Attribute attr = ( Attribute ) attrs.next();
293 if ( !registry.hasAttributeType( attr.getID() ) )
294 {
295 if ( !isQuietEnabled() )
296 {
297 System.out
298 .println( "# Cannot properly filter unrecognized attribute " + attr.getID() + " in " + dn );
299 }
300 continue;
301 }
302
303 AttributeType type = registry.lookup( attr.getID() );
304 boolean isOperational = type.getUsage() != UsageEnum.USER_APPLICATIONS;
305 if ( exclusions.contains( attr.getID() ) || ( isOperational && ( !includeOperational ) ) )
306 {
307 toRemove.add( attr.getID() );
308 }
309 }
310 for ( int ii = 0; ii < toRemove.size(); ii++ )
311 {
312 String id = ( String ) toRemove.get( ii );
313 entry.remove( id );
314 if ( isDebugEnabled() )
315 {
316 System.out.println( "# Excluding attribute " + id + " in " + dn );
317 }
318 }
319 }
320
321
322 public Options getOptions()
323 {
324 Options opts = new Options();
325 Option op = new Option( "f", "file", true, "file to output the dump to" );
326 op.setRequired( false );
327 opts.addOption( op );
328 op = new Option( "p", "partitions", true, "the partitions to dump" );
329 op.setRequired( true );
330 op.setValueSeparator( File.pathSeparatorChar );
331 opts.addOption( op );
332 op = new Option( "e", "excluded-attributes", true, "the attributes to exclude" );
333 op.setRequired( false );
334 op.setValueSeparator( File.pathSeparatorChar );
335 opts.addOption( op );
336 op = new Option( "o", "include-operational", false, "include operational attributes: defaults to false" );
337 op.setRequired( false );
338 opts.addOption( op );
339 op = new Option( "i", "install-path", true, "path to apacheds installation directory" );
340 op.setRequired( true );
341 opts.addOption( op );
342 return opts;
343 }
344 }