Overview

Packages

  • None
  • pdb

Classes

  • Java
  • java_AbstractJava
  • java_ApplyArg
  • java_Arg
  • java_ArrayProxy
  • java_ArrayProxyFactory
  • java_CacheEntry
  • java_ChunkedSocketChannel
  • java_class
  • java_Client
  • java_CompositeArg
  • java_EmptyChannel
  • java_ExceptionProxy
  • java_ExceptionProxyFactory
  • java_GlobalRef
  • java_HttpTunnelHandler
  • java_InternalJava
  • java_IteratorProxy
  • java_IteratorProxyFactory
  • java_JavaProxy
  • java_JavaProxyProxy
  • java_NativeParser
  • java_objectIterator
  • java_Parser
  • java_ParserString
  • java_ParserTag
  • java_Protocol
  • java_ProxyFactory
  • java_SimpleFactory
  • java_SimpleHttpHandler
  • java_SimpleHttpTunnelHandler
  • java_SimpleParser
  • java_SocketChannel
  • java_SocketChannelP
  • java_SocketHandler
  • java_ThrowExceptionProxyFactory
  • JavaClass
  • pdb_AddBreakpointRequest
  • pdb_AddBreakpointResponse
  • pdb_AddFilesRequest
  • pdb_AddFilesResponse
  • pdb_Breakpoint
  • pdb_ContinueProcessFileNotification
  • pdb_DebugScriptEndedNotification
  • pdb_DebugSessionStart
  • pdb_End
  • pdb_Environment
  • pdb_ErrorNotification
  • pdb_FileContentExtendedRequest
  • pdb_FileContentExtendedResponse
  • pdb_GetCallStackRequest
  • pdb_GetCallStackResponse
  • pdb_GetCWDRequest
  • pdb_GetCWDResponse
  • pdb_GetVariableValueRequest
  • pdb_GetVariableValueResponse
  • pdb_GoRequest
  • pdb_GoResponse
  • pdb_HeaderOutputNotification
  • pdb_In
  • pdb_Logger
  • pdb_Message
  • pdb_MessageRequest
  • pdb_MsgEvalRequest
  • pdb_MsgEvalResponse
  • pdb_Out
  • pdb_OutputNotification
  • pdb_Parser
  • pdb_ReadyNotification
  • pdb_RemoveAllBreakpointsRequest
  • pdb_RemoveAllBreakpointsResponse
  • pdb_RemoveBreakpointRequest
  • pdb_RemoveBreakpointResponse
  • pdb_Serializer
  • pdb_SetProtocolRequest
  • pdb_SetProtocolResponse
  • pdb_StartProcessFileNotification
  • pdb_StartRequest
  • pdb_StartResponse
  • pdb_StepIntoRequest
  • pdb_StepIntoResponse
  • pdb_StepOutRequest
  • pdb_StepOutResponse
  • pdb_StepOverRequest
  • pdb_StepOverResponse

Interfaces

  • java_JavaType

Exceptions

  • java_ConnectException
  • java_exception
  • java_IllegalArgumentException
  • java_IllegalStateException
  • java_InternalException
  • java_IOException
  • java_JavaException
  • java_RuntimeException
  • JavaException

