Pin Netbeans 6.9 to Windows 7 x64 Taskbar

netbeans-x64-bugIf you try to pin Netbeans 6.9 to the Windows 7 x64 taskbar and have the x64 JDK running, you get a new icon every time Netbeans runs. This is Netbeans bug 178273. The gist is that the netbeans.exe and nbexec.dll which bootstrap netbeans startup are 32-bit native binaries. Netbeans.exe can’t host the 64-bit Java so it copes by launching a child javaw process with a huge list of arguments.

nb-daughter-javaw-process

A possible solution would be to create a shortcut to Javaw with all the arguments for Netbeans and pin that to the Taskbar. Unfortunately, the list of arguments is so large that it isn’t possible to create a shortcut directly to javaw passing everything in. The list gets truncated and the shortcut doesn’t work.

A workable solution is to install the 32-bit JDK and make that the default platform for Netbeans. This works but you have to override the installer which prefers to put Netbeans into the x64 Program Files tree and use the x64 JDK if it is detected.

netbeans-32-bit-sdk-override

This does solve the problem but it’s not that pretty. The downside here is you have to maintain a second 32-bit JDK. You can still build applications with the x64 JDK but you have to fiddle around with registering the extra x64 platform in Netbeans and you have to reference the correct platform in each project.

SevenBeans Plug-In Does it Better

Jump ListSevenBeans is a Netbeans plugin that improves Netbeans Windows 7 taskbar integration. It adds jumplists, icon overlays and taskbar progress bar for background processes in Netbeans such as updating plugins. It fixes the taskbar integration whether you use the x64 or the x86 JDK

SevenBeans uses a native J7Goodies native DLL for integrating with the Windows 7 taskbar which it extracts  J7G<random-number>.tmp in your Temp directory and dynamically loads. If you are using AppLocker DLL rules, you need to create a per-user white list for C:\Users\<username>\AppData\Local\Temp\J7G*.tmp

Once SevenBeans is installed, launch Netbeans and then pin icon you have after Netbeans is up and running to the taskbar.

SevenBeans is cool and it is much nicer than dealing with an extra JDK installation that I didn’t want.

The Daily Flashback: The String in, String out API

I just ran across a recent Daily WTF story “XML’d XML” in my news feed. The gist is that some web service call which inherently has XML as return data returned a “string” as its payload. And it was a string, but a string of XML.

I instantly flashed back on an integration project from a few years back that we did for a Fortune 500 company. The company had contracted with a 3rd party service provider that provided a SOAP API for all of its message passing and we thought this would be much better than something out of the 1990s like passing PGP-encrypted CSV files over FTP. We were working with an—even at the time—ancient Sun ONE 6.0 server platform but it was able to support SOAP web services using Apache Axis.

I became concerned when I realized that every method took a single string “input” argument and returned a string.

I just pulled a sample from our source repository for old time sake.

/**
 * SubscriberAPISoap_PortType.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */

package com.shallRemainNameless;

import javax.xml.soap.SOAPException;

