FileDocCategorySizeDatePackage
ResourceInputStream.javaAPI DocphoneME MR2 API (J2ME)7647Wed May 02 17:59:54 BST 2007com.sun.cldc.io

ResourceInputStream

public class ResourceInputStream extends InputStream
Input stream class for accessing resource files in classpath.

Fields Summary
private Object
fileDecoder
private Object
savedDecoder
Constructors Summary
public ResourceInputStream(String name)
Construct a resource input stream for accessing objects in the jar file.

param
name the name of the resource in classpath to access. The name must not have a leading '/'.
exception
IOException if an I/O error occurs.

        String fixedName = fixResourceName(name);
        fileDecoder = open(fixedName);
        if (fileDecoder == null) {
            throw new IOException();
        }
     
Methods Summary
public intavailable()
Gets the number of bytes remaining to be read.

return
the number of bytes remaining in the resource.
exception
IOException if an I/O error occurs.

        if (fileDecoder == null) {
            throw new IOException();
        }
        return bytesRemain(fileDecoder);
    
private static native intbytesRemain(java.lang.Object fileDecoder)

private static native java.lang.Objectclone(java.lang.Object source)

public voidclose()

        fileDecoder = null;
    
private static java.lang.StringfixResourceName(java.lang.String name)
Fixes the resource name to be conformant with the CLDC 1.0 specification. We are not allowed to use "../" to get outside of the .jar file.

param
name the name of the resource in classpath to access.
return
the fixed string.
exception
IOException if the resource name points to a classfile, as determined by the resource name's extension.

        Vector dirVector = new Vector();
        int    startIdx = 0;
        int    endIdx = 0;
        String curDir;

        while ((endIdx = name.indexOf('/", startIdx)) != -1) {
            if (endIdx == startIdx) {
                // We have a leading '/' or two consecutive '/'s
                startIdx++;
                continue;
            }

            curDir = name.substring(startIdx, endIdx);
            startIdx = endIdx + 1;

            if (curDir.equals(".")) {
                // Ignore a single '.' directory
                continue;
            }
            if (curDir.equals("..")) {
                // Go up a level
                try {
                    dirVector.removeElementAt(dirVector.size()-1);
                } catch (ArrayIndexOutOfBoundsException aioobe) {
                     // "/../resource" Not allowed!
                     throw new IOException();
                }
                continue;
            }
            dirVector.addElement(curDir);
        }

        // save directory structure
        StringBuffer dirName = new StringBuffer();

        int nelements = dirVector.size();
        for (int i = 0; i < nelements; ++i) {
          dirName.append((String)dirVector.elementAt(i));
          dirName.append("/");
        }

        // save filename
        if (startIdx < name.length()) {
            String filename = name.substring(startIdx);
            // Throw IOE if the resource ends with ".class", but, not
            //  if the entire name is ".class"
            if ((filename.endsWith(".class")) &&
                (! ".class".equals(filename))) {
                throw new IOException();
            }
            dirName.append(name.substring(startIdx));
        }
        return dirName.toString();
    
public voidmark(int readlimit)
Remembers current position in ResourceInputStream so that subsequent call to reset will rewind the stream to the saved position.

param
readlimit affects nothing
see
java.io.InputStream#reset()

        if (fileDecoder != null) {
            savedDecoder = clone(fileDecoder);
        }
    
public booleanmarkSupported()
Indicates that this ResourceInputStream supports mark/reset functionality

return
true

        return true;
    
private static native java.lang.Objectopen(java.lang.String name)

public intread()
Reads the next byte of data from the input stream.

return
the next byte of data, or -1 if the end of the stream is reached.
exception
IOException if an I/O error occurs.

        // Fix for CR 6303054
        if (fileDecoder == null) {
            throw new IOException();
        }
        return readByte(fileDecoder);
    
public intread(byte[] b, int off, int len)
Reads bytes into a byte array.

param
b the buffer to read into.
param
off offset to start at in the buffer.
param
len number of bytes to read.
return
the number of bytes read, or -1 if the end of the stream is reached.
exception
IOException if an I/O error occurs.

        // Fix for CR 6303054
        if (fileDecoder == null) {
            throw new IOException();
        }
        if (b == null) {
            throw new NullPointerException();
        } else if ((off < 0) || (off > b.length) || (len < 0) ||
                   ((off + len) > b.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        }
        return readBytes(fileDecoder, b, off, len);
    
private static native intreadByte(java.lang.Object fileDecoder)

private static native intreadBytes(java.lang.Object fileDecoder, byte[] b, int off, int len)

public voidreset()
Repositions this stream to the position at the time the mark method was last called on this input stream.

exception
IOException if this stream has not been marked
see
java.io.InputStream#mark(int)

        if (fileDecoder == null || savedDecoder == null) {
            throw new IOException();
        }
        fileDecoder = clone(savedDecoder);