IDMLlib for Java with PHP

May 20th, 2010 by ohaeuser

Hier finden Sie die deutsche Version dieses Artikels.

Since we did have a couple of requests by PHP coders to work with IDML, IDMLlib and PHP we took a look at the PHP JavaBridge Project on Sourceforge.

To make a long story short – it seems to work ok :-) We will try out some more complex examples to see how stable everything is.

Here is my recipe to make IDMLlib for Java work with apache2, tomcat6, java6 and php5.

Updates for this article:

2010-08-29:

  • Missing JavaBridge: Of course you need the JavaBridge by itself – this was not very clear so far.
  • Inserted the Download Link for the binary Package of the JavaBridge.war
  • Init Script: Missing tomcat policy files for the Init Script
  • Added warning about the right naming of the idmllib.jar

In order to use the IDMLlib for Java with PHP you need the following components:

  • Of course the IDMLlib for Java which you can request from http://idmllib.com
  • A working apache2 and php5 Setup as well as a tomcat 6 Installation.
  • And last but not least the PHP-Java Bridge.

For this tutorial I will use a debian 5 Lenny setup. But you can use the configuration hints for anything else be it Windows, Mac OS X, Redhat Linux, Suse Linux or whatever runs Java, Apache2, Tomcat 6 and PHP.

1 Debian Linux

Install a basic debian Lenny distribution.

Make sure you have non-free in your apt.sources list.

deb http://debian.uni-essen.de/debian/ lenny main non-free
deb-src http://debian.uni-essen.de/debian/ lenny main non-free

deb http://security.debian.org/ lenny/updates main contrib non-free
deb-src http://security.debian.org/ lenny/updates main contrib non-free

2 Install apache2 and php5

 apt-get install apache2 php5 libapache2-mod-php5 php5-cli php5-common php5-cgi

3 Install Tomcat6

Since there is not tomcat6 debian package available we install tomcat6 manually.

apt-get install sun-java6-jdk
echo 'JAVA_HOME="/usr/lib/jvm/java-6-sun"' | tee -a /etc/environment

For wget insert the latest URL for the latest tomcat version!

wget http://tomcat.apache.org/download-60.cgi
tar xfvz apache-tomcat-6.0.24.tar.gz
mkdir /opt/tomcat6
groupadd -g 109 tomcat6
useradd -b /opt/tomcat6 -g tomcat6 -s /bin/false -u 109 tomcat6

Install the Jakarta Commons Daemon

apt-get install jsvc

And create an Initscript to Start and Stop tomcat6.

/etc/init.d/tomcat6

#!/bin/sh
#
# /etc/init.d/tomcat6 -- startup script for the Tomcat 5 servlet engine
#
# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
# Modified for Debian GNU/Linux by Ian Murdock <imurdock@gnu.ai.mit.edu>.
# Modified for Tomcat by Stefan Gybas <sgybas@debian.org>.
# Modified for Tomcat 6 by ohaeuser - 16.02.2009
### BEGIN INIT INFO
# Provides:          tomcat
# Required-Start:    $local_fs $remote_fs $network
# Required-Stop:     $local_fs $remote_fs $network
# Should-Start:      $named
# Should-Stop:       $named
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start Tomcat.
# Description:       Start the Tomcat servlet engine.
### END INIT INFO
 
set -e
 
PATH=/bin:/usr/bin:/sbin:/usr/sbin
NAME=tomcat6
DESC="Tomcat servlet engine"
DAEMON=/usr/bin/jsvc
CATALINA_HOME=/opt/$NAME
DEFAULT=/etc/default/$NAME
 
if [ `id -u` -ne 0 ]; then
        echo "You need root privileges to run this script"
        exit 1
fi
 
# Make sure tomcat is started with system locale
if [ -r /etc/default/locale ]; then
        . /etc/default/locale
        export LANG
fi
 
. /lib/lsb/init-functions
. /etc/default/rcS
 
# The following variables can be overwritten in $DEFAULT
 
# Run Tomcat 5 as this user ID
TOMCAT6_USER=tomcat6
 
# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not
# defined in $DEFAULT)
JDK_DIRS="/usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm /usr/lib/j2sdk1.4-sun /usr/lib/j2sdk1.4-blackdown
/usr/lib/j2se/1.4 /usr/lib/j2sdk1.4-ibm /usr/lib/j2sdk1.3-sun /usr/lib/j2sdk1.3-blackdown /usr/lib/jvm/java-gcj /usr/lib/kaffe"
 
# Look for the right JVM to use
for jdir in $JDK_DIRS; do
    if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
        JAVA_HOME_TMP="$jdir"
        # checks for a real JDK like environment, needed to check if
        # really the java-gcj-compat-dev package is installed
        if [ -r "$jdir/bin/jdb" ]; then
            JAVA_HOME="$JAVA_HOME_TMP"
        fi
    fi
