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

COVERAGE SUMMARY FOR SOURCE FILE [MemoryFileOperations.java]

nameclass, %method, %block, %line, %
MemoryFileOperations.java100% (1/1)71%  (17/24)69%  (382/554)66%  (77.8/118)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MemoryFileOperations100% (1/1)71%  (17/24)69%  (382/554)66%  (77.8/118)
MemoryFileOperations (byte []): void 0%   (0/1)0%   (0/23)0%   (0/7)
MemoryFileOperations (int): void 0%   (0/1)0%   (0/15)0%   (0/5)
clone (): Object 0%   (0/1)0%   (0/9)0%   (0/3)
close (): void 0%   (0/1)0%   (0/1)0%   (0/1)
equals (Object): boolean 0%   (0/1)0%   (0/23)0%   (0/5)
getCapacity (): int 0%   (0/1)0%   (0/4)0%   (0/1)
hashCode (): int 0%   (0/1)0%   (0/25)0%   (0/5)
write (byte [], int, int): void 100% (1/1)64%  (48/75)69%  (11/16)
setFilePointer (long): void 100% (1/1)67%  (12/18)75%  (3/4)
read (OutputStream): void 100% (1/1)75%  (15/20)80%  (4/5)
read (byte [], int, int): int 100% (1/1)77%  (92/119)79%  (19/24)
write (InputStream): void 100% (1/1)81%  (22/27)83%  (5/6)
getStreamBuffer (): byte [] 100% (1/1)89%  (16/18)94%  (2.8/3)
MemoryFileOperations (): void 100% (1/1)100% (13/13)100% (5/5)
ensureCapacity (int): void 100% (1/1)100% (67/67)100% (10/10)
getData (): byte [] 100% (1/1)100% (18/18)100% (4/4)
getFilePointer (): long 100% (1/1)100% (3/3)100% (1/1)
getLength (): long 100% (1/1)100% (4/4)100% (1/1)
getLocale (): Locale 100% (1/1)100% (6/6)100% (1/1)
getLogResizeMessage (Locale, Number): String 100% (1/1)100% (12/12)100% (1/1)
getLogger (): Logger 100% (1/1)100% (6/6)100% (1/1)
getMemoryManager (): MemoryManager 100% (1/1)100% (6/6)100% (1/1)
getStreamBufferSize (): int 100% (1/1)100% (7/7)100% (1/1)
setLength (long): void 100% (1/1)100% (35/35)100% (7/7)

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.io.InputStream;
25import java.io.OutputStream;
26import java.io.Serializable;
27import java.util.Arrays;
28import java.util.Locale;
29import org.jdtaus.core.container.ContainerFactory;
30import org.jdtaus.core.io.FileOperations;
31import org.jdtaus.core.lang.spi.MemoryManager;
32import org.jdtaus.core.logging.spi.Logger;
33 
34/**
35 * Implementation of elementary I/O operations in heap memory.
36 * <p>This implementation performs I/O in memory. The value of property
37 * {@code length} is limited to a maximum of {@code Integer.MAX_VALUE} (4 GB).
38 * </p>
39 *
40 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
41 * @version $JDTAUS: MemoryFileOperations.java 8853 2014-01-10 13:50:00Z schulte $
42 */
43public final class MemoryFileOperations
44    implements FileOperations, Serializable, Cloneable
45{
46    //--Fields------------------------------------------------------------------
47 
48    /**
49     * Data to operate on.
50     * @serial
51     */
52    private byte[] data;
53 
54    /**
55     * FilePointer.
56     * @serial
57     */
58    private long filePointer;
59 
60    /**
61     * Actual length.
62     * @serial
63     */
64    private int length;
65 
66    /**
67     * Default temporary buffer.
68     * @serial
69     */
70    private byte[] defaultBuffer;
71 
72    //------------------------------------------------------------------Fields--
73    //--Properties--------------------------------------------------------------
74 
75// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties
76    // This section is managed by jdtaus-container-mojo.
77 
78    /**
79     * Gets the value of property <code>streamBufferSize</code>.
80     *
81     * @return Size of the buffer for buffering streams.
82     */
83    private int getStreamBufferSize()
84    {
85        return ( (java.lang.Integer) ContainerFactory.getContainer().
86            getProperty( this, "streamBufferSize" ) ).intValue();
87 
88    }
89 
90// </editor-fold>//GEN-END:jdtausProperties
91 
92    //--------------------------------------------------------------Properties--
93    //--Dependencies------------------------------------------------------------
94 
95// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies
96    // This section is managed by jdtaus-container-mojo.
97 
98    /**
99     * Gets the configured <code>Logger</code> implementation.
100     *
101     * @return The configured <code>Logger</code> implementation.
102     */
103    private Logger getLogger()
104    {
105        return (Logger) ContainerFactory.getContainer().
106            getDependency( this, "Logger" );
107 
108    }
109 
110    /**
111     * Gets the configured <code>MemoryManager</code> implementation.
112     *
113     * @return The configured <code>MemoryManager</code> implementation.
114     */
115    private MemoryManager getMemoryManager()
116    {
117        return (MemoryManager) ContainerFactory.getContainer().
118            getDependency( this, "MemoryManager" );
119 
120    }
121 
122    /**
123     * Gets the configured <code>Locale</code> implementation.
124     *
125     * @return The configured <code>Locale</code> implementation.
126     */
127    private Locale getLocale()
128    {
129        return (Locale) ContainerFactory.getContainer().
130            getDependency( this, "Locale" );
131 
132    }
133 
134// </editor-fold>//GEN-END:jdtausDependencies
135 
136    //------------------------------------------------------------Dependencies--
137    //--FileOperations----------------------------------------------------------
138 
139    public long getLength()
140    {
141        return this.length;
142    }
143 
144    /**
145     * {@inheritDoc}
146     *
147     * @throws IllegalArgumentException if {@code newLength} is negative or
148     * greater than {@code Integer.MAX_VALUE}.
149     */
150    public void setLength( final long newLength )
151    {
152        if ( newLength < 0L || newLength > Integer.MAX_VALUE )
153        {
154            throw new IllegalArgumentException( Long.toString( newLength ) );
155        }
156 
157        this.ensureCapacity( (int) newLength );
158        this.length = (int) newLength;
159        if ( this.filePointer > this.length )
160        {
161            this.filePointer = this.length;
162        }
163    }
164 
165    public long getFilePointer()
166    {
167        return this.filePointer;
168    }
169 
170    public void setFilePointer( final long pos )
171    {
172        // Preconditions.
173        if ( pos < 0L || pos > Integer.MAX_VALUE )
174        {
175            throw new IllegalArgumentException( Long.toString( pos ) );
176        }
177 
178        this.filePointer = pos;
179    }
180 
181    public int read( final byte[] buf, final int off, final int len )
182    {
183        final int ret;
184 
185        // Preconditions.
186        if ( buf == null )
187        {
188            throw new NullPointerException( "buf" );
189        }
190        if ( off < 0 )
191        {
192            throw new ArrayIndexOutOfBoundsException( off );
193        }
194        if ( len < 0 )
195        {
196            throw new ArrayIndexOutOfBoundsException( len );
197        }
198        if ( off + len > buf.length )
199        {
200            throw new ArrayIndexOutOfBoundsException( off + len );
201        }
202        if ( this.filePointer + len > Integer.MAX_VALUE )
203        {
204            throw new ArrayIndexOutOfBoundsException( Integer.MAX_VALUE );
205        }
206 
207        if ( len == 0 )
208        {
209            ret = 0;
210        }
211        else if ( this.filePointer >= this.length )
212        {
213            // EOF
214            ret = FileOperations.EOF;
215        }
216        else if ( this.filePointer + len > this.length )
217        {
218            // less than len byte before EOF
219            final int remaining = (int) ( this.length - this.filePointer );
220            System.arraycopy( this.data, (int) this.filePointer, buf, off,
221                              remaining );
222 
223            this.filePointer += remaining;
224            ret = remaining;
225        }
226        else
227        {
228            // copy len byte into buf.
229            System.arraycopy(
230                this.data, (int) this.filePointer, buf, off, len );
231 
232            this.filePointer += len;
233            ret = len;
234        }
235 
236        return ret;
237    }
238 
239    public void write( final byte[] buf, final int off, final int len )
240    {
241        // Preconditions.
242        if ( buf == null )
243        {
244            throw new NullPointerException( "buf" );
245        }
246        if ( off < 0 )
247        {
248            throw new ArrayIndexOutOfBoundsException( off );
249        }
250        if ( len < 0 )
251        {
252            throw new ArrayIndexOutOfBoundsException( len );
253        }
254        if ( off + len > buf.length )
255        {
256            throw new ArrayIndexOutOfBoundsException( off + len );
257        }
258 
259        final long newLen = this.filePointer + len;
260        if ( newLen > Integer.MAX_VALUE )
261        {
262            throw new ArrayIndexOutOfBoundsException( Integer.MAX_VALUE );
263        }
264 
265        if ( newLen > this.length )
266        {
267            this.setLength( newLen );
268        }
269 
270        System.arraycopy( buf, off, this.data, (int) this.filePointer, len );
271        this.filePointer += len;
272    }
273 
274    public void read( final OutputStream out ) throws IOException
275    {
276        if ( out == null )
277        {
278            throw new NullPointerException( "out" );
279        }
280 
281        out.write( this.data, 0, this.length );
282        this.filePointer = this.length;
283    }
284 
285    public void write( final InputStream in ) throws IOException
286    {
287        if ( in == null )
288        {
289            throw new NullPointerException( "in" );
290        }
291 
292        int read;
293        final byte[] buf = this.getStreamBuffer();
294 
295        while ( ( read = in.read( buf, 0, buf.length ) ) != FileOperations.EOF )
296        {
297            this.write( buf, 0, read );
298        }
299    }
300 
301    /**
302     * {@inheritDoc}
303     * <p>Since this implementation does not use any system resources to
304     * release, this method does nothing. In contrast to other
305     * {@code FileOperations} implementations the instance can still be used
306     * after calling this method. It would be a mistake to write an application
307     * which relies on this behaviour, however.</p>
308     */
309    public void close()
310    {
311    }
312 
313    //----------------------------------------------------------FileOperations--
314    //--MemoryFileOperations----------------------------------------------------
315 
316    /** Creates a new {@code MemoryFileOperations} instance of no length. */
317    public MemoryFileOperations()
318    {
319        this.filePointer = 0L;
320        this.data = new byte[ 0 ];
321        this.length = 0;
322    }
323 
324    /**
325     * Creates a new {@code MemoryFileOperations} instance of no length
326     * taking an initial capacity.
327     *
328     * @param initialCapacity the number of bytes to pre-allocate when
329     * creating the new instance.
330     *
331     * @throws OutOfMemoryError if not enough memory is available to create a
332     * buffer with a length of {@code initialCapacity}.
333     *
334     * @see #ensureCapacity(int)
335     */
336    public MemoryFileOperations( final int initialCapacity )
337    {
338        this.filePointer = 0L;
339        this.length = 0;
340        this.data = this.getMemoryManager().allocateBytes( initialCapacity );
341    }
342 
343    /**
344     * Creates a new {@code MemoryFileOperations} instance holding {@code buf}.
345     *
346     * @param buf bytes to initialize the instance with.
347     *
348     * @throws NullPointerException if {@code buf} is {@code null}.
349     */
350    public MemoryFileOperations( final byte[] buf )
351    {
352        this();
353 
354        if ( buf == null )
355        {
356            throw new NullPointerException( "buf" );
357        }
358 
359        this.data = (byte[]) buf.clone();
360        this.length = buf.length;
361        this.filePointer = 0L;
362    }
363 
364    /**
365     * Gets the capacity of the instance.
366     *
367     * @return the capacity of the instance in byte.
368     */
369    public int getCapacity()
370    {
371        return this.data.length;
372    }
373 
374    /**
375     * Increases the capacity of the instance, if necessary, to ensure that it
376     * can hold at least the number of bytes specified by the minimum capacity
377     * argument.
378     *
379     * @param minimumCapacity the minimum capacity to ensure.
380     */
381    public void ensureCapacity( final int minimumCapacity )
382    {
383        final int oldLength = this.data.length;
384 
385        while ( this.data.length < minimumCapacity )
386        {
387            final byte[] newData = this.getMemoryManager().allocateBytes(
388                this.data.length * 2 >= minimumCapacity
389                ? this.data.length * 2
390                : minimumCapacity );
391 
392            Arrays.fill( newData, (byte) 0 );
393            System.arraycopy( this.data, 0, newData, 0, this.data.length );
394            this.data = newData;
395        }
396 
397        if ( oldLength != this.data.length &&
398             this.getLogger().isDebugEnabled() )
399        {
400            this.getLogger().debug(
401                this.getLogResizeMessage( this.getLocale(),
402                                          new Long( this.data.length ) ) );
403 
404        }
405    }
406 
407    /**
408     * Gets the file contents.
409     *
410     * @return the file contents of the instance.
411     *
412     * @throws OutOfMemoryError if not enough memory is available.
413     */
414    public byte[] getData()
415    {
416        final int len = (int) this.getLength();
417        final byte[] ret = this.getMemoryManager().allocateBytes( len );
418 
419        System.arraycopy( this.data, 0, ret, 0, len );
420 
421        return ret;
422    }
423 
424    /**
425     * Gets a buffer for buffering streams.
426     *
427     * @return a buffer for buffering streams.
428     */
429    private byte[] getStreamBuffer()
430    {
431        if ( this.defaultBuffer == null )
432        {
433            this.defaultBuffer = this.getMemoryManager().
434                allocateBytes( this.getStreamBufferSize() < 0
435                               ? 0
436                               : this.getStreamBufferSize() );
437 
438        }
439 
440        return this.defaultBuffer;
441    }
442 
443    //----------------------------------------------------MemoryFileOperations--
444    //--Object------------------------------------------------------------------
445 
446    /**
447     * Indicates whether some other object is equal to this one by comparing
448     * the contents from memory.
449     *
450     * @param o the reference object with which to compare.
451     *
452     * @return {@code true} if this object is the same as {@code o};
453     * {@code false} otherwise.
454     */
455    public boolean equals( final Object o )
456    {
457        boolean equal = this == o;
458 
459        if ( !equal && o instanceof MemoryFileOperations )
460        {
461            final MemoryFileOperations that = (MemoryFileOperations) o;
462            equal = Arrays.equals( getData(), that.getData() );
463        }
464 
465        return equal;
466    }
467 
468    /**
469     * Returns a hash code value for this object.
470     *
471     * @return a hash code value for this object.
472     */
473    public int hashCode()
474    {
475        // JDK: As of JDK 1.5, Arrays.hashCode( getData() ).
476        final byte[] bytes = getData();
477 
478        int result = 1;
479        for ( int i = 0, s0 = bytes.length; i < s0; i++ )
480        {
481            result = 31 * result + bytes[i];
482        }
483 
484        return result;
485    }
486 
487    /**
488     * Creates and returns a deep copy of this object.
489     *
490     * @return a clone of this instance.
491     */
492    public Object clone()
493    {
494        try
495        {
496            return super.clone();
497        }
498        catch ( final CloneNotSupportedException e )
499        {
500            throw new AssertionError( e );
501        }
502    }
503 
504    //------------------------------------------------------------------Object--
505    //--Messages----------------------------------------------------------------
506 
507// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausMessages
508    // This section is managed by jdtaus-container-mojo.
509 
510    /**
511     * Gets the text of message <code>logResize</code>.
512     * <blockquote><pre>aktuelle Puffergröße: {0, number} Byte</pre></blockquote>
513     * <blockquote><pre>current buffer size: {0, number} byte</pre></blockquote>
514     *
515     * @param locale The locale of the message instance to return.
516     * @param bufferSize The current size of the internal buffer.
517     *
518     * @return Information about the size of the internal buffer.
519     */
520    private String getLogResizeMessage( final Locale locale,
521            final java.lang.Number bufferSize )
522    {
523        return ContainerFactory.getContainer().
524            getMessage( this, "logResize", locale,
525                new Object[]
526                {
527                    bufferSize
528                });
529 
530    }
531 
532// </editor-fold>//GEN-END:jdtausMessages
533 
534    //----------------------------------------------------------------Messages--
535}

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