Functions

  • __javaproxy_Client_getClient
  • Java
  • java_autoload
  • java_autoload_function
  • java_autoload_function5
  • java_begin_document
  • java_call_with_continuation
  • java_cast
  • java_cast_internal
  • java_checkCliSapi
  • java_closure
  • java_closure_array
  • java_context
  • java_defineHostFromInitialQuery
  • java_end_document
  • java_eval
  • java_get_base
  • java_get_closure
  • java_get_context
  • java_get_lifetime
  • java_get_server_name
  • java_get_session
  • java_get_values
  • java_getCompatibilityOption
  • java_getHeader
  • java_inspect
  • java_inspect_internal
  • java_instanceof
  • java_instanceof_internal
  • java_invoke
  • java_is_false
  • java_is_null
  • java_is_true
  • java_isfalse
  • java_isnull
  • java_istrue
  • java_last_exception_clear
  • java_last_exception_get
  • java_require
  • java_reset
  • java_server_name
  • java_session
  • java_session_array
  • java_set_encoding
  • java_set_file_encoding
  • java_shutdown
  • java_truncate
  • java_unwrap
  • java_values
  • java_values_internal
  • java_virtual
  • java_wrap
  • pdb_endInclude
  • pdb_error_handler
  • pdb_getDebugHeader
  • pdb_getDefinedVars
  • pdb_shutdown
  • pdb_startCall
  • pdb_startInclude
  • pdb_step
  • Overview
  • Package
  • Class
  • Todo
  • Deprecated
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553: 554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655: 656: 657: 658: 659: 660: 661: 662: 663: 664: 665: 666: 667: 668: 669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679: 680: 681: 682: 683: 684: 685: 686: 687: 688: 689: 690: 691: 692: 693: 694: 695: 696: 697: 698: 699: 700: 701: 702: 703: 704: 705: 706: 707: 708: 709: 710: 711: 712: 713: 714: 715: 716: 717: 718: 719: 720: 721: 722: 723: 724: 725: 726: 727: 728: 729: 730: 731: 732: 733: 734: 735: 736: 737: 738: 739: 740: 741: 742: 743: 744: 745: 746: 747: 748: 749: 750: 751: 752: 753: 754: 755: 756: 757: 758: 759: 760: 761: 762: 763: 764: 765: 766: 767: 768: 769: 770: 771: 772: 773: 774: 775: 776: 777: 778: 779: 780: 781: 782: 783: 784: 785: 786: 787: 788: 789: 790: 791: 792: 793: 794: 795: 796: 797: 798: 799: 800: 801: 802: 803: 804: 805: 806: 807: 808: 809: 810: 811: 812: 813: 814: 815: 816: 817: 818: 819: 820: 821: 822: 823: 824: 825: 826: 827: 828: 829: 830: 831: 832: 833: 834: 835: 836: 837: 838: 839: 840: 841: 842: 843: 844: 845: 846: 847: 848: 849: 850: 851: 852: 853: 854: 855: 856: 857: 858: 859: 860: 861: 862: 863: 864: 865: 866: 867: 868: 869: 870: 871: 872: 873: 874: 875: 876: 877: 878: 879: 880: 881: 882: 883: 884: 885: 886: 887: 888: 889: 890: 891: 892: 893: 894: 895: 896: 897: 898: 899: 900: 901: 902: 903: 904: 905: 906: 907: 908: 909: 910: 911: 912: 913: 914: 915: 916: 917: 918: 919: 920: 921: 922: 923: 
<?php /*-*- mode: php; tab-width:4 -*-*/

  /** java_Protocol.php -- PHP/Java Bridge protocol implementation
   *
   * Copyright (C) 2003-2007 Jost Boekemeier
   * 
   * This file is part of the PHP/Java Bridge.
   * 
   * The PHP/Java Bridge ("the library") is free software; you can
   * redistribute it and/or modify it under the terms of the GNU General
   * Public License as published by the Free Software Foundation; either
   * version 2, or (at your option) any later version.
   * 
   * The library 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
   * General Public License for more details.
   * 
   * You should have received a copy of the GNU General Public License
   * along with the PHP/Java Bridge; see the file COPYING.  If not, write to the
   * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   * 02111-1307 USA.
   * 
   * Linking this file statically or dynamically with other modules is
   * making a combined work based on this library.  Thus, the terms and
   * conditions of the GNU General Public License cover the whole
   * combination.
   * 
   * As a special exception, the copyright holders of this library give you
   * permission to link this library with independent modules to produce an
   * executable, regardless of the license terms of these independent
   * modules, and to copy and distribute the resulting executable under
   * terms of your choice, provided that you also meet, for each linked
   * independent module, the terms and conditions of the license of that
   * module.  An independent module is a module which is not derived from
   * or based on this library.  If you modify this library, you may extend
   * this exception to your version of the library, but you are not
   * obligated to do so.  If you do not wish to do so, delete this
   * exception statement from your version. 
   *
   * @author     Jost Boekemeier
   * @license    GPL
   * @link       http://php-java-bridge.sf.net
   */
require_once (java_get_base()."/Options.inc");
require_once (java_get_base()."/Client.inc");

/**
 * @access private
 */
function java_getHeader($name, $array) {
  if (array_key_exists($name, $array)) return $array[$name];
  $name="HTTP_$name"; // apache uses HTTP_ prefix
  if (array_key_exists($name, $array)) return $array[$name];
  return null;
}

/**
 * @access private
 */
function java_checkCliSapi() {
  $sapi=substr(php_sapi_name(), 0, 3);
  return ((($sapi == 'cgi') && !get_cfg_var("java.session")) || ($sapi == 'cli'));
}

/**
 * @access private
 */
function java_getCompatibilityOption($client) {
  static $compatibility = null;

  if ($compatibility) return $compatibility;

  $compatibility = $client->RUNTIME["PARSER"]=="NATIVE"
    ? (0103-JAVA_PREFER_VALUES)
    : (0100+JAVA_PREFER_VALUES);
  if(is_int(JAVA_LOG_LEVEL)) {
    $compatibility |= 128 | (7 & JAVA_LOG_LEVEL)<<2;
  }
  $compatibility = chr ($compatibility);
  return $compatibility;
}

/**
 * A simple channel, used in phase 1
 *
 * @access private
 */
class java_EmptyChannel {
  protected $handler;
  private $res;

  function __construct($handler) {
    $this->handler = $handler;
  }
  function shutdownBrokenConnection () {}
  function fwrite($data) {
    return $this->handler->fwrite($data);
  }
  function fread($size) {
    return $this->handler->fread($size);
  }

