Read Me
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_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 5 different modes:
1. Invoked from the dl() function. This is very slow because it
starts a new Java VM for each request. But this mode does not
require any administrative privileges.
2. Compiled into PHP. This is not recommended because it
requires a compilation of the entire PHP library. If you want to
do this, please see the Windows install description below.
3. Permanently activated in the global php.ini file and started as
a sub-component of the HTTP server. Recommended for test
installations only.
4. Permanently activated in the global php.ini file with an
external java process. Recommended for production servers, see
below. This mode is used by the RPM package available for RedHat
Enterprise Linux.
5. Compiled with the GNU Java library. You can either start
GNU Java as a separate process (just like a "real" Java VM) or
compile the GNU Java library into the PHP/Java Bridge.
You can even compile the PHP/Java Bridge + GNU/Java directly
into PHP to create a huge PHP binary or library.
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=1
java.log_file=/var/log/php-java-bridge.log
# Comment out the following option if you want to
# start the bridge automatically as a sub-process
# of the web-server, not recommended
java.socketname=/var/run/.php-java-bridge_socket
Re-start the web-server, for example with the command:
apachectl restart
Copy the php-java-bridge executable into the /usr/sbin directory
and start the bridge, if it isn't already running.
sh /usr/sbin/php-java-bridge
After the module is activated verify that the module is running by
typing:
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.class>
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>
If you change the above values, please first look at the output of
phpinfo() to see the original values.
---------------------------------------------
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.
------------------------------------
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 9047),
you must use an integer. For example:
java.socketname=8009
The host is currently hard-coded (in natcJavaBridge.c and in java.c)
to 127.0.0.1, which is the local interface. You can change this,
for example if you want to run the server part of the bridge on a
unix machine, but opening a port on a web-server can be dangerous.
Furthermore it is possible to compile the server part of the bridge
for a win32 target on any unix operating system by using a cross
compiler:
cd server
/opt/jdk1.4/bin/javac JavaBridge.java
i386-pc-mingw32-gcc -I. -DEXTENSION_DIR=\".\" -c natcJavaBridge.c
i386-pc-mingw32-dllwrap --export-all-symbols -k \
-o natcJavaBridge.dll natcJavaBridge.o -lws2_32
After that you can copy natcJavaBridge.dll and JavaBridge*.class to
your windows machine and start the server part of the bridge as usual,
for example with:
c:\jdk1.4\bin\java.exe JavaBridge 9047 3 ""
------------------------------------
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_INPROCESS: Do not use exec() but call the JVM directly.
Experimental.
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 Mac/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" and 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
------------
Versions 5.0.0 up to 5.0.3RC cannot load the Bridge from the dl()
function. 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