javacommons/fileutils/javasrc/com/nokia/mj/impl/fileutils/FileStreamHandler.java
branchRCL_3
changeset 19 04becd199f91
child 78 71ad690e91f5
child 83 26b2b12093af
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/fileutils/javasrc/com/nokia/mj/impl/fileutils/FileStreamHandler.java	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,349 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+package com.nokia.mj.impl.fileutils;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+
+import com.nokia.mj.impl.rt.support.ApplicationInfo;
+import com.nokia.mj.impl.rt.support.ApplicationUtils;
+import com.nokia.mj.impl.rt.support.Finalizer;
+import com.nokia.mj.impl.rt.support.Jvm;
+
+/**
+ * FileStreamHandler helps in creation of InputStream and OutputStream and
+ * provides data to them from the native side.
+ */
+class FileStreamHandler
+{
+    protected int iNativeHandle;
+
+    protected FileInputStream iInputStream;
+
+    protected FileOutputStream iOutputStream;
+
+    protected DataInputStream iDataInputStream;
+
+    protected DataOutputStream iDataOutputStream;
+
+    // Synchronizes close and open operations.
+    protected final Object iCloseOperation;
+
+    protected boolean iIsClosed;
+
+    private Finalizer iFinalizer;
+
+    private FileStreamHandler()
+    {
+        iCloseOperation = new Object();
+    }
+
+    protected FileStreamHandler(String aFileName)
+    {
+        iNativeHandle = createNativePeer(aFileName);
+        iCloseOperation = new Object();
+        iIsClosed = false;
+        iFinalizer = registerFinalize();
+    }
+
+    protected int createNativePeer(String aFileName)
+    {
+        return _createNativePeer(aFileName);
+    }
+
+    /**
+     * Registers with Finalizer to call a method when the object gets collected
+     * by GC
+     *
+     * @return Finalizer object that will be notified when GC happens
+     */
+    private Finalizer registerFinalize()
+    {
+        return new Finalizer()
+        {
+            public void finalizeImpl()
+            {
+                doFinalize();
+            }
+        };
+    }
+
+    private synchronized void doFinalize()
+    {
+        _dispose(iNativeHandle);
+    }
+
+    protected void stopRead()
+    {
+        synchronized (iCloseOperation)
+        {
+            _stopReading(iNativeHandle);
+            closeInputStreams();
+        }
+    }
+
+    protected void stopWrite()
+    {
+        synchronized (iCloseOperation)
+        {
+            closeOutputStreams();
+            _stopWriting(iNativeHandle);
+        }
+    }
+
+    protected InputStream openInputStream() throws IOException
+    {
+        synchronized (iCloseOperation)
+        {
+            if (null == iInputStream)
+            {
+                iInputStream = new FileInputStream(this);
+            }
+            else
+            {
+                throw new IOException("InputStream already open");
+            }
+        }
+        return iInputStream;
+    }
+
+    protected DataInputStream openDataInputStream() throws IOException
+    {
+        synchronized (iCloseOperation)
+        {
+            if (null == iDataInputStream)
+            {
+                iDataInputStream = new DataInputStream(openInputStream());
+            }
+            else
+            { // TCK2 compliance
+                throw new IOException("InputStream already open");
+            }
+        }
+        return iDataInputStream;
+    }
+
+    /**
+     * This method is called by InputStreamBase whenever it needs to fill its
+     * internal buffer with the next block of data.
+     *
+     * @param aBuffer
+     *            is the buffer that needs to be filled with data.
+     * @return the number of bytes read
+     * @throws InterruptedIOException
+     *             in case connection was closed while read was in progress.
+     * @throws IOException
+     *             in case where there were problems during read.
+     */
+    protected synchronized int readBytes(byte[] aBuffer, int aOffset,
+                                         int aLength) throws InterruptedIOException, IOException
+    {
+        return _readData(iNativeHandle, aBuffer, aOffset, aLength);
+    }
+
+    /**
+     * Closes all input streams
+     *
+     */
+    protected void closeInputStreams()
+    {
+        synchronized (iCloseOperation)
+        {
+            try
+            {
+                if (iInputStream != null)
+                {
+                    iInputStream.close();
+                    iInputStream = null;
+                }
+
+                if (iDataInputStream != null)
+                {
+                    iDataInputStream.close();
+                    iDataInputStream = null;
+                }
+            }
+            catch (IOException ex)
+            {
+                // Do nothing. Deleting Streams anyhow
+            }
+        }
+    }
+
+    protected OutputStream openOutputStream() throws IOException
+    {
+        synchronized (iCloseOperation)
+        {
+            if (null == iOutputStream)
+            {
+                iOutputStream = new FileOutputStream(this);
+            }
+            else
+            { // TCK2 compliance
+                throw new IOException("OutputStream already open");
+            }
+        }
+        return iOutputStream;
+    }
+
+    protected DataOutputStream openDataOutputStream() throws IOException
+    {
+        synchronized (iCloseOperation)
+        {
+            if (null == iDataOutputStream)
+            {
+                iDataOutputStream = new DataOutputStream(openOutputStream());
+            }
+            else
+            {
+                throw new IOException("OutputStream already open");
+            }
+        }
+        return iDataOutputStream;
+    }
+
+    /**
+     * This method is called by OutputStreamBase whenever its internal buffer
+     * overruns or when flush is called or when output stream is closed.
+     *
+     * @param aBytes
+     *            the buffer that has to be written to native.
+     * @param aOffset
+     *            offset from which data needs to be written in aBytes.
+     * @param aLength
+     *            the length of data from offset that has to be written.
+     * @throws IOException
+     *             in case write operation fails.
+     */
+    protected synchronized void writeBytes(byte[] aBytes, int aOffset,
+                                           int aLength) throws IOException
+    {
+        _writeData(iNativeHandle, aBytes, aOffset, aLength);
+    }
+
+    /**
+     * Closes all output streams.
+     *
+     */
+    protected void closeOutputStreams()
+    {
+        synchronized (iCloseOperation)
+        {
+            try
+            {
+                if (iOutputStream != null)
+                {
+                    iOutputStream.close();
+                    iOutputStream = null;
+                }
+
+                if (iDataOutputStream != null)
+                {
+                    iDataOutputStream.close();
+                    iDataOutputStream = null;
+                }
+            }
+            catch (IOException ex)
+            {
+                // Do nothing. Deleting Streams anyhow
+            }
+        }
+    }
+
+    /**
+     * Checks the validity of the parameters passed.
+     *
+     * @param aBytes
+     *            byte array with data
+     * @param aOffset
+     *            offset from which operations have to start
+     * @param aLength
+     *            length of data from offset
+     */
+    static void checkIOParams(byte[] aBytes, int aOffset, int aLength)
+    {
+        if (aOffset < 0 || aLength < 0 || (aOffset + aLength) > aBytes.length)
+        {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+    protected void closeFileStream()
+    {
+        _closeFileStream(iNativeHandle);
+    }
+
+    protected void openFileForReading()
+    {
+        _openFileForReading(iNativeHandle);
+    }
+
+    protected void openFileForWriting(long aOffset)
+    {
+        _openFileForWriting(iNativeHandle, aOffset);
+    }
+
+    /**
+     * Moves the current read position on the native side forward and back.
+     * NOTE: Method needs to be called by InputStream only. Native only sets
+     * read position forward or backward.
+     *
+     * @param aOffset
+     *            relative offset to the current native position. Positive moves
+     *            the offset forward and negative moves it back.
+     * @return actual number of bytes that can be skipped.
+     */
+    protected long skip(long aOffset)
+    {
+        return _skip(iNativeHandle, aOffset);
+    }
+
+    protected long available()
+    {
+        return _available(iNativeHandle);
+    }
+
+    private native long _available(int aNativePeer);
+
+    private native long _skip(int aNativePeer, long aOffset);
+
+    private native int _readData(int aNativePeer, byte[] aBuffer, int aOffset,
+                                 int aLength);
+
+    private native void _writeData(int aNativePeer, byte[] aBytes, int aOffset,
+                                   int aLength);
+
+    private native void _closeFileStream(int aHandle);
+
+    private native void _openFileForReading(int aHandle);
+
+    private native void _openFileForWriting(int aHandle, long aOffset);
+
+    private native void _dispose(int aNativeHandle);
+
+    private native void _stopReading(int iNativeHandle);
+
+    private native void _stopWriting(int iNativeHandle);
+
+    private native int _createNativePeer(String aFileName);
+
+}