at 2005-05-17
in Examples
by friebe
(0 comments)
With the implementation of RFC #0022, a lot of new possibilities open up. I explored one of them this weekend: Integrating Java classes.
I installed JDK 1.5 by downloading the Windows webinstaller from java.sun.com and then choosing "Install all". After that, I uncommented the php_java.dll from the extensions list in php.ini and configured the Java library paths accordingly. The example script from the PHP manual worked out of the box
After playing around with the Java wrappers a bit, I noticed the following downsides:
- Static methods could not be called as such.
Prominent example: java.lang.Class::forName().
- Exceptions would not blend in nicely with the XP exceptions.
This is due to the fact that you need to check with java_last_exception_get() if there is an exception
- The new Java('classname', constructor_args) approach looks clumsy
I wanted Java proxy classes instantiation to look just like any other class.
- A var_dump() of the proxy instances showed nothing exciting
You'd only get something like object(java)(1) { [0] => 27 }
Considering the above list, I went ahead and wrote a uses wrapper. With this, we'd be able to load the classes just like XP classes, sort of like:
uses('java+xp://java.lang.Class'); The java wrapper now needs to be named sapi/java.uwrp.php so that lang.base.php can find it, so I created that file and began experimenting. My first idea was to create a wrapper-class on the fly in stream_open(). The class names need to be, of course, unique, and because there are so many classes in the XP framework with names identical to those in Java, I decided to name use the middle dot (·) to replace the dot (.) in the class names. Means: java.util.Date would become java·util·Date. This is possible as PHP permits quite a bit of characters to be used as class names
To catch the method calls, I'd use PHP4's overload extension on the wrapper. Problem is: Static method calls aren't intercepted, meaning that
$c= &java·lang·Class::forName($name); wouldn't trigger a user-defined __call() interceptor. OK, that rendered this approach useless.
The next idea I had was to use Java reflection to get a list of all methods and then create PHP wrappers for them. The Java reflection API offers Method.getModifiers() which returns a bitfield of modifiers (that is, public, private, protected, static, final, and so on), so that I'd be able to create different wrapper sourcecode based on whether a method was static or not. Or, in pseudo-code:
- Use java.lang.Class.forName() to retrieve a Class object
- Iterate over the results of its getMethods() method
- Check modifiers for ($modifiers & 8)
- Create wrapper function if not already existant (hint: method overloading!)
This approach worked!
Here's what I used to test my sourcecode:
require('lang.base.php'); uses('java+xp://java.lang.Class');
try(); { $c= &java·lang·Class::forName($argv[1]); } if (catch('Exception', $e)) { $e->printStackTrace(); exit(0); } echo 'new '.$c->getName().'()= '; $d= &$c->newInstance(); var_dump($d->toString()); Here's what the above script outputs:
$ php java.php java.util.Date new java.util.Date()= string(29) "Tue May 17 21:46:12 CEST 2005" You'll find the uses wrapper at http://xp-framework.net/downloads/java.uwrp.phps - it needs to be saved to sapi/java.uwrp.phps.
There's still some bugs within this wrapper, but maybe you're encouraged to play around with it. I don't consider this particularily useful for the general case, because we can do almost everything Java can (why would I want to use java.util.Date, for example?) - but if you find this important, you might up writing an RFC
|
Subscribe
You can subscribe to the XP framework's news by using RSS syndication.
CategoriesNews General PHP5 Announcements RFCs Further reading Examples Editorial EASC Experiments Unittests Databases 5.8-SERIES Unicode Language 5.9-SERIES
RelatedFind related articles by a search for «Java».
|