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.
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
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(OptRuntime.java:240)
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" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <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
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 280north.com 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(java.io.File);
importClass(java.io.BufferedReader);
importClass(java.io.FileReader);
importClass(java.io.BufferedWriter);
importClass(java.io.FileWriter);
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.