  function getKeepAliveA() {
    return "<F p=\"A\" />";
  }
  function getKeepAliveE() {
    return "<F p=\"E\" />";
  }
  function getKeepAlive() {
    return $this->getKeepAliveE();
  }

  function error() {
    trigger_error("An unchecked exception occured during script execution. Please check the server log files for details.", E_USER_ERROR);
  }
  function checkA($peer) {
    $val=$this->res[6];
    if ($val !='A') fclose($peer);
    if ($val !='A' && $val !='E') {
      $this->error();
    }
  }
  function checkE() {
    $val = $this->res[6];
    if ($val !='E') {
      $this->error();
    }
  }
  /** Used by socket channel (phase 2) */
  function keepAliveS() {
    $this->res = $this->fread(10); // <F p="E"/>
  }
  /** Used by chunked socket channel (phase 2) */
  function keepAliveSC() {
    $this->res = $this->fread(10);// <F p="E"/>
    $this->fwrite(""); // 0\r\n\r\n
    $this->fread(JAVA_RECV_SIZE); // read 0\r\n\r\n  JAVA_RECV_SIZE is dummy
  }

  /** Used by EmptyChannel (phase 1) */
  function keepAliveH() {
    $this->res = $this->handler->read(10);//  HTTP response <F p="E"/>
  }

  function keepAlive() {
    $this->keepAliveH();
    $this->checkE();
  }
}

/**
 * A simple socket channel, used in phase 2 or
 * when connecting to a simple socket listener
 *
 * @access private
 */
abstract class java_SocketChannel extends java_EmptyChannel {
  public $peer, $host;

  function __construct($peer, $host) {
    $this->peer = $peer;
    $this->host = $host;
  }
  function fwrite($data) {
    return fwrite($this->peer, $data);
  }
  function fread($size) {
    return fread($this->peer, $size);
  }
  function shutdownBrokenConnection () {
    fclose($this->peer);
  }
}
/**
 * Persistent version of the above
 *
 * @access private
 */
class java_SocketChannelP extends java_SocketChannel {
  function getKeepAlive() {return $this->getKeepAliveA();}
  function keepAlive() { $this->keepAliveS(); $this->checkA($this->peer); }
}

/**
 * Chunked version of the socket channel. Used in phase 2.
 * 
 * @access private
 */
class java_ChunkedSocketChannel extends java_SocketChannel {
  function fwrite($data) {
    $len = dechex(strlen($data));
    return fwrite($this->peer, "${len}\r\n${data}\r\n");
  }
  function fread($size) {
    $length = hexdec(fgets($this->peer, JAVA_RECV_SIZE));
    $data = "";
    while ($length > 0) {
      $str = fread($this->peer, $length);
      if (feof ($this->peer)) return null;
          
      $length -= strlen($str);
      $data .= $str;
    }
    fgets($this->peer, 3); // \r\n
    return $data;
  }
  function keepAlive() { $this->keepAliveSC(); $this->checkE(); fclose ($this->peer); }
}

/**
 * Used when PHP connects to a non-http socket or in phase 2
 *
 * Always uses a persistent connection to the socket.
 *
 * @access private
 */
class java_SocketHandler {
  public $protocol, $channel;

  function __construct($protocol, $channel) {
    $this->protocol = $protocol;
    $this->channel = $channel;
  }
  function write($data) {
      return $this->channel->fwrite($data);
  }
  // fallback for EmptyChannel, phase 1
  function fwrite($data) {return $this->write($data);}

  function read($size) {
    return $this->channel->fread($size);
  }
  // fallback for EmptyChannel, phase 1
  function fread($size) {return $this->read($size);}

  function redirect() {}
  function getKeepAlive() {
    return $this->channel->getKeepAlive();
  }
  function keepAlive() {
    $this->channel->keepAlive();
  }
  function dieWithBrokenConnection($msg) {
    unset($this->protocol->client->protocol);
    trigger_error ($msg?$msg:"unknown error: please see back end log for details", E_USER_ERROR);
  }
  function shutdownBrokenConnection ($msg) {
    $this->channel->shutdownBrokenConnection();
    $this->dieWithBrokenConnection($msg);
  }
}
/**
 * Used when PHP is running within a servlet environment.
 *
 * It connects to the ContextRunner directly w/o
 * sending a PUT request to the PhpJavaServlet.
 * Must not be used when a SocketContextServer
 * is not available in the back end.
 *
 * @access private
 */
class java_SimpleHttpHandler extends java_SocketHandler {
  public $headers, $cookies;
  
