Zend Studio 5.x for OS X Lion (Java SE 6)

2011.07.30 02:15 MDT

Running Zend Studio 5.x in OS X Snow Leopard or OS X Lion has traditionally been accomplished by sacrificing a goat attempting to install Java 1.5 JRE from OS X Leopard and hoping that nothing would change too much that would break the workaround. A better solution would be to get Zend Studio 5.x running under Java SE 6 for OS X Lion which gets installed by default the first time you run a Java application (or by download). The advantages are you're using the most up to date Java released for the OS and any future updates will not clobber the Java 1.5 workaround.

BEFORE YOU BEGIN: If you previously installed a Java 1.5 JRE from OS X Leopard from the instruction here or there or from anywhere else on the internet, it is very important that you go undo all that stuff and get everything back to the way it was. Including, but not limited to, pointing the 1.5 and 1.5.0 symlinks back to CurrentJDK in the /System/Library/Frameworks/JavaVM.framework/Versions directory.

Contents

Background · Issue · Cause · Solution · Install · Results · Other Issues

Background

Zend Studio 5 was introduced November 2005 and ran on the just released OS X Tiger provided you installed J2SE 5.0 (release 1). Zend Studio 5.5 was announced December 2006, also in the OS X Tiger era, although OS X Leopard had previously been announced. When OS X Leopard finally shipped in October 2007, Zend provided a compatibilty update and released Zend Studio 5.5.1.

Zend Studio 5.5.1 would be the last version of the ZDE released prior to Zend moving their Studio product to the Eclipse platform. However, many people prefer the pre-Eclipse version of Zend Studio and have made it their mission to defer updating (currently version 8.0.1) until they absolutely have to. Zend has abandoned Zend Studio 5.x and it was declared End Of Life (EOL) in May 2010 and later End of Support (EOS) in September of the same year. Worse still J2SE 5.0, which Zend Studio 5.x relied upon, had already reached its End of Life (EOL) the previos November.

When OS X Snow Leopard shipped August 2009, Zend had just released its Eclipse-based Zend Studio 7.0. If, however, you were still holding on to Zend Studio 5.5.1 only to be pried from your cold dead fingers you found yourself with many who where surprised to find that Java 1.5 wasn't installed in the new OS. There were some Java applications that wern't behaving very well, Zend Studio 5.x among them. Most Java developers just fixed and redeployed their applications to run under Java 1.6. Zend wasn't going to.

The more enterprising of the diehards figured out how to install a Java 1.5 on OS X Snow Leopard which worked really well in OS X Snow Leopard which only had Java 1.6 installed. Later, we figured out how to do the same in OS X Lion. But what we really need is to get Zend Studio 5.5.1 running under Java 1.6.

Issue

UPDATE: If you're having issues getting the ZendStudio-5_5_1 installer running under OS X Lion or missing open parenthesis and pipes when using the Courier New font when running Zend Studio 5.x under Java SE 6 then skip to the Other Issues section.

The most notable issue with Zend Studio 5.5.1 under Java 1.6 is that there is a drawing problem. The tabs and editor and even the preferences don't redraw correctly. When invalidated with the mouse, they may even show correctly for a moment, but are quicly obscured again and basically show as a big gray blob:

Cause

So what's causing this? Why does it not work in Java 1.6 when it worked fine in Java 1.5? We can find some interesting information in the zde.log file:

------------------ NEW MESSAGE ---- Fri Jul 29 16:23:45 MDT 2011------------------
 - opening (Version 5.5.1)
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: com/sun/java/swing/SwingUtilities2
	at com.zend.ide.p.e.a.c.paintText(Unknown Source)
	at javax.swing.plaf.basic.BasicTabbedPaneUI.paintTab(BasicTabbedPaneUI.java:864)
	at javax.swing.plaf.basic.BasicTabbedPaneUI.paintTabArea(BasicTabbedPaneUI.java:819)
	at javax.swing.plaf.basic.BasicTabbedPaneUI.paint(BasicTabbedPaneUI.java:781)
	at javax.swing.plaf.metal.MetalTabbedPaneUI.paint(MetalTabbedPaneUI.java:826)
	at javax.swing.plaf.metal.MetalTabbedPaneUI.update(MetalTabbedPaneUI.java:707)

The SwingUtilities2 class, a collection of utility methods for Swing, cannot be found. The SwingUtilities2 class itself comes with this warning:

