FileDocCategorySizeDatePackage
ProxyListener.javaAPI DocJ2ME CLDC 1.17213Wed Feb 05 15:56:04 GMT 2003kdp

ProxyListener.java

/*
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package kdp;
import java.util.*;
import java.io.*;

abstract class ProxyListener extends Thread {

    int verbose=0;
    static int method_index_base = 0;

    // if bits 15-16 == 10 on the return option bits from the VM then the method
    // index is base one, not base zero.  We use '10' so that we protect from 
    // implementations that just blindly send all 0's or all 1's or 0xFFFF
    final int METHOD_BASE_SHIFT = 15;
    final int METHOD_BASE_BITS = 3 << METHOD_BASE_SHIFT;
    final int METHOD_BASE_ONE_FLAG = 2;

    final int MAJOR_VERSION = 1;
    final int MINOR_VERSION = 2;

    Map waitingQueue = new HashMap(8, 0.75f);
    private List packetQueue;
    boolean timeToQuit = false;

    String VMcmds[][] = 
                      { { "" },   // make the list 1-based
                        { "Virtual Machine", 
                              "Version", "ClassBySignature", "AllClasses",
                              "AllThreads", "TopLevelThreadGroups",
                              "Dispose", "IDSizes", "Suspend", "Resume",
                              "Exit", "CreateString", "Capabilities",
                              "ClassPaths", "DisposeObjects",
                              "HoldEvents", "ReleaseEvents" },
                        { "ReferenceType", 
                              "Signature", "ClassLoader", "Modifiers",
                              "Fields", "Methods", "GetValues", 
                              "SourceFile", "NestedTypes", "Status",
                              "Interfaces", "ClassObject" },
                        { "ClassType",
                              "Superclass", "SetValues", "InvokeMethod",
                              "NewInstance" },
                        { "ArrayType",
                              "NewInstance" },
                        { "InterfaceType",
                              "" },
                        { "Method",
                              "LineTable", "VariableTable", "Bytecodes" },
                        { "UNUSED", "UNUSED" },
                        { "Field",
                              "" },
                        { "ObjectReference",
                              "ReferenceType", "GetValues", "SetValues",
                              "UNUSED", "MonitorInfo", "InvokeMethod", 
                              "DisableCollection", "EnableCollection",
                              "IsCollected" },
                        { "StringReference",
                              "Value" },
                        { "ThreadReference",
                              "Name", "Suspend", "Resume", "Status",
                              "ThreadGroup", "Frames", "FrameCount",
                              "OwnedMonitors", "CurrentCountendedMonitor",
                              "Stop", "Interrupt", "SuspendCount" },
                        { "ThreadGroupReference", 
                              "Name", "Parent", "Children" },
                        { "ArrayReference",
                              "Length", "GetValues", "SetValues" },
                        { "ClassLoaderReference",
                              "VisibleClasses" },
                        { "EventRequest", 
                              "Set", "Clear", "ClearAllBreakpoints" },
                        { "StackFrame",
                              "GetValues", "SetValues", "ThisObject" },
                        { "ClassObjectReference", 
                              "ReflectedType" },
                      };

    String DBGcmds[][] = 
                      { { "Event",
                              "Composite" },
                   
                      };

    String VENcmds[][] = 
                      { { "Vender-Specific",
                              "UNKNOWN" }
                      };

    public ProxyListener() {
        packetQueue = Collections.synchronizedList(new LinkedList());
    }

    public void newPacket(Packet p) {

    if (p == null) {
        quit();
        synchronized(packetQueue) {
            packetQueue.notify();
        }
        return;
    }
    synchronized(packetQueue) {
        packetQueue.add(p);
        packetQueue.notify();
    }
    }

    public Packet waitForPacket() {

    synchronized(packetQueue) {
        while (!timeToQuit && packetQueue.size() == 0) {
            try {
                packetQueue.wait();
            } catch (InterruptedException e) {
            }
        }
    }
    if (timeToQuit)
        return null;
    return ((Packet)packetQueue.remove(0));
    }

    void replyReceived(Packet p) {
        Packet p2;
        if (p == null) {
            quit();
            synchronized(waitingQueue) {
                Iterator iter = waitingQueue.values().iterator();
                while (iter.hasNext()) {
                p2 = (Packet)iter.next();
                p2.notify();
                }
            }
            return;
        }
            
        String idString = String.valueOf(p.id);
        synchronized(waitingQueue) {
            p2 = (Packet)waitingQueue.get(idString);
            if (p2 != null)
                waitingQueue.remove(idString);
        }
        if (p2 == null) {
            System.err.println("Received reply with no sender!");
            return;
        }
        p2.errorCode = p.errorCode;
        p2.data = p.data;
        p2.replied = true;
        synchronized(p2) {
            p2.notify();
        }

    }
    
    public void waitForReply(Packet p) {

        synchronized(p) {
            while (!timeToQuit && !p.replied) {
                try { p.wait();
                } catch (InterruptedException e) {
                }
            }
            if (!p.replied)
                throw new RuntimeException();
        }
    }

    public void verbose( int lvl ) {
        verbose = lvl;
    }
    abstract public void send(Packet p) throws IOException;

    abstract public void quit();

    protected void vp( int vlevel, String str ) {
        if ( verbose >= vlevel )
            System.out.print( str );
    }

    protected void vpe( int vlevel, String str ) {
        if ( verbose == vlevel )
            vp( vlevel, str );
    }

    protected void disp(Packet p ) {
        String[][] cmds;
    int cmdSet = p.cmdSet;
    int cmd = p.cmd;
    int cmdSetIndex = cmdSet;
    int cmdIndex = cmd;

        if ( cmdSet < 64 ) {
            cmds = VMcmds;
        } else if ( cmdSet < 128 ) {
            cmds = DBGcmds;
            cmdSetIndex -= 64;
/*
 * THIS IS LIKELY TO CAUSE PROBLEMS IN THE FUTURE
 */
            cmdIndex -= 99;
        } else {
            cmds = VENcmds;
            cmdSetIndex = cmdIndex = 0;
        }

        try {
            Log.LOGN(3, "Sending through: " +
                    cmds[ cmdSetIndex ][ 0  ] + "(" + cmdSet + ")/" +
                    cmds[ cmdSetIndex ][ cmdIndex ] + "(" + cmd    + ")" );
        Log.LOGN(8, "Packet: " + p);
        } catch ( ArrayIndexOutOfBoundsException e ) {
            System.out.println( "UNKNOWN COMMAND: " + cmdSet + "/" + cmd );
        }
    }

} // ProxyListener