  public $context, $ssl, $port; // used by reopen
  public $host; // used when creating a socket channel lazily.
  /**
   * Create a SocketChannel which is used to communicate with the SocketContextServer
   */
  function createChannel() {
    // fast path; used by the JEE or servlet back end to connect to PHP
    $channelName = java_getHeader("X_JAVABRIDGE_REDIRECT", $_SERVER);
    $context = java_getHeader("X_JAVABRIDGE_CONTEXT", $_SERVER);
    $len = strlen($context);
    $len0 = java_getCompatibilityOption($this->protocol->client); // short path S1: no PUT request
    $len1 = chr($len&0xFF); $len>>=8;
    $len2 = chr($len&0xFF);
    // simulate phase 1: PUT request to the back end
    $this->channel = new java_EmptyChannel($this);
    // simulate phase 2 : parse headers and extract comm. channel
    $this->channel = $this->getChannel($channelName);
    // we know the comm. channel is a socket channel, otherwise this class wouldn't be used
    $this->protocol->socketHandler=new java_SocketHandler($this->protocol, $this->channel);
    $this->protocol->write("\177${len0}${len1}${len2}${context}");
    $this->context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $context);
    
    $this->protocol->handler = $this->protocol->socketHandler;
    $this->protocol->handler->write($this->protocol->client->sendBuffer)
        or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle");
    $this->protocol->client->sendBuffer=null;
    $this->protocol->handler->read(1)
        or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle");
  }

  function __construct($protocol, $ssl, $host, $port) {
    $this->cookies = array();
    $this->protocol = $protocol;
    $this->ssl = $ssl;
    $this->host = $host;
    $this->port = $port;
    $this->createChannel();
  }
  function getCookies() {
    $str="";
    $first=true;
    foreach($_COOKIE as $k => $v) {
      $str .= ($first ? "Cookie: $k=$v":"; $k=$v");
      $first=false;
    }
    if(!$first) $str .= "\r\n";
    return $str;
  }
  function getContextFromCgiEnvironment() {
    $ctx = java_getHeader('X_JAVABRIDGE_CONTEXT', $_SERVER);
    return $ctx;
  }
  function getContext() {
    static $context = null;
    if($context) return $context;

    $ctx = $this->getContextFromCgiEnvironment();
    $context = "";
    if($ctx) {
      $context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $ctx);
    }
    return $context;
  }
  function getWebAppInternal() {
    // from createHttpHandler
    $context = $this->protocol->webContext;
    if(isset($context)) return $context;

    /* Coerce a http://xyz.com/kontext/foo.php request to the back
       end: http://xyz.com:{java_hosts[0]}/kontext/foo.php.  For
       example if we receive a request:
       http://localhost/sessionSharing.php and java.servlet is On and
       java.hosts is "127.0.0.1:8080" the code would connect to the
       back end:
       http://127.0.0.1:8080/sessionSharing.phpjavabridge. This
       creates a cookie with PATH value "/".  If java_servlet is User
       the request http://localhost/myContext/sessionSharing.php the
       code would connect to
       http://127.0.0.1/myContext/sessionSharing.phpjavabridge and a
       cookie with a PATH value "/myContext" would be created.
    */
    return (JAVA_SERVLET == "User" &&
            array_key_exists('PHP_SELF', $_SERVER) &&
            array_key_exists('HTTP_HOST', $_SERVER))
      ? $_SERVER['PHP_SELF']."javabridge"
      : null;
  }
  function getWebApp() {
    $context = $this->getWebAppInternal();
    if(is_null($context)) $context = JAVA_SERVLET;
    if(is_null($context) || $context[0]!="/") 
      $context = "/JavaBridge/JavaBridge.phpjavabridge";
    return $context;
  }
  function write($data) {
    return $this->protocol->socketHandler->write($data);
  }
  function doSetCookie($key, $val, $path) {
    $path=trim($path);

    $webapp = $this->getWebAppInternal(); if(!$webapp) $path="/";
    setcookie($key, $val, 0, $path);
  }
  function read($size) {
    return $this->protocol->socketHandler->read($size);
  }

  function getChannel($channelName) {
    $errstr = null; $errno = null;
    $peer = pfsockopen($this->host, $channelName, $errno, $errstr, 20);
    if (!$peer) throw new java_IllegalStateException("No ContextServer for {$this->host}:{$channelName}. Error: $errstr ($errno)\n");
    stream_set_timeout($peer, -1);
    return new java_SocketChannelP($peer, $this->host);
  }
  function keepAlive() {
    parent::keepAlive();
  }

  /**
   * Prepare for phase 2: Open a SocketChannel and redirect further
   * communication to this channel.
   */
  function redirect() {}
}

/**
 * Used when PHP connects to a servlet environment using a PUT request.
 * It uses a chunked, non-persistent stream in phase 1 and will
 * redirect to a simple java_SocketHandler for phase 2.
 *
 * @access private
 */
class java_SimpleHttpTunnelHandler extends java_SimpleHttpHandler  {
  // the initial socket connection, may redirect to
  // a socket connection later on
  public $socket;
  protected $hasContentLength = false;
  
