www.pudn.com > d4j.zip > IOTT.java


// IOTT: Model I/O Transfer Table 
// $Id: IOTT.java,v 1.4 2003/11/13 11:46:17 cgm8 Exp $ 
/*  
 * Copyright (c) 1999 Carlos G Mendioroz. 
 * 
 *  This file is part of D4J. 
 * 
 *  D4J is free software; you can redistribute it and/or 
 *  modify it under the terms of the GNU Lesser General Public 
 *  License as published by the Free Software Foundation; either 
 *  version 2 of the License, or (at your option) any later version. 
 *   
 *  D4J is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 *  Lesser General Public License for more details. 
 *   
 *  You should have received a copy of the GNU Lesser General Public 
 *  License along with this library; if not, write to the 
 *  Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
 *  Boston, MA  02111-1307, USA. 
 * 
 * Report problems and direct all questions to: 
 * 
 *	tron@acm.org 
 */ 
package local.dialogic; 
 
import java.io.*; 
import java.util.Vector; 
 
public class IOTT extends java.lang.Object 
{ 
     
// This is what we model: 
 
//     typedef struct dx_iott { 
//       unsigned short io_type;          /* Transfer type */ 
//       unsigned short rfu;              /* Reserved */ 
//       int              io_fhandle;     /* File descriptor */ 
//       char *           io_bufp;        /* Pointer to base memory */ 
//       unsigned long    io_offset;      /* File/Buffer offset */ 
//       long int         io_length;      /* Length of data */ 
//       DX_IOTT          *io_nextp;      /* Ptr to next DX_IOTT if IO_LINK set */ 
//       DX_IOTT          *io_prevp;      /* (Optional) Ptr to previous DX_IOTT */ 
//    }DX_IOTT; 
 
// io_type := {IO_MEM,IO_DEV | IO_CONT,IO_LINK,IO_EOT} 'we use IO_DEV only 
// Low level interface reconstructs this based on our variables: 
 
    protected int size; 
    protected int handle[]; 
    protected int offset[]; 
    protected int length[]; 
 
// This is used to know if we (did not) open a file using Dialogic.openFile 
 
    protected boolean externalFd[]; 
 
// This class is also the placeholder for the callback methods 
// used by dx_setuio() to implement user level IO, and thus enable 
// InputStream/OutputStream/RandomAccessFile IO. 
// Currently used streams are kept here: 
 
    static Vector streams = new Vector(); 
     
    public IOTT() 
    { 
        this.handle = new int[10]; 
        this.offset = new int[10]; 
        this.length = new int[10]; 
        this.externalFd = new boolean[10]; 
        size = 0; 
    } 
     
    public IOTT(String filename) throws IOException { 
        this(filename, false, 0, -1); 
    } 
  
    public IOTT(String filename, boolean forWrite) throws IOException { 
        this(filename, forWrite, 0, -1); 
    } 
 
    public IOTT(String filename, boolean forWrite, int offset, int length) 
            throws IOException  { 
        int fd = Dialogic.openFile(filename, forWrite?1:0); 
         
        if (fd < 0) 
            throw new IOException("Invalid file"); 
         
        this.handle = new int[10]; 
        this.offset = new int[10]; 
        this.length = new int[10]; 
        this.externalFd = new boolean[10]; 
        this.handle[0] = fd; 
        this.offset[0] = offset; 
        this.length[0] = length; 
        externalFd[0] = false; 
        size = 1; 
    } 
     
    public IOTT(int fd, int offset, int length) throws IOException { 
        if (fd < 0) 
            throw new IOException("Invalid file"); 
             
        this.handle = new int[10]; 
        this.offset = new int[10]; 
        this.length = new int[10]; 
        this.externalFd = new boolean[10]; 
        this.handle[0] = fd; 
        this.offset[0] = offset; 
        this.length[0] = length; 
        externalFd[0] = true; 
        size = 1; 
    } 
 
    public void add(String filename) throws IOException { 
        add(filename, 0, -1); 
    } 
 
    public void add(String filename, int offset, int length) throws IOException { 
        int fd = Dialogic.openFile(filename, 0); 
 
        if (fd < 0) 
            throw new IOException("Invalid file"); 
         
        if (size == this.handle.length) { 
            int i, p[]; 
            boolean b[]; 
             
            p = this.handle; 
            this.handle = new int[size+10]; 
            for(i = 0; i < size; i++) this.handle[i] = p[i]; 
            p = this.offset; 
            this.offset = new int[size+10]; 
            for(i = 0; i < size; i++) this.offset[i] = p[i]; 
            p = this.length; 
            this.length = new int[size+10]; 
            for(i = 0; i < size; i++) this.length[i] = p[i]; 
            p = null; 
            b = this.externalFd; 
            this.externalFd = new boolean[size+10]; 
            for(i = 0; i < size; i++) this.externalFd[i] = b[i]; 
            b = null; 
        } 
        this.handle[size] = fd; 
        this.offset[size] = offset; 
        this.length[size] = length; 
        externalFd[size] = false; 
        size ++; 
    } 
     
    public void add(int fd, int offset, int length) throws IOException { 
        if (fd < 0) 
            throw new IOException("Invalid file"); 
         
        if (size == this.handle.length) { 
            int i, p[]; 
            boolean b[]; 
             
            p = this.handle; 
            this.handle = new int[size+10]; 
            for(i = 0; i < size; i++) this.handle[i] = p[i]; 
            p = this.offset; 
            this.offset = new int[size+10]; 
            for(i = 0; i < size; i++) this.offset[i] = p[i]; 
            p = this.length; 
            this.length = new int[size+10]; 
            for(i = 0; i < size; i++) this.length[i] = p[i]; 
            p = null; 
            b = this.externalFd; 
            this.externalFd = new boolean[size+10]; 
            for(i = 0; i < size; i++) this.externalFd[i] = b[i]; 
            b = null; 
        } 
        this.handle[size] = fd; 
        this.offset[size] = offset; 
        this.length[size] = length; 
        externalFd[size] = true; 
        size ++; 
    } 
 
    public IOTT(InputStream is) throws IOException  { 
        int index = addToStreamTable(is); 
         
        this.handle = new int[10]; 
        this.offset = new int[10]; 
        this.length = new int[10]; 
        this.externalFd = new boolean[10]; 
        this.handle[0] = -index;  
        this.offset[0] = 0; 
        this.length[0] = -1; 
        externalFd[0] = true; 
        size = 1; 
    } 
 
    public IOTT(OutputStream os) throws IOException  { 
        int index = addToStreamTable(os); 
         
        this.handle = new int[10]; 
        this.offset = new int[10]; 
        this.length = new int[10]; 
        this.externalFd = new boolean[10]; 
        this.handle[0] = -index;  
        this.offset[0] = 0; 
        this.length[0] = -1; 
        externalFd[0] = true; 
        size = 1; 
    } 
 
    public IOTT(RandomAccessFile raf) throws IOException  { 
        this(raf, 0, -1); 
    } 
 
    public IOTT(RandomAccessFile raf, int offset, int length) throws IOException  { 
        int index = addToStreamTable(raf); 
         
        this.handle = new int[10]; 
        this.offset = new int[10]; 
        this.length = new int[10]; 
        this.externalFd = new boolean[10]; 
        this.handle[0] = -index;  
        this.offset[0] = offset; 
        this.length[0] = length; 
        externalFd[0] = true; 
        size = 1; 
    } 
 
    public void add(RandomAccessFile raf) throws IOException { 
        add(raf, 0, -1); 
    } 
     
    public void add(RandomAccessFile raf, int offset, int length) throws IOException { 
        int index = addToStreamTable(raf); 
         
        if (size == this.handle.length) { 
            int i, p[]; 
            boolean b[]; 
             
            p = this.handle; 
            this.handle = new int[size+10]; 
            for(i = 0; i < size; i++) this.handle[i] = p[i]; 
            p = this.offset; 
            this.offset = new int[size+10]; 
            for(i = 0; i < size; i++) this.offset[i] = p[i]; 
            p = this.length; 
            this.length = new int[size+10]; 
            for(i = 0; i < size; i++) this.length[i] = p[i]; 
            p = null; 
            b = this.externalFd; 
            this.externalFd = new boolean[size+10]; 
            for(i = 0; i < size; i++) this.externalFd[i] = b[i]; 
            b = null; 
        } 
        this.handle[size] = -index; 
        this.offset[size] = offset; 
        this.length[size] = length; 
        externalFd[size] = true; 
        size ++; 
    } 
 
    private int addToStreamTable(Object stream) { 
        int i; 
        for (i = 0; i < streams.size(); i++) { 
            if (streams.elementAt(i) == null) { 
                streams.setElementAt(stream, i); 
                break; 
            } 
        } 
        if (i == streams.size()) 
            streams.addElement(stream); 
             
        if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
            System.out.println("IOTT new stream("+(i+1)+")"); 
             
        return i+1; 
    } 
 
    // Clean system resources, i.e. close file descriptors 
    public void close() { 
        for(int i = 0; i < size; i++)  
            if (!externalFd[i]) 
                Dialogic.closeFile(handle[i]); 
            else if (handle[i] < 0) { 
                Object stream = streams.elementAt(-handle[i]-1); 
                try { 
                    if (stream instanceof InputStream)  
                        ((InputStream)stream).close(); 
                    else if (stream instanceof OutputStream) 
                        ((OutputStream)stream).close(); 
                    else 
                        ((RandomAccessFile)stream).close(); 
                } catch (IOException ioe) {}; 
                removeFromStreamTable(-handle[i]); 
            } 
        size = 0; 
    } 
     
    private void removeFromStreamTable(int fd) { 
        int i,s; 
        streams.setElementAt(null, fd-1); 
        if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
            System.out.println("IOTT close stream(" + fd + ")"); 
         
        // Garbage collect ... 
        s = i = streams.size(); 
        while (i > 0 && streams.elementAt(i - 1) == null) 
            i--; 
        if (s != i) 
	    streams.setSize(i); 
    } 
     
    public void finalize() throws Throwable { 
        close(); 
    } 
 
    // Dialogic callbacks for User IO 
    private static int read(int fd, byte buf[]) { 
        Object stream; 
        try { 
            stream = streams.elementAt(fd-1); 
        } catch(Exception e) { 
            stream = null; 
        } 
        if (stream == null) { 
            if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                System.out.println("IOTT read("+fd+",[]) = 0 (closed ?)"); 
            return 0; 
        } 
         
        int s, r = 0; 
        for (s = 0; r >= 0 && (s += r) < buf.length;) { 
            if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                System.out.print("IOTT read("+fd+",[],"+ (buf.length-s) + ")" ); 
            try { 
                if (stream instanceof RandomAccessFile) 
                    r = ((RandomAccessFile)stream).read(buf, s, buf.length-s); 
                else  
                    r = ((InputStream)stream).read(buf, s, buf.length-s); 
            } catch(Exception e) { 
                if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                    System.out.println("IOTT read("+fd+",[]) = 0 (e)"); 
                return 0; 
            } 
            if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                System.out.println(" = " + r); 
        } 
        if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
            System.out.println("IOTT read("+fd+",[]) = "+s); 
        return s; 
    } 
     
    private static int write(int fd, byte buf[]) { 
        Object stream; 
        try { 
            stream = streams.elementAt(fd-1); 
        } catch(Exception e) { 
            stream = null; 
        } 
        if (stream == null) { 
            if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                System.out.println("IOTT write("+fd+",[]) = 0 (closed ?)"); 
            return 0; 
        } 
         
        try { 
            if (stream instanceof RandomAccessFile) 
                ((RandomAccessFile)stream).write(buf); 
            else  
                ((OutputStream)stream).write(buf); 
        } catch(Exception e) { 
            if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                System.out.println("IOTT write("+fd+",[]) = 0"); 
            return 0; 
        } 
        if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
            System.out.println("IOTT write("+fd+",[]) = "+buf.length); 
        return buf.length; 
    } 
     
    private static long seek(int fd, long offset, int type) { 
        // Somehow seek is being call with garbage instead of 0 
        // for type (actually x13B1A0) in some calls... 
         
        Object stream; 
        try { 
            stream = streams.elementAt(fd-1); 
        } catch(Exception e) { 
            stream = null; 
        } 
        if (stream == null) { 
            if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                System.out.println("IOTT seek("+fd+",[]) = 0 (closed ?)"); 
            return 0; 
        } 
         
        if (stream instanceof RandomAccessFile) { 
            try { 
                RandomAccessFile raf = (RandomAccessFile)stream; 
                switch(type) { 
                case 0: 
                default: 
                    raf.seek(offset); 
                    break; 
                case 1: 
                    raf.seek(raf.getFilePointer() + offset); 
                    break; 
                case 2: 
                    raf.seek(raf.length() + offset); 
                    break; 
                } 
                if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                    System.out.println("IOTT seek("+fd+","+offset+","+type+ 
                        ") = " + raf.getFilePointer()); 
                return raf.getFilePointer(); 
            } catch (Exception e) {}; 
        }  
        // No chance to get it right always ? Fool them to think it worked 
        // if it was absolute pos... 
        if (type != 1 && type != 2) { 
            if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                System.out.println("IOTT seek("+fd+","+offset+","+type+") = " + offset); 
            return offset; 
        } else {  
            if ((Dialogic.debug & Dialogic.DEBUG_IOTT) != 0) 
                System.out.println("IOTT seek("+fd+","+offset+","+type+") = 0"); 
            return 0; 
        } 
    } 
}