WARNING: While this class is public, it should not be treated as public API and its API may change in incompatable ways between dot dot releases and even patch releases. You should not rely on this class even existing.

It turns out that the package of the SwingUtilities2 class changed from com.sun.java.swing in J2SE 5.0 to sun.swing in Java SE 6. Further, it would appear, like many a J2SE 5.0 application developer, the Zend team used these methods. Unlike their cohorts who fixed and recompiled their applications to account for the change, the Zend developers had moved on to bigger and better things. Our challenge is to let Zend Studio 5.x find it's SwingUtilities2 class using the package name com.sun.java.swing and it just so happens we can build one...

Solution

NOTE: This section is for those geeks that want to know how to do it themselves. You might be really, really lazy uninstrested in reading about how to build the missing SwingUtilites2 class and just want everything to work, now. If this is you, then skip to the Install section and just do the drag and drop install. Otherwise, continue reading...

UPDATE: I've simplified one part of this as it's not necessary (nor desirable) to compile (and override) the whole SwingUtilities2 class. Rather we'd like to proxy to the existing sun.swing.SwingUtilities2 class that ships with Java SE 6.0 and reduce the possibility of introducing problems in future updates. So, we simply extend the existing class and make sure it gets into the package that Zend Studio 5.x wants, com.sun.java.swing.

  1. Open a terminal, create a working directory and change to it:

    $ mkdir -v /tmp/SU2
    mkdir: created directory '/tmp/SU2'
    cd /tmp/SU2
  2. Download a copy of the SwingUtilities2.java source:

    $ curl -O http://www.s-seven.net/zend_5x_patch/SwingUtilities2.java
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 69459  100 69459    0     0  54522      0  0:00:01  0:00:01 --:--:-- 94889
  3. Take a look at SwingUtilities2.java, this is the proxy:

    $ cat SwingUtilities2.java
    package com.sun.java.swing;
    import sun.swing.*;
    
    /**
     * A proxy for sun.swing.SwingUtilities2
     */
    public class SwingUtilities2 
    	extends sun.swing.SwingUtilities2 { }
  4. Compile the SwingUtilities2.java source using the javac compiler:

    $ javac -d . SwingUtilities2.java
    Note: SwingUtilities2.java uses or overrides a deprecated API.
    Note: Recompile with -Xlint:deprecation for details.
    Note: SwingUtilities2.java uses unchecked or unsafe operations.
    Note: Recompile with -Xlint:unchecked for details.
  5. Create the SwingUtilities2.jar archive with the jar utility:

    $ jar cf SwingUtilities2.jar com
    $ jar tf SwingUtilities2.jar
    META-INF/
    META-INF/MANIFEST.MF
    com/
    com/sun/
    com/sun/java/
    com/sun/java/swing/
    com/sun/java/swing/SwingUtilities2$1.class
    com/sun/java/swing/SwingUtilities2$2$1.class
    com/sun/java/swing/SwingUtilities2$2.class
    com/sun/java/swing/SwingUtilities2$AATextInfo.class
    com/sun/java/swing/SwingUtilities2$LSBCacheEntry.class
    com/sun/java/swing/SwingUtilities2$Section.class
    com/sun/java/swing/SwingUtilities2.class
  6. Copy the SwingUtilities2.jar archive to the bin directory of your Zend Studio install. By default this is /Applications/Zend/ZendStudio/bin but if you've moved it, substitue the approprate directory:

    $ cp -v SwingUtilities2.jar /Applications/Zend/ZendStudio/bin
    SwingUtilities2.jar -> /Applications/Zend/ZendStudio/bin/SwingUtilities2.jar
  7. Use vi (or nano) to edit Info.plist in the ZDE.app to tell it to use the new SwingUtilities2.jar file:

    $ cd /Applications/Zend/ZendStudio/bin/
    $ vi ZDE.app/Contents/Info.plist
  8. Edit the values for key ClassPath prepending SwingUtilities2.jar to the list of files and key JVMVersion making it 1.6.*:

    <key>ClassPath</key>
    <string>SwingUtilities2.jar:ZendIDE.jar:axis.jar:commons-discovery-0.2.jar:commons-logging-1.0.4.jar:javaxzombie.jar:jaxrpc.jar:saaj.jar:wsdl4j-1.5.1.jar:jhall.jar:sftp.jar:../docs/help/bsscjhrs.jar:../docs/help.zip</string>
    <key>JVMVersion</key>
    <string>1.6.*</string>
  9. Save and exit your editor. Optionally you could do the same to the runZDE.sh script.
  10. Launch ZDE.app and behold your Zend Studio 5.5.1 in Java SE 6!