public interface SubscriberAPISoap extends java.rmi.Remote, SoapAuthentication {
    public java.lang.String createSubscriber(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String updateSubscriber(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String addCategory(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String removeCategory(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String getSubscriber(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String getSubscriberData(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String authenticateSubscriber(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String getSubscribers(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String getSubscribersByField(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String deactivateSubscriber(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String activateSubscriber(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String sendOptInMessage(java.lang.String input) throws java.rmi.RemoteException;
    public java.lang.String getRegistrationMetaData(java.lang.String input) throws java.rmi.RemoteException;
}

Every one of those input and return strings was actually XML. I remember when I realized it was XML all the way down, I sent an internal email with the subject “String in, String out == [expletive-deleted]”.

We created a wrapper API to hide the insanity but the actual XML API wasn’t so much better than the String version. They had a unified ApiResultDocument XML schema that encoded any possible result and an ApiRequestDocument schema which encoded any possible combination of arguments across all web methods.

/*
 * SubscriberAPISoapDocument.java
 *
 * Created on December 4, 2006, 2:59 PM
 *
 */

package com.shallRemainNameless.service;

/**
 *
 * @author breiter
 */

import com.shallRemainNameless.service.schemas.apiResult.ApiResultDocument;
import java.rmi.RemoteException;
import javax.xml.soap.SOAPException;
import org.apache.xmlbeans.XmlException;

public interface SubscriberAPISoapStrong extends java.rmi.Remote, SoapAuthentication 
{
    public ApiResultDocument createSubscriber(com.shallRemainNameless.service.schemas.subscriberCreateAndUpdate.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument updateSubscriber(com.shallRemainNameless.service.schemas.subscriberCreateAndUpdate.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument addCategory(com.shallRemainNameless.service.schemas.addRemoveCategory.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument removeCategory(com.shallRemainNameless.service.schemas.addRemoveCategory.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument getSubscriber(com.shallRemainNameless.service.schemas.getSubscriber.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument getSubscriberData(com.shallRemainNameless.service.schemas.getSubscriber.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument authenticateSubscriber(com.shallRemainNameless.service.schemas.authenticateSubscriber.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument getSubscribers(com.shallRemainNameless.service.schemas.getSubscriber.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument getSubscribersByField(com.shallRemainNameless.service.schemas.getSubscribersByField.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument deactivateSubscriber(com.shallRemainNameless.service.schemas.deactivateSubscriber.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument activateSubscriber(com.shallRemainNameless.service.schemas.activateSubscriber.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument sendOptInMessage(com.shallRemainNameless.service.schemas.sendOptInMessage.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
    public ApiResultDocument getRegistrationMetaData(com.shallRemainNameless.service.schemas.getSubscribers.ApiRequestDocument xmldoc) throws RemoteException, XmlException;
}

I remember that things got interesting when we created unit tests to confirm that the SOAP API did what it was supposed to do. There are 15 versions of unit tests checked in as we established that the documentation provided was not, in fact, based on the actual behavior of the system.

At least the designer of this API didn’t realize s/he could have just added an <ApiMethodRequest /> element to the ApiRequestDocument and used a single ApiResultDocument doApiRequest( ApiRequestDocument ) method. Oh wait, it would have been String doApiRequest( String ). That would have been epic.

Good times.

Embedding Arbitrary Language Glyphs in PDF with ItextSharp

One of my clients has an application which generates a PDF using ITextSharp. The document largely contains English text in the Latin character set but a portion of the PDF is supposed to contain contact information in a foreign language. In the first version of the software, the requirement was to support Latin, Cyrillic, Georgian and Armenian character sets.

We quickly discovered during testing that the Adobe Type 1 fonts embedded in itextsharp.dll only support Latin characters. Code points from the Cyrillic, Georgian and Armenian character sets showed up as white space in the document. Fortunately, iTextSharp supports TrueType font embedding with the correct incantation which enabled us to use Sylfaen to provide the necessary glyphs.

string sylfaenpath = Environment.GetEnvironmentVariable( "SystemRoot" ) + "\\fonts\\sylfaen.ttf";
BaseFont sylfaen = BaseFont.CreateFont( sylfaenpath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED );
Font easternEuroTextFont = new Font( sylfaen, 9f, Font.NORMAL );

With the second version of the application, we needed to support a bunch of new character sets in addition to the ones we previously supported including Hebrew, Arabic, Devangari, Sinhala, Lao, Thai and more South Asian and Southeast Asian scripts.

One option is to pick supporting fonts for each character set but we elected to pick something universal, which is Arial Unicode which includes glyphs for every code point defined in Unicode 2.1. Arial Unicode is from the Afra Monotype foundry and is bundled with Office 2007 and later but can be purchased separately if Office isn’t installed. (The main side effect of this font choice is moving from a serif font to a sans serif one.)

Universal Glyph Support Can Still Yield Gibberish

The remaining wrinkle is that Hebrew and Arabic are right-to-left languages which means that the characters in a Hebrew or Arabic string are supposed to be rendered from right-to-left instead of left-to-right. Just rendering an Arabic string with Arial Unicode in iTextSharp will yield reflected output which is gibberish.

Here is some reference Arabic text rendered in Arial. It says “al-ingliziya”, the Arabic word for English.

al-ingliziyah

Here’s what you get by default using Arial Unicode in iTextSharp.

default-broken-al-ingliziyah

Clearly, this is different from the reference rendering. Arabic is complicated because of the way the ligatures work so that the shape of a letter is heavily influenced by the letters next to it but basically, it’s backwards. What we have is now not nothing but Hebrew and Arabic are gibberish instead. We need to alter the rendering for Hebrew and Arabic and make them right-to-left.

A simple algorithm is to detect the presence of Hebrew or Arabic code points in a string and turn on right-to-left rendering. Regular Expressions define \p{Hebrew} and \p{Arabic} character classes which would be useful but unfortunately those aren’t supported in System.Text.RegularExpressions at this point. We need to roll our own.

const string regex_match_arabic_hebrew = @"[\u0600-\u06FF,\u0590-\u05FF]+";
if( Regex.IsMatch( text, regex_match_arabic_hebrew, RegexOptions.IgnoreCase ) 
    //arabic or hebrew characters exist, fix rendering

There’s no obvious RTL option for a text element in iTextSharp, so I tried reversing the strings, which is a slight improvement but it’s still broken. What we have is brain-dead rendering. The ligatures are not connecting the letters correctly.

string-reverse-broken-al-ingliziyah

On closer examination, there is RTL support in iTextSharp. It is exposed through object graph elements that implement IPdfRunDirection. (This is one of the places where it really shows that iTextSharp is a Java port. The use of static integer constants rather than enums is very Java 1.4. Enums are much more discoverable and the correct usage is more intuitively obvious.)

element.RunDirection = PdfWriter.RUN_DIRECTION_RTL;

Now the output from iTextSharp looks like the reference rendering.

correct-rtl-al-ingliziyah

Transliterate to Java and the same concepts apply to iText.

Example Snippet Code in C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using iTextSharp.text;
using iTextSharp.text.pdf;

//... assume a class that does stuff exists

pubilc byte[] CreatePdfStreamPdfWithRandomLanguageSupport( IEnumerable<string> textList )
{
	//C# does not support \p{Arabic} and \p{Hebrew} character classes. We have to roll our own.
	//We are assuming any string that contains an Arabic or Hebrew character is meant to be RTL.
	//Better would be to break strings into word tokens and test each word.
	const string regex_match_arabic_hebrew = @"[\u0600-\u06FF,\u0590-\u05FF]+";
	const string arialunicodepath          = Environment.GetEnvironmentVariable( "SystemRoot" ) + "\\fonts\\ARIALUNI.TTF";

	Document document = new Document( PageSize.LETTER );
	using(MemoryStream stream = new MemoryStream())
	{
		PdfWriter writer = PdfWriter.GetInstance( document, stream );
		try
		{
			//bunch of document setup here.
			document.Open();
			//arbitrarily, creating a 5 columnt table.
			PdfPTable table = new PdfPTable( 5 );
			
			//embed a Unicode font with broad glyph support for any code point we might need.
			//only the glyphs for code points actually used will be embedded in the document
			BaseFont nationalBase;
			if( File.Exists( arialunicaodepath ) 
				BaseFont.CreateFont( arialunicodepath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED ); 
			else
				throw new FileNotFoundException( "Could not find \"Arial Unicode MS\" font installed on this system." );

			Font nationalTextFont = new Font( nationalBase, 9f, Font.NORMAL );

			foreach( string text in textList )
			{
				//PdfPCell implements IPdfRunDirection
				PdPCell cell = new PdfPCell();
				//Arabic and Hebrew strings need to be reversed for right-to-left rendering
				//which is done by setting IPdfRunDirection.RunDirection. Otherwise, your RTL language text
				//comes out as backwards gibberish.
				if( text != null && Regex.IsMatch( text, regex_match_arabic_hebrew, RegexOptions.IgnoreCase ) )
			   		cell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
			    //apply unicode font
			    Phrase phrase = new Phrase( text, nationalTextFont );
				cell.Add( phrase );
				table.AddCell( cell );
			}
			document.add( table );
		}
		finally
	    {
	        document.Close();
	        writer.Close();
	    }
	    return stream.GetBuffer();
	}
}

Java Built with Unsupported Old Compilers

When I turned off DLL loading from the current working directory to defeat DLL pre-loading luring attacks, one of the things I discovered was that the Java plug-in was broken in Firefox and Chrome. This problem of Java finding its C library is not new at all. The tubes are choked with posts and bug reports about getting various things that are dependent on Java to work when msvcr71.dll can’t be found. The new CWDIllegalInDllSearch = 0xFFFFFFFF option just exacerbates an existing deployment problem.

PS> cd 'C:\Program Files (x86)\Java\jre6\bin\new_plugin'
PS> dumpbin /dependents .\npjp2.dll
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file .\npjp2.dll

File Type: DLL

  Image has the following dependencies:

    USER32.dll
    GDI32.dll
    ADVAPI32.dll
    MSVCR71.dll
    KERNEL32.dll
    ole32.dll

  Summary

        6000 .data
        3000 .rdata
        1000 .reloc
        7000 .rsrc
        4000 .text

The root of the Mozilla-compatible browser Java plugin problem is npj2.dll which is dynamically linked to msvcr71.dll. Because it is a plugin, the DLL loading is done by Windows on behalf of the executable and  (Chrome or Firefox) rather than the plugin. The new_plugin directory includes msvcr71.dll which probably helped if a browser changed its CWD to the new_plugin directory when loading npj2.dll but with searching CWD out of the picture it doesn’t.

Java simply doesn’t do a good job of loading its C runtime correctly on Windows. It’s not a new problem. I don’t understand why don’t just change a switch on the complier to /MT instead of /MD and statically link the C runtime into jpjp2.dll. That would make the whole problem go away.

There are also some other oddities here. There are 2 different C runtimes used in the 32-bit version of Java 6 for Windows. For some reason they are redistributing msvcr71.dll (C runtime from Visual Studio .NET 2003) and also msvcrt.dll which is supposed to be the name of the private C runtime used by Windows components. However, the msvcrt.dll in the Java directory is actually the C runtime from Visual Studio 6 or possibly a very old Platform SDK.

By implication Oracle/Sun is using the C/C++ optimizing compiler from Visual Studio 6 (1998) and Visual Studio .NET 2003 to build the 32-bit version of Java. Holy cow those are 5 and 3 versions back from the current compilers and between 12 and 7 years old. I’m pretty sure that Visual Studio 6 is no longer supported and unfortunately both predate the side-by-side C runtime distribution system that starts with Visual Studio 2005.

The x64 version of Java is even stranger. It links against a Microsoft  x64 C runtime library called msvcrt.dll. Again this is the name reserved for the private Windows platform C runtime but this msvcrt.dll has file version 6.10.2207.0 either from a very old version of the Windows Platform SDK that provided x64 compilation support prior to Visual Studio 2005 or from a tool chain that was available by request (and is no longer available) for Visual Studio 2003.

It seems like the Java team has made a bit of a fetish of using really old compilers for the Microsoft platforms. I can understand that there is a risk of breaking stuff when upgrading a tool chain but this has been taken a bit to the extreme by the Java build team. There is a cost to testing a huge platform like Java when building with a new tool chain. Sun was cash-constrained and, although popular, Java SE didn’t really make them any money directly.

Good News for Java 7 (Probably)

It looks like the problem is being addressed. OpenJDK 7 builds, it looks like Oracle is upgrading to the C/C++ compiler from Visual Studio 2010.

BEGIN WARNING: At this time (Spring/Summer 2010) JDK 7 is starting a transition to use the newest VS2010 Microsoft compilers. These build instructions are updated to show where we are going. We have a QA process to go through before official builds actually use VS2010. So for now, official builds are still using VS2003. No other compilers are known to build the entire JDK, including non-open portions. So for now you should be able to build with either VS2003 or VS2010. We do not guarantee that VS2008 will work, although there is sufficient makefile support to make at least basic JDK builds plausible. Visual Studio 2010 Express compilers are now able to build all the open source repositories, but this is 32 bit only. To build 64 bit Windows binaries use the the 7.1 Windows SDK.END WARNING.

The 32-bit OpenJDK Windows build requires Microsoft Visual Studio C++ 2010 (VS2010) Professional Edition or Express compiler. The compiler and other tools are expected to reside in the location defined by the variable VS100COMNTOOLS which is set by the Microsoft Visual Studio installer.

So maybe in 2011 Java will have its C runtime library sorted out by virtue of having a supported global mechanism to register the Visual Studio 2010 C runtime.

Java Browser Plugin for Mozilla Vulnerable to DLL Preloading Attack

chrome-java-bonkThe “Next Generation Java Plug-in 1.6.0_21 for Mozilla browsers” 32-bit version for Windows uses CWD to load its C runtime library (msvcr71.dll). If you have globally disabled loading libraries from the current working directory (CWD) by globally setting CWDIllegalInDllSearch to 0xfffffff, you will get a bonk like the one shown at the right. Firefox also fails to load the JVM but it doesn’t give any feedback about why it isn’t working.

Note that this is not a general problem with Java. Java desktop applications like Eclipse work and the Java ActiveX plugin for IE works. The problem is specific to the NSAPI plugin and this indicates that the Java plugin for Google Chrome and Mozilla Firefox is one of the applications that is vulnerable to a DLL preloading luring attack. Specifically, when a Java applet is loaded, the JVM will cause the browser to load msvcr71.dll from whatever is the current working directory for the browser.

The error can be fixed by dialing back your global CWDIllegalInDllSearch to 2 or create an exception for chrome and firefox. However, I would rather not open those programs to attack from a USB drive.

The first location that Windows uses to search for a DLL is the directory containing the binary executable. Placing a copy of msvcr71.dll in the same directory with Firefox and Chrome fixes the problem. The problem with that is if Java services the msvcr71.dll with a newer version, then Chrome and Firefox will cause the JRE to load the wrong C runtime causing bad things to maybe happen. Another option is to create a symbolic link (which requires Vista or later).

Incidentally, the mklink command is not a standalone utility, it is a built-in to the cmd.exe shell. If you want to use mklink via powershell, you need a function to invoke cmd.exe.

function mklink { & "$env:systemroot\system32\cmd.exe" /c mklink $args }

Running mklink requires Administrator privilege.

PS> cd C:\Users\breiter\appdata\Local\Google\Chrome\Application
PS> mklink msvcr71.dll 'C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll'
symbolic link created for msvcr71.dll <<===>> C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll
PS> cd 'C:\users\breiter\AppData\Local\Google\Chrome SxS\Application'
PS> mklink msvcr71.dll 'C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll'
symbolic link created for msvcr71.dll <<===>> C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll
PS> cd 'C:\Program Files (x86)\Mozilla Firefox'
PS> mklink msvcr71.dll 'C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll'
symbolic link created for msvcr71.dll <<===>> C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll
PS>

With the symlink fix in place, the Java version test page loads correctly in Chrome with no bonks with loading libraries from CWD disabled.

chrome-java-crt-symlink

Can Google Sidestep Oracle Patent Payouts with Mono/C#?

android-monoOracle has sued Google over patent and copyright violations related to Google’s use of Java technologies in Android. Oracle acquired the Java IP as a part of its acquisition of Sun Microsystems. The details are somewhat different but this has the same general flavor as when Sun sued Microsoft over its non-conforming Java runtime and J++ language compiler. That lawsuit was based in contracts law because Microsoft did license Java from Sun and violated the terms of the license. In this case, Google has attempted to sidestep the licensing requirements of Java with their Dalvik VM. Once could reasonably argue that the technical basis was similar. Both Microsoft and Google want to achieve significant performance improvement and platform integration over a vanilla JVM at the cost of incompatibility with the Java standard. It’s not entirely clear that Davlik actually achieves superior performance, though. I have to wonder if the stack-based VM concept was incidental to the goal of making an end-run around J2SE runtime licensing requirements.

One intriguing—if a bit self-serving and improbable—proposal has been floated by Miguel de Icaza: Why not just replace Dalik with Mono, the free and open source implementation of Microsoft’s .NET? The Mono runtime is LGPLv2 and the class libraries are MIT licensed. Additionally the .NET Micro edition has been placed entirely under the Microsoft Public License which is a BSD-style license with an explicit patent grant. The Microsoft Community Promise explicitly indemnifies patent claims against anyone wishing to implement C# and the CLI and unlike Sun’s patent grant for Java, embrace-and-extend is OK—you can implement a superset of the C# and CLI features and you are still covered.

Google definitely has the wherewithal to migrate Android from Dalvik to Mono if they want to. They could make it a seamless transition and even migrate the bytecode of existing Dalvik (or Java) apps to IL. They could also provide a tool to migrate projects from Java language to C# as Microsoft did. Other implementations exist.

I think it would be pleasantly symmetrical if history repeated itself. Sun’s lawsuit put the kibosh on Microsoft using Java the way it wanted and essentially gave birth to C#, the CLI and the CLR. It would be ironic if history repeated and Android just adopted Mono as its runtime. The road is much easier to tread this time around because a fully open source implementation already exists and it has already been ported onto Android and bytecode-to-IL and Java-to-C# tools exist and are mature.

%d bloggers like this: