EMMA Coverage Report (generated Tue Jan 14 02:29:45 CET 2014)
[all classes][org.jdtaus.core.io.util]

COVERAGE SUMMARY FOR SOURCE FILE [StructuredFileOperations.java]

nameclass, %method, %block, %line, %
StructuredFileOperations.java100% (1/1)75%  (24/32)56%  (624/1113)61%  (132.7/218)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class StructuredFileOperations100% (1/1)75%  (24/32)56%  (624/1113)61%  (132.7/218)
StructuredFileOperations (int, int, FileOperations): void 0%   (0/1)0%   (0/47)0%   (0/14)
addStructuredFileListener (StructuredFileListener): void 0%   (0/1)0%   (0/13)0%   (0/2)
close (): void 0%   (0/1)0%   (0/11)0%   (0/5)
getAlreadyClosedMessage (Locale): String 0%   (0/1)0%   (0/7)0%   (0/1)
getLocale (): Locale 0%   (0/1)0%   (0/6)0%   (0/1)
getStructuredFileListeners (): StructuredFileListener [] 0%   (0/1)0%   (0/14)0%   (0/1)
getTaskMonitor (): TaskMonitor 0%   (0/1)0%   (0/6)0%   (0/1)
removeStructuredFileListener (StructuredFileListener): void 0%   (0/1)0%   (0/13)0%   (0/2)
deleteBlocksImpl (long, long, long): void 100% (1/1)24%  (58/240)27%  (13/48)
assertNotClosed (): void 100% (1/1)33%  (4/12)67%  (2/3)
fireBlocksDeleted (long, long): void 100% (1/1)34%  (12/35)57%  (2.8/5)
fireBlocksInserted (long, long): void 100% (1/1)34%  (12/35)57%  (2.8/5)
assertValidFileLength (): void 100% (1/1)54%  (14/26)67%  (2/3)
assertValidArguments (long, int, byte [], int, int): void 100% (1/1)62%  (43/69)58%  (7/12)
getBuffer (int): byte [] 100% (1/1)64%  (30/47)74%  (4.4/6)
insertBlocks (long, long): void 100% (1/1)71%  (29/41)75%  (6/8)
StructuredFileOperations (int, FileOperations): void 100% (1/1)72%  (28/39)83%  (10/12)
deleteBlocks (long, long): void 100% (1/1)72%  (31/43)75%  (6/8)
<static initializer> 100% (1/1)80%  (12/15)80%  (0.8/1)
insertBlocksImpl (long, long, long): void 100% (1/1)83%  (188/226)89%  (41.1/46)
readBlock (long, int, byte [], int, int): void 100% (1/1)91%  (50/55)98%  (10.7/11)
flush (): void 100% (1/1)100% (11/11)100% (4/4)
getBlockCount (): long 100% (1/1)100% (21/21)100% (4/4)
getBlockSize (): int 100% (1/1)100% (3/3)100% (1/1)
getDefaultBufferSize (): int 100% (1/1)100% (7/7)100% (1/1)
getDefaultMonitoringThreshold (): Integer 100% (1/1)100% (6/6)100% (1/1)
getFileOperations (): FileOperations 100% (1/1)100% (3/3)100% (1/1)
getMemoryManager (): MemoryManager 100% (1/1)100% (6/6)100% (1/1)
getMonitoringThreshold (): int 100% (1/1)100% (11/11)100% (3/3)
readBlock (long, int, byte []): void 100% (1/1)100% (9/9)100% (2/2)
writeBlock (long, int, byte []): void 100% (1/1)100% (9/9)100% (2/2)
writeBlock (long, int, byte [], int, int): void 100% (1/1)100% (27/27)100% (5/5)

1/*
2 *  jDTAUS Core Utilities
3 *  Copyright (C) 2005 Christian Schulte
4 *  <cs@schulte.it>
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU Lesser General Public
8 *  License as published by the Free Software Foundation; either
9 *  version 2.1 of the License, or any later version.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *  Lesser General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Lesser General Public
17 *  License along with this library; if not, write to the Free Software
18 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 *
20 */
21package org.jdtaus.core.io.util;
22 
23import java.io.IOException;
24import java.math.BigDecimal;
25import java.util.Locale;
26import javax.swing.event.EventListenerList;
27import org.jdtaus.core.container.ContainerFactory;
28import org.jdtaus.core.io.FileOperations;
29import org.jdtaus.core.io.StructuredFile;
30import org.jdtaus.core.io.StructuredFileListener;
31import org.jdtaus.core.lang.spi.MemoryManager;
32import org.jdtaus.core.messages.DeletesBlocksMessage;
33import org.jdtaus.core.messages.InsertsBlocksMessage;
34import org.jdtaus.core.monitor.spi.Task;
35import org.jdtaus.core.monitor.spi.TaskMonitor;
36 
37/**
38 * {@code StructuredFile} implementation based on {@code FileOperations}.
39 * <p>Pre {@code FlushableFileOperations} and its implementations this
40 * implementation performed read-ahead caching. This behaviour got changed
41 * in favour of {@code ReadAheadFileOperations} and
42 * {@code CoalescingFileOperations} which are generalized replacements for any
43 * cacheing formerly performed by this implementation. Since this class does
44 * not implement any cacheing anymore, the {@link #flush()} method will write
45 * out pending changes of an underlying {@code FlushableFileOperations}
46 * implementation, if any, by calling the corresponding {@code flush()} method
47 * of that {@code FlushableFileOperations} instance.</p>
48 * <p>This implementation uses task monitoring for the {@code deleteBlocks()}
49 * and {@code insertBlocks()} methods. Task monitoring is controlled by
50 * property {@code monitoringThreshold} holding the number of bytes which
51 * need to minimally be copied to enable any task monitoring during the
52 * copy operation (defaults to 5242880 - 5MB).</p>
53 *
54 * <p><b>Note:</b><br>
55 * This implementation is not thread-safe and concurrent changes to the
56 * underlying {@code FileOperations} implementation are not supported.</p>
57 *
58 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
59 * @version $JDTAUS: StructuredFileOperations.java 8641 2012-09-27 06:45:17Z schulte $
60 *
61 * @see CoalescingFileOperations
62 * @see ReadAheadFileOperations
63 */
64public final class StructuredFileOperations implements StructuredFile
65{
66    //--Fields------------------------------------------------------------------
67 
68    /** Pre-allocated temporary buffer. */
69    private byte[] defaultBuffer;
70 
71    /** Caches the value of property blockCount. */
72    private long cachedBlockCount = NO_CACHED_BLOCKCOUNT;
73 
74    private static final long NO_CACHED_BLOCKCOUNT = Long.MIN_VALUE;
75 
76    /** List for {@code StructuredFileListener}s. */
77    private final EventListenerList fileListeners = new EventListenerList();
78 
79    /** Value of property {@code blockSize} as a {@code BigDecimal}. */
80    private final BigDecimal decimalBlockSize;
81 
82    //------------------------------------------------------------------Fields--
83    //--Dependencies------------------------------------------------------------
84 
85// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies
86    // This section is managed by jdtaus-container-mojo.
87 
88    /**
89     * Gets the configured <code>MemoryManager</code> implementation.
90     *
91     * @return The configured <code>MemoryManager</code> implementation.
92     */
93    private MemoryManager getMemoryManager()
94    {
95        return (MemoryManager) ContainerFactory.getContainer().
96            getDependency( this, "MemoryManager" );
97 
98    }
99 
100    /**
101     * Gets the configured <code>Locale</code> implementation.
102     *
103     * @return The configured <code>Locale</code> implementation.
104     */
105    private Locale getLocale()
106    {
107        return (Locale) ContainerFactory.getContainer().
108            getDependency( this, "Locale" );
109 
110    }
111 
112    /**
113     * Gets the configured <code>TaskMonitor</code> implementation.
114     *
115     * @return The configured <code>TaskMonitor</code> implementation.
116     */
117    private TaskMonitor getTaskMonitor()
118    {
119        return (TaskMonitor) ContainerFactory.getContainer().
120            getDependency( this, "TaskMonitor" );
121 
122    }
123 
124// </editor-fold>//GEN-END:jdtausDependencies
125 
126    //------------------------------------------------------------Dependencies--
127    //--Properties--------------------------------------------------------------
128 
129// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties
130    // This section is managed by jdtaus-container-mojo.
131 
132    /**
133     * Gets the value of property <code>defaultMonitoringThreshold</code>.
134     *
135     * @return Number of bytes which need to minimally be copied to enable any task monitoring during copy operations.
136     */
137    private java.lang.Integer getDefaultMonitoringThreshold()
138    {
139        return (java.lang.Integer) ContainerFactory.getContainer().
140            getProperty( this, "defaultMonitoringThreshold" );
141 
142    }
143 
144    /**
145     * Gets the value of property <code>defaultBufferSize</code>.
146     *
147     * @return Size of the pre-alocated default buffer in byte.
148     */
149    private int getDefaultBufferSize()
150    {
151        return ( (java.lang.Integer) ContainerFactory.getContainer().
152            getProperty( this, "defaultBufferSize" ) ).intValue();
153 
154    }
155 
156// </editor-fold>//GEN-END:jdtausProperties
157 
158    //--------------------------------------------------------------Properties--
159    //--StructuredFile----------------------------------------------------------
160 
161    public int getBlockSize()
162    {
163        return this.blockSize;
164    }
165 
166    public long getBlockCount() throws IOException
167    {
168        this.assertNotClosed();
169 
170        if ( this.cachedBlockCount == NO_CACHED_BLOCKCOUNT )
171        {
172            this.cachedBlockCount = BigDecimal.valueOf(
173                this.getFileOperations().getLength() ).divide(
174                this.decimalBlockSize, BigDecimal.ROUND_UNNECESSARY ).
175                longValue();
176 
177        // TODO JDK 1.5 longValueExact()
178        }
179 
180        return this.cachedBlockCount;
181    }
182 
183    public void deleteBlocks( final long index,
184                              final long count ) throws IOException
185    {
186        final long blockCount = this.getBlockCount();
187 
188        // Preconditions.
189        if ( index < 0L || index > blockCount - count )
190        {
191            throw new ArrayIndexOutOfBoundsException( (int) index );
192        }
193        if ( count <= 0 || count > blockCount - index )
194        {
195            throw new ArrayIndexOutOfBoundsException( (int) count );
196        }
197 
198        this.assertNotClosed();
199 
200        this.deleteBlocksImpl( index, count, blockCount );
201    }
202 
203    private void deleteBlocksImpl( final long index, final long count,
204                                   final long blockCount ) throws IOException
205    {
206        final long block = index + count;
207        final Task task = new Task();
208        long toMoveByte = ( blockCount - block ) * this.getBlockSize();
209        long readPos = block * this.getBlockSize();
210        long writePos = index * this.getBlockSize();
211        long progress = 0L;
212        long progressDivisor = 1L;
213        long maxProgress = toMoveByte;
214 
215        // Clear the cached block count.
216        this.cachedBlockCount = NO_CACHED_BLOCKCOUNT;
217 
218        // No blocks are following the ones to remove.
219        if ( toMoveByte == 0L )
220        {
221            this.getFileOperations().setLength(
222                this.getFileOperations().getLength() - count *
223                                                       this.getBlockSize() );
224 
225            this.fireBlocksDeleted( index, count );
226            return;
227        }
228 
229        final byte[] buf = this.getBuffer( toMoveByte > Integer.MAX_VALUE
230                                           ? Integer.MAX_VALUE
231                                           : (int) toMoveByte );
232 
233        while ( maxProgress > Integer.MAX_VALUE )
234        {
235            maxProgress /= 2L;
236            progressDivisor *= 2L;
237        }
238 
239        task.setIndeterminate( false );
240        task.setCancelable( false );
241        task.setMinimum( 0 );
242        task.setMaximum( (int) maxProgress );
243        task.setProgress( (int) progress );
244        task.setDescription( new DeletesBlocksMessage() );
245 
246        final boolean monitoring = toMoveByte > this.getMonitoringThreshold();
247        if ( monitoring )
248        {
249            this.getTaskMonitor().monitor( task );
250        }
251 
252        try
253        {
254            // Move following blocks to the position of the first block to
255            // remove.
256            while ( toMoveByte > 0L )
257            {
258                this.getFileOperations().setFilePointer( readPos );
259                final int len = toMoveByte <= buf.length
260                                ? (int) toMoveByte
261                                : buf.length;
262 
263                int read = 0;
264                int total = 0;
265                do
266                {
267                    read = this.getFileOperations().
268                        read( buf, total, len - total );
269 
270                    assert read != FileOperations.EOF :
271                        "Unexpected end of file.";
272 
273                    total += read;
274 
275                }
276                while ( total < len );
277 
278                // Move the block count blocks to the beginning.
279                this.getFileOperations().setFilePointer( writePos );
280                this.getFileOperations().write( buf, 0, len );
281 
282                readPos += len;
283                writePos += len;
284                toMoveByte -= len;
285                progress += len;
286 
287                task.setProgress( (int) ( progress / progressDivisor ) );
288            }
289 
290            // Truncate the file.
291            this.getFileOperations().setLength( this.getFileOperations().
292                getLength() - count *
293                              this.getBlockSize() );
294 
295            this.fireBlocksDeleted( index, count );
296        }
297        finally
298        {
299            if ( monitoring )
300            {
301                this.getTaskMonitor().finish( task );
302            }
303        }
304    }
305 
306    public void insertBlocks( final long index,
307                              final long count ) throws IOException
308    {
309        final long blockCount = this.getBlockCount();
310 
311        // Preconditions.
312        if ( index < 0L || index > blockCount )
313        {
314            throw new ArrayIndexOutOfBoundsException( (int) index );
315        }
316        if ( count <= 0L || count > Long.MAX_VALUE - blockCount )
317        {
318            throw new ArrayIndexOutOfBoundsException( (int) count );
319        }
320 
321        this.assertNotClosed();
322 
323        this.insertBlocksImpl( index, count, blockCount );
324    }
325 
326    private void insertBlocksImpl( final long index, final long count,
327                                   final long blockCount ) throws IOException
328    {
329        final Task task = new Task();
330        long toMoveByte = ( blockCount - index ) * this.getBlockSize();
331        long readPos = blockCount * this.getBlockSize();
332        long writePos = readPos + count * this.getBlockSize();
333        long progress = 0L;
334        long progressDivisor = 1L;
335        long maxProgress = toMoveByte;
336 
337        // Clear the cached block count.
338        this.cachedBlockCount = NO_CACHED_BLOCKCOUNT;
339 
340        // Increase the length of the file.
341        this.getFileOperations().setLength( this.getFileOperations().
342            getLength() + this.getBlockSize() *
343                          count );
344 
345        // New blocks are inserted at the end of the file.
346        if ( toMoveByte <= 0L )
347        {
348            this.fireBlocksInserted( index, count );
349            return;
350        }
351 
352        final byte[] buf = this.getBuffer( toMoveByte > Integer.MAX_VALUE
353                                           ? Integer.MAX_VALUE
354                                           : (int) toMoveByte );
355 
356        while ( maxProgress > Integer.MAX_VALUE )
357        {
358            maxProgress /= 2L;
359            progressDivisor *= 2L;
360        }
361 
362        task.setIndeterminate( false );
363        task.setCancelable( false );
364        task.setMinimum( 0 );
365        task.setMaximum( (int) maxProgress );
366        task.setProgress( (int) progress );
367        task.setDescription( new InsertsBlocksMessage() );
368 
369        final boolean monitoring = toMoveByte > this.getMonitoringThreshold();
370        if ( monitoring )
371        {
372            this.getTaskMonitor().monitor( task );
373        }
374 
375        try
376        {
377            // Move all blocks from index inclusive count blocks to the end of
378            // the file.
379            while ( toMoveByte > 0L )
380            {
381                final int moveLen = buf.length >= toMoveByte
382                                    ? (int) toMoveByte
383                                    : buf.length;
384 
385                readPos -= moveLen;
386                writePos -= moveLen;
387                this.getFileOperations().setFilePointer( readPos );
388                int read = 0;
389                int total = 0;
390 
391                do
392                {
393                    read = this.getFileOperations().
394                        read( buf, total, moveLen - total );
395 
396                    assert read != FileOperations.EOF :
397                        "Unexpected end of file.";
398 
399                    total += read;
400 
401                }
402                while ( total < moveLen );
403 
404                // Move the block count blocks to the end.
405                this.getFileOperations().setFilePointer( writePos );
406                this.getFileOperations().write( buf, 0, moveLen );
407 
408                toMoveByte -= moveLen;
409                progress += moveLen;
410 
411                task.setProgress( (int) ( progress / progressDivisor ) );
412            }
413 
414            this.fireBlocksInserted( index, count );
415        }
416        finally
417        {
418            if ( monitoring )
419            {
420                this.getTaskMonitor().finish( task );
421            }
422        }
423    }
424 
425    public void readBlock( final long block, final int off,
426                           final byte[] buf ) throws IOException
427    {
428        this.readBlock( block, off, buf, 0, buf.length );
429    }
430 
431    public void readBlock( final long block, final int off, final byte[] buf,
432                           final int index, final int length )
433        throws IOException
434    {
435        this.assertValidArguments( block, off, buf, index, length );
436        this.assertNotClosed();
437 
438        int totalRead = 0;
439        int toRead = length;
440 
441        this.getFileOperations().setFilePointer(
442            block * this.getBlockSize() + off );
443 
444        do
445        {
446            final int read = this.getFileOperations().
447                read( buf, index + totalRead, toRead );
448 
449            assert read != FileOperations.EOF :
450                "Unexpected end of file.";
451 
452            totalRead += read;
453            toRead -= read;
454 
455        }
456        while ( totalRead < length );
457    }
458 
459    public void writeBlock( final long block, final int off,
460                            final byte[] buf ) throws IOException
461    {
462        this.writeBlock( block, off, buf, 0, buf.length );
463    }
464 
465    public void writeBlock( final long block, final int off,
466                            final byte[] buf,
467                            final int index, final int length )
468        throws IOException
469    {
470        this.assertValidArguments( block, off, buf, index, length );
471        this.assertNotClosed();
472 
473        this.getFileOperations().setFilePointer(
474            block * this.getBlockSize() + off );
475 
476        this.getFileOperations().write( buf, index, length );
477    }
478 
479    /**
480     * {@inheritDoc}
481     * Flushes the instance and closes the {@code FileOperations} implementation
482     * backing the instance.
483     *
484     * @throws IOException if closing the {@code FileOperations} implementation
485     * backing the instance fails, or if the instance already is closed.
486     */
487    public void close() throws IOException
488    {
489        this.assertNotClosed();
490 
491        this.flush();
492        this.getFileOperations().close();
493        this.closed = true;
494    }
495 
496    public void addStructuredFileListener(
497        final StructuredFileListener listener )
498    {
499        this.fileListeners.add( StructuredFileListener.class, listener );
500    }
501 
502    public void removeStructuredFileListener(
503        final StructuredFileListener listener )
504    {
505        this.fileListeners.remove( StructuredFileListener.class, listener );
506    }
507 
508    public StructuredFileListener[] getStructuredFileListeners()
509    {
510        return (StructuredFileListener[]) this.fileListeners.getListeners(
511            StructuredFileListener.class );
512 
513    }
514 
515    //----------------------------------------------------------StructuredFile--
516    //--StructuredFileOperations------------------------------------------------
517 
518    /** Number of bytes per block. */
519    private int blockSize;
520 
521    /** Mininum number of bytes to copy to start any task monitoring. */
522    private Integer monitoringThreshold;
523 
524    /** {@code FileOperations} backing the instance. */
525    private FileOperations fileOperations;
526 
527    /** Flags the instance as beeing closed. */
528    private boolean closed;
529 
530    /**
531     * Creates a new {@code StructuredFileOperations} instance taking the size
532     * of one block in byte and the {@code FileOperations} operations are to be
533     * performed with.
534     *
535     * @param blockSize Number of bytes per block.
536     * @param fileOperations {@code FileOperations} implementation to operate
537     * on.
538     *
539     * @throws NullPointerException if {@code fileOperations} is {@code null}.
540     * @throws IllegalArgumentException if {@code blockSize} is incompatible
541     * with the length of {@code fileOperations}.
542     * @throws IOException if getting the length from the {@code fileOperations}
543     * fails.
544     */
545    public StructuredFileOperations( final int blockSize,
546                                     final FileOperations fileOperations )
547        throws IOException
548    {
549        super();
550 
551        if ( fileOperations == null )
552        {
553            throw new NullPointerException( "fileOperations" );
554        }
555        if ( blockSize <= 0 )
556        {
557            throw new IllegalArgumentException( Integer.toString( blockSize ) );
558        }
559 
560        this.blockSize = blockSize;
561        this.decimalBlockSize = BigDecimal.valueOf( blockSize );
562        this.fileOperations = fileOperations;
563        this.assertValidFileLength();
564    }
565 
566    /**
567     * Creates a new {@code StructuredFileOperations} instance taking the size
568     * of one block in byte, task monitoring configuration and the
569     * {@code FileOperations} operations are to be performed with.
570     *
571     * @param blockSize Number of bytes per block.
572     * @param monitoringThreshold the mininum number of bytes to copy to start
573     * any task monitoring.
574     * @param fileOperations {@code FileOperations} implementation to operate
575     * on.
576     *
577     * @throws NullPointerException if {@code fileOperations} is {@code null}.
578     * @throws IllegalArgumentException if {@code blockSize} is incompatible
579     * with the length of {@code fileOperations}.
580     * @throws IOException if getting the length from the {@code fileOperations}
581     * fails.
582     */
583    public StructuredFileOperations( final int blockSize,
584                                     final int monitoringThreshold,
585                                     final FileOperations fileOperations )
586        throws IOException
587    {
588        super();
589 
590        if ( fileOperations == null )
591        {
592            throw new NullPointerException( "fileOperations" );
593        }
594        if ( blockSize <= 0 )
595        {
596            throw new IllegalArgumentException( Integer.toString( blockSize ) );
597        }
598 
599        this.blockSize = blockSize;
600        this.decimalBlockSize = BigDecimal.valueOf( blockSize );
601        this.fileOperations = fileOperations;
602 
603        if ( monitoringThreshold > 0 )
604        {
605            this.monitoringThreshold = new Integer( monitoringThreshold );
606        }
607 
608        this.assertValidFileLength();
609    }
610 
611    /**
612     * Gets the {@code FileOperations} implementation operations are performed
613     * with.
614     *
615     * @return the {@code FileOperations} implementation operations are
616     * performed with.
617     */
618    public FileOperations getFileOperations()
619    {
620        return this.fileOperations;
621    }
622 
623    /**
624     * Calls the {@code flush()} method of an underlying
625     * {@code FlushableFileOperations} instance, if any.
626     *
627     * @throws IOException if reading or writing fails.
628     */
629    public void flush() throws IOException
630    {
631        this.assertNotClosed();
632 
633        if ( this.getFileOperations() instanceof FlushableFileOperations )
634        {
635            ( (FlushableFileOperations) this.getFileOperations() ).flush();
636        }
637    }
638 
639    /**
640     * Checks arguments provided to the {@code readBlock} and {@code writeBlock}
641     * methods.
642     *
643     * @throws NullPointerException if {@code buf} is {@code null}.
644     * @throws IndexOutOfBoundsException if {@code block} is negative,
645     * greater than or equal to {@code getBlockCount()}, or {@code off} is
646     * negative, greater than or equal to {@code getBlockSize()}, or
647     * {@code index} is negative, greater than or equal to the length of
648     * {@code buf}, or {@code length} is negative or greater than the
649     * length of {@code buf} minus {@code index} or greater than
650     * {@code getBlockSize() minus {@code off}.
651     */
652    private void assertValidArguments( final long block, final int off,
653                                       final byte[] buf, final int index,
654                                       final int length ) throws
655        NullPointerException, IndexOutOfBoundsException, IOException
656    {
657        final long blockCount = this.getBlockCount();
658 
659        if ( buf == null )
660        {
661            throw new NullPointerException( "buf" );
662        }
663        if ( block < 0 || block >= blockCount )
664        {
665            throw new ArrayIndexOutOfBoundsException( (int) block );
666        }
667        if ( off < 0 || off >= this.getBlockSize() )
668        {
669            throw new ArrayIndexOutOfBoundsException( off );
670        }
671        if ( index < 0 || index >= buf.length )
672        {
673            throw new ArrayIndexOutOfBoundsException( index );
674        }
675        if ( length < 0L || length > buf.length - index ||
676             length > this.getBlockSize() - off )
677        {
678            throw new ArrayIndexOutOfBoundsException( length );
679        }
680    }
681 
682    /**
683     * Checks the length of the provided {@code FileOperations} implementation
684     * against property {@code blockSize}.
685     *
686     * @throws IllegalArgumentException if the combination of property
687     * {@code blockSize} and {@code getFileOperations().getLength()} is invalid.
688     * @throws IOException if the getting the length fails.
689     */
690    private void assertValidFileLength() throws IOException
691    {
692        if ( this.getFileOperations() != null &&
693             this.getFileOperations().getLength() % this.getBlockSize() != 0L )
694        {
695            throw new IllegalArgumentException(
696                Long.toString( this.getFileOperations().getLength() %
697                               this.getBlockSize() ) );
698 
699        }
700    }
701 
702    /**
703     * Checks that the instance is not closed.
704     *
705     * @throws IOException if the instance is closed.
706     */
707    private void assertNotClosed() throws IOException
708    {
709        if ( this.closed )
710        {
711            throw new IOException( this.getAlreadyClosedMessage(
712                this.getLocale() ) );
713 
714        }
715    }
716 
717    /**
718     * Gets the value of property {@code monitoringThreshold}.
719     *
720     * @return the mininum number of bytes to copy to start any task monitoring.
721     */
722    public int getMonitoringThreshold()
723    {
724        if ( this.monitoringThreshold == null )
725        {
726            this.monitoringThreshold = this.getDefaultMonitoringThreshold();
727        }
728 
729        return this.monitoringThreshold.intValue();
730    }
731 
732    /**
733     * Notifies all registered {@code StructuredFileListener}s about inserted
734     * blocks.
735     *
736     * @param index the index new blocks were inserted.
737     * @param insertedBlocks the number of blocks which were inserted at
738     * {@code index}.
739     *
740     * @throws IOException if reading or writing fails.
741     */
742    private void fireBlocksInserted(
743        final long index, final long insertedBlocks ) throws IOException
744    {
745        final Object[] listeners = this.fileListeners.getListenerList();
746        for ( int i = listeners.length - 2; i >= 0; i -= 2 )
747        {
748            if ( listeners[i] == StructuredFileListener.class )
749            {
750                ( (StructuredFileListener) listeners[i + 1] ).blocksInserted(
751                    index, insertedBlocks );
752 
753            }
754        }
755    }
756 
757    /**
758     * Notifies all registered {@code StructuredFileListener}s about deleted
759     * blocks.
760     *
761     * @param index the index blocks were deleted at.
762     * @param deletedBlocks the number of blocks which were deleted starting at
763     * {@code index}.
764     *
765     * @throws IOException if reading or writing fails.
766     */
767    private void fireBlocksDeleted(
768        final long index, final long deletedBlocks ) throws IOException
769    {
770        final Object[] listeners = this.fileListeners.getListenerList();
771        for ( int i = listeners.length - 2; i >= 0; i -= 2 )
772        {
773            if ( listeners[i] == StructuredFileListener.class )
774            {
775                ( (StructuredFileListener) listeners[i + 1] ).blocksDeleted(
776                    index, deletedBlocks );
777 
778            }
779        }
780    }
781 
782    private byte[] getBuffer( final int requested ) throws IOException
783    {
784        final long length = this.getFileOperations().getLength();
785 
786        if ( requested <= 0 || requested > length )
787        {
788            throw new IllegalArgumentException( Integer.toString( requested ) );
789        }
790 
791        if ( this.defaultBuffer == null )
792        {
793            this.defaultBuffer = this.getMemoryManager().
794                allocateBytes( this.getDefaultBufferSize() );
795 
796        }
797 
798        return requested <= this.defaultBuffer.length ||
799               this.getMemoryManager().getAvailableBytes() < requested
800               ? this.defaultBuffer
801               : this.getMemoryManager().allocateBytes( requested );
802 
803    }
804 
805    //------------------------------------------------StructuredFileOperations--
806    //--Messages----------------------------------------------------------------
807 
808// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausMessages
809    // This section is managed by jdtaus-container-mojo.
810 
811    /**
812     * Gets the text of message <code>alreadyClosed</code>.
813     * <blockquote><pre>Instanz geschlossen - keine E/A-Operationen möglich.</pre></blockquote>
814     * <blockquote><pre>Instance closed - cannot perform I/O.</pre></blockquote>
815     *
816     * @param locale The locale of the message instance to return.
817     *
818     * @return Message stating that an instance is already closed.
819     */
820    private String getAlreadyClosedMessage( final Locale locale )
821    {
822        return ContainerFactory.getContainer().
823            getMessage( this, "alreadyClosed", locale, null );
824 
825    }
826 
827// </editor-fold>//GEN-END:jdtausMessages
828 
829    //----------------------------------------------------------------Messages--
830}

[all classes][org.jdtaus.core.io.util]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov