Discover the cappuccino tools : cplutil

In the tutorial about objj and ojunit, we have learned how to use "objj" (Objective-J interpreter) and "ojtest" part of the "ojunit" unit test framework. We have several utilities still to be discovered. One of them is "cplutil". The name comes from CP (cappuccino) L (Plist) util (utility). This utility can convert between 280N format plists and XML plists. Cappuccino's XML plists should be exactly the same as Cocoa's. The 280N format is simply a different text format for plist, the same way that there is currently the NeXT, XML, and binary formats.

How to use cplutil

Well, the best way to discover how the cappuccino tools are working seems to be by reading the source code. The tool source code is the file "main.js" in the directory "Objective-J/Tools/cplutil".

$ cd /path/to/cappuccino_07beta/280north-cappuccino-07b/Objective-J/Tools/cplutil $ cat main.js

We can see from the source code that we have to use the syntax :

cplutil -convert format input1 ... inputn cplutil -convert format [-o output] input

where format can be either 280north1 or xml1. For example:

$ cplutil -convert 280north1 Info1.plist Info2.plist $ cplutil -convert xml1 -o Info3.plist Info1.plist

Patching your first bug

If you try it yourself with cappucinno 0.7b, well it won't work. You have to patch your first bug ;-)

$ cplutil -convert 280north1 Info1.plist Info2.plist java -classpath /usr/local/share/objj/lib:/usr/local/share/objj/lib/js.jar:/usr/local/share/objj/lib/cplutil: main -convert 280north1 Info1.plist Info2.plist Setting up Rhino utilties Exception in thread "main" org.mozilla.javascript.EcmaError: ReferenceError: "args" n'est pas défini at org.mozilla.javascript.optimizer.OptRuntime.main( at main.main(Unknown Source)

Open the file "main.js" and browse to the end. Change "main.apply(main, args);" to "main.apply(main, arguments);". You now have just to rebuild cappuccino with:

cd /path/to/cappuccino_07beta/280north-cappuccino-07b rake release rake install

You can now take a cappuccino and type with delectation:

$ cplutil -convert 280north1 Info1.plist Info2.plist $ more Info1.plist 280NPLIST;1.0;D;K;26;CPApplicationDelegateClassS;13; AppControllerK;12;CPBundleNameS;11; Hello WorldK;16;CPPrincipalClassS;13;CPApplicationE; $ cplutil -convert xml1 Info1.plist Info2.plist $ cat Info1.plist <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" ""> <plist version = "1.0"> <dict> <key>CPApplicationDelegateClass</key> <string>AppController</string> <key>CPBundleName</key> <string>Hello World</string> <key>CPPrincipalClass</key> <string>CPApplication</string> </dict> </plist> $ cplutil -convert 280north1 -o Info3.plist Info1.plist

Learning from cplutil source code

What can you learned from the source code and the small bug ? A lot ! First, the cappuccino tools are javascript programs that are executed, not in a browser, but embedded into a Java application. In fact, the developers at are using Rhino which is an open-source implementation of JavaScript written entirely in Java.

For us this means that if we want to improve/fix the tools, we have to use only JavaScript and not Objective-J. We can not use [CPData dataWithString:fileContents] but we should use what the objjc compiler will have generated for us: var data = new objj_data(); data.string = fileContents;

var data = new objj_data(); data.string = fileContents; var plistObject = new CPPropertyListCreateFromData(data); if (format === "280north1") data = CPPropertyListCreate280NorthData(plistObject); else if (format === "xml1") data = CPPropertyListCreateXMLData(plistObject);

We have also learned that by combining javascript and java, we can now have access to file on disk. We need to import the java classes into our javascript program first.

importPackage(java.lang); importClass(; importClass(; importClass(; importClass(; importClass(;

We can now read some files.

// Read the plist file var file = new File(filePaths[index]), reader = new BufferedReader(new FileReader(file)), fileContents = ""; // Get contents of the file while (reader.ready()) fileContents += reader.readLine() + '\n'; reader.close();

or write some others.

// Write out file var writer = new BufferedWriter(new FileWriter(outFile)); writer.write(data.string); writer.close();

It could be interesting to know how to use the Objective-J compiler (objjc) to translate our Objective-J programs into simple Javascript ones to be embeded later in java program for scripting.

Copyright © 2009 - Philippe Laval. Cappuccino and Objective-J are registered Trademarks of 280 North.