  function createSimpleChannel () {
    $this->channel = new java_EmptyChannel($this);
  }
  function createChannel() {
    $this->createSimpleChannel();
  }
  function shutdownBrokenConnection ($msg) {
    fclose($this->socket);
    $this->dieWithBrokenConnection($msg);
  }
  function checkSocket($socket, &$errno, &$errstr) {
    if (!$socket) {
      $msg="Could not connect to the JEE server {$this->ssl}{$this->host}:{$this->port}. Please start it.";
      $msg.=java_checkCliSapi()
        ?" Or define('JAVA_HOSTS', 9267); define('JAVA_SERVLET', false); before including 'Java.inc' and try again. Error message: $errstr ($errno)\n"
        :" Error message: $errstr ($errno)\n";
      throw new java_ConnectException($msg);
    }
  }
  function open() {
    $errno = null; $errstr = null;
    $socket = fsockopen("{$this->ssl}{$this->host}", $this->port, $errno, $errstr, 20);
    $this->checkSocket($socket, $errno, $errstr);
    
    stream_set_timeout($socket, -1);
    $this->socket = $socket;
  }
  // fallback for EmptyChannel, phase 1
  function fread($size) {
    $length = hexdec(fgets($this->socket, JAVA_RECV_SIZE));
    $data = "";
    while ($length > 0) {
      $str = fread($this->socket, $length);
      if (feof ($this->socket)) return null;
      
      $length -= strlen($str);
      $data .= $str;
    }
    fgets($this->socket, 3); //\r\n
    return $data;
  }
  // fallback for EmptyChannel, phase 1
  function fwrite($data) {
    $len = dechex(strlen($data));
    return fwrite($this->socket, "${len}\r\n${data}\r\n");
  }
  function close() {
    fwrite($this->socket, "0\r\n\r\n");
    fgets($this->socket, JAVA_RECV_SIZE); // 0\r\n
    fgets($this->socket, 3); // \r\n
    fclose($this->socket);
  }
  function __construct($protocol, $ssl, $host, $port) {
    parent::__construct($protocol, $ssl, $host, $port);
    $this->open();
  }
  function read($size) {
    if(is_null($this->headers)) $this->parseHeaders();
    if (isset($this->headers["http_error"])) {
      if (isset($this->headers["transfer_chunked"])) {
        $str = $this->fread(JAVA_RECV_SIZE);
      } elseif (isset($this->headers['content_length'])) {
        $len = $this->headers['content_length'];
        for($str=fread($this->socket, $len); strlen($str)<$len; $str.=fread($this->socket,$len-strlen($str)))
            if (feof ($this->socket)) break;
      } else {
        $str=fread($this->socket, JAVA_RECV_SIZE);
      }
      $this->shutdownBrokenConnection($str);
    }
    return $this->fread(JAVA_RECV_SIZE);
  }
  function getBodyFor ($compat, $data) {
    $len = dechex(2+strlen($data));
    return "Cache-Control: no-cache\r\nPragma: no-cache\r\nTransfer-Encoding: chunked\r\n\r\n${len}\r\n\177${compat}${data}\r\n";
  }
  function write($data) {
    $compat = java_getCompatibilityOption($this->protocol->client);
    $this->headers = null;
    $socket = $this->socket;
    $webapp = $this->getWebApp();
    $cookies = $this->getCookies();
    $context = $this->getContext();
    $res = "PUT ";
    $res .= $webapp;
    $res .= " HTTP/1.1\r\n"; 
    $res .= "Host: {$this->host}:{$this->port}\r\n";
    $res .= $context;
    $res .= $cookies;
    $res .= $this->getBodyFor($compat, $data);
    
    $count = fwrite($socket, $res) or $this->shutdownBrokenConnection("Broken connection handle");
    fflush($socket)                or $this->shutdownBrokenConnection("Broken connection handle");
    
    return $count;
  }
     
  function parseHeaders() {
    $this->headers = array();
    $line = trim(fgets($this->socket, JAVA_RECV_SIZE));
    $ar = explode (" ", $line);

    $code = ((int)$ar[1]);
    if  ($code != 200) $this->headers["http_error"] = $code;

    while (($str = trim(fgets($this->socket, JAVA_RECV_SIZE)))) {
      if($str[0]=='X') {
        if(!strncasecmp("X_JAVABRIDGE_REDIRECT", $str, 21)) {
          $this->headers["redirect"]=trim(substr($str, 22));
        } else if(!strncasecmp("X_JAVABRIDGE_CONTEXT", $str, 20)) {
          $this->headers["context"]=trim(substr($str, 21));
        }
      } else if($str[0]=='S') { // Set-Cookie:
        if(!strncasecmp("SET-COOKIE", $str, 10)) {
          $str=substr($str, 12);
          $this->cookies[]=$str;

          $ar = explode(";", $str);
          $cookie = explode("=",$ar[0]);
          $path = "";
          if(isset($ar[1])) $p=explode("=", $ar[1]);
          if(isset($p)) $path=$p[1];
          $this->doSetCookie($cookie[0], $cookie[1], $path);
        }
      } else if($str[0]=='C') { // Content-Length
        if(!strncasecmp("CONTENT-LENGTH", $str, 14)) {
          $this->headers["content_length"]=trim(substr($str, 15));
          $this->hasContentLength = true;
        } else if(!strncasecmp("CONNECTION", $str, 10) && !strncasecmp("close", trim(substr($str, 11)), 5)) {
          $this->headers["connection_close"] = true;
        }
      } else  if($str[0]=='T') { // Transfer-Encoding
        if(!strncasecmp("TRANSFER-ENCODING", $str, 17) && !strncasecmp("chunked", trim(substr($str, 18)), 7)) {
            $this->headers["transfer_chunked"] = true;
        }
      }
    }
  }
  function getSimpleChannel() {
    return new java_ChunkedSocketChannel($this->socket, $this->protocol, $this->host);
  }

