FileDocCategorySizeDatePackage
Protocol.javaAPI DocphoneME MR2 API (J2ME)46409Wed May 02 18:00:28 BST 2007com.sun.midp.io.j2me.file

Protocol

public class Protocol extends ConnectionBaseAdapter implements FileConnection
This class implements the necessary functionality for a File connection.

Fields Summary
private SecurityToken
classSecurityToken
Security token for using FileConnection API from PIM
private int
mode
Stores file connection mode
private String
fileName
File name string
private String
filePath
File path string including root filesystem
private String
fileRoot
Root filesystem for the file
private String
fileURL
File original URL
private BaseFileHandler
fileHandler
A peer to the native file
private static boolean
hasOtherFileHandler
Indicates if there is a need to try to load alternative file handler
InputStream
fis
Input stream associated with this connection
OutputStream
fos
Output stream associated with this connection
private static String
sep
Separator for file path components
Constructors Summary
public Protocol()
Constructor for file connection implementation.


          
     
        char[] t = new char[1];
        t[0]= DefaultFileHandler.getFileSeparator();
        sep = new String(t);
        if (sep == null) {
            throw new
                NullPointerException("Undefined \"file.separator\" property");
        }
    
        connectionOpen = false;
        fileHandler = null;
    
Methods Summary
public longavailableSize()

        long size = -1;

        try {
            checkRootReadPermission();

            ensureOpenAndConnected();

            size = fileHandler.availableSize();
        } catch (IOException e) {
            size = -1;
        }

        return size;
    
public booleancanRead()

        boolean res = false;

        try {
            checkReadPermission();

            ensureOpenAndConnected();

            res = fileHandler.canRead();
        } catch (IOException e) {
            res = false;
        }

        return res;
    
public booleancanWrite()

        boolean res = false;

        try {
            checkReadPermission();

            ensureOpenAndConnected();

            res = fileHandler.canWrite();
        } catch (IOException e) {
            res = false;
        }

        return res;
    
private voidcheckIllegalChars(java.lang.String name)
Spec is not consistent: sometimes it requires IOException and sometimes IllegalArgumentException in case of illegal chars in the filename

param
name URL path fragment
throws
IOException if name contains unsupported characters


        String illegalChars = fileHandler.illegalFileNameChars();
        for (int i = 0; i < illegalChars.length(); i++) {
            if (name.indexOf(illegalChars.charAt(i)) != -1) {
                throw new
                    IOException("Contains characters invalid for a filename");
            }
        }
    
private final voidcheckReadPermission(java.lang.String fileURL, int mode)
Checks that the application has permission to read.

param
fileURL complete file URL
param
mode access mode
throws
InterruptedIOException if the permission dialog is terminated before completed
throws
SecurityException if read is not allowed
throws
IllegalModeException if connection is write only


        if (classSecurityToken == null) { // FC permission
            MIDletSuite suite = Scheduler.getScheduler().getMIDletSuite();

            try {
                suite.checkForPermission(Permissions.FILE_CONNECTION_READ,
                    fileURL);
            } catch (InterruptedException ie) {
                throw new InterruptedIOException(
                    "Interrupted while trying to ask the user permission");
            }
        } else { // call from PIM
            classSecurityToken.checkIfPermissionAllowed(
                Permissions.FILE_CONNECTION_READ);
        }

        if (mode == Connector.WRITE) {
            throw new IllegalModeException("Connection is write only");
        }
    
protected final voidcheckReadPermission()
Checks that the application has permission to read.

throws
InterruptedIOException if the permission dialog is terminated before completed
throws
SecurityException if read is not allowed
throws
IllegalModeException if connection is write only

        checkReadPermission(fileURL, mode);
    
protected final voidcheckRootReadPermission()
Checks that the application has permission to read the root path.

