javacommons/gcfprotocols/file/javasrc/com/nokia/mj/impl/file/FileConnectionImpl.java
changeset 21 2a9601315dfc
child 23 98ccebc37403
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/gcfprotocols/file/javasrc/com/nokia/mj/impl/file/FileConnectionImpl.java	Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,1028 @@
+/*
+* 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.file;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.microedition.io.Connector;
+import javax.microedition.io.file.ConnectionClosedException;
+import javax.microedition.io.file.FileConnection;
+import javax.microedition.io.file.IllegalModeException;
+
+import com.nokia.mj.impl.fileutils.FileUtility;
+import com.nokia.mj.impl.fileutils.FileUTF8Handler;
+import com.nokia.mj.impl.rt.support.ApplicationUtils;
+import com.nokia.mj.impl.rt.support.Finalizer;
+import com.nokia.mj.impl.rt.support.Jvm;
+
+/**
+ * FileConnectionImpl implements all the methods of
+ * javax.microedition.io.file.FileConnection;
+ */
+public final class FileConnectionImpl implements FileConnection
+{
+    static
+    {
+        try
+        {
+            Jvm.loadSystemLibrary("javafile");
+        }
+        catch (Exception e)
+        {
+            FileLogger.ELog("Unable to load javafile native library");
+        }
+    }
+
+    private FileUtility iFileUtility;
+
+    private Finalizer iFinalizer;
+
+    private boolean iIsOpen;
+
+    private int iMode;
+
+    private String iInitialUrl;
+
+    private String FILE_LOCALHOST = "//localhost/";
+
+    private String FILE_SIMPLE = "///";
+
+    private FileConnectionURL iFileConnectionUrl;
+
+    public FileConnectionImpl(String aName, int aMode, boolean aTimeouts)
+    throws IOException
+    {
+        iInitialUrl = "file:" + aName;
+
+        String decodedUrl = FileUTF8Handler.decode(iInitialUrl);
+        decodedUrl = decodedUrl.replace('|', ':');
+
+        // Validate File URL first.
+        FileConnectionURL.checkFileUrlValidity(decodedUrl);
+        String actual = FileUrlValidator.validateFileUrl(decodedUrl);
+
+        if (iInitialUrl.startsWith("file:" + FILE_SIMPLE))
+        {
+            // Construct a FileConnectionURL type if the validation passes.
+            iFileConnectionUrl = new FileConnectionURL(iInitialUrl, "file:///"
+                    + actual, false);
+        }
+        else
+        {
+            // Construct a FileConnectionURL type if the validation passes.
+            iFileConnectionUrl = new FileConnectionURL(iInitialUrl,
+                    "file://localhost/" + actual, false);
+        }
+
+        // Check access.
+        checkAccess(actual, aMode, true);
+
+        // Go ahead to prompt the user
+        checkSecurityPermission(actual, aMode);
+
+        FileLogger.Log("FileConnectionImpl: Creating FileUtility With: "
+                       + actual);
+
+        // FileUtility can handle multiple "//" in the path.
+        // Need to check it ourselves.
+        if (actual.indexOf("//") != -1)
+        {
+            throw new IllegalArgumentException("Invalid Uri :" + aName);
+        }
+        iFileUtility = new FileUtility(actual);
+        iFinalizer = registerFinalize();
+        iIsOpen = true;
+        iMode = aMode;
+
+        FileLogger.Log("FileConnectionImpl: Connector.open succeeded");
+    }
+
+    /**
+     * 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();
+            }
+        };
+    }
+
+    /**
+     * Checks for already granted permissions and prompts the user if access is
+     * allowed to the particular path. Prompting is delegated to
+     * ApplicationUtils
+     *
+     * @param aAbsolutePath
+     *            target to which the connection is currently open
+     * @param aMode
+     *            can either be FileAccessHelper.INTENT_READ or
+     *            FileAccessHelper.INTENT_WRITE
+     */
+    private static void checkSecurityPermission(String aAbsolutePath, int aMode)
+    {
+        ApplicationUtils appUtils = ApplicationUtils.getInstance();
+
+        String accessIntent = (aMode == Connector.READ) ? FileAccessHelper.INTENT_READ
+                              : FileAccessHelper.INTENT_WRITE;
+
+        FileLogger.Log("FileConnectionImpl: Check Permission to "
+                       + aAbsolutePath + " in " + accessIntent + " mode");
+
+        // Go ahead to prompt the user
+        if (Connector.READ_WRITE == aMode)
+        {
+            FileInternalPermission permission = new FileInternalPermission(
+                aAbsolutePath, FileAccessHelper.INTENT_READ);
+            appUtils.checkPermission(permission);
+
+            FileInternalPermission permission1 = new FileInternalPermission(
+                aAbsolutePath, FileAccessHelper.INTENT_WRITE);
+            appUtils.checkPermission(permission1);
+        }
+        else
+        {
+            FileInternalPermission permission = new FileInternalPermission(
+                aAbsolutePath, accessIntent);
+            appUtils.checkPermission(permission);
+        }
+    }
+
+    /**
+     * Checks access to a specified path given its absolute path and the mode in
+     * which the connection has been opened.
+     *
+     * @param aAbsolutePath
+     *            path of the connection
+     * @param aMode
+     *            mode in which the connection has been opened.
+     * @throws SecurityException
+     *             in case access was allowed for the application for the given
+     *             intent and target.
+     */
+    private static void checkAccess(String aAbsolutePath, int aMode)
+    {
+        checkAccess(aAbsolutePath, aMode, false);
+    }
+
+    /**
+     * Checks access to a specified path given its absolute path and the mode in
+     * which the connection has been opened.
+     *
+     * @param aAbsolutePath
+     *            path of the connection
+     * @param aMode
+     *            mode in which the connection has been opened.
+     * @param aIsOpening
+     *            specifies if the access check is being made on a method that
+     *            is considered as open operation (setFileConnection and
+     *            Connector.open)
+     * @throws SecurityException
+     *             in case access was allowed for the application for the given
+     *             intent and target.
+     */
+    private static void checkAccess(String aAbsolutePath, int aMode,
+                                    boolean aIsOpening)
+    {
+        FileLogger.Log("FileConnectionImpl: Check Access to " + aAbsolutePath
+                       + " in " + aMode + " mode");
+
+        String modeString;
+        switch (aMode)
+        {
+        case Connector.READ:
+            modeString = FileAccessHelper.INTENT_READ;
+            break;
+        case Connector.WRITE:
+            modeString = FileAccessHelper.INTENT_WRITE;
+            break;
+        default:
+            modeString = FileAccessHelper.INTENT_READ_WRITE;
+        }
+
+        if (!(FileAccessHelper.accessAllowed(aAbsolutePath, modeString,
+                                             FileSystemUtils.getProtectionDomain(), aIsOpening)))
+        {
+            // Access to the specified path not allowed.
+            // Throw Security Exception
+            throw new SecurityException("Permission denied: " + aAbsolutePath);
+        }
+    }
+
+    private synchronized void doFinalize()
+    {
+        iFileUtility = null;
+    }
+
+    public void close()
+    {
+        iIsOpen = false;
+        iFileUtility = null;
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public final void create() throws IOException
+    {
+        checkConnection();
+        checkConnectionMode(Connector.READ);
+
+        String domain = FileSystemUtils.getProtectionDomain();
+
+        // We need to check if we have access to base directory and not the file
+        // itself :-)
+        if (!FileAccessHelper.isCreateAllowedWithinDir(iFileUtility.getPath(),
+                domain))
+        {
+            throw new SecurityException("Permission denied: "
+                                        + iFileUtility.getAbsolutePath());
+        }
+
+        if (!iFileUtility.createNewFile())
+        {
+            FileLogger.WLog("FileConnectionImpl: File Creation failed. "
+                            + "Throwing IOException");
+            throw new IOException("Unable to create file: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public final void rename(String aName) throws IOException
+    {
+        FileLogger.Log("FileConnectionImpl: rename(): " + aName);
+
+        checkConnection();
+        checkConnectionMode(Connector.READ);
+        checkAccess(iFileUtility.getAbsolutePath(), Connector.WRITE);
+
+        if (!iFileUtility.rename(aName))
+        {
+            FileLogger
+            .ELog("FileConnectionImpl: File rename failed. Throwing IOException");
+            throw new IOException("Unable to rename file or directory: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+
+        String curUrl = iFileConnectionUrl.getUrl();
+        if (curUrl.endsWith("/"))
+        {
+            // Remove trailing "/"
+            curUrl = curUrl.substring(0, curUrl.length() - 1);
+        }
+        String newUrl = curUrl.substring(0, curUrl.lastIndexOf('/') + 1);
+        newUrl += iFileUtility.getName();
+
+        iFileConnectionUrl = new FileConnectionURL(newUrl);
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public final void mkdir() throws IOException
+    {
+        checkConnection();
+        checkConnectionMode(Connector.READ);
+        checkAccess(iFileUtility.getAbsolutePath(), Connector.WRITE);
+
+        FileLogger.Log("FileConnectionImpl: mkdir(): "
+                       + iFileUtility.getAbsolutePath());
+        if (!iFileUtility.mkdir())
+        {
+            FileLogger.WLog("  FileConnectionImpl: "
+                            + "FileUtility was unable to create directory.");
+            throw new IOException("Unable to create directory: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public final void delete() throws IOException
+    {
+        checkConnection();
+        checkConnectionMode(Connector.READ);
+        checkAccess(iFileUtility.getAbsolutePath(), Connector.WRITE);
+
+        FileLogger.Log("FileConnectionImpl: delete(): "
+                       + iFileUtility.getAbsolutePath());
+        try
+        {
+            if (!iFileUtility.delete())
+            {
+                FileLogger.WLog("FileConnectionImpl: Unable to delete file. "
+                                + "Throwing IOException.");
+                throw new IOException("Unable to delete file or directory: "
+                                      + iFileUtility.getAbsolutePath());
+            }
+        }
+        catch (SecurityException ex)
+        {
+            throw new IOException("Unable to delete file or directory: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public boolean exists()
+    {
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.exists();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public String getName()
+    {
+        String name = iFileConnectionUrl.getName();
+        if (name.equals(""))
+        {
+            return "";
+        }
+
+        if (iFileUtility.isDirectory())
+        {
+            name += "/";
+        }
+        else if (!iFileUtility.exists())
+        {
+            // If it does not exist, and of the initial url ended with "/"
+            // we must return with a trailing "/"
+            if (iInitialUrl.endsWith("/"))
+            {
+                name += "/";
+            }
+        }
+
+        return name;
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public String getPath()
+    {
+        String path = iFileConnectionUrl.getPath();
+        return path;
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public String getURL()
+    {
+        String ret = iFileConnectionUrl.getUrl();
+        if (iFileUtility.isDirectory())
+        {
+            if (!ret.endsWith("/"))
+            {
+                ret += "/";
+            }
+        }
+        else
+        {
+            if (iFileUtility.isFile())
+            {
+                if (ret.endsWith("/"))
+                {
+                    ret = ret.substring(0, ret.length() - 1);
+                }
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     *
+     */
+    public boolean isOpen()
+    {
+        return iIsOpen;
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public boolean canRead()
+    {
+        // Access Check
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.canRead();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public boolean canWrite()
+    {
+        // Access Check
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+
+        if (Connector.READ == iMode)
+        {
+            return false;
+        }
+        return iFileUtility.canWrite();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public long lastModified()
+    {
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.lastModified();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public boolean isDirectory()
+    {
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.isDirectory();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public void setReadable(boolean aReadable) throws IOException
+    {
+        checkConnection();
+        checkAccess(iFileUtility.getAbsolutePath(), Connector.WRITE);
+        checkConnectionMode(Connector.READ);
+        iFileUtility.setReadable(aReadable);
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public void setWritable(boolean aWritable) throws IOException
+    {
+        checkConnection();
+        checkAccess(iFileUtility.getAbsolutePath(), Connector.WRITE);
+        checkConnectionMode(Connector.READ);
+        iFileUtility.setWritable(aWritable);
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public void setHidden(boolean aHidden) throws IOException
+    {
+        checkConnection();
+        checkAccess(iFileUtility.getAbsolutePath(), Connector.WRITE);
+        checkConnectionMode(Connector.READ);
+        iFileUtility.setHidden(aHidden);
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public Enumeration list() throws IOException
+    {
+        return list("*", false);
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public Enumeration list(String aFilter, boolean aIncludeHidden)
+    throws IOException
+    {
+        FileLogger.Log("+FileConnectionImpl: list()");
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+
+        String filter = aFilter;
+        filter = trimFilter(filter);
+        checkFilter(filter);
+
+        // Ask FileUtility to give a list of files depending on its hidden
+        // status.
+        String[] fileList = iFileUtility.listFileArray(aIncludeHidden);
+        Vector accessibleFileList = new Vector();
+        String parent = iFileUtility.getAbsolutePath();
+
+        if (!parent.endsWith("/"))
+        {
+            parent += "/";
+        }
+
+        String domain = FileSystemUtils.getProtectionDomain();
+
+        // Check if read access is allowed to all contents in the list.
+        boolean accessCheckNeeded = FileAccessHelper.isDirRestricted(parent);
+        boolean accessAllowed = true;
+
+        for (int index = 0; index < fileList.length; index++)
+        {
+            String fullPath = parent + fileList[index];
+
+            if (FileUtility.matchString(filter.toLowerCase(), fileList[index]))
+            {
+                // If it passes the filter, check if midlet has access.
+                // if check access is true, then accessAllowed is not checked.
+                if (accessCheckNeeded)
+                {
+                    accessAllowed = FileAccessHelper.accessAllowed(fullPath,
+                                    FileConstants.INTENT_READ, domain, true);
+                }
+
+                if (accessAllowed)
+                {
+                    accessibleFileList.addElement(fileList[index]);
+                }
+            }
+        }
+        return accessibleFileList.elements();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public void truncate(long aByteOffset) throws IOException
+    {
+        checkConnection();
+        checkConnectionMode(Connector.READ);
+        checkAccess(iFileUtility.getAbsolutePath(), Connector.WRITE);
+        iFileUtility.truncate(aByteOffset);
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public final void setFileConnection(String aName) throws IOException
+    {
+        int result = 0;
+        checkConnection();
+
+        if (aName == null)
+        {
+            FileLogger.ELog("FileConnectionImpl: setFileConnection(null)");
+            throw new NullPointerException("Argument passed was null");
+        }
+
+        aName = aName.trim();
+        checkSetFileConnParam(aName);
+
+        if (aName.equals("."))
+        {
+            FileLogger.Log("FileConnectionImpl: Set FileConnection to current");
+            // already in current directory
+            return;
+        }
+
+        if (!iFileUtility.isDirectory())
+        {
+            if (iFileUtility.exists())
+            {
+                throw new IOException("Connection is not a directory: "
+                                      + iFileUtility.getAbsolutePath());
+            }
+        }
+
+        // Case where we move up a directory
+        if (aName.equals("..") || aName.equals("../"))
+        {
+            FileLogger.Log("FileConnectionImpl: Set FileConnection to parent");
+            FileLogger.Log("     Current target: "
+                           + iFileUtility.getAbsolutePath());
+            FileLogger.Log("     Next target   : " + iFileUtility.getPath());
+
+            String parent = iFileUtility.getPath();
+
+            FileUtility tempTarget;
+            try
+            {
+                // If no exception is thrown, its safe to set connection
+                tempTarget = new FileUtility(parent);
+            }
+            catch (IllegalArgumentException ex)
+            {
+                FileLogger.WLog("FileConnectionImpl: setFileConnection: "
+                                + "Unable to create new FileUtility object. "
+                                + "Cannot set fileconnection to new target.");
+                throw new IOException(
+                    "File name is invalid or not accessible: " + aName);
+            }
+            catch (Exception e)
+            {
+                throw new IOException(
+                    "File name is invalid or not accessible: " + aName);
+            }
+
+            // See if access is allowed. True because setting to new target is
+            // as good as opening.
+            checkAccess(tempTarget.getAbsolutePath(), iMode, true);
+            checkSecurityPermission(tempTarget.getAbsolutePath(), iMode);
+
+            // if we reach here, it is fine :-)
+            iFileUtility = tempTarget;
+
+            String prevUrl = iFileConnectionUrl.getUrl();
+            if (prevUrl.endsWith("/"))
+            {
+                prevUrl = prevUrl.substring(0, prevUrl.length() - 1);
+            }
+
+            String newUrl = prevUrl.substring(0, prevUrl.lastIndexOf('/'));
+            FileLogger.Log("FileConnectionImpl: setFileConnection: "
+                           + "Creating new FileConnectionURL With: " + newUrl);
+            iFileConnectionUrl = new FileConnectionURL(newUrl, false);
+            return;
+        }
+
+        if (!iFileUtility.exists())
+        {
+            throw new IOException("Current directory does not exist: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+
+        FileLogger.Log("FileConnectionImpl: setFileConnection(): "
+                       + " Setting FileConnectionUrl to: " + aName);
+
+        String newTarget = iFileUtility.getAbsolutePath() + aName;
+
+        FileLogger.Log("FileConnectionImpl: setFileConnection(): "
+                       + " Creating FileUtility with " + newTarget);
+
+        FileUtility tempTarget = new FileUtility(newTarget);
+
+        if (!tempTarget.exists())
+        {
+            FileLogger.WLog("FileConnectionImpl: setFileConnection(): "
+                            + " New Target does not exist: "
+                            + tempTarget.getAbsolutePath());
+
+            throw new IllegalArgumentException(
+                "File name is invalid or not accessible: " + aName);
+        }
+
+        // See if access is allowed. True because setting to new target is
+        // as good as opening.
+        checkAccess(tempTarget.getAbsolutePath(), iMode, true);
+        checkSecurityPermission(tempTarget.getAbsolutePath(), iMode);
+
+        // If no exception is thrown, its safe to set connection
+        iFileUtility = tempTarget;
+
+        String prevUrl = iFileConnectionUrl.getUrl();
+        if (!prevUrl.endsWith("/"))
+        {
+            prevUrl += "/";
+        }
+        String newUrl = prevUrl + iFileUtility.getName();
+
+        FileLogger.Log("FileConnectionImpl: setFileConnection: "
+                       + "Creating new FileConnectionURL With: " + newUrl);
+
+        iFileConnectionUrl = new FileConnectionURL(newUrl, false);
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public boolean isHidden()
+    {
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.isHidden();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public long availableSize()
+    {
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.availableSize();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public long usedSize()
+    {
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.usedSize();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public long totalSize()
+    {
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.totalSize();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public long fileSize() throws IOException
+    {
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.fileSize();
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public long directorySize(boolean aIncludeSubDirs) throws IOException
+    {
+        checkConnection();
+        checkConnectionMode(Connector.WRITE);
+        return iFileUtility.directorySize(aIncludeSubDirs);
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public InputStream openInputStream() throws IOException
+    {
+        checkConnectionMode(Connector.WRITE);
+        if (!isOpen())
+        {
+            throw new IOException();
+        }
+
+        checkSecurityPermission(iFileUtility.getAbsolutePath(), Connector.READ);
+        try
+        {
+            return iFileUtility.openInputStream();
+        }
+        catch (SecurityException ex)
+        {
+            FileLogger.ELog("FileConnectionImpl: " + "openInputStream(): "
+                            + " SecurityException Caught from FileUtility. "
+                            + "Throwing IOException.");
+
+            throw new IOException("Unable to open InputStream: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public DataInputStream openDataInputStream() throws IOException
+    {
+        checkConnectionMode(Connector.WRITE);
+
+        if (!isOpen())
+        {
+            throw new IOException();
+        }
+
+        checkSecurityPermission(iFileUtility.getAbsolutePath(), Connector.READ);
+        try
+        {
+            return iFileUtility.openDataInputStream();
+        }
+        catch (SecurityException ex)
+        {
+            FileLogger.ELog("FileConnectionImpl: " + "openDataInputStream(): "
+                            + " SecurityException Caught from FileUtility. "
+                            + "Throwing IOException.");
+
+            throw new IOException("Unable to open DataInputStream: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+    }
+
+    /**
+     * Opens an Output Stream. If there an already open output stream,
+     * IOException is thrown. Open succeeds only in case the application has
+     * access to open the file in write mode.
+     */
+    public OutputStream openOutputStream() throws IOException
+    {
+        checkConnectionMode(Connector.READ);
+        if (!isOpen())
+        {
+            throw new IOException();
+        }
+
+        checkSecurityPermission(iFileUtility.getAbsolutePath(), Connector.WRITE);
+        try
+        {
+            return iFileUtility.openOutputStream();
+        }
+        catch (SecurityException ex)
+        {
+            FileLogger.ELog("FileConnectionImpl: " + "openOutputStream(): "
+                            + " SecurityException Caught from FileUtility. "
+                            + "Throwing IOException.");
+
+            throw new IOException("Unable to open OutputStream: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public DataOutputStream openDataOutputStream() throws IOException
+    {
+        checkConnectionMode(Connector.READ);
+
+        if (!isOpen())
+            throw new IOException();
+
+        checkSecurityPermission(iFileUtility.getAbsolutePath(), Connector.WRITE);
+        try
+        {
+            return iFileUtility.openDataOutputStream();
+        }
+        catch (SecurityException ex)
+        {
+            FileLogger.ELog("FileConnectionImpl: " + "openDataOutputStream(): "
+                            + " SecurityException Caught from FileUtility."
+                            + " Throwing IOException.");
+
+            throw new IOException("Unable to open DataOutputStream: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+    }
+
+    /**
+     * Please refer JSR 75 for more details.
+     */
+    public OutputStream openOutputStream(long aOffset) throws IOException
+    {
+        checkConnectionMode(Connector.READ);
+        if (!isOpen())
+            throw new IOException();
+
+        if (aOffset < 0)
+        {
+            throw new IllegalArgumentException();
+        }
+
+        checkSecurityPermission(iFileUtility.getAbsolutePath(), Connector.WRITE);
+        try
+        {
+            checkSecurityPermission(iFileUtility.getAbsolutePath(), iMode);
+            return iFileUtility.openOutputStream(aOffset);
+        }
+        catch (SecurityException ex)
+        {
+            FileLogger.ELog("FileConnectionImpl: "
+                            + "openDataOutputStream(offset): "
+                            + " SecurityException Caught from FileUtility."
+                            + " Throwing IOException.");
+
+            throw new IOException("Unable to open OutputStream: "
+                                  + iFileUtility.getAbsolutePath());
+        }
+    }
+
+    /** * ----------------------------- HELPERS ----------------------------- */
+
+    /**
+     * If the filter contains escaped characters, it unescapes them.
+     *
+     * @param aFilter
+     *            filter string passed to list method
+     * @return new string with unescaped characters
+     */
+    private static String trimFilter(String aFilter)
+    {
+        String filter;
+        // If the name contains escaped sequences, remove them: %20
+        filter = FileUTF8Handler.decode(aFilter);
+        filter = filter.trim();
+        return filter;
+    }
+
+    /**
+     * Checks to see if the filter given by the user is valid. Checks against
+     * special charaters that must not be in the filter string.
+     *
+     * @param aFilter
+     *            parameter passed to list method.
+     * @throws IllegalArgumentException
+     *             in case it contains a character that is not allowed to be in
+     *             a filer.
+     */
+    private static void checkFilter(String aFilter)
+    {
+        if ((aFilter.indexOf('?') != -1) || (aFilter.indexOf(":") != -1)
+                || (aFilter.indexOf("/") != -1)
+                || (aFilter.indexOf("\\") != -1)
+                || (aFilter.indexOf("//") != -1)
+                || (aFilter.indexOf("|") != -1) || (aFilter.indexOf("<") != -1)
+                || (aFilter.indexOf(">") != -1))
+        {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    /**
+     * Checks to see if the connection is open.
+     *
+     */
+    private void checkConnection()
+    {
+        if (!iIsOpen)
+            throw new ConnectionClosedException("Connection has been closed");
+    }
+
+    /**
+     * Checks to see if the mode given aMode matches with the mode of the
+     * Connection.
+     *
+     * @param aMode
+     *            mode in which the connection must not be opened.
+     * @throws IllegalModeException
+     *             in case the mode is invalid
+     */
+    private final void checkConnectionMode(int aMode)
+    throws IllegalModeException
+    {
+        if (iMode == aMode)
+        {
+            throw new IllegalModeException(
+                "Illegal mode for this operation call");
+        }
+    }
+
+    /**
+     * Checks for sanity of the name passed to setFileConnection method. It must
+     * not contain characters that are not allowed in file names. Also, it must
+     * not have any path separators in it. Will throw IllegalArgumentException
+     * if the name was found to be improper.
+     *
+     * @param aName
+     *            name of file/directory to which the target needs to be renamed
+     * @throws IOException
+     *             in case it contains any of invalid characters.
+     */
+    private void checkSetFileConnParam(String aName) throws IOException
+    {
+        String toCheck = aName;
+        if (toCheck.endsWith("/"))
+        {
+            toCheck = toCheck.substring(0, toCheck.length() - 1);
+        }
+
+        if (toCheck.indexOf('?') != -1 || (toCheck.indexOf('<') != -1)
+                || (toCheck.indexOf('<') != -1) || (toCheck.indexOf(':') != -1)
+                || (toCheck.indexOf('|') != -1))
+        {
+            throw new IOException("Invalid file or directory name");
+        }
+
+        if ((toCheck.indexOf('*') != -1) || (toCheck.indexOf("/") != -1)
+                || (toCheck.indexOf("\\") != -1))
+        {
+            throw new IllegalArgumentException(
+                "Argument passed has path specification");
+        }
+    }
+}