  function redirect() {
    $this->isRedirect = isset($this->headers["redirect"]);
    if ($this->isRedirect)
      $channelName = $this->headers["redirect"];
    
    $context = $this->headers["context"];
    $len = strlen($context);
    $len0 = chr(0xFF);
    $len1 = chr($len&0xFF); $len>>=8;
    $len2 = chr($len&0xFF);
    if ($this->isRedirect) { // slow path; used by JavaBridgeRunner back end
      /* SocketContextServer: redirect to ContextRunner */
      $this->protocol->socketHandler=new java_SocketHandler($this->protocol, $this->getChannel($channelName));
      $this->protocol->write("\177${len0}${len1}${len2}${context}");
      $this->context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $context);

      $this->close ();

      $this->protocol->handler = $this->protocol->socketHandler;
      // short path for $this->protocol->flush(): avoid ContextRunner wait timeout
      $this->protocol->handler->write($this->protocol->client->sendBuffer)
        or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle");
      $this->protocol->client->sendBuffer=null;

      // dummy: avoid ack delay
      $this->protocol->handler->read(1)
        or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle");
    } else           { // fast path; used by JEE or servlet engine
       /* No SocketContextServer: keep using the current HTTP connection */
      $this->protocol->handler = $this->protocol->socketHandler=new java_SocketHandler($this->protocol, $this->getSimpleChannel());
    }
  }
}
/**
 * Used when PHP connects to a servlet environment using a PUT request.
 * It uses a chunked, non-persistent stream in phase 1 and will
 * redirect to a simple java_SocketHandler for phase 2.
 *
 * @access private
 */
class java_HttpTunnelHandler extends java_SimpleHttpTunnelHandler {
  // fallback for EmptyChannel, phase 1
  function fread($size) {
    if ($this->hasContentLength) 
        return fread($this->socket, $this->headers["content_length"]);
    else
        return parent::fread($size);
  }
  // fallback for EmptyChannel, phase 1
  function fwrite($data) {
    if ($this->hasContentLength) 
        return fwrite($this->socket, $data);
    else
        return parent::fwrite($data);
  }
  function close() {
    if ($this->hasContentLength) {
        fwrite($this->socket, "0\r\n\r\n");
        fclose($this->socket);
    } else {
        parent::fclose($this->socket);
    }
  }
}
/**
 * @access private
 */
class java_Protocol {
  public $client;
  public $webContext;
  public $serverName;

