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 | What is the PHP/Java Bridge?
----------------------------
The PHP/Java Bridge is PHP module which connects the PHP object system
with the java object system. It implements JSR 223 (where applicable)
and can be used to access java based applications from PHP
scripts. The PHP/Java Bridge communicates with the java VM through
local sockets using an efficient communication protocol. Each
request-handling PHP process of a multi-process HTTP server
communicates with a corresponding thread spawned by the java VM.
Requests from more than one client may either be routed to a single
application server running the PHP/Java Bridge or each client may
own a PHP/Java Bridge and communicate with a J2EE application server
by exchanging java value objects; client stub classes (ejb/j2ee client .jar)
can be loaded at run-time.
The bridge adds the following primitives to PHP:
* new java("CLASSNAME"): References and instanciates the class
CLASSNAME. After script execution the referenced classes may be
garbage collected. Example:
$String = new java("java.lang.String");
print $String->valueOf(null);
$hello = new java("java.lang.String", "hello");
print $hello;
// access the inner class AQUA within HSSFColor, note the $ syntax.
$Color = new java('org.apache.poi.hssf.util.HSSFColor$AQUA');
print $Color->index;
* new java_class("CLASSNAME"): References the class CLASSNAME
without creating an instance. The object returned is the class object
itself, not an object of the class. After script execution the
referenced classes may be garbage collected. Example:
$Object = new java_class("java.lang.Object");
$obj = $Object->newInstance();
* java_set_library_path("JAR1;JAR2"): Makes additional libraries
available to the current script. JAR can either be a "http:", "ftp:",
"file:" or a "jar:" location. Example:
$file=new java("java.io.File", "WEB_INF/web.xml");
java_set_library_path("file:c:/xerces.jar;http://localhost/jdom.jar");
$builder = new java("org.jdom.input.SAXBuilder");
$doc = $builder->build($file);
$root = $doc->getRootElement();
$servlets = $root->getChildren("servlet");
java_set_library_path("");
echo "this file has " . $servlets->size() . " servlets\n";
* java_exception: A java exception class. Available in PHP 5 and
above only. Example:
try {
new java("java.lang.String", null);
} catch(java_exception $ex) {
$trace = new java("java.io.ByteArrayOutputStream");
$ex->printStackTrace(new java("java.io.PrintStream", $trace));
print "java stack trace: $trace\n";
}
* foreach(COLLECTION): It is possible to iterate over values of
java classes that implement java.util.Collection or
java.util.Map. Available in PHP 5 and above only. Example:
$conversion = new java("java.util.Properties");
$conversion->put("long", "java.lang.Byte java.lang.Short java.lang.Integer");
$conversion->put("boolean", "java.lang.Boolean");
foreach ($conversion as $key=>$value)
echo "$key => $value\n";
* [index]: It is possible to access elements of java arrays or
elements of java classes that implement the java.util.Map
interface. Available in PHP 5 and above only. Example:
$Array = new java_class("java.lang.reflect.Array");
$String = new java_class("java.lang.String");
$entries = $Array->newInstance($String, 3);
$entries[0] ="Jakob der Luegner, Jurek Becker 1937--1997";
$entries[1] ="Mutmassungen ueber Jakob, Uwe Johnson, 1934--1984";
$entries[2] ="Die Blechtrommel, Guenter Grass, 1927--";
for ($i = 0; $i < $Array->getLength($entries); $i++) {
echo "$i: " . $entries[$i] ."\n";
}
* java_instanceof(JAVA_OBJ, JAVA_CLASS): Tests if JAVA_OBJ is an
instance of JAVA_CLASS. Example:
$Collection=new java_class("java.util.Collection");
$list = new java("java.util.ArrayList");
$list->add(0);
$list->add(null);
$list->add(new java("java.lang.Object"));
$list->add(new java("java.util.ArrayList"));
foreach ($list as $value) {
if($value instanceof java && java_instanceof($value, $Collection))
/* iterate through nested ArrayList */
else
echo "$value\n";
}
* java_get_server_name(): Returns the name:<socket> of the server used by
this php instance. Example:
if(!($name=java_get_server_name())) {
echo "We're sorry, the java service is not available.\n";
exit(1);
} else {
echo "Java backend available on $name.\n";
}
* java_last_exception_get(): Returns the last exception instance
or null. Since PHP 5 you can use try/catch instead.
* java_last_exception_clear(): Clears the error condition. Since
PHP 5 you can use try/catch instead.
There is one example provided: test.php. You can either invoke the
test.php by typing ./test.php or copy the example into the document
root of you web server and evaluate the file using the browser.
The PHP/Java bridge is a replacement for the experimental ext/java
bridge shipped with PHP 4. It is not possible to run the build-in
bridge and the PHP/Java bridge at the same time.
The module has been tested on a Mandrake Linux System (Version 9.2),
on RedHat Enterprise 3, RedHat Fedora Core 1..3, Solaris 9..10 (Sparc,
64 bit JVM), FreeBSD 5.3 and Windows with RedHat Cygwin, but it should
run on all Unix-like operating systems including HP-UX, WinXP.
Custom java libraries (.jar files) can be stored in the following
locations:
1. Somewhere on a HTTP or FTP server, see PHP function
java_set_library_path.
2. In the sub-directory "lib" of the PHP extension directory, if it
exists and is accessible when the JVM starts the bridge.
This is usually "`php-config --extension-dir`/lib".
3. In the /usr/share/java/ directory, if it exists and is accessible
when the JVM starts the bridge.
The PHP/Java Bridge can operate in 3 different modes:
1. Invoked from the dl() function. In this mode the bridge starts
when the HTTP server receives a client request and terminates after
the response is written. This is very slow because it starts a new
Java VM for each request. But it does not require any administrative
privileges.
2. Permanently activated in the global php.ini file with an
internal java process running in the HTTP server domain. In this mode
the bridge starts when the HTTP server starts and terminates when the
HTTP server terminates. Recommended during development.
3. Permanently activated in the global php.ini file with an
external java process. Recommended for production systems. This mode
is used by the RPM package available for RedHat Enterprise Linux. In
this mode the bridge starts and stops as a system service.
Furthermore the PHP/Java Bridge can be:
* Compiled into PHP. This is not recommended because it requires a
compilation of the entire PHP library. If you want to do this, please
read the README file. This should only be necessary if the OS does not
support shared libraries.
* Compiled with the GNU Java library. You can either start GNU Java
as a separate process (just like a "real" Java VM) or compile
everything into a PHP binary. This should only be necessary if there
is no official JRE available for the OS or one doesn't want to ship a
JRE with the product.
* Compiled with Novell's MONO (a ".NET" clone). This is currently
experimental.
Build and execution instructions:
---------------------------------
In the directory php-java-bridge-1.x.y type:
java -version # 1.3 or above (1.4.2_02 or IBM JVM recommended)
gcc --version # 3.2.3 or above.
apachectl -version # Apache 1.3 or above.
php-config --version # PHP 4.3.2 or above.
make null --version # GNU make 3.79 or above
phpize &&
./configure --with-java=/opt/IBMJava2-14 &&
make &&
su -c "make install"
If your administrator allows you to dynamically load extensions, you
can now test the extension by invoking the test.php with the
command: php ./test.php.
Please see the output of ./configure --help=recursive for further
configure options.
------------------------------------
Permanently activate the module
-------------------------------
To permanently activate the extension for all users please add the
following lines to the php.ini or add a file java.ini to the
directory that contains the php module descriptions (usually
/etc/php.d/) with the following content:
extension = java.so
[java]
java.log_level="3"
java.log_file="/var/log/php-java-bridge.log"
java.socketname="/var/run/.php-java-bridge_socket"
#java.hosts="localhost:9167;192.168.6.30:8009"
Re-start the web server, for example with the command:
apachectl restart
OPTION 1: You can use local sockets to connect to a local backend.
Copy the executable php-java-bridge to /usr/sbin and start it with
the command:
sh /usr/sbin/php-java-bridge
This is the only option available on Security Enhanced Linux.
OPTION 2: You can use TCP/IP sockets to communicate with different
backends on different hosts. Disable the java.socketname option,
edit and enable the java.hosts option and re-start the web server.
Start the backends on all hosts, for example with the command:
java -jar JavaBridge.jar INET:9167 3 ""
On Security Enhanced Linux the communication via TCP/IP sockets is
switched off for security reasons.
OPTION 3: You can start the bridge as a sub-process of apache. Disable
java.hosts and java.socketname, re-start apache and check if apache
has started java as a sub-process. For example with the commands:
apachectl restart
pstree | fgrep httpd
Starting or re-starting the bridge with the apache web server is
convenient during development but not recommended for production
systems, see UTF-8 section below. This option cannot be used on
Security Enhanced Linux.
Check the status:
echo "<?php phpinfo()?>" | php | fgrep "java status"
Other configuration options which should have been set up by the
configure script but which can be changed later are:
java.libpath = <system dependent path to natcJavaBridge.so>
java.classpath = <system dependent path to JavaBridge.jar>
java.java_home = <system dependent path to the java install dir>
java.java = <system dependent path to the java binary>
java.socketname= <hard-coded socketname to start the VM separately>
java.hosts = <add. bridge hosts e.g.: server1:8091;server2:9001>
Please first look at the output of phpinfo() to see the original
values.
The java.hosts setting specifies additional hosts running the
PHP/Java Bridge. If not set or if the bridge cannot connect to one of
these servers nor to java.socketname, the bridge will start a private
java VM.
---------------------------------------------
Starting the PHP/Java Bridge automatically
------------------------------------------
When the java.socketname option is not set, the web server will
start or re-start the bridge automatically as a sub-component when the
http service is started or re-started.
However, when running the bridge in a production environment, it is
recommended to start the PHP/Java Bridge as a system service,
independent of the web server. The script "php-java-bridge.service"
can be used on SysV based init systems to automatically start and stop
the bridge as a system service. Please see the RedHat RPM download
for an example.
---------------------------------------------
Deploying into a J2EE/EJB server
--------------------------------
The following description applies to the Sun J2EE application
server.
1. Start your application server, for example with the command:
$app_server/bin/asadmin start-domain domain1
2. Log into your application server, for example by visiting
http://localhost:4848/asadmin
and open
Application Server -> Applications -> EJB Modules
Click on "Deploy..." and deploy JavaBridge.jar.
3. Direct the PHP/Java Bridge to the application server by setting
the java.hosts to the application server host. For example:
java.hosts=SERVER1
4. Re-start apache to activate the new setting.
------------------------------------
64 Bit issues
-------------
It is possible to compile the bridge into 64 bit code:
phpize && ./configure --with-java=$JAVA_HOME
make CFLAGS="-m64"
The scripts expect that the default JVM found in
$JAVA_HOME/bin/java is a 64 bit VM. Unfortunately this is not true
for the SUN JDK (Linux and Solaris) installation. The SUN JDK
installs the 64 bit VM in some sub-directory of $JAVA_HOME/bin. On
Solaris9 this is $JAVA_HOME/bin/sparcv9. The location on Linux may
depend on the architecture.
Since there is no standard installation directory and we cannot
blindly search all sub-directories, it is your job to direct the
bridge to the 64 bit JVM. The relevant php.ini entry is java.java,
see install instructions above.
------------------------------------
Windows Installation
--------------------
This operating system has some unusal problems with shared libraries
(DLL's). The autoconf/libtool documentation states:
- Macro: AC_LIBTOOL_WIN32_DLL
This macro should be used if the package has been ported to build
clean dlls on win32 platforms. Usually this means that any
library data items are exported with `__declspec(dllexport)' and
imported with `__declspec(dllimport)'. If this macro is not used,
libtool will assume that the package libraries are not dll clean
and will build only static libraries on win32 hosts.
Until someone ports the sources to use __declspec, we avoid
creating shared libraries on this system. Instead we will
compile the extension into PHP:
1. Install the source code of PHP 4.3.x.
2. Install RedHat's Cygwin (PHP needs autoconf).
3. Delete the java sub-directory from php-4.3.x/ext and replace it
with our php-java-bridge. Rename ext/php-java-bridge to
ext/java. Update the "m4_include" paths in
php-4.3.x/ext/java/config.m4 so that they start with "ext/java/":
m4_include(ext/java/tests.m4/function_checks.m4)
m4_include(ext/java/tests.m4/java_check_broken_stdio_buffering.m4)
...
m4_include(ext/java/tests.m4/java_check_broken_gcc_installation.m4)
4. Invoke autoconf to register our java module within the PHP build
tree:
buildconf.bat --force
Instead of running "buildconf" you can also use autoconf directly:
aclocal && autoheader && autoconf && libtoolize -f && automake
Then configure and compile php as usual:
./configure --with-java=%JAVA_HOME%
make
This will create a php binary with the PHP/Java Bridge included.
You can then copy the executable into the CGI directory of your IIS
web server.
To also install the server part into the modules directory:
make install
make install-modules
Windows uses TCP/IP sockets instead of unix domain sockets. If you
want to change the java.socketname from its default (which is 9167),
you must use an integer. For example:
java.socketname=9168
------------------------------------
Loading on-demand with dl()
---------------------------
It is possible to load the bridge for each new request, for example
with:
<?php
if (!extension_loaded('java')) {
if (!dl("java.so")) {
exit(1);
}
}
phpinfo();
?>
However, this feature is meant for testing, only. For a production
system it is recommended to compile PHP in save mode (which switches
off the dl() function) and to activate all modules in the global
php ini file.
------------------------------------
Recognized CFLAGS
-----------------
During compilation you can use the following CFLAGS.
* -DJAVA_COMPILE_DEBUG: Enables the assert() statement and other
debug code.
* -DJAVA_COMPILE_DEBUG -O0 -g3: Include full debug information into
the binary.
* -m64: Build 64 bit code. Required if you run a 64 bit JVM.
* -m32: Build 32 bit code. Required if you run a 32 bit JVM on a 64
bit system.
* -DCFG_JAVA_SOCKET_INET: Disables local ("unix domain")
sockets on systems which support them.
Example: make CFLAGS="-m64"
------------------------------------
Log levels
----------
You can set the java.log_level to 5 values:
0: Log nothing, not even fatal errors.
1: Log fatal system errors such as "out of memory error".
2: Log java exceptions.
3: Log info messages such as "loading jar xyz.jar from http://xy.com"
4: Log debug messages, including the c/s communication protocol.
The default log level is 1.
------------------------------------
UTF-8
-----
The PHP/Java Bridge uses the java VM's default "file.encoding" to
convert characters into the host representation. On Unix the java VM
determines the host representation by looking at the LANG environment
variable.
In order to use UTF-8 in your PHP scripts, the LANG environment
variable must be set to an UTF-8 locale, for example en_US.UTF-8. This
is default on all modern operating systems, but certain components may
select a different locale. Apache for example runs with the C locale
and if the PHP/Java bridge is started automatically as a sub-component
of apache, it will inherit this setting. -- This is one of the reasons
why it is recommended to start the bridge as a system service outside of
apache.
You can check the file.encoding with the test.php script, see above.
------------------------------------
Macintosh/PPC Installation
--------------------------
The PHP/Java Bridge doesn't compile on OSX 10.2 or earlier because
certain functionality (sys/poll) is missing. OSX 10.3 has issues
with the dynamic loader and the Apple Java VM, which cannot run
the bridge reliably.
If you want to run the Bridge on a PPC, please install IBM java
1.4.1 or above on RedHat Enterprise Linux for Power PC, please see
http://www-106.ibm.com/developerworks/java/jdk/linux/tested.html
for details.
---------------------------------------------
GCJ/GNU Java issues
-------------------
gcc3.4 cannot invoke virtual functions from jni code. Please apply
the gcc3.4-broken-jni-method-lookup.patch or use gcc 3.3.3 or gcc 4.x
instead.
Running the PHP/Java Bridge under GCJ/GNU Java is supported on Linux
and Solaris only. If you run FreeBSD 5.3, please use Sun, Blackdown
or IBM java instead.
------------------------------------
Security Enhanced Linux
-----------------------
SELinux is an implementation of a flexible and fine-grained
mandatory access control architecture implemented in the Linux kernel.
It is used in recent Linux distributions such as Debian or RedHat
Fedora Core 3.
A system component running on a SELinux kernel must declare
exactly a) which resources of the operating system it needs in order
to function properly and b) what it provides to other components.
The PHP/Java Bridge distribution contains two policy files,
"php-java-bridge.te" and "php-java-bridge.fc". The
"php-java-bridge.te" declares the javabridge_t domain and the
resources it requires. httpd and user domains are granted connect,
read and write to the PHP/Java Bridge server socket, which is
"@var/run/.php-java-bridge_socket" in the Linux abstract namespace,
and file create/read/write in the tmp_t. Everything else (connections
to other servers, file access, ...) is currently denied.
The "php-java-bridge.fc" contains the file contexts for the PHP/Java
Bridge and the log.
Installation:
-------------
The following discussion assumes that you have a RedHat Linux system
and you are running SELinux with the targeted policy.
1. Install selinux-policy-targeted-sources-*.rpm, for example with
the command:
rpm -i selinux-policy-targeted-sources-1.17.30-2.19.noarch.rpm
2. Update the policy files with the PHP/Java Bridge policy:
su -c "sh update_policy.sh /etc/selinux/targeted/src/policy"
If the default policy is too restrictive and e.g. you want to use the
PHP/Java Bridge to connect to your J2EE server(s), you can temporarily
set the policy to "permissive", for example with the command "setenforce
Permissive". Connect to the server, then extract the permissions
from the audit log, for example with the command "audit2allow -d", then
append them at the end of the "php-java-bridge.te" file and load the
updated policy into the kernel. Don't forget to switch back, for
example with "setenforce Enforcing".
------------------------------------
PHP 5 issues
------------
All known PHP 5 versions crash when the dl() function is used. They
first unload the module and then try to invoke its shutdown method.
If you use one of these versions, please either apply the
php5-crash-in-evaluator-shutdown_workaround.patch or add an entry to
the php.ini, see install instructions above.
------------------------------------
Mailing List
------------
Please report bugs/problems to the mailing list:
php-java-bridge-users@lists.sourceforge.net
|