1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.ldap.schema.extractor.impl;
21
22
23 import java.io.File;
24 import java.io.FileNotFoundException;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InvalidObjectException;
28 import java.io.OutputStream;
29 import java.io.OutputStreamWriter;
30 import java.io.Writer;
31 import java.net.URL;
32 import java.nio.charset.Charset;
33 import java.nio.file.Files;
34 import java.nio.file.Paths;
35 import java.util.ArrayDeque;
36 import java.util.Deque;
37 import java.util.Enumeration;
38 import java.util.Map;
39 import java.util.Map.Entry;
40 import java.util.UUID;
41 import java.util.regex.Pattern;
42
43 import org.apache.directory.api.i18n.I18n;
44 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
45 import org.apache.directory.api.ldap.model.exception.LdapException;
46 import org.apache.directory.api.ldap.model.ldif.LdifEntry;
47 import org.apache.directory.api.ldap.model.ldif.LdifReader;
48 import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
49 import org.apache.directory.api.ldap.schema.extractor.UniqueResourceException;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53
54
55
56
57
58
59 public class DefaultSchemaLdifExtractor implements SchemaLdifExtractor
60 {
61
62 private static final String BASE_PATH = "";
63
64
65 private static final String SCHEMA_SUBDIR = "schema";
66
67
68 private static final Logger LOG = LoggerFactory.getLogger( DefaultSchemaLdifExtractor.class );
69
70
71
72
73
74 private static final Pattern EXTRACT_PATTERN = Pattern.compile( ".*schema" + "[/\\Q\\\\E]" + "ou=schema.*\\.ldif" );
75
76
77 private boolean extracted;
78
79
80 private File outputDirectory;
81
82
83
84
85
86
87
88
89 public DefaultSchemaLdifExtractor( File outputDirectory )
90 {
91 LOG.debug( "BASE_PATH set to {}, outputDirectory set to {}", BASE_PATH, outputDirectory );
92 this.outputDirectory = outputDirectory;
93 File schemaDirectory = new File( outputDirectory, SCHEMA_SUBDIR );
94
95 if ( !outputDirectory.exists() )
96 {
97 LOG.debug( "Creating output directory: {}", outputDirectory );
98 if ( !outputDirectory.mkdir() )
99 {
100 LOG.error( "Failed to create outputDirectory: {}", outputDirectory );
101 }
102 }
103 else
104 {
105 LOG.debug( "Output directory exists: no need to create." );
106 }
107
108 if ( !schemaDirectory.exists() )
109 {
110 LOG.info( "Schema directory '{}' does NOT exist: extracted state set to false.", schemaDirectory );
111 extracted = false;
112 }
113 else
114 {
115 LOG.info( "Schema directory '{}' does exist: extracted state set to true.", schemaDirectory );
116 extracted = true;
117 }
118 }
119
120
121
122
123
124
125
126 @Override
127 public boolean isExtracted()
128 {
129 return extracted;
130 }
131
132
133
134
135
136
137
138
139 @Override
140 public void extractOrCopy( boolean overwrite ) throws IOException
141 {
142 if ( !outputDirectory.exists() && !outputDirectory.mkdirs() )
143 {
144 throw new IOException( I18n.err( I18n.ERR_09001_DIRECTORY_CREATION_FAILED, outputDirectory
145 .getAbsolutePath() ) );
146 }
147
148 File schemaDirectory = new File( outputDirectory, SCHEMA_SUBDIR );
149
150 if ( !schemaDirectory.exists() )
151 {
152 if ( !schemaDirectory.mkdirs() )
153 {
154 throw new IOException( I18n.err( I18n.ERR_09001_DIRECTORY_CREATION_FAILED, schemaDirectory
155 .getAbsolutePath() ) );
156 }
157 }
158 else if ( !overwrite )
159 {
160 throw new IOException( I18n.err( I18n.ERR_08001, schemaDirectory.getAbsolutePath() ) );
161 }
162
163 Map<String, Boolean> list = ResourceMap.getResources( EXTRACT_PATTERN );
164
165 for ( Entry<String, Boolean> entry : list.entrySet() )
166 {
167 if ( entry.getValue() )
168 {
169 extractFromClassLoader( entry.getKey() );
170 }
171 else
172 {
173 File resource = new File( entry.getKey() );
174 copyFile( resource, getDestinationFile( resource ) );
175 }
176 }
177 }
178
179
180
181
182
183
184
185
186
187 @Override
188 public void extractOrCopy() throws IOException
189 {
190 extractOrCopy( false );
191 }
192
193
194
195
196
197
198
199
200
201
202 private void copyFile( File source, File destination ) throws IOException
203 {
204 LOG.debug( "copyFile(): source = {}, destination = {}", source, destination );
205
206 if ( !destination.getParentFile().exists() && !destination.getParentFile().mkdirs() )
207 {
208 throw new IOException( I18n.err( I18n.ERR_09001_DIRECTORY_CREATION_FAILED, destination.getParentFile()
209 .getAbsolutePath() ) );
210 }
211
212 if ( !source.getParentFile().exists() )
213 {
214 throw new FileNotFoundException( I18n.err( I18n.ERR_08002, source.getAbsolutePath() ) );
215 }
216
217 try ( Writer out = new OutputStreamWriter( Files.newOutputStream( Paths.get( destination.getPath() ) ),
218 Charset.defaultCharset() );
219 LdifReader ldifReader = new LdifReader( source ) )
220 {
221 boolean first = true;
222 LdifEntry ldifEntry = null;
223
224 while ( ldifReader.hasNext() )
225 {
226 if ( first )
227 {
228 ldifEntry = ldifReader.next();
229
230 if ( ldifEntry.get( SchemaConstants.ENTRY_UUID_AT ) == null )
231 {
232
233 UUID entryUuid = UUID.randomUUID();
234 ldifEntry.addAttribute( SchemaConstants.ENTRY_UUID_AT, entryUuid.toString() );
235 }
236
237 first = false;
238 }
239 else
240 {
241
242 String msg = I18n.err( I18n.ERR_08003, source );
243 LOG.error( msg );
244 throw new InvalidObjectException( msg );
245 }
246 }
247
248
249 String ldifString;
250
251 if ( ldifEntry != null )
252 {
253 ldifString = "version: 1\n" + ldifEntry.toString();
254 }
255 else
256 {
257 ldifString = "version: 1\n";
258 }
259
260 out.write( ldifString );
261 out.flush();
262 }
263 catch ( LdapException le )
264 {
265 String msg = I18n.err( I18n.ERR_08004, source, le.getLocalizedMessage() );
266 LOG.error( msg );
267 throw new InvalidObjectException( msg );
268 }
269 }
270
271
272
273
274
275
276
277
278
279 private File assembleDestinationFile( Deque<String> fileComponentStack )
280 {
281 File destinationFile = outputDirectory.getAbsoluteFile();
282
283 while ( !fileComponentStack.isEmpty() )
284 {
285 destinationFile = new File( destinationFile, fileComponentStack.pop() );
286 }
287
288 return destinationFile;
289 }
290
291
292
293
294
295
296
297
298 private File getDestinationFile( File resource )
299 {
300 File parent = resource.getParentFile();
301 Deque<String> fileComponentStack = new ArrayDeque<>();
302 fileComponentStack.push( resource.getName() );
303
304 while ( parent != null )
305 {
306 if ( "schema".equals( parent.getName() ) )
307 {
308
309
310
311 fileComponentStack.push( "schema" );
312
313 return assembleDestinationFile( fileComponentStack );
314 }
315
316 fileComponentStack.push( parent.getName() );
317
318 if ( parent.equals( parent.getParentFile() ) || parent.getParentFile() == null )
319 {
320 throw new IllegalStateException( I18n.err( I18n.ERR_08005 ) );
321 }
322
323 parent = parent.getParentFile();
324 }
325
326 throw new IllegalStateException( I18n.err( I18n.ERR_08006 ) );
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340 public static InputStream getUniqueResourceAsStream( String resourceName, String resourceDescription )
341 throws IOException
342 {
343 URL result = getUniqueResource( BASE_PATH + resourceName, resourceDescription );
344 return result.openStream();
345 }
346
347
348
349
350
351
352
353
354
355
356 public static URL getUniqueResource( String resourceName, String resourceDescription ) throws IOException
357 {
358 Enumeration<URL> resources = DefaultSchemaLdifExtractor.class.getClassLoader().getResources( resourceName );
359 if ( !resources.hasMoreElements() )
360 {
361 throw new UniqueResourceException( resourceName, resourceDescription );
362 }
363 URL result = resources.nextElement();
364 if ( resources.hasMoreElements() )
365 {
366 throw new UniqueResourceException( resourceName, result, resources, resourceDescription );
367 }
368 return result;
369 }
370
371
372
373
374
375
376
377
378 private void extractFromClassLoader( String resource ) throws IOException
379 {
380 byte[] buf = new byte[512];
381 InputStream in = DefaultSchemaLdifExtractor.getUniqueResourceAsStream( resource,
382 "LDIF file in schema repository" );
383
384 try
385 {
386 File destination = new File( outputDirectory, resource );
387
388
389
390
391 if ( destination.exists() )
392 {
393 return;
394 }
395
396 if ( !destination.getParentFile().exists() && !destination.getParentFile().mkdirs() )
397 {
398 throw new IOException( I18n.err( I18n.ERR_09001_DIRECTORY_CREATION_FAILED, destination
399 .getParentFile().getAbsolutePath() ) );
400 }
401
402 OutputStream out = Files.newOutputStream( Paths.get( destination.getPath() ) );
403 try
404 {
405 while ( in.available() > 0 )
406 {
407 int readCount = in.read( buf );
408 out.write( buf, 0, readCount );
409 }
410 out.flush();
411 }
412 finally
413 {
414 out.close();
415 }
416 }
417 finally
418 {
419 in.close();
420 }
421 }
422 }