  function getOverrideHosts() {
      if(array_key_exists('X_JAVABRIDGE_OVERRIDE_HOSTS', $_ENV)) {
          $override = $_ENV['X_JAVABRIDGE_OVERRIDE_HOSTS'];
          if(!is_null($override) && $override!='/') return $override;
      }
      // fcgi: override for redirect
      return 
        java_getHeader('X_JAVABRIDGE_OVERRIDE_HOSTS_REDIRECT', $_SERVER);
  }
  static function getHost() {
    static $host = null;
    if(is_null($host)) {
      $hosts = explode(";", JAVA_HOSTS);
      $host = explode(":", $hosts[0]); // TODO: check host list
      
      // backward compatibility; changed from host:port to [ssl:]host:port
      while(count ($host) < 3) array_unshift($host, "");
      if (substr($host[1], 0, 2) == "//") $host[1] = substr($host[1], 2);
    }
    return $host;
  }
  function createHttpHandler() {
    $overrideHosts = $this->getOverrideHosts();
    $ssl = "";
    if($overrideHosts) {
      // handle "s:127.0.0.1:8080//JavaBridge/test.phpjavabridge" 
      // or "s:127.0.0.1:8080" 
      // or "/" 
      // or ""
     $s=$overrideHosts;
     if((strlen($s)>2) && ($s[1]==':')) {
       if($s[0]=='s')
         $ssl="ssl://";
       $s = substr($s, 2);
     }
     $webCtx = strpos($s, "//");
     if($webCtx)
       $host = substr($s, 0, $webCtx);
     else
       $host = $s;

     $idx = strpos($host, ':');
     if($idx) {
       if($webCtx)
         $port = substr($host, $idx+1, $webCtx);
       else
         $port = substr($host, $idx+1);
       $host = substr($host, 0, $idx);
     } else {
       $port = "8080";
     }
 
     if($webCtx) $webCtx = substr($s, $webCtx+1);
      $this->webContext = $webCtx;
    } else {
      $hostVec = java_Protocol::getHost();
      if ($ssl = $hostVec[0]) $ssl .= "://";
      $host = $hostVec[1];
      $port = $hostVec[2];
    }

    $this->serverName = "${ssl}${host}:$port";

    // short path S1: no PUT request
    if ((array_key_exists("X_JAVABRIDGE_REDIRECT", $_SERVER)) || 
        (array_key_exists("HTTP_X_JAVABRIDGE_REDIRECT", $_SERVER))) 
      return new java_SimpleHttpHandler($this, $ssl, $host, $port);

    return new java_HttpTunnelHandler($this, $ssl, $host, $port);
  }
  /**
   * connect to a local channel (no servlet engine or app server)
   */
  function createSimpleHandler($name, $again=true) {
    $channelName = $name;
    $errno = null; $errstr = null;
    if(is_numeric($channelName)) {
      $peer = @pfsockopen($host="127.0.0.1", $channelName, $errno, $errstr, 5);
    } else {
      $type = $channelName[0];
      list($host, $channelName) = explode(":", $channelName);
      $peer = pfsockopen($host, $channelName, $errno, $errstr, 20);
      if (!$peer) 
        throw new java_ConnectException("No Java server at $host:$channelName. Error message: $errstr ($errno)");
    }
    if (!$peer) {

      $java=file_exists(ini_get("extension_dir")."/JavaBridge.jar")?ini_get("extension_dir")."/JavaBridge.jar":(java_get_base()."/JavaBridge.jar");
      if (!file_exists($java)) 
        throw new java_IOException("Could not find $java in ".getcwd().". Download it from http://sf.net/projects/php-java-bridge/files/Binary%20package/php-java-bridge_".JAVA_PEAR_VERSION."/exploded/JavaBridge.jar/download and try again.");
      $java_cmd = "java -Dphp.java.bridge.daemon=true -jar \"${java}\" INET_LOCAL:$channelName 0"; 

      if (!$again) 
         throw new java_ConnectException("No Java back end! Please run it with: $java_cmd. Error message: $errstr ($errno)");

      if (!java_checkCliSapi()) 
        trigger_error("This PHP SAPI requires a JEE or SERVLET back end. Start it, define ('JAVA_SERVLET', true); define('JAVA_HOSTS', ...); and try again.", E_USER_ERROR);

      system ($java_cmd);

      return $this->createSimpleHandler($name, false);
    }
    stream_set_timeout($peer, -1);
    $handler = new java_SocketHandler($this, new java_SocketChannelP($peer, $host));

    $compatibility = java_getCompatibilityOption($this->client);
    $this->write("\177$compatibility");
    $this->serverName = "127.0.0.1:$channelName";
    return $handler;
  }
  function java_get_simple_channel() {
    return (JAVA_HOSTS&&(!JAVA_SERVLET||(JAVA_SERVLET=="Off"))) ? JAVA_HOSTS : null;
  }
  function createHandler() {
    if(!java_getHeader('X_JAVABRIDGE_OVERRIDE_HOSTS', $_SERVER)&&
       ((function_exists("java_get_default_channel")&&($defaultChannel=java_get_default_channel())) ||
        ($defaultChannel=$this->java_get_simple_channel())) ) {
      // if bind.c has started a local back end from Apache/IIS
      return $this->createSimpleHandler($defaultChannel);
    } else {
      return $this->createHttpHandler();
    }
  }
  function __construct ($client) {
    $this->client = $client;
    $this->handler = $this->createHandler();
  }

  function redirect() {
    $this->handler->redirect();
  }

  function read($size) {
    return $this->handler->read($size);
  }

  function sendData() {
    $this->handler->write($this->client->sendBuffer);
    $this->client->sendBuffer=null;
  }
  function flush() {
    if(JAVA_DEBUG) {echo "sending::: "; echo $this->client->sendBuffer; echo "\n";}
    $this->sendData();
  }
  function getKeepAlive() {
    return $this->handler->getKeepAlive();
  }
  function keepAlive() {
    $this->handler->keepAlive();
  }
  function handle() {
    $this->client->handleRequests();
  }
  function write($data) {
    $this->client->sendBuffer.=$data;
  }
  function finish() {
    $this->flush();
    $this->handle();
    $this->redirect();
  }
  