done
export JAVA_HOME
 
# Directory for per-instance configuration files and webapps
CATALINA_BASE=/opt/$NAME
 
# Use the Java security manager? (yes/no)
TOMCAT6_SECURITY=yes
 
# Timeout in seconds for the shutdown of all webapps
TOMCAT6_SHUTDOWN=30
 
# End of variables that can be overwritten in $DEFAULT
 
# overwrite settings from default file
if [ -f "$DEFAULT" ]; then
        . "$DEFAULT"
fi
 
test -f $DAEMON || exit 0
 
[ -z "$TOMCAT6_USER" ] && TOMCAT6_USER=tomcat6
 
# Check if we use gij
gij=no
"$JAVA_HOME/bin/java" -version 2>&1 | grep -q "^gij (GNU libgcj)" && gij=yes
 
# gij doesn't support a security manager yet (see bug #399595)
if [ "$gij" = "yes" ]; then
    printf "The java-gcj-compat-dev environment currently doesn't\nsupport a security manager. See README.Debian." | logger -p daemon.warning -t $NAME
fi
 
# Set java.awt.headless=true if JAVA_OPTS is not set so the
# Xalan XSL transformer can work without X11 display on JDK 1.4+
# It also looks like the default heap size of 64M is not enough for most cases
# se the maximum heap size is set to 128M
if [ -z "$JAVA_OPTS" ]; then
        JAVA_OPTS="-Djava.awt.headless=true -Xmx128M"
fi
 
JAVA_OPTS="$JAVA_OPTS -Djava.endorsed.dirs=$CATALINA_HOME/common/endorsed -Dcatalina.base=$CATALINA_BASE -Dcatalina.home=$CATALINA_HOME
-Djava.io.tmpdir=$CATALINA_BASE/temp"
 
# Set the JSP compiler if set in the tomcat6.default file
if [ -n "$JSP_COMPILER" ]; then
        JAVA_OPTS="$JAVA_OPTS -Dbuild.compiler=$JSP_COMPILER"
fi
 
if [ "$TOMCAT6_SECURITY" = "yes" ]; then
        JAVA_OPTS="$JAVA_OPTS -Djava.security.manager -Djava.security.policy=$CATALINA_BASE/conf/catalina.policy"
fi
 
# juli LogManager disabled if running under gij (see bug #395167)
if [ "$gij" != "yes" ]; then
        JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
                   -Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties"
fi
 
# Define other required variables
CATALINA_PID="/var/run/$NAME.pid"
BOOTSTRAP_CLASS=org.apache.catalina.startup.Bootstrap
JSVC_CLASSPATH="/usr/share/java/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar"
 
# Look for Java Secure Sockets Extension (JSSE) JARs
if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then
    JSSE_HOME="${JAVA_HOME}/jre/"
fi
export JSSE_HOME
 
echo $JSSE_HOME
 
