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.IOException;
24 import java.util.Iterator;
25 import java.util.Map;
26 import org.jdtaus.banking.dtaus.Checksum;
27 import org.jdtaus.banking.dtaus.Header;
28 import org.jdtaus.banking.dtaus.LogicalFile;
29 import org.jdtaus.banking.dtaus.PhysicalFile;
30 import org.jdtaus.banking.dtaus.PhysicalFileFactory;
31 import org.jdtaus.banking.dtaus.spi.HeaderValidator;
32 import org.jdtaus.banking.dtaus.spi.IllegalHeaderException;
33 import org.jdtaus.banking.messages.AnalysesFileMessage;
34 import org.jdtaus.core.container.ContainerFactory;
35 import org.jdtaus.core.io.FileOperations;
36 import org.jdtaus.core.monitor.spi.Task;
37 import org.jdtaus.core.monitor.spi.TaskMonitor;
38
39
40
41
42
43
44
45
46
47 public final class DefaultPhysicalFile implements PhysicalFile
48 {
49
50
51 private AbstractLogicalFile[] index;
52
53
54 private int dtausCount = 0;
55
56
57 private final java.util.Properties properties;
58
59
60 private FileOperations fileOperations;
61
62
63 private final int format;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public DefaultPhysicalFile(
80 final int format, final FileOperations fileOperations, final java.util.Properties properties )
81 throws IOException
82 {
83 super();
84
85 if ( fileOperations == null )
86 {
87 throw new NullPointerException( "fileOperations" );
88 }
89 if ( properties == null )
90 {
91 throw new NullPointerException( "properties" );
92 }
93 if ( format != PhysicalFileFactory.FORMAT_DISK && format != PhysicalFileFactory.FORMAT_TAPE )
94 {
95 throw new IllegalArgumentException( Integer.toString( format ) );
96 }
97
98 this.properties = properties;
99 this.fileOperations = fileOperations;
100 this.format = format;
101 this.checksum();
102 }
103
104 public int count()
105 {
106 return this.dtausCount;
107 }
108
109 public LogicalFile add( final Header header ) throws IOException
110 {
111 if ( header == null )
112 {
113 throw new NullPointerException( "header" );
114 }
115
116 IllegalHeaderException result = null;
117 final HeaderValidator[] validators = this.getHeaderValidator();
118
119 for ( int i = validators.length - 1; i >= 0; i-- )
120 {
121 result = validators[i].assertValidHeader( header, result );
122 }
123
124 if ( result != null && result.getMessages().length > 0 )
125 {
126 throw result;
127 }
128
129 this.resizeIndex( this.dtausCount );
130
131 final AbstractLogicalFile lFile = this.newLogicalFile(
132 ( this.dtausCount == 0 ? 0L : this.index[this.dtausCount - 1].getChecksumPosition() +
133 this.index[this.dtausCount - 1].getBlockSize() ) );
134
135 lFile.insertBytes( lFile.getHeaderPosition(), this.format * 2 );
136 lFile.writeHeader( header );
137 lFile.writeChecksum( new Checksum() );
138 lFile.checksum();
139 this.index[this.dtausCount] = lFile;
140 return this.index[this.dtausCount++];
141 }
142
143 public LogicalFile get( int dtausId )
144 {
145 if ( !this.checkLogicalFileExists( dtausId ) )
146 {
147 throw new IllegalArgumentException( "dtausId" );
148 }
149 return this.index[dtausId];
150 }
151
152 public void remove( int dtausId ) throws IOException
153 {
154 if ( !this.checkLogicalFileExists( dtausId ) )
155 {
156 throw new IllegalArgumentException( "dtausId" );
157 }
158
159 this.index[dtausId].removeBytes(
160 this.index[dtausId].getHeaderPosition(), this.index[dtausId].getChecksumPosition() -
161 this.index[dtausId].getHeaderPosition() + this.format );
162
163 System.arraycopy( this.index, dtausId + 1, this.index, dtausId, --this.dtausCount - dtausId );
164 }
165
166 public void commit() throws IOException
167 {
168 this.getFileOperations().close();
169 }
170
171 public int getLogicalFileCount() throws IOException
172 {
173 return this.count();
174 }
175
176 public LogicalFile addLogicalFile( final Header header ) throws IOException
177 {
178 return this.add( header );
179 }
180
181 public LogicalFile getLogicalFile( final int index ) throws IOException
182 {
183 return this.get( index );
184 }
185
186 public void removeLogicalFile( final int index ) throws IOException
187 {
188 this.remove( index );
189 }
190
191
192 private FileOperations getFileOperations()
193 {
194 return this.fileOperations;
195 }
196
197 private boolean checkLogicalFileExists( int dtausId )
198 {
199 return dtausId < this.dtausCount && dtausId >= 0;
200 }
201
202 private void checksum() throws IOException
203 {
204 this.dtausCount = 0;
205 int dtausIndex = 0;
206 final long length = this.getFileOperations().getLength();
207 long maximumProgress = length;
208 long progressDivisor = 1L;
209
210 while ( maximumProgress > Integer.MAX_VALUE )
211 {
212 maximumProgress /= 2L;
213 progressDivisor *= 2L;
214 }
215
216 final Task task = new Task();
217 task.setIndeterminate( false );
218 task.setCancelable( false );
219 task.setDescription( new AnalysesFileMessage() );
220 task.setMinimum( 0 );
221 task.setProgress( 0 );
222 task.setMaximum( (int) maximumProgress );
223
224 try
225 {
226 this.getTaskMonitor().monitor( task );
227
228 for ( long position = 0L; position < length;
229 position = this.index[dtausIndex].getChecksumPosition() + this.index[dtausIndex++].getBlockSize() )
230 {
231 task.setProgress( (int) ( position / progressDivisor ) );
232 this.resizeIndex( dtausIndex );
233 this.index[dtausIndex] = this.newLogicalFile( position );
234 this.index[dtausIndex].checksum();
235 this.dtausCount++;
236 }
237 }
238 finally
239 {
240 this.getTaskMonitor().finish( task );
241 }
242 }
243
244 private AbstractLogicalFile newLogicalFile( final long headerPosition ) throws IOException
245 {
246 final AbstractLogicalFile ret;
247
248 switch ( this.format )
249 {
250 case PhysicalFileFactory.FORMAT_DISK:
251 ret = new DTAUSDisk();
252 break;
253 case PhysicalFileFactory.FORMAT_TAPE:
254 ret = new DTAUSTape();
255 break;
256 default:
257 throw new IllegalStateException();
258
259 }
260
261 ret.setFileOperations( this.getFileOperations() );
262 ret.setHeaderPosition( headerPosition );
263 ret.setChecksumPosition( headerPosition + this.format );
264
265 for ( Iterator it = this.properties.entrySet().iterator(); it.hasNext(); )
266 {
267 final Map.Entry e = (Map.Entry) it.next();
268 final String key = (String) e.getKey();
269
270 if ( key.startsWith( DefaultPhysicalFileFactory.ATTRIBUTE_SPACE_CHARACTERS_ALLOWED ) )
271 {
272 int field = Integer.parseInt( key.substring( key.lastIndexOf( '.' ) + 1 ), 16 );
273 final boolean allowed =
274 e.getValue() != null && Boolean.valueOf( e.getValue().toString() ).booleanValue();
275
276 ret.getConfiguration().setSpaceCharacterAllowed( field, allowed );
277 }
278 }
279
280 ret.addListener( new AbstractLogicalFile.Listener()
281 {
282
283 public void bytesInserted( final long position, final long bytes ) throws IOException
284 {
285 final int fileIndex = this.getFileIndex( position );
286 if ( fileIndex >= 0 )
287 {
288
289 for ( int i = fileIndex + 1; i < dtausCount; i++ )
290 {
291 index[i].setHeaderPosition( index[i].getHeaderPosition() + bytes );
292 index[i].setChecksumPosition( index[i].getChecksumPosition() + bytes );
293 }
294 }
295 }
296
297 public void bytesDeleted( final long position, final long bytes ) throws IOException
298 {
299 final int fileIndex = this.getFileIndex( position );
300 if ( fileIndex >= 0 )
301 {
302
303 for ( int i = fileIndex + 1; i < dtausCount; i++ )
304 {
305 index[i].setHeaderPosition( index[i].getHeaderPosition() - bytes );
306 index[i].setChecksumPosition( index[i].getChecksumPosition() - bytes );
307 }
308 }
309 }
310
311 private int getFileIndex( final long position )
312 {
313 for ( int i = dtausCount - 1; i >= 0; i-- )
314 {
315 if ( position >= index[i].getHeaderPosition() && position <= index[i].getChecksumPosition() )
316 {
317 return i;
318 }
319 }
320
321 return -1;
322 }
323
324 } );
325
326 return ret;
327 }
328
329 private void resizeIndex( int index )
330 {
331 if ( this.index == null )
332 {
333 this.index = new AbstractLogicalFile[ index + 1 ];
334 }
335 else if ( this.index.length < index + 1 )
336 {
337 while ( this.index.length < index + 1 )
338 {
339 final int newLength = this.index.length * 2;
340 final AbstractLogicalFile[] newIndex = new AbstractLogicalFile[ newLength ];
341 System.arraycopy( this.index, 0, newIndex, 0, this.index.length );
342 this.index = newIndex;
343 }
344 }
345 }
346
347
348
349
350
351
352
353
354
355
356
357 private TaskMonitor getTaskMonitor()
358 {
359 return (TaskMonitor) ContainerFactory.getContainer().
360 getDependency( this, "TaskMonitor" );
361
362 }
363
364
365
366
367
368
369 private HeaderValidator[] getHeaderValidator()
370 {
371 return (HeaderValidator[]) ContainerFactory.getContainer().
372 getDependency( this, "HeaderValidator" );
373
374 }
375
376
377
378
379 }