  function referenceBegin($name) {
    $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
    if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";}
    $this->client->preparedToSendBuffer=null;

    $signature=sprintf("<H p=\"1\" v=\"%s\">", $name);
    $this->write($signature);
    $signature[6]="2";
    $this->client->currentArgumentsFormat = $signature;
  }
  function referenceEnd() {
    $this->client->currentArgumentsFormat.=$format="</H>";
    $this->write($format);
    $this->finish();
    $this->client->currentCacheKey=null;
  }
  function createObjectBegin($name) {
    $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
    if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";}
    $this->client->preparedToSendBuffer=null;

    $signature=sprintf("<K p=\"1\" v=\"%s\">", $name);
    $this->write($signature);
    $signature[6]="2";
    $this->client->currentArgumentsFormat = $signature;
  }
  function createObjectEnd() {
    $this->client->currentArgumentsFormat.=$format="</K>";
    $this->write($format);
    $this->finish();
    $this->client->currentCacheKey=null;
  }
  function propertyAccessBegin($object, $method) {
    $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
    if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";}
    $this->client->preparedToSendBuffer=null;

    $this->write(sprintf("<G p=\"1\" v=\"%x\" m=\"%s\">", $object, $method));
    $this->client->currentArgumentsFormat="<G p=\"2\" v=\"%x\" m=\"${method}\">";
  }
  function propertyAccessEnd() {
    $this->client->currentArgumentsFormat.=$format="</G>";
    $this->write($format);
    $this->finish();
    $this->client->currentCacheKey=null;
  }
  function invokeBegin($object, $method) {
    $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
    if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";}
    $this->client->preparedToSendBuffer=null;

    $this->write(sprintf("<Y p=\"1\" v=\"%x\" m=\"%s\">", $object, $method));
    $this->client->currentArgumentsFormat="<Y p=\"2\" v=\"%x\" m=\"${method}\">";
  }
  function invokeEnd() {
    $this->client->currentArgumentsFormat.=$format="</Y>";
    $this->write($format);
    $this->finish();
    $this->client->currentCacheKey=null;
  }
  function resultBegin() {
    $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
    if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";}
    $this->client->preparedToSendBuffer=null;
    
    $this->write("<R>");
  }
  function resultEnd() {
    $this->client->currentCacheKey=null;
    $this->write("</R>");
    $this->flush();
  }
  function writeString($name) {
    $this->client->currentArgumentsFormat.=$format="<S v=\"%s\"/>";
    $this->write(sprintf($format, htmlspecialchars($name, ENT_COMPAT,"ISO-8859-1")));

  }
  function writeBoolean($boolean) {
    $this->client->currentArgumentsFormat.=$format="<T v=\"%s\"/>";
    $this->write(sprintf($format, $boolean));
  }
  function writeLong($l) {
    $this->client->currentArgumentsFormat.="<J v=\"%d\"/>";
    if($l<0) {
      $this->write(sprintf("<L v=\"%x\" p=\"A\"/>",-$l));
    } else {
      $this->write(sprintf("<L v=\"%x\" p=\"O\"/>",$l));
    }
  }
  function writeULong($l) {
    $this->client->currentArgumentsFormat.=$format="<L v=\"%x\" p=\"O\"/>";
    $this->write(sprintf($format,$l));
  }
  function writeDouble($d) {
    $this->client->currentArgumentsFormat.=$format="<D v=\"%.14e\"/>";
    $this->write(sprintf($format, $d));
  }
  function writeObject($object) {
    $this->client->currentArgumentsFormat.=$format="<O v=\"%x\"/>";
    $this->write(sprintf($format, $object));
  }

  /* the following routines are not cached */
  function writeException($object, $str) {
    $this->write(sprintf("<E v=\"%x\" m=\"%s\"/>",$object, htmlspecialchars($str, ENT_COMPAT,"ISO-8859-1")));
  }
  function writeCompositeBegin_a() {
    $this->write("<X t=\"A\">");
  }
  function writeCompositeBegin_h() {
    $this->write("<X t=\"H\">");
  }
  function writeCompositeEnd() {
    $this->write("</X>");
  }
  function writePairBegin_s($key) {
    $this->write(sprintf("<P t=\"S\" v=\"%s\">", htmlspecialchars($key, ENT_COMPAT,"ISO-8859-1")));
  }
  function writePairBegin_n($key) {
    $this->write(sprintf("<P t=\"N\" v=\"%x\">",$key));
  }
  function writePairBegin() {
    $this->write("<P>");
  }
  function writePairEnd() {
    $this->write("</P>");
  }
  function writeUnref($object) {
    $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
    $this->client->preparedToSendBuffer=null;
    $this->write(sprintf("<U v=\"%x\"/>", $object));
  }
  function writeExitCode($code) {
    $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
    $this->client->preparedToSendBuffer=null;
    $this->write(sprintf("<Z v=\"%x\"/>", 0xffffffff&$code));
  }

  function getServerName() {
    return $this->serverName;
  }
}
?>
VM Bridge API documentation generated by ApiGen