throws
InterruptedIOException if the permission dialog is terminated before completed
throws
SecurityException if read is not allowed
throws
IllegalModeException if connection is write only


        if (classSecurityToken == null) { // FC permission
            MIDletSuite suite = Scheduler.getScheduler().getMIDletSuite();

            try {
                suite.checkForPermission(Permissions.FILE_CONNECTION_READ,
                                     "file://" + fileRoot);
            } catch (InterruptedException ie) {
                throw new InterruptedIOException(
                    "Interrupted while trying to ask the user permission");
            }
        } else { // call from PIM
            classSecurityToken.checkIfPermissionAllowed
                (Permissions.FILE_CONNECTION_READ);
        }

        if (mode == Connector.WRITE) {
            throw new IllegalModeException("Connection is write only");
        }
    
private final voidcheckWritePermission(java.lang.String fileURL, int mode)
Checks that the application has permission to write.

param
fileURL complete file URL
param
mode access mode
throws
InterruptedIOException if the permission dialog is terminated before completed
throws
SecurityException if write is not allowed
throws
IllegalModeException if connection is read only


        if (classSecurityToken == null) { // FC permission
            MIDletSuite suite = Scheduler.getScheduler().getMIDletSuite();

            try {
                suite.checkForPermission(Permissions.FILE_CONNECTION_WRITE,
                                     fileURL);
            } catch (InterruptedException ie) {
                throw new InterruptedIOException(
                    "Interrupted while trying to ask the user permission");
            }
        } else { // call from PIM
            classSecurityToken.checkIfPermissionAllowed
                (Permissions.FILE_CONNECTION_WRITE);
        }

        if (mode == Connector.READ) {
            throw new IllegalModeException("Connection is read only");
        }
    
protected final voidcheckWritePermission()
Checks that the application has permission to write.

throws
InterruptedIOException if the permission dialog is terminated before completed
throws
SecurityException if write is not allowed
throws
IllegalModeException if connection is read only

        checkWritePermission(fileURL, mode);
    
protected voidcloseInputStream()
Called once by each child input stream. If the input stream is marked open, it will be marked closed and the if the connection and output stream are closed the disconnect method will be called.

exception
IOException if the subclass throws one

        maxIStreams++;
        fileHandler.closeForRead();
        super.closeInputStream();
    
protected voidcloseOutputStream()
Called once by each child output stream. If the output stream is marked open, it will be marked closed and the if the connection and input stream are closed the disconnect method will be called.

exception
IOException if the subclass throws one

        maxOStreams++;
        flush();
        fileHandler.closeForWrite();
        super.closeOutputStream();
    
protected voidconnect(java.lang.String name, int mode, boolean timeouts)
Establishes the connection.

param
name URL path fragment
param
mode access mode
param
timeouts flag to indicate that timeouts allowed
throws
IOException if an error occurs

public voidcreate()

        checkWritePermission();

        ensureOpenAndConnected();

        if (fileName.charAt(fileName.length() - 1) == '/") {
            throw new IOException("Can not create directory");
        }

        fileHandler.create();
    
public voiddelete()

        checkWritePermission();

        ensureOpenAndConnected();

        try {
            if (fis != null) {
                fis.close();
                fis = null;
            }
        } catch (IOException e) {
            // Ignore silently
        }

        try {
            if (fos != null) {
                fos.close();
                fos = null;
            }
        } catch (IOException e) {
            // Ignore silently
        }

        try {
            fileHandler.closeForReadWrite();
        } catch (IOException e) {
            // Ignore silently
        }

        fileHandler.delete();
    
public longdirectorySize(boolean includeSubDirs)

        long size = 0;

        // Permissions and ensureOpenAndConnected called by exists()
        if (exists()) {
            if (!isDirectory()) {
                throw new
                    IOException("directorySize is not invoked on directory");
            }
        } else {
            return -1L;
        }

        try {
            size = fileHandler.directorySize(includeSubDirs);
        } catch (IOException e) {
            size = -1;
        }

        return size;
    
protected voiddisconnect()
Free up the connection resources.

