Just An Application

July 7, 2009

What’s New In MIDP 3.0 ? Part 23; LCDUI – FileSelector

Filed under: Java, JME, LCDUI, MIDP, MIDP3, MIDP3Issues, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 10:49 am

The FileSelector class is a sub-class of Screen which can be used by a MIDlet to interact with the user to obtain file system related choices.

1. Support

Support for FileSelectors is not mandatory.

A platform may not have a file system, or may not have a file system capable of providing the functionality required for their support, in which case an attempt to create a FileSelector will cause an UnsupportedOperationException to be thrown.

2. Modes

A FlleSelector can be used in four different modes. A mode enables a user to perform a specific task. The possible tasks are

  • specify a directory to create
  • select a directory
  • select a file to load
  • select a file to save to

A FileSelector is created in a specific mode, but that mode can be changed as required.

2.1 Runtime Constants

The following constants defined in the FileSelector class define the modes corresponding to the tasks above

  • DIRECTORY_CREATE
  • DIRECTORY_SELECT
  • LOAD
  • SAVE

3. Filter Extensions

The files visible to the user in a FileSelector can be filtered on the basis of their extensions.

A collection of extensions, termed the filter extensions, can be set on a FileSelector and as a result only those files with matching extensions will be visible to the user.

4. Creating A FileSelector

A FileSelector can be created by using the

    public FileSelector(String title, int mode)

constructor.

The mode argument must be one of the mode constants. If it is not then an IllegalArgumentException will be thrown.

If the platform does not support FileSelectors an UnsupportedOperationException will be thrown.

5. Getting And Setting The Mode

The current mode of a FileSelector can be determined by calling its

    public int getMode()

method, which will return one of the mode constants.

The current mode of a FileSelector can be set by calling its

    public void setMode(int mode)

It is an error if the mode arguments is not one of the mode constants, and an IllegalArgumentException will be thrown.

6. Getting And Setting The Filter Extensions

A FileSelector’s current set of filter extensions can be obtained by calling it’s

    public java.lang.String[] getFilterExtensions()

method.

If there are currently no filter extensions specified an empty String array will be returned.

A FileSelector’s current set of filter extensions can be set by calling the FileSelector’s

    public void setFilterExtensions(String[] extensions)

The extensions argument can be null which is equivalent to specifying an empty String array.

Notes

  1. The specification does not explicitly define what a file extension is. Presumably it is the canonical
    part of the file name, if any, after the dot

  2. The specification does not explicitly state that filter extensions are only used if the FileSelector is in the
    LOAD or SAVE modes. Possibly this was felt to be self-evident.

  3. On the basis of the examples in the documentation when specified extensions do not include the dot.

7. Getting The User Selected URL

The URL of the directory or file selected by a user can be obtained by calling the FileSelector’s

    public String getURL()

method.

If the user has not selected a directory or file, or if they cancelled the selection, then the method will return null.

Note

  • It is not clear how long the user’s last selection remains current. Presumably until the user selects OK or Cancel
    on this FileSelector again ?

8. Setting The Default Directory Or File URL

The URL of the default directory or file to be presented to the user by a FileSelector can be set by calling it’s

    public void setURL(String url)
                throws 
                    java.io.IOException

method.

It is an error if the url argument is not a valid absolute file URL as specified by RFC3986, and an IllegalArgumentException
will be thrown.

The url argument is also constrained by the current mode of the FileSelector as follows

  • DIRECTORY_CREATE

    • the parent directory of the file specified by the URL must exist

    • the MIDlet must have permission to create directories in the parent directory

    • the URL must not refer to an existing file</p

  • DIRECTORY_SELECT

    • the URL must refer to an existing directory

  • LOAD

    • the URL must refer to an existing file

  • SAVE

    • the parent directory of the file specified by the URL must exist

    • the MIDlet must have permission to create files in the parent directory

    • the URL must not refer to an existing directory</p

