--- /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);
+
+}