exception
IOException if an I/O error occurs.

        try {
            if (fileHandler != null) {
                fileHandler.close();
            }
        } finally {
            fileHandler = null;
        }
    
protected voidensureConnected()
Checks that the connection is already open.

throws
IOException if the connection is closed

        if (!isRoot(fileRoot)) {
            throw new IOException("Root is not accessible");
        }

        if (fileHandler == null) {
            fileHandler = getFileHandler();

            fileHandler.connect(fileRoot, filePath + fileName);

            fileHandler.createPrivateDir(fileRoot);
        }
    
protected voidensureOpenAndConnected()
Checks that the connection is already open and connected.

throws
ConnectionClosedException if the connection is closed
throws
IOException if any error occurs while connecting

        if (!isOpen()) {
            throw new ConnectionClosedException("Connection is closed");
        }

        ensureConnected();
    
public booleanexists()

        boolean res = false;

        try {
            checkReadPermission();

            ensureOpenAndConnected();

            res = fileHandler.exists();
        } catch (IOException e) {
            res = false;
        }

        return res;
    
public longfileSize()

        long size = -1;

        checkReadPermission();

        if (isDirectory()) {
            throw new IOException("fileSize invoked on a directory");
        }

        try {
            ensureOpenAndConnected();

            size = fileHandler.fileSize();
        } catch (IOException e) {
            size = -1;
        }

        return size;
    
protected voidflush()
Forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written that have been buffered by the connection, should immediately be written to their intended destination.

The flush method of ConnectionBaseAdapter does nothing.

exception
IOException if an I/O error occurs.

        checkWritePermission();

        ensureConnected();

        fileHandler.flush();
    
private static BaseFileHandlergetFileHandler()
Gets the file handler.

return
handle to current file connection

        String def = "com.sun.midp.io.j2me.file.DefaultFileHandler";
        String n = null;
        if (hasOtherFileHandler) {
            n = Configuration.getProperty(
                               "com.sun.midp.io.j2me.fileHandlerImpl");
            if (n == null) {
                hasOtherFileHandler = false;
            }
        }
        if (hasOtherFileHandler) {
            try {
                return (BaseFileHandler) (Class.forName(n)).newInstance();
            } catch (ClassNotFoundException e) {
                hasOtherFileHandler = false;
            } catch (Error e) {
                hasOtherFileHandler = false;
            } catch (IllegalAccessException e) {
                hasOtherFileHandler = false;
            } catch (InstantiationException e) {
                hasOtherFileHandler = false;
            }
        }
        try {
            return (BaseFileHandler) (Class.forName(def)).newInstance();
        } catch (ClassNotFoundException e) {
        } catch (Error e) {
        } catch (IllegalAccessException e) {
        } catch (InstantiationException e) {
        }
        throw new Error("Unable to create FileConnection Handler");
    
public java.lang.StringgetName()

        String name = fileName;

        try {
            if (exists()) {
                int lastPos = name.length() - 1;
                if (isDirectory()) {
                    if (!name.equals("") && name.charAt(lastPos) != '/") 
                        name += '/";
                } else {
                    if (name.charAt(lastPos) == '/")
                        name = name.substring(0, lastPos);
                }
            }
        } catch (SecurityException e) {
            // According to spec should silently ignore any exceptions
        } catch (IllegalModeException e) {
            // According to spec should silently ignore any exceptions
        } catch (ConnectionClosedException e) {
            // According to spec should silently ignore any exceptions
        }

        return name;
    
public java.lang.StringgetPath()

        return filePath;
    
public java.lang.StringgetURL()

        String url = EscapedUtil.getEscapedString(fileURL);

        try {
            if (exists()) {
                int lastPos = url.length() - 1;
                if (isDirectory()) {
                    if (url.charAt(lastPos) != '/") {
                        url += '/";
                    }
                } else {
                    if (url.charAt(lastPos) == '/") {
                        url = url.substring(0, lastPos);
                    }
                }
            }
        } catch (SecurityException e) {
            // According to spec should silently ignore any exceptions
        } catch (IllegalModeException e) {
            // According to spec should silently ignore any exceptions
        } catch (ConnectionClosedException e) {
            // According to spec should silently ignore any exceptions
        }

        return url;
    
public booleanisDirectory()

        boolean res = false;

        try {
            checkReadPermission();

            ensureOpenAndConnected();

            res = fileHandler.isDirectory();
        } catch (IOException e) {
            res = false;
        }

        return res;
    
public booleanisHidden()

        boolean res = false;

        try {
            checkReadPermission();

            ensureOpenAndConnected();

            res = fileHandler.isHidden();
        } catch (IOException e) {
            res = false;
        }

        return res;
    
public booleanisOpen()

        return connectionOpen;
    
private booleanisRoot(java.lang.String root)
Checks if path is a root path.

param
root path to be checked
return
true if path is a root, false otherwise.

        Vector r = listRoots(); // retrieve up-to-date list of mounted roots
        for (int i = 0; i < r.size(); i++) {
            String name = (String)r.elementAt(i);
            if (name.equals(root)) {
                return true;
            }
        }
        return false;
    
public longlastModified()

        long res = 0;

        try {
            checkReadPermission();

            ensureOpenAndConnected();

            res =  fileHandler.lastModified();
        } catch (IOException e) {
            res = 0;
        }

        return res;
    
public java.util.Enumerationlist()

        return listInternal(null, false);
    
public java.util.Enumerationlist(java.lang.String filter, boolean includeHidden)


        if (filter == null) {
            throw new NullPointerException("List filter is null");
        }

        return listInternal(EscapedUtil.getUnescapedString(filter),
            includeHidden);
    
private java.util.EnumerationlistInternal(java.lang.String filter, boolean includeHidden)
Gets a filtered list of files and directories contained in a directory. The directory is the connection's target as specified in Connector.open().

param
filter String against which all files and directories are matched for retrieval. An asterisk ("*") can be used as a wildcard to represent 0 or more occurrences of any character.
param
includeHidden boolean indicating whether files marked as hidden should be included or not in the list of files and directories returned.
return
An Enumeration of strings, denoting the files and directories in the directory matching the filter. Directories are denoted with a trailing slash "/" in their returned name. The Enumeration has zero length if the directory is empty or no files and/or directories are found matching the given filter. Any current directory indication (".") and any parent directory indication ("..") is not included in the list of files and directories returned.
exception
SecurityException if the security of the application does not have read access for the directory.
exception
IllegalModeException if the application does have read access to the connection's target but has opened the connection in Connector.WRITE mode.
exception
IOException if invoked on a file, the directory does not exists, the directory is not accessible, or an I/O error occurs.
exception
ConnectionClosedException if the connection is closed.
exception
IllegalArgumentException if filter contains any path specification or is an invalid filename for the platform (e.g. contains characters invalid for a filename on the platform).

        checkReadPermission();

        ensureOpenAndConnected();

        if (filter != null) {
            if (filter.indexOf('/") != -1) {
                throw new IllegalArgumentException(
                    "Filter contains any path specification");
            }

            String illegalChars = fileHandler.illegalFileNameChars();
            for (int i = 0; i < illegalChars.length(); i++) {
                if (filter.indexOf(illegalChars.charAt(i)) != -1) {
                    throw new
                        IllegalArgumentException("Filter contains characters "
                            + "invalid for a filename");
                }
            }
        }

        return fileHandler.list(filter, includeHidden).elements();
    
public static java.util.VectorlistRoots()
Gets an array of file system roots.

return
up-to-date array of file system roots; empty array is returned if there are no roots available.

        BaseFileHandler fh = getFileHandler();
        return fh.listRoots();
    
public voidmkdir()

        checkWritePermission();

        ensureOpenAndConnected();

        fileHandler.mkdir();
    
public java.io.InputStreamopenInputStream()
Open and return an input stream for a connection. The connection's target must already exist and be accessible for the input stream to be created.

return
An open input stream
exception
IOException if an I/O error occurs, if the method is invoked on a directory, if the connection's target does not yet exist, or the connection's target is not accessible.
exception
IllegalModeException if the application does have read access to the connection's target but has opened the connection in Connector.WRITE mode.
exception
SecurityException If the application is not granted read access to the connection's target.


        checkReadPermission();

        try {
            ensureOpenAndConnected();
        } catch (ConnectionClosedException e) {
            throw new IOException(e.getMessage());
        }

        // IOException when target file doesn't exist
        if (!fileHandler.exists()) {
            throw new IOException("Target file doesn't exist");
        }

        if (!fileHandler.canRead()) { // no read access
            throw new SecurityException("No read access");
        }

        fileHandler.openForRead();

        fis = super.openInputStream();

        return fis;
    
public java.io.OutputStreamopenOutputStream()
Open and return an output stream for a connection. The output stream is positioned at the start of the file. Writing data to the output stream overwrites the contents of the files (i.e. does not insert data). Writing data to output streams beyond the current end of file automatically extends the file size. The connection's target must already exist and be accessible for the output stream to be created. {@link #openOutputStream(long)} should be used to position an output stream to a different position in the file.

Changes made to a file through an output stream may not be immediately made to the actual file residing on the file system because platform and implementation specific use of caching and buffering of the data. Stream contents and file length extensions are not necessarily visible outside of the application immediately unless flush() is called on the stream.? The returned output stream is automatically and synchronously flushed when it is closed.

return
An open output stream
exception
IOException If an I/O error occurs, if the method is invoked on a directory, the file does not yet exist, or the connection's target is not accessible.
exception
IllegalModeException if the application does have write access to the connection's target but has opened the connection in Connector.READ mode.
exception
SecurityException If the application is not granted write access to the connection's target.
see
#openOutputStream(long)

        return openOutputStream(0);
    
public java.io.OutputStreamopenOutputStream(long byteOffset)

        if (byteOffset < 0) {
            throw new IllegalArgumentException("Offset has a negative value");
        }

        checkWritePermission();

        try {
            ensureOpenAndConnected();
        } catch (ConnectionClosedException e) {
            throw new IOException(e.getMessage());
        }

        // IOException when target file doesn't exist
        if (!fileHandler.exists()) {
            throw new IOException("Target file doesn't exist");
        }

        if (!fileHandler.canWrite()) {
            // no write access
            throw new SecurityException("No write access");
        }

        fileHandler.openForWrite();
        fileHandler.positionForWrite(byteOffset);

        fos = super.openOutputStream();

        return fos;
    
public ConnectionopenPrim(java.lang.String name, int mode, boolean timeouts)
Opens the file connection.

param
name URL path fragment
param
mode access mode
param
timeouts flag to indicate that timeouts allowed
return
an opened Connection
throws
IOException if some other kind of I/O error occurs.

        return openPrimImpl(name, mode, timeouts, true);
    
public ConnectionopenPrim(SecurityToken token, java.lang.String name)
Opens the file connection and receive security token.

param
token security token from PIM
param
name URL path fragment
return
an opened Connection
throws
IOException if some other kind of I/O error occurs.

        return openPrim(token, name, Connector.READ_WRITE);
    
public ConnectionopenPrim(SecurityToken token, java.lang.String name, int mode)
Opens the file connection and receive security token.

param
token security token from PIM
param
name URL path fragment
param
mode access mode
return
an opened Connection
throws
IOException if some other kind of I/O error occurs.

        classSecurityToken = token;
        return openPrim(name, mode, false);
    
private ConnectionopenPrimImpl(java.lang.String name, int mode, boolean timeouts, boolean unescape)
Opens the file connection.

param
name URL path fragment
param
mode access mode
param
timeouts flag to indicate that timeouts allowed
param
unescape flag to indicate whether URL must be unescaped
return
an opened Connection
throws
IOException if some other kind of I/O error occurs.


        if (!name.startsWith("//")) {
            throw new IllegalArgumentException("Missing protocol separator");
        }

        int rootStart = name.indexOf('/", 2);

        if (rootStart == -1) {
            throw new IllegalArgumentException("Malformed File URL");
        }

        /* The string must be a valid URL path separated by "/" */
		
        if (name.indexOf("/../", rootStart) != -1 ||
            name.indexOf("/./", rootStart) != -1 ||
            name.endsWith("/..") ||
            name.endsWith("/.") ||
            !"/".equals(sep) && name.indexOf(sep, rootStart) != -1 ||
            name.indexOf('\\") != -1) {
                throw new
                    IllegalArgumentException("/. or /.. is not supported "
                    + "or other illegal characters found");
        }

        if (unescape) {
            name = EscapedUtil.getUnescapedString(name);
        }
        String fileURL = "file:" + name;

        // Perform security checks before any object state changes since
        // this method is used not only by Connector.open() but
        // by FileConnection.setFileConnection() too.
        switch (mode) {
        case Connector.READ:
            checkReadPermission(fileURL, mode);
            maxOStreams = 0;
            break;
        case Connector.WRITE:
            checkWritePermission(fileURL, mode);
            maxIStreams = 0;
            break;
        case Connector.READ_WRITE:
            checkReadPermission(fileURL, mode);
            checkWritePermission(fileURL, mode);
            break;
        default:
            throw new IllegalArgumentException("Invalid mode");
        }

        this.fileURL = fileURL;
        this.mode = mode;

        int nameLength = name.length();
        int pathStart = name.indexOf('/", rootStart + 1);

        if (pathStart == -1) {
            throw new IllegalArgumentException("Root is not specified");
        }

        if (pathStart == (nameLength - 1)) {
            fileName = "";
            fileRoot = name.substring(rootStart + 1);
            filePath = name.substring(rootStart);
        } else {
            fileRoot = name.substring(rootStart + 1, pathStart + 1);

            int fileStart = name.lastIndexOf('/", nameLength - 2);

            if (fileStart <= pathStart) {
                fileName = name.substring(pathStart + 1);
                filePath = name.substring(rootStart, pathStart + 1);
            } else {
                filePath = name.substring(rootStart, fileStart + 1);
                fileName = name.substring(fileStart + 1);
            }
        }

        connectionOpen = true;
        return this;
    
protected intreadBytes(byte[] b, int off, int len)
Reads up to len bytes of data from the input stream into an array of bytes, blocks until at least one byte is available.

param
b the buffer into which the data is read.
param
off the start offset in array b at which the data is written.
param
len the maximum number of bytes to read.
return
the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.
exception
IOException if an I/O error occurs.


        checkReadPermission();

        ensureConnected();

        int readBytes = fileHandler.read(b, off, len);
        // return '-1' instead of '0' as stream specification requires
        // in case the end of the stream has been reached
        return (readBytes > 0) ? readBytes : -1;
    
public voidrename(java.lang.String newName)

        checkWritePermission();

        newName = EscapedUtil.getUnescapedString(newName);
        // Following line will throw NullPointerException if newName is null
        int dirindex = newName.indexOf('/");
        if (dirindex != -1 && dirindex != (newName.length() - 1)) {
            throw new
              IllegalArgumentException("New name contains path specification");
        }

        if (!"/".equals(sep) && newName.indexOf(sep) != -1) {
            throw new
              IllegalArgumentException("New name contains path specification");
        }

        ensureOpenAndConnected();
        checkIllegalChars(newName);

        try {
            if (fis != null) {
                fis.close();
                fis = null;
            }
        } catch (IOException e) {
            // Ignore silently
        }

        try {
            if (fos != null) {
                fos.close();
                fos = null;
            }
        } catch (IOException e) {
            // Ignore silently
        }

        try {
            fileHandler.closeForReadWrite();
        } catch (IOException e) {
            // Ignore silently
        }

        fileHandler.rename(filePath + newName);

        fileName = newName;
        fileURL = "file://" + filePath + fileName;
    
public voidsetFileConnection(java.lang.String fileName)

        ensureOpenAndConnected();

        // Note: permissions are checked by openPrim method

        // Following line will throw NullPointerException if fileName is null
        int dirindex = fileName.indexOf('/");
        if (dirindex != -1 && dirindex != (fileName.length() - 1)) {
            throw new IllegalArgumentException(
                "Contains any path specification");
        }

        if (fileName.equals("..") && this.fileName.length() == 0) {
            throw new IOException(
                "Cannot set FileConnection to '..' from a file system root");
        }

        if (!"/".equals(sep) && fileName.indexOf(sep) != -1) {
            throw new
            IllegalArgumentException("Contains any path specification");
        }

        checkIllegalChars(fileName);

        // According to the spec, the current FileConnection object must refer
        // to a directory.
        // Check this right here in order to avoid IllegalModeException instead
        // of IOException.
        if (!fileHandler.isDirectory()) {
            throw new IOException("Not a directory");
        }

        String origPath = filePath, origName = this.fileName;

        String tmp_sep;
        // Note: security checks are performed before any object state changes
        if (fileName.equals("..")) {
            // go one directory up
            openPrim("//" + filePath, mode, false);
        } else {
            int fileNameLen = this.fileName.length();
            if (fileNameLen == 0 || this.fileName.charAt(fileNameLen - 1) == '/") {
                tmp_sep = "";
            } else {
                tmp_sep = "/";
            }
            // go deeper in directory structure
            openPrimImpl("//" + filePath 
                     + this.fileName + tmp_sep + fileName,
                     mode, false, false);
        }

        // Old file connection must be a directory. It can not have open
        // streams so no need to close it. Just reset it to null
        fileHandler = null;

        // Reconnect to the new target
        ensureOpenAndConnected();

        // At this point we are already refer to the new file
        if (!fileHandler.exists()) {
            // Revert to an old file
            openPrim("//" + origPath + origName, mode, false);
            fileHandler = null;

            throw new IllegalArgumentException("New target does not exists");
        }
    
public voidsetHidden(boolean hidden)

        checkWritePermission();

        ensureOpenAndConnected();

        fileHandler.setHidden(hidden);
    
public voidsetReadable(boolean readable)

        checkWritePermission();

        ensureOpenAndConnected();

        fileHandler.setReadable(readable);
    
public voidsetWritable(boolean writable)

        checkWritePermission();

        ensureOpenAndConnected();

        fileHandler.setWritable(writable);
    
public longtotalSize()

        long size = -1;

        try {
            checkRootReadPermission();

            ensureOpenAndConnected();

            size = fileHandler.totalSize();
        } catch (IOException e) {
            size = -1;
        }

        return size;
    
public voidtruncate(long byteOffset)

        checkWritePermission();

        ensureOpenAndConnected();

        if (byteOffset < 0) {
            throw new IllegalArgumentException("offset is negative");
        }

        try {
            if (fos != null) {
                fos.flush();
            }
        } catch (IOException e) {
            // Ignore silently
        }

        fileHandler.truncate(byteOffset);
    
public longusedSize()

        long size = -1;

        try {
            checkRootReadPermission();

            ensureOpenAndConnected();

            size = fileHandler.usedSize();
        } catch (IOException e) {
            size = -1;
        }

        return size;
    
protected intwriteBytes(byte[] b, int off, int len)
Writes len bytes from the specified byte array starting at offset off to this output stream.

Polling the native code is done here to allow for simple asynchronous native code to be written. Not all implementations work this way (they block in the native code) but the same Java code works for both.

param
b the data.
param
off the start offset in the data.
param
len the number of bytes to write.
return
number of bytes written
exception
IOException if an I/O error occurs. In particular, an IOException is thrown if the output stream is closed.

        checkWritePermission();

        ensureConnected();

        return fileHandler.write(b, off, len);