Install

NOTE: This section is for those underachievers that just want to get it installed fast. If you have a morbid desire to do all the heavy lifting yourself, then go back to the Solution section and do that. Otherwise, continue reading...

  1. Download the patch zend_5x_patch.dmg and mount the disk image:
  2. Open a new Finder window and navigate to your Zend Studio bin directory -OR- you can click on the Go followed by Go to Folder... menu items and type in /Applications/Zend/ZendStudio/bin and click Go.
  3. Drag SwingUtilities2.jar and runStudio_mac.sh from the mounted disk image into the Zend Studio bin directory. Replace files if prompted:
  4. Right-click ZDE.app and select Show Package Contents then navigate into the Contents directory -OR- you can click on the Go followed by Go to Folder... menu items and type in /Applications/Zend/ZendStudio/bin/ZDE.app/Contents and click Go.
  5. Drag Info.plist from the mounted disk image into the ZDE.app Contents directory. Replace files if prompted:
  6. Launch ZDE.app now running in Java SE 6!

Results

Other Issues

This section contains other issues with installing and running Zend Studio 5.x under Java SE 6. It's unrealistic to think that everything is going to work perfectly, but we've already come a long, long way from needing to install a Leopard J2SE 5.0.

  1. ZendStudio-5_5_1 installer requires Rosetta: Even though Zend Studio 5.5.1 was released as a Universal Binary, the installer uses a PPC only JavaApplicationStub. You can fix the installer to use the JavaApplicationStub that shipped with the OS X Lion version of Java SE 6 by following the instructions here. In a nutshell (where path is where your installer is):

    $ cd [path]/ZendStudio-5_5_1.app/Contents/MacOS
    $ ls -Fla * && file *
    -rwxr-xr-x 1 ben staff 13816 Dec 19 2007 ZendStudio-5_5_1*
    ZendStudio-5_5_1: Mach-O executable ppc
    cp -iv /System/Library/Frameworks/JavaVM.framework/Resources/MacOS/JavaApplicationStub ./ZendStudio-5_5_1
    overwrite ./ZendStudio-5_5_1? (y/n [n]) y
    /System/Library/Frameworks/JavaVM.framework/Resources/MacOS/JavaApplicationStub -> ./ZendStudio-5_5_1
    $ ls -Fla * && file *
    -rwxr-xr-x 1 ben staff 35072 Aug 15 23:31 ZendStudio-5_5_1*
    ZendStudio-5_5_1: Mach-O universal binary with 2 architectures
    ZendStudio-5_5_1 (for architecture x86_64): Mach-O 64-bit executable x86_64
    ZendStudio-5_5_1 (for architecture i386): Mach-O executable i386
  2. Why does the Courier New font looked whacked? Using Courier New as your editor font while running Zend Studio 5.x under Java SE 6 in OS X Lion causes open parenthesis to render incorrectly and pipes do not render at all. This isn't specific to Zend Studio 5.x and may be an issue with the JEditTextArea control as reported by others. If you have any further information as to the cause or can confirmation if the cause lies in the font or the JRE, please let me know. I actually prefer the Anonymous Pro font (or DejaVu Mono) for my editor font, but you can choose any monospaced font (except Courier New).
  3. That fixed the editor but the code completion font is Courier New and there's no setting for it. Can I fix that? Yes... but you're not going to like it... or maybe you will. I can't write out verbose detailed instructions right now but here's the steps you need to take:

    • Extract /Applications/Zend/ZendStudio/bin/ZendIDE.jar
    • Use a hex editor like 0xED to open the enclosed ./com/zend/ide/util/cr.class
    • Find Courier New and replace it with Andale Mono

      NOTE: It's important that you overwrite the bytes and I chose Andale Mono because it doesn't change the length of the file. Trust me on this one.
    • Repackage the ZendIDE.jar archive using the jar utility. You'll want to make sure that
      Main-Class: com.zend.ide.desktop.Main gets added to the manifest.
    • Extra credit: If you're really curious why this works, you can get a copy of the JAD Java Decompiler and look at the source of the cr.class file and see that when on Mac OS, the font is always Courier New. It seems an oversite to me that there was never a setting for this in Preferences.

Questions or comments to blog [at] s [hyphen] seven [dot] net.