case "$1" in
  start)
        if [ -z "$JAVA_HOME" ]; then
                log_failure_msg "no JDK found - please set JAVA_HOME"
                exit 1
        fi
 
        if [ ! -d "$CATALINA_BASE/conf" ]; then
                log_failure_msg "invalid CATALINA_BASE specified"
                exit 1
        fi
 
 log_daemon_msg "Starting $DESC" "$NAME"
        if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
                --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
                >/dev/null; then
 
                # Create catalina.policy (for the security manager)
                rm -f "$CATALINA_BASE/conf/catalina.policy"
                umask 022
                echo "// AUTO-GENERATED FILE -- DO NOT EDIT!" \
                        > "$CATALINA_BASE/conf/catalina.policy"
                echo "// Edit the files in /opt/tomcat6/conf/policy.d/ instead" \
                        >> "$CATALINA_BASE/conf/catalina.policy"
                echo ""  >> "$CATALINA_BASE/conf/catalina.policy"
                cat /opt/tomcat6/conf/policy.d/*.policy \
                        >> "$CATALINA_BASE/conf/catalina.policy"
 
                # Clean up and set permissions on required files
                find "$CATALINA_BASE"/temp/ -mindepth 1 -exec rm -fr {} +
                REQUIRED_FILES='"$CATALINA_BASE/conf"
                        "$CATALINA_BASE/logs" "$CATALINA_BASE/temp"
                        "$CATALINA_BASE/webapps" "$CATALINA_BASE/work"'
                if [ -e "$CATALINA_BASE/conf/tomcat-users.xml" ]; then
                        REQUIRED_FILES=$REQUIRED_FILES'
                                "$CATALINA_BASE/conf/tomcat-users.xml"'
                fi
                eval chown --dereference "$TOMCAT6_USER" $REQUIRED_FILES \
                        || true
 
                cd "$CATALINA_BASE/temp"
 
                $DAEMON -user "$TOMCAT6_USER" -cp "$JSVC_CLASSPATH" \
                    -outfile SYSLOG -errfile SYSLOG \
                    -pidfile "$CATALINA_PID" $JAVA_OPTS "$BOOTSTRAP_CLASS"
 
else
                log_progress_msg "(already running)"
        fi
        log_end_msg 0
        ;;
  stop)
        log_daemon_msg "Stopping $DESC" "$NAME"
        if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
                --user "$TOMCAT6_USER" --startas "$JAVA_HOME/bin/java" \
                >/dev/null; then
                log_progress_msg "(not running)"
        else
                $DAEMON -cp "$JSVC_CLASSPATH" -pidfile "$CATALINA_PID" \
                     -stop "$BOOTSTRAP_CLASS"
        fi
        log_end_msg 0
        ;;
   status)
        if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
                --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
                >/dev/null; then
 
                if [ -f "$CATALINA_PID" ]; then
                    log_success_msg "$DESC is not running, but pid file exists."
                else
                    log_success_msg "$DESC is not running."
                fi
        else
                log_success_msg "$DESC is running with pid `cat $CATALINA_PID`"
        fi
        ;;
 
restart|force-reload)
        if start-stop-daemon --test --stop --pidfile "$CATALINA_PID" \
                --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
                >/dev/null; then
                $0 stop
                sleep 1
        fi
        $0 start
        ;;
  try-restart)
        if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
                --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
                >/dev/null; then
                $0 start
        fi
        ;;
  *)
        log_success_msg "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
        exit 1
        ;;
esac
 
exit 0

And for some default Settings the /etc/defaults/tomcat6:

# Modified for tomcat6 16.02.2009 - ohaeuser
# Run Tomcat as this user ID. Not setting this or leaving it blank will use the
# default of tomcat6.
#TOMCAT6_USER=tomcat6
 
# The home directory of the Java development kit (JDK). You need at least
# JDK version 1.4. If JAVA_HOME is not set, some common directories for
# the Sun JDK, various J2SE 1.4 versions, and the free runtimes
# java-gcj-compat-dev and kaffe are tried.
JAVA_HOME=/usr/lib/jvm/java-6-sun
 
# Directory for per-instance configuration files and webapps. It contain the
# directories conf, logs, webapps, work and temp. See RUNNING.txt for details.
# Default: /var/lib/tomcat5.5
CATALINA_BASE=/opt/tomcat6
 
# Arguments to pass to the Java virtual machine (JVM).
#JAVA_OPTS="-Djava.awt.headless=true -Xmx128M"
JAVA_OPTS="-Djava.awt.headless=true -Xms256m -Xmx512m -XX:MaxPermSize=256m -Dlog.home=$CATALINA_BASE -Dsolr.solr.home=/home/solr -Dcom.idmllib.license=ILJD10-xxxx-xxxx-xxxx-xxxx"
 
# Java compiler to use for translating JavaServer Pages (JSPs). You can use all
# compilers that are accepted by Ant's build.compiler property.
#JSP_COMPILER=jikes
 
# Use the Java security manager? (yes/no, default: yes)
# WARNING: Do not disable the security manager unless you understand
# the consequences!
# NOTE: java-gcj-compat-dev currently doesn't support a security
# manager.
TOMCAT6_SECURITY=no
#Export for AWT
#export LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/amd64/

The most important line is this one:

JAVA_OPTS=”-Djava.awt.headless=true -Xms256m -Xmx512m -XX:MaxPermSize=256m -Dlog.home=$CATALINA_BASE -Dsolr.solr.home=/home/solr -Dcom.idmllib.license=ILJD10-xxxx-xxxx-xxxx-xxxx”

It configures memory settings you might need plus it sets the IDMLlib license flag.

-Dcom.idmllib.license=ILJD10-xxxx-xxxx-xxxx-xxxx

You need a valid license key which you can get from http://idmllib.com

Something that is missing here: The Init Script looks under tomcat/conf/policy.d for missing Policy files. Either uncomment the line who tries to load the policies. Or add the files. A simple way is too install a debian tomcat like tomcat5.5 and just use the policy.d folder for a good start for your own stuff!

4 Check if the basic setup is working

Create a info.php file in your apache2 web root.

 <?php phpinfo() ?>

And test if apache2 and php is working: http://server_ip/index.php

If you see the php Infopage – everything is working!

phpinfo Apache2 status page

Now test is the tomcat 6 is installed by trying: http://server_ip:8080/

If you see the default tomcat Status page  we can start to setup the PHP JavaBridge.

5 PHP-JAVA-Bridge Templatefile

This is the main page from the project:  http://php-java-bridge.sourceforge.net/

You need the main Package here which is called JavaBridg.war – Download this and put it into your webapps folder.

It’s in the document Package: http://sourceforge.net/projects/php-java-bridge/files/Binary%20package/php-java-bridge_6.2.1rc2/php-java-bridge_6.2.1rc2_documentation.zip/download

Unzip this and cop the JavaBridge.war file to our Tomcat webapps. There is a README in it that mentions alternative ways. I have not tried this so you are on your own there.
But it is working with a Tomcat 6 and Java 6 great.

Now you download your own template war which you will rename and where you put the IDMlib.jar into it.

You need a JavaBridgeTemplate.war File: http://sourceforge.net/projects/php-java-bridge/files/Binary%20package/php-java-bridge_6.1.2.1/JavaBridgeTemplate6121.war/download

Rename the File to IDML.war and copy it to they webapps folder. Tomcat should auto deploy it.

Copy the idmllib.jar file to /opt/tomcat6/webapps/IDML/WEB-INF/lib

olitest:/root/# ls -l /opt/tomcat6/webapps/IDML/WEB-INF/lib/
total 4040
-rw-r--r-- 1 root    root    3554086 2010-05-20 11:34 idmllib.jar
-rw-r--r-- 1 tomcat6 tomcat6  405003 2010-05-02 13:22 JavaBridge.jar
-rw-r--r-- 1 tomcat6 tomcat6   41347 2010-05-02 13:22 php-script.jar
-rw-r--r-- 1 tomcat6 tomcat6  114991 2010-05-02 13:22 php-servlet.jar

Attention: For some reason I could not get this to run when I used the normal filename with the version in it … idmllib-1.1.0.jar.
Don’t ask me why … works if you rename it to idmllib.jar.

6 Configure Apache and php

Set URL_FOPEN to on stellen.

;Whether to allow the treatment of URLs (like http:// or ftp://) as files.
allow_url_fopen = On
; Whether to allow include/require to open URLs (like http:// or ftp://) as files.
allow_url_include = On

You can protect your setup with suhosin – so URL_FOPEN is restricted to a specific address:

suhosin.executor.include.whitelist=http://localhost:8080

Please check out http://www.hardened-php.net/suhosin/configuration.html for more interesting settings.

7 Test the IDMLlib

If you did everything correct start InDesign, use any InDesign file and export it to an IDML file.
You need of course at least one Textbox with content in the InDesign file.
Upload the file to your web folder and access the file with a small php script:

<?php
require_once("http://localhost:8080/IDML/java/Java.inc");
 
echo "This is a Test - this is PHP";
 
$idml = new java("de.fhcon.idmllib.api.elements.Idml", "/var/www/java/text.idml");
$document = $idml->getDocument();
$cmykProfile = $document->getCMYKProfile();
$rgbProfile = $document->getRGBProfile();
 
echo "<br>This is the cmyk Profile: ".$cmykProfile;
echo "<br>And the RGB Profile: ".$rgbProfile;
 
$story = $idml->getAbstractDocument()->getStoryById("uec");
$content  = java("de.fhcon.idmllib.api.util.StoryUtil")->getContent($story);
echo "<br>This is the Content from the Textbox: <br>".$content;
echo "<br>";
?>

Note: You must provide a path for the IDML file. And we did not query all the stories. We “cheated” a bit here and just provided the correct story ID from the IDML file.
Just unzip the IDML file and look for the Stories folder. There are of course some utility functions in the IDMLlib to get the Story IDs from the spreads and iterate through them.

olitest:/var/www/java/test# ls -l
total 84
-rw-r--r-- 1 root root 24210 2010-01-22 15:50 designmap.xml
drwxr-xr-x 2 root root  4096 2010-05-20 13:46 MasterSpreads
-rw-r--r-- 1 root root 30060 2010-05-20 11:51 mein.zip
drwxr-xr-x 2 root root  4096 2010-05-20 13:46 META-INF
-rw-r--r-- 1 root root    43 2010-01-22 15:50 mimetype
drwxr-xr-x 2 root root  4096 2010-05-20 13:46 Resources
drwxr-xr-x 2 root root  4096 2010-05-20 13:46 Spreads
drwxr-xr-x 2 root root  4096 2010-05-20 13:46 Stories
drwxr-xr-x 2 root root  4096 2010-05-20 13:46 XML
olitest:/var/www/java/test# ls -l Stories/
total 4
-rw-r--r-- 1 root root 924 2010-01-22 15:50 Story_uec.xml

So be on the lookout for more complex examples using IDMLlib for Java with PHP5!

Next code example shows how to modify story contents and write an IDML file back!

Leave a Reply

You must be logged in to post a comment.