Tape Devices & Java
by Chad Gibbons

Example 1:

import java.io.*;
public class BasicTapeDevice {
    public TapeDevice(String pathName) throws IOException { ... }
    public synchronized void close() throws IOException { ... }
    public InputStream getInputStream() throws IOException { ... }
    public OutputStream getOutputStream() throws IOException { . }    public int getBlockSize() throws IOException { ... }
    public void setBlockSize(int bs) throws IOException { ... }
    public void rewind() throws IOException { ... }
    public void spaceEOD() throws IOException { ... }
    public void clearEOF() throws IOException { ... }
    public void clearEOM() throws IOException { ... }
    /* ... */
}


Example 2:

/* field IDs for commonly used object fields */
static jfieldID td_fdID;
static jfieldID td_eofID;
static jfieldID td_eomID;
static jfieldID IO_fd_fdID;

/* Class:     TapeDevice
 * Method:    initFields
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_BasicTapeDevice_initFields
  (JNIEnv *env, jclass cls) 
{
    /* retrieve field IDs for the fd, eof, and eom member variables */
    td_fdID = (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;");
    td_eofID = (*env)->GetFieldID(env, cls, "eof", "Z");
    td_eomID = (*env)->GetFieldID(env, cls, "eom", "Z");

    /* retrieve the field ID for the private fd member of FileDescriptor */
    cls = (*env)->FindClass(env, "java/io/FileDescriptor");
    IO_fd_fdID = (*env)->GetFieldID(env, cls, "fd", "I");
}


Listing One
/* BasicTapeDevice.java */
import java.io.*;
public class BasicTapeDevice {
    private FileDescriptor fd;
    private InputStream in;
    private OutputStream out;
    private boolean eof;
    private boolean eom;
    private boolean ignoreEOM;

    public BasicTapeDevice(String pathName) throws IOException {
        fd = new FileDescriptor();
        tapeOpen(pathName);
        in = new TapeInputStream();
        out = new TapeOutputStream();
        eof = false;
        eom = false;
        ignoreEOM = false;
    }
    public synchronized void close() throws IOException {
        if (fd != null) {
            try {
                if (fd.valid()) {
                    tapeClose();
                }
            } finally {
                fd = null;
            }
        }
    }
    public InputStream getInputStream() throws IOException {
        ensureOpen();
        return in;
    }
    public OutputStream getOutputStream() throws IOException {
        ensureOpen();
        return out;
    }
    public int getBlockSize() throws IOException {
        ensureOpen();
        return tapeGetBlockSize();
    }
    public void setBlockSize(int bs) throws IOException {
        ensureOpen();
        tapeSetBlockSize(bs);
    }
    public void rewind() throws IOException {
        ensureOpen();
        tapeRewind();
    }
    public void spaceEOD() throws IOException {
        ensureOpen();
        tapeSpaceEOD();
    }
    public void clearEOF() throws IOException {
        ensureOpen();
        if (eof) {
            eof = false;
            /* assume that the file mark has already been skipped */
        } else { 
            throw new IOException("not at end of file");
        }
    }
    public void clearEOM() throws IOException {
        ensureOpen();

        if (eom) {
            ignoreEOM = true;
        } else {
            throw new IOException("not at logical end of media");
        }
    }
    class TapeInputStream extends InputStream {
        private byte[] temp = new byte[1];
        public int read() throws IOException {
            int n = read(temp, 0, 1);
            if (n <= 0) {
                return -1;
            }
            return temp[0] & 0xff;
        }
        public int read(byte[] b, int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException();
            }
            if (off < 0 || len < 0 || off+len > b.length) {
                throw new IndexOutOfBoundsException();
            }
            if (len == 0) {
                return 0;
            }
            if (eof) {
                return -1;
            }
            ensureOpen();
            int n = tapeRead(b, off, len);
            if (n <= 0) {
                return -1;
            }
            return n;
        }
        public long skip(long numbytes) throws IOException {
            return 0;
        }
        public void close() throws IOException {
            BasicTapeDevice.this.close();
        }
    }
    class TapeOutputStream extends OutputStream {
        private byte[] temp = new byte[1];

        public void write(int b) throws IOException {
            temp[0] = (byte) b;
            write(temp, 0, 1);
        }
        public void write(byte[] b) throws IOException {
            write(b, 0, b.length);
        }
        public void write(byte[] b, int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException();

            }
            if (off < 0 || len < 0 || off+len > b.length) {
                throw new IndexOutOfBoundsException();
            }
            if (eom && !ignoreEOM) {
                throw new LogicalEOMException("logical end-of-media");
            }
            int n = tapeWrite(b, off, len);
            while (n < len) {
                n += tapeWrite(b, off + n, len - n);
            }
        }
        public void close() throws IOException {
            BasicTapeDevice.this.close();
        }
    }
    protected void finalize() {
        try {
            close();
        } catch (IOException ex) {
        }
    }
    private void ensureOpen() throws IOException {
        if (fd == null || !fd.valid()) {
            throw new IOException("tape device is not open");
        }
    }
    private static native void initFields();
    private native void tapeOpen(String pathName) throws IOException;
    private native void tapeClose() throws IOException;
    private native int tapeRead(byte[] b, int off, int len) throws IOException;
    private native int tapeWrite(byte[] b, int off, int len) throws IOException;
    private native int tapeGetBlockSize() throws IOException;
    private native void tapeSetBlockSize(int bs) throws IOException;
    private native void tapeRewind() throws IOException;
    private native void tapeSpaceEOD() throws IOException;

    /* load the JNI library specific for this platform */
    static {
        StringBuffer buf = new StringBuffer("Tape");
        String osName = System.getProperty("os.name");
        if (osName.equals("Windows NT") || osName.equals("Windows 2000")) {
            buf.append("WinNT");
        } else {
            buf.append(osName);
        }
        System.loadLibrary(buf.toString());
        initFields();
    }
}


Listing Two
/* LogicalEOMException.java */
import java.io.IOException;
public class LogicalEOMException extends IOException {
    public LogicalEOMException() {
        super();
    }
    public LogicalEOMException(String s) {
        super(s);
    }
}




1