In each case an IOException is thrown if all the necessary constraints are not met.

It is an error if the MIDlet does not have permission to access the directory or file specified by the URL, and a SecurityException will be thrown.

Notes

  1. It is not very clear what the URL specifies for certain modes. One possible interpretation is as follows

    DIRECTORY_CREATE

    the directory to create

    DIRECTORY_SELECT

    the default selected directory

    LOAD

    the file to load

    SAVE

    the default file to save to

  2. In the DIRECTORY_CREATE mode it appears to be possible to specify an existing directory.

  3. In the SAVE mode it appears to be necessary for the MIDlet to be able to create files in the specified parent directory even if an existing file is specified.

  4. It is unclear why permission issues can result in either an IOException or a SecurityException.

  5. The method documentation states that if the url argument is null this denotes

    the default directory is the URL of the MIDlet suite’s private storage directory.

    which does not make a lot of sense except in the DIRECTORY_SELECT case.

  6. The method documentation states that

    If supported by the filesystem, specifying a file that does not exist will result in creation of a new file by that name.

    which does not make a lot of sense either.

9. Opening A Connection

Once a user has selected a directory or file an associated GCF StreamConnection can be obtained by calling a FileSelector’s

    public javax.microedition.io.StreamConnection 
               open(
                   int     mode,
                   boolean timeouts)
               throws 
                   javax.microedition.io.ConnectionNotFoundException,
                   java.io.IOException

method.

The mode and timesouts arguments are as for the javax.microedition.io.Connector version of this method.

Calling this method will not result in security prompts unlike a call to the equivalent Connector method with the same arguments.

Notes

  1. The method is declared to throw a ConnectionNotFoundException

    If the target of the name cannot be found, or if the requested protocol type is not supported.

    There is an identical declaration in the equivalent Connector method and it is thus possibly the result of some over-zealous copying.

    Alternatively it may be a round-about way of specifying what happens if the method is called before the user has made a selection, which is otherwise unspecified.

  2. The method is declared to throw a SecurityException

    If access to the content is prohibited.

    In the FileSelector class documentation, it says

    The application can also call the FileSelector.open method and access the content via the Connection it returns. Since the user has explicitly given the MIDlet access to the file, no additional security prompts are required.

    so, if the user is not going to be prompted and given the opportunity to refuse access, it is difficult to see where the SecurityException is going to originate from.

10. Commands

Each FileSelector has two associated Commands.

These are defined in the FileSelector class

  • public static final Command CANCEL_COMMAND

  • public static final Command OK_COMMAND

and are of type

  • Command.CANCEL

  • Command.OK

respectively.

The two Command objects are used solely to communicate the user’s actions via a CommandListener interface. Neither the label or long label of either Command will be used by the implementation.

To prevent further Commands being added, or the Cancel and OK Commands being removed, the

    public void addCommand(Command cmd)

and the

    public void removeCommand(Command cmd)

methods are over-ridden. They are both defined to throw an IllegalStateException when called.

11. Command Layout

FileSelectors do not support Command layout and the following methods are all explicitly over-ridden and defined to throw an IllegalStateException when called.

  • removeCommandOrMenu(int)

  • setCommandLayoutPolicy(CommandLayoutPolicy)

  • setCommand(Command,int)

  • setMenu(Menu,int)

Notes

  1. Only the setCommandLayoutPolicy(CommandLayoutPolicy) actually needs to be over-ridden. The remaining methods cannot be used other than via a call to a CommandLayoutPolicy object’s doLayout() method anyway.

  2. The Displayable.getCommands)() method is not over-ridden. Presumably it returns a Command array containing the Cancel and OK commands ?

12. Issues

12.1 FileSelector Support And Capabilities ?

On a platform which does not support FileSelectors it is unclear what Display.getCapabilities() is actually going to return. Ideally the return value would not include the Display.SUPPORTS_FILESELECTORS flag.

However, if this were true then a call to the Display static method getDisplays(int) passing only the Display.SUPPORTS_FILESELECTORS flag should result in an empty array of Displays which according to the method documentation is not possible.

At the moment it appears that the only way to determine whether FileSelectors are actually supported on a device is to try and create one and see what happens

12.2 Mode And Default URL Interactions ?

The default URL set by a call to a FileSelector’s setURL(String) method is subject to a number of constraints dependent on the current mode. The converse however does not appear to be true.

For example, if a FileSelector’s current mode is DIRECTORY_SELECT and a call to its setURL(String)method passes the URL of an existing file then it is an error and an IOException is thrown.

However, if the FileSelector’s current mode is LOAD and its default URL specifies an existing file, and a call to the FileSelector’s setMode(int) method is called with an argument of DIRECTORY_SELECT then this is apparently allowed.

12.3 Filter Extensions And Default URL Interactions ?

It is not clear whether there is intended to be any interaction between filter extensions and the default URL in LOAD or SAVE mode. After all it is at least possible, if not probable, for a MIDlet to specify a file which is not visible to the user on the basis of the current filter extensions.

12.4 Security

The FileSelector class documentation begins by saying

The FileSelector maintains the confidentiality of the filesystem by revealing only the URL of the file or directory explicitly selected by the user. The application only receives information and access to the file permitted by the user.

It then goes on to explain why calling the FileSelector.open(int,boolean) following a user’s selection of a directory or file does not result in security prompts as follows

Since the user has explicitly given the MIDlet access to the file, no additional security prompts are required.

It is is difficult to see what this means other than that the FileSelector.open(int,boolean) method does no permission checking at all. If it does permission checking but user permissions are always assumed to be yes then that amounts to the same thing.

If so, then a FileSelector has to ensure that a user can never successfully select a directory or file which the MIDlet does not have both read and write permission for, since the FileSelector.open(int,boolean)method takes a read/write mode and there is no suggestion that there is any attempt to correlate the read/write mode passed to the method with the mode of the FileSelector when the user selected the directory or file.

The example in the FileSelector class documentation illustrates this. It uses a FileSelector in SAVE mode to obtain the URL of a file to be deleted. The FileSelector.open(int,boolean) is then used twice, once to open the selected file in read mode in order to load it, then again in write mode in order to delete it. Neither operation comes close to being a save. Amongst other things this would seem to imply that a FileSelector UI should not explicitly include any visual indication as to the mode it is currently in, or issue any security prompts worded in terms of its current mode, or risk seriously confusing the user.

The apparent requirement that both read and write permissions be obtained irrespective of the FileSelector mode means that MIDlets cannot load files to which they have read-only access which they should by rights be able to load.

The apparent requirement that the FileSelector be responsible for obtaining permissions at all means that it will either have to issue some kind of permission prompt of its own at the point the user selects OK, or perform a pair of permission checks at that point. In either case it then has to go on and use some non-permission controlled method of accessing the file system each time it is asked to open the selected directory or file.

Trying to short-circuit the permission based access control of the file system is a very risky undertaking. It will still be necessary to prevent access to large parts of the file system presumably by preventing navigation to them via a FileSelector and it will require an understanding of the file system and the access policy that it simply should not need to have.

The only safe way is to use the permission system at the point the directory or file is selected. This at least leaves the file system access policy where it belongs, but it may either result in a SecurityException straight away which may lead the user to wonder why they were allowed to select the directory or file in the first place, or in some cases one additional user prompt. As an aside, if the user has disallowed all file writes, and both read and write permissions have to be granted in every case, then FileSelectors cannot be successfully used at all.

Removing the read/write mode argument from the FileSelector.open(int,boolean) and using a value based on the FileSelector mode when the directory or file was selected would help a little, but it is not going to fundamentally improve the user’s experience of interacting with FileSelectors.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: