PHP/Java Bridge protocol version 3.2

Requests are marked with "->", responses with "<-".  The server
continues to process requests until EOF. Only the first character is
significant.

The communication must begin with [C]reateInstance or [I]nvoke. The
server responds with a single ARG which also carries the last request
context ID. The request context ID is your request context, for
example the location of a cell where the response should be stored; a
structure or something like that. In PHP for example we allocate a
pval and pass it as the ID to the Invoke or Create request. When the
response arrives, we receive our ID along with the result so we know
exactly where to store the result. Context ID's are optional and can
be switched off, if the client can keep track of the context, see
NOTES below.

Example:

     $o = new java("java.lang.Long", 6);
     $o->toString(); // discard result

->  <CreateInstance value="java.lang.Long" predicate="Instance" id="78532"> 
      <Long value="6"/> 
    </CreateInstance>

<-  <Object value="1" predicate="O" id="78532"/>

->  <Invoke value="1" method="toString" predicate="Invoke" id="0">
    </Invoke>

<-  <Object value="2" predicate="O" id="0"/>

->  <Unref value="2" />

->  <Unref value="1" />

A second example which shows how to avoid round-trips. 

     java_begin_document()
     $o = new java("java.lang.Long", 6);
     $o->toString(); // discard result
     java_end_document();

->  <Invoke value="0" method="beginDocument" predicate="Invoke" id="0">
    </Invoke>

<-  <Null id="0"/>

->  <CreateInstance value="java.lang.Long" predicate="Instance" id="78532"> 
      <Long value="6" /> 
    </CreateInstance>

->  <Invoke value="1" method="toString" predicate="Invoke" id="0">
    </Invoke>

->  <Unref value="2" />

->  <Unref value="1" />

->  <Invoke value="0" method="endDocument" predicate="Invoke" id="0">
    </Invoke>

<-  <Null id="0"/>


Optional requests:

All aquired [O]bject handles may be destroyed by invoking U (destroy).
However, the server tracks all handles and automatically destroys them
after EOF. It is an error to further reference destroyed handles.

If [F]inish is called, the server closes or recycles the connection
and responds with F p=A, if the connection has been recycled, p=E
otherwise. Instead of sending <F p=E/> and waiting for the response,
it is also possible to simply close the connection.



Main requests:

->
CreateInstance:
<C v=name p=C|I i=ID> ...ARGS...
</C>
v: string
p: char (Reference[C]lass, Create[I]nstance)
i: unsigned long

->
Invoke:
<I v=object m=method p=P|I i=ID> ...ARGS...
</I>
v: unsigned long
m: string
p: char (examine[P]roperty, [I]nvoke method)
i: unsigned long

When v=0, the call is directed to the current request-handling
instance of the java bridge.




ARGS or response:
<->
String:
<S v=str [i=ID] />
v: string
i: unsigned long (reply only)

<->
Boolean:
<B v=T|F [i=ID] />
v: char ([T]rue, [F]alse)
i: unsigned long (reply only)

<->
Long:
<L v=l [i=ID] />
v: long
i: unsigned long (reply only)

<->
unsigned Long: (if base 16, see protocol header description below)
<L v=l p=[O|A] [i=ID] />
v: unsigned long
p: char (p[O]sitive, neg[A]tive)
i: unsigned long (reply only)

<->
Double:
<D v=d [i=ID] />
v: double
i: unsigned long (reply only)

->
Object:
<O v=object />
v: unsigned long
NULL values can be sent as either v="" or v="0"

<-
Object:
<O v=object p=TYPE i=ID />
v: unsigned long
p: char ([A]rray/Map, [C]ollection, [O]bject, [E]xception)
i: unsigned long 

<-
Null:
<N i=ID />
i: unsigned long 

<-
Apply:
<A v=object p=cname m=fname n=param# i=ID> ...PAIRS...
</A>
v: unsigned long
p: string
m: string
n: unsigned long
i: unsigned long
Result can be used to send back the result of the current apply
call. If v is null, the function name p must be searched in the
"current" environment.

->
Result:
<R i=ID> ...ARG...
</R>
i: unsigned long

<->
Exception:
<E v=object m=stringRepresentation [i=ID] />
v: unsigned long
m: string
i: unsigned long

->  (or <->, see below)
Composite:
<X t=A|H [i=ID] /> ...PAIRS...
</X>
t: char ([A]rray, [H]ashtable)
i: unsigned long (reply only)

->  (or <->, see below)
Pair:
<P [t=N|S v=key]> ...ARG...
</P>
t: char (key is [N]umeric, [S]tring or doesn't exist (if X=A))
v: unsigned long (if X=H and t=N)
v: string (if X=H and t=S)



OPTIONAL requests:
->
Destroy:
<U v=object />
v: unsigned long

<->
EndConnection:
<F p=A|E />
p: char (Keep [A]live, [E]nd connection)
After the F=... reply appeared, it is save to switch to a secondary
("override-redirect") channel.



NOTES:

If the first byte is neither a "<" nor a space, bits [0,1], [2,4] and
[6,7] have a special meaning:

Bits 0..6 set to 1: the following byte contains an extended header
described below.

Bit 1 0
-------
    0 0: Backward compatibility disabled, client sends and receives O,
         O id's are base 10
    0 1: Backward compatibility disabled, client sends and receives O,
         O id's are base 16
    1 0: Backward compatibility disabled, clients sends and receives X/P
         O id's are base 10
    1 1: Backward compatibility enabled, client sends and receives X/P
         O id's are base 10

Bit 2,3,4: log level (from java.log_level)

Bit 5: always 0

Bit 6: set to 1 if bit[0,1] are used
Bit 7: set to 1 if bit[2,4] are used


Extended header (byte 1)

Bit 1 0
-------
         keep object  keep array, base  send   binary             comment/php
          identity    Map, Coll.         ID     data              impl. (pure
                      identity                                    PHP or C)

    - -    yes          no         10   yes    base64 encoded     default
    0 0    yes          yes        16   no     binary             PHP
    0 1    yes          yes        16   yes    binary             C, php>4
    1 0    no           no         16   yes    binary             C, php=4
    1 1    yes          yes        16   no     base64 encoded     PHP

Bit 2,3,4: log level (from java.log_level)

Bit 5: always 0

Bit 6: set to 1 if bit[0,1] are used
Bit 7: set to 1 if bit[2,4] are used


It is possible to "ping" the server by sending it the byte 0x0. If
alive it will send back a 0x0.
