1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.jdtaus.banking.dtaus.ri.zka;
22
23 import java.io.EOFException;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.RandomAccessFile;
27 import java.util.Iterator;
28 import java.util.Locale;
29 import java.util.Map;
30 import org.jdtaus.banking.dtaus.CorruptedException;
31 import org.jdtaus.banking.dtaus.PhysicalFile;
32 import org.jdtaus.banking.dtaus.PhysicalFileException;
33 import org.jdtaus.banking.dtaus.PhysicalFileFactory;
34 import org.jdtaus.banking.dtaus.spi.Fields;
35 import org.jdtaus.banking.messages.IllegalDataMessage;
36 import org.jdtaus.banking.messages.IllegalFileLengthMessage;
37 import org.jdtaus.core.container.ContainerFactory;
38 import org.jdtaus.core.container.Implementation;
39 import org.jdtaus.core.container.ModelFactory;
40 import org.jdtaus.core.container.PropertyException;
41 import org.jdtaus.core.io.FileOperations;
42 import org.jdtaus.core.io.util.CoalescingFileOperations;
43 import org.jdtaus.core.io.util.RandomAccessFileOperations;
44 import org.jdtaus.core.io.util.ReadAheadFileOperations;
45 import org.jdtaus.core.nio.util.Charsets;
46 import org.jdtaus.core.text.Message;
47
48
49
50
51
52
53
54 public final class DefaultPhysicalFileFactory implements PhysicalFileFactory
55 {
56
57
58
59
60
61
62
63
64
65 public static final String ATTRIBUTE_READAHEAD_CACHING =
66 DefaultPhysicalFileFactory.class.getName() + ".readAheadCaching";
67
68
69
70
71
72
73
74
75
76 public static final String ATTRIBUTE_READAHEAD_CACHESIZE =
77 DefaultPhysicalFileFactory.class.getName() + ".readAheadCacheSize";
78
79
80
81
82
83
84
85
86
87 public static final String ATTRIBUTE_COALESCING_CACHING =
88 DefaultPhysicalFileFactory.class.getName() + ".coalescingCaching";
89
90
91
92
93
94
95
96
97
98
99 public static final String ATTRIBUTE_COALESCING_BLOCKSIZE =
100 DefaultPhysicalFileFactory.class.getName() + ".coalescingBlockSize";
101
102
103
104
105
106
107
108
109
110
111 public static final String ATTRIBUTE_SPACE_CHARACTERS_ALLOWED =
112 DefaultPhysicalFileFactory.class.getName() + ".spaceCharactersAllowed.";
113
114
115 private Implementation implementation;
116
117 public int analyse( final File file ) throws PhysicalFileException, IOException
118 {
119 if ( file == null )
120 {
121 throw new NullPointerException( "file" );
122 }
123
124 this.assertValidProperties();
125 final FileOperations ops = new RandomAccessFileOperations( new RandomAccessFile( file, "r" ) );
126 final int format = this.analyse( ops );
127 ops.close();
128 return format;
129 }
130
131 public int analyse( final FileOperations fileOperations ) throws PhysicalFileException, IOException
132 {
133 int blockSize = 128;
134 long remainder = 0;
135 int read = 0;
136 int ret = FORMAT_DISK;
137 int total = 0;
138
139 final Message[] messages;
140 final byte[] buf = new byte[ 4 ];
141 final String str;
142 final long length;
143
144 if ( fileOperations == null )
145 {
146 throw new NullPointerException( "fileOperations" );
147 }
148
149 this.assertValidProperties();
150 length = fileOperations.getLength();
151 try
152 {
153 ThreadLocalMessages.getMessages().clear();
154 ThreadLocalMessages.setErrorsEnabled( false );
155
156 if ( length >= 128 )
157 {
158
159 fileOperations.setFilePointer( 0L );
160 do
161 {
162 read = fileOperations.read( buf, total, buf.length - total );
163 if ( read == FileOperations.EOF )
164 {
165 throw new EOFException();
166 }
167 else
168 {
169 total += read;
170 }
171 }
172 while ( total < buf.length );
173
174
175 str = Charsets.decode( buf, "ISO646-DE" );
176 if ( "0128".equals( str ) )
177 {
178 remainder = length % blockSize;
179 }
180 else
181 {
182 final int size = ( ( buf[0] & 0xFF ) << 8 ) | ( buf[1] & 0xFF );
183 if ( size == 150 )
184 {
185 ret = FORMAT_TAPE;
186 blockSize = 150;
187 remainder = 0;
188 }
189 else
190 {
191 if ( ThreadLocalMessages.isErrorsEnabled() )
192 {
193 throw new CorruptedException( this.getImplementation(), 0L );
194 }
195 else
196 {
197 final Message msg = new IllegalDataMessage(
198 Fields.FIELD_A1, IllegalDataMessage.TYPE_CONSTANT, 0L, str );
199
200 ThreadLocalMessages.getMessages().addMessage( msg );
201 }
202 }
203 }
204 }
205 else
206 {
207 if ( ThreadLocalMessages.isErrorsEnabled() )
208 {
209 throw new CorruptedException( this.getImplementation(), length );
210 }
211 else
212 {
213 final Message msg = new IllegalFileLengthMessage( length, blockSize );
214 ThreadLocalMessages.getMessages().addMessage( msg );
215 }
216 }
217
218 if ( remainder > 0 )
219 {
220 if ( ThreadLocalMessages.isErrorsEnabled() )
221 {
222 throw new CorruptedException( this.getImplementation(), length );
223 }
224 else
225 {
226 final Message msg = new IllegalFileLengthMessage( length, blockSize );
227 ThreadLocalMessages.getMessages().addMessage( msg );
228 }
229 }
230
231 messages = ThreadLocalMessages.getMessages().getMessages();
232 if ( messages.length > 0 )
233 {
234 throw new PhysicalFileException( messages );
235 }
236
237 return ret;
238 }
239 finally
240 {
241 ThreadLocalMessages.setErrorsEnabled( true );
242 }
243 }
244
245 public PhysicalFile createPhysicalFile( final File file, final int format )
246 throws IOException
247 {
248 return this.createPhysicalFile( file, format, this.getDefaultProperties() );
249 }
250
251 public PhysicalFile createPhysicalFile( final File file, final int format, final java.util.Properties properties )
252 throws IOException
253 {
254 if ( file == null )
255 {
256 throw new NullPointerException( "file" );
257 }
258
259 this.assertValidProperties();
260 this.assertValidProperties( properties );
261
262 FileOperations ops = new RandomAccessFileOperations( new RandomAccessFile( file, "rw" ) );
263 ops = this.configureCoalescingCaching( ops, properties );
264 return this.createPhysicalFile( ops, format, properties );
265 }
266
267 public PhysicalFile createPhysicalFile(
268 final FileOperations ops, final int format ) throws IOException
269 {
270 return this.createPhysicalFile( ops, format,
271 this.getDefaultProperties() );
272
273 }
274
275 public PhysicalFile createPhysicalFile( FileOperations ops, final int format, final java.util.Properties properties )
276 throws IOException
277 {
278 if ( ops == null )
279 {
280 throw new NullPointerException( "ops" );
281 }
282 if ( format != FORMAT_DISK && format != FORMAT_TAPE )
283 {
284 throw new IllegalArgumentException( Integer.toString( format ) );
285 }
286
287 this.assertValidProperties();
288 this.assertValidProperties( properties );
289
290 try
291 {
292 ops.setLength( 0L );
293 return this.getPhysicalFile( ops, format, properties );
294 }
295 catch ( PhysicalFileException e )
296 {
297 throw new AssertionError( e );
298 }
299 }
300
301 public PhysicalFile getPhysicalFile( final File file ) throws PhysicalFileException, IOException
302 {
303 return this.getPhysicalFile( file, this.getDefaultProperties() );
304 }
305
306 public PhysicalFile getPhysicalFile( final FileOperations ops ) throws PhysicalFileException, IOException
307 {
308 return this.getPhysicalFile( ops, this.getDefaultProperties() );
309 }
310
311 public PhysicalFile getPhysicalFile( final FileOperations ops, final java.util.Properties properties )
312 throws PhysicalFileException, IOException
313 {
314 if ( ops == null )
315 {
316 throw new NullPointerException( "ops" );
317 }
318
319 this.assertValidProperties();
320 this.assertValidProperties( properties );
321 return this.getPhysicalFile( ops, this.getDefaultFormat(), properties );
322 }
323
324 public PhysicalFile getPhysicalFile( final File file, final java.util.Properties properties )
325 throws PhysicalFileException, IOException
326 {
327 if ( file == null )
328 {
329 throw new NullPointerException( "file" );
330 }
331
332 this.assertValidProperties();
333 this.assertValidProperties( properties );
334
335 FileOperations ops = new RandomAccessFileOperations( new RandomAccessFile( file, "rw" ) );
336 ops = this.configureReadAheadCaching( ops, properties );
337 return this.getPhysicalFile( ops, properties );
338 }
339
340
341
342
343
344
345 private void assertValidProperties()
346 {
347 final int defaultFormat = this.getDefaultFormat();
348 if ( defaultFormat != FORMAT_DISK && defaultFormat != FORMAT_TAPE )
349 {
350 throw new PropertyException( "defaultFormat", new Integer( defaultFormat ) );
351 }
352 }
353
354
355
356
357
358
359
360
361
362 private void assertValidProperties( final java.util.Properties properties )
363 {
364 if ( properties == null )
365 {
366 throw new NullPointerException( "properties" );
367 }
368
369 for ( Iterator it = properties.entrySet().iterator(); it.hasNext(); )
370 {
371 final Map.Entry entry = (Map.Entry) it.next();
372 final String name = (String) entry.getKey();
373 final String value = (String) entry.getValue();
374
375 if ( name.startsWith( ATTRIBUTE_SPACE_CHARACTERS_ALLOWED ) )
376 {
377 try
378 {
379 Integer.parseInt( name.substring( name.lastIndexOf( '.' ) + 1 ), 16 );
380 }
381 catch ( NumberFormatException e )
382 {
383 throw (IllegalArgumentException) new IllegalArgumentException(
384 name + ": " + e.getMessage() ).initCause( e );
385
386 }
387 }
388
389 if ( value != null && ( ATTRIBUTE_READAHEAD_CACHESIZE.equals( name ) ||
390 ATTRIBUTE_COALESCING_BLOCKSIZE.equals( name ) ) )
391 {
392 try
393 {
394 Integer.parseInt( value );
395 }
396 catch ( NumberFormatException e )
397 {
398 throw (IllegalArgumentException) new IllegalArgumentException( this.getIllegalAttributeTypeMessage(
399 this.getLocale(), name, ( value != null ? value.getClass().getName() : null ),
400 Integer.class.getName() ) ).initCause( e );
401
402 }
403 }
404 }
405 }
406
407 private java.util.Properties getDefaultProperties()
408 {
409 final java.util.Properties properties = new java.util.Properties();
410 properties.setProperty( ATTRIBUTE_READAHEAD_CACHING, Boolean.toString( true ) );
411 properties.setProperty( ATTRIBUTE_COALESCING_CACHING, Boolean.toString( true ) );
412 return properties;
413 }
414
415 private FileOperations configureReadAheadCaching( FileOperations ops, final java.util.Properties properties )
416 throws IOException
417 {
418 final String readAheadCaching = properties.getProperty( ATTRIBUTE_READAHEAD_CACHING );
419 final String readAheadCacheSize = properties.getProperty( ATTRIBUTE_READAHEAD_CACHESIZE );
420 final boolean isReadAheadCaching =
421 readAheadCaching != null && Boolean.valueOf( readAheadCaching ).booleanValue();
422
423 if ( isReadAheadCaching )
424 {
425 if ( readAheadCacheSize != null )
426 {
427 ops = new ReadAheadFileOperations( ops, Integer.parseInt( readAheadCacheSize ) );
428 }
429 else
430 {
431 ops = new ReadAheadFileOperations( ops );
432 }
433 }
434
435 return ops;
436 }
437
438 private FileOperations configureCoalescingCaching( FileOperations ops, final java.util.Properties properties )
439 throws IOException
440 {
441 final String coalescingCaching = properties.getProperty( ATTRIBUTE_COALESCING_CACHING );
442 final String coalescingBlockSize = properties.getProperty( ATTRIBUTE_COALESCING_BLOCKSIZE );
443 final boolean isCoalescingCaching =
444 coalescingCaching != null && Boolean.valueOf( coalescingCaching ).booleanValue();
445
446 if ( isCoalescingCaching )
447 {
448 if ( coalescingBlockSize != null )
449 {
450 ops = new CoalescingFileOperations( ops, Integer.parseInt( coalescingBlockSize ) );
451 }
452 else
453 {
454 ops = new CoalescingFileOperations( ops );
455 }
456 }
457
458 return ops;
459 }
460
461 private PhysicalFile getPhysicalFile( final FileOperations ops, int format, final java.util.Properties properties )
462 throws PhysicalFileException, IOException
463 {
464 if ( ops == null )
465 {
466 throw new NullPointerException( "ops" );
467 }
468 if ( format != FORMAT_DISK && format != FORMAT_TAPE )
469 {
470 throw new IllegalArgumentException( Integer.toString( format ) );
471 }
472
473 this.assertValidProperties( properties );
474
475 final DefaultPhysicalFile ret;
476 final Message[] messages;
477 format = ops.getLength() > 0 ? this.analyse( ops ) : format;
478
479 try
480 {
481 ThreadLocalMessages.getMessages().clear();
482 ThreadLocalMessages.setErrorsEnabled( false );
483 ret = new DefaultPhysicalFile( format, ops, properties );
484 messages = ThreadLocalMessages.getMessages().getMessages();
485 if ( messages.length > 0 )
486 {
487 throw new PhysicalFileException( messages );
488 }
489
490 return ret;
491 }
492 finally
493 {
494 ThreadLocalMessages.setErrorsEnabled( true );
495 }
496 }
497
498 protected Implementation getImplementation()
499 {
500 if ( this.implementation == null )
501 {
502 this.implementation = ModelFactory.getModel().getModules().
503 getImplementation( DefaultPhysicalFileFactory.class.getName() );
504
505 }
506
507 return this.implementation;
508 }
509
510
511
512
513
514
515
516 public DefaultPhysicalFileFactory()
517 {
518 super();
519 }
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534 private int getDefaultFormat()
535 {
536 return ( (java.lang.Integer) ContainerFactory.getContainer().
537 getProperty( this, "defaultFormat" ) ).intValue();
538
539 }
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554 private Locale getLocale()
555 {
556 return (Locale) ContainerFactory.getContainer().
557 getDependency( this, "Locale" );
558
559 }
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581 private String getIllegalAttributeTypeMessage( final Locale locale,
582 final java.lang.String attributeName,
583 final java.lang.String typeName,
584 final java.lang.String expectedTypeName )
585 {
586 return ContainerFactory.getContainer().
587 getMessage( this, "illegalAttributeType", locale,
588 new Object[]
589 {
590 attributeName,
591 typeName,
592 expectedTypeName
593 });
594
595 }
596
597
598
599
600 }