otr4j is part of my GSoC 09' project and is encouraged by the SIP Communicator development. otr4j is an implementation of the OTR (Off-the-Record) protocol in java.
Sunday, October 11, 2009
otr4j I/O redesign almost complete
The java.net.otr4j.io package development is complete now. It has been developed independently from the existing otr4j code base because it was not possible to both develop the package and refactor it's dependencies at the same time.
As soon as I complete the refactoring and make sure everything works as expected, I will commit the code.
These code changes will fix issue 1 (Enhance serialization/deserialization) and issue 8 (non-(ISO Latin 1) characters do not display correctly), both of which are very important.
Thursday, September 17, 2009
Life After GSoC
So what's going on after GSoC (relevant to GSoC)?
The truth is that I don't have much free time, but I try to devote some time in otr4j and SIP Communicator. The SIP Communicator plugin is in a good state but there are some open issues for otr4j.
I have already worked on otr4j issue 3 because there was demand. Currently I'm reading Java I/O so I can work on issue 1 with more confidence.
The code changes required for closing issue 1 would affect 20-25% of the code approximately and will improve code quality and readability a lot and a bit it's efficiency.
Another thing I've started working on is a port of otr4j in .NET (otr4net), I think that will follow IO changes because I want to have a good model before I finish the port.
That's about it :)
Saturday, August 22, 2009
Debugging SIP Communicator Tests
These properties come from the testing.properties and accounts.properties files, that SIP Communicator does not yet have the ability to read.
-Daccounts.icq.TESTED_IMPL_ACCOUNT_ID=
-Daccounts.icq.TESTED_IMPL_PWD=
-Daccounts.icq.TESTING_IMPL_ACCOUNT_ID=
-Daccounts.icq.TESTING_IMPL_PWD=
-Daccounts.icq.CONTACT_LIST=
-Daccounts.sip.PRESERVE_PEER_INFO=false
-Daccounts.sip.account1.USER_ID=
-Daccounts.sip.account1.DISPLAY_NAME=
-Daccounts.sip.account1.PASSWORD=
-Daccounts.sip.account1.SERVER_ADDRESS=
-Daccounts.sip.account1.SERVER_PORT=
-Daccounts.sip.account1.PROXY_ADDRESS=
-Daccounts.sip.account1.PROXY_PORT=
-Daccounts.sip.account2.USER_ID=
-Daccounts.sip.account2.DISPLAY_NAME=
-Daccounts.sip.account2.PASSWORD=
-Daccounts.sip.account2.SERVER_ADDRESS=
-Daccounts.sip.account2.SERVER_PORT=
-Daccounts.sip.account2.PROXY_ADDRESS=
-Daccounts.sip.account2.PROXY_PORT=
-Daccounts.jabber.account1.USER_ID=
-Daccounts.jabber.account1.SERVER_PORT=
-Daccounts.jabber.account1.PASSWORD=
-Daccounts.jabber.account1.SERVER_ADDRESS=
-Daccounts.jabber.account2.USER_ID=
-Daccounts.jabber.account2.PASSWORD=
-Daccounts.jabber.account2.SERVER_ADDRESS=
-Daccounts.jabber.account2.SERVER_PORT=
-Daccounts.jabber.CONTACT_LIST=
-Daccounts.reporting.JABBER_REPORT_LIST=
-Daccounts.msn.account1.USER_ID=
-Daccounts.msn.account1.PASSWORD=
-Daccounts.msn.account2.USER_ID=
-Daccounts.msn.account2.PASSWORD=
-Daccounts.msn.CONTACT_LIST=
-Daccounts.reporting.MSN_REPORT_LIST=
-Daccounts.yahoo.account1.USER_ID=
-Daccounts.yahoo.account1.PASSWORD=
-Daccounts.yahoo.account2.USER_ID=
-Daccounts.yahoo.account2.PASSWORD=
-Daccounts.yahoo.CONTACT_LIST=
-Daccounts.reporting.YAHOO_REPORT_LIST=
-Daccounts.gibberish.account1.USER_ID=gibacc1
-Daccounts.gibberish.account1.PASSWORD=whatever
-Daccounts.gibberish.account2.USER_ID=gibacc2
-Daccounts.gibberish.account2.PASSWORD=whatever2
-Daccounts.gibberish.CONTACT_LIST=test-group.user1
-Dnet.java.sip.communicator.slick.runner.TEST_LIST=JabberProtocolProviderSlick
-Dnet.java.sip.communicator.CONFIGURATION_FILE_NAME=testing.sip-communicator.xml
Monday, August 17, 2009
August 17 Update
1. Make the OTR plugin register an encryption button in the tool (Implemented) and menu (Implemented) bars of the chat window.
2. The above mentioned button should indicate the status of the current chat (Implemented)
3. The above mentioned button should also contain (at least) the following options
* Start an ecnrypted chat (Implemented)
* End encrypted chat (Implemented)
* Authenticate/Verify contact (Implemented)
* Auto encrypt every session with this contact (Implemented)
* Help/ What is this (Implemented)
4. Implement support for clients that do not have OTR (Implemented)
5. Add support for incoming fragmented messages (Pending, otr4j has to be extended)
6. Configuration intertface that allows generating and displaying our own key as well as managing other people’s keys (Implemented, screenshot)
7. JUnit tests that run with every protocol (Pending)
Saturday, August 15, 2009
August 15 Update
1. Make the OTR plugin register an encryption button in the tool (Implemented, see bellow) and menu (Implemented) bars of the chat window.
Current implementation adds a button in the tool bar which is dummy for the time being. I'm not sure what this button should do. For example it could be a toggle button (start/stop encryption) or it could bring up the whole OTR menu.
UPDATE, August 16: Toggle button functionality implemented.
2. The above mentioned button should indicate the status of the current chat (Implemented)
3. The above mentioned button should also contain (at least) the following options
* Start an ecnrypted chat (Implemented)
* End encrypted chat (Implemented)
* Authenticate/Verify contact (Implemented)
* Auto encrypt every session with this contact (Implemented)
* Help/ What is this (Implemented)
4. Implement support for clients that do not have OTR (Implemented)
5. Add support for incoming fragmented messages (Pending, otr4j has to be extended)
6. Configuration intertface that allows generating and displaying our own key as well as managing other people’s keys (Pending)
7. JUnit tests that run with every protocol (Pending)
Tuesday, August 11, 2009
Midterm milestones status
1. Make the OTR plugin register an encryption button in the tool (Pending, see bellow) and menu (Implemented) bars of the chat window
Current implementation adds a button in the tool bar which is dummy for the time being. I'm not sure what this button should do. For example it could be a toggle button (start/stop encryption) or it could bring up the whole OTR menu.
2. The above mentioned button should indicate the status of the current chat (Implemented)
3. The above mentioned button should also contain (at least) the following options
* Start an ecnrypted chat (Implemented)
* End encrypted chat (Implemented)
* Authenticate/Verify contact (Implemented)
* Auto encrypt every session with this contact (Pending. This can only be set globally in the configuration form for the time being.)
* Help/ What is this (Implemented)
4. Implement support for clients that do not have OTR (Implemented)
5. Add support for incoming fragmented messages (Pending, otr4j has to be extended)
6. Configuration intertface that allows generating and displaying our own key as well as managing other people’s keys (Pending)
7. JUnit tests that run with every protocol (Pending)
Thursday, July 23, 2009
Progress by July 23
More specifically, message transformation operation sets where added earlier tonight for MSN, Yahoo! and ICQ (Jabber transformation set has been added some time ago). Now OtrTransformationLayer can hook into all of these protocols (MSN, Yahoo!, ICQ and Jabber) and provide encrypted communication!
Wednesday, July 15, 2009
DSA Signature sign/verify using JCE/BouncyCastle/libgcrypt
- Problem 1: signing with standard JCE and verifying with BouncyCastle (and vica versa)
The answer to this problem is that... the BouncyCastle DSA code does not perform the SHA1 hash of the message; they expect you to do that and pass the 20 byte hash in rather than the message. The JCE code automatically does the hashing for you; you just pass it the message you want to get signed, as ghstark and Werner mention here and here accordingly.
- Problem 2: signing with BouncyCastle and verifying with libgcrypt (and vica versa)
This problem is slightly more complicated and in order to understand what's going on I had to debug SIP Communicator/otr4j/BC & Pidgin/libotr/libgcrypt simultaneously. Fortunately we got to an end.
The BC DSA signature algorithm implements the latest standard according to FIPS-186-3 while libgcrypt adheres to FIPS-186-1, FIPS-186-2.
According to FIPS-186-3/p. DSA Signature Generation, (r,s) should be generated as follows:
Let N be the bit length of q. Let min(N, outlen) denote the minimum of the positive integers N and outlen, where outlen is the bit length of the hash function output block. The signature of a message M consists of the pair of numbers r and s that is computed according to the following equations:
r = (g^k mod p) mod q.
z = the leftmost min(N, outlen) bits of Hash(M).
s = (k^-1 (z + xr)) mod q.
while according to FIPS-186-1, FIPS-186-2
z = Hash(M)
Full topic discussion is available here.
Finally, Ian Goldberg in this thread provided a solution to this problem to pass to the signature generator (Hash(M) mod q) rather than truncating the Hash(M) value.
Note that this solution will not work with standard JCE because it requires a DSA signer implementation that doesn't hash it's input...
Friday, July 10, 2009
First term period results
Here I present the results from my first term period. The list is based on my first term planning.
- Develop a java library that handles encryption (see The current state of OTR libraries in Java)
- Build methods to Assemble/Dissasemble OTR Messages and tests to verify things work properly
- OTR Query Messages
- Tagged plaintext messages
- OTR Error Messages (Completed)
- D-H Commit Message
- D-H Key Message
- Reveal Signature Message
- Signature Message
- Data Message (Completed)
- Handle state transitions for the following actions (detailed description of state transitions here),build key management infrastructure (NOTE: key management for the library, not SC) and build tests to verify things work properly
In this period functionality for Requesting an OTR conversation, Authenticated Key Exchange (AKE), and Data Exchange will be added.- Plaintext message without the whitespace tag
- Plaintext message with the whitespace tag
- Query Message
- Error Message
- D-H Commit Message
- D-H Key Message (Completed)
- Reveal Signature Message
- Signature Message
- Version 1 Key Exchange Message
- Data Message
- User requests to start an OTR conversation
- User requests to end an OTR conversation
- User types a message to be sent (Completed)
- Build methods to Assemble/Dissasemble OTR Messages and tests to verify things work properly
- Create a transformation operation set (Completed)
- Implement support for the transformation set in all protocols (Failed)
- Implement an OTR encryption bundle prototype/proof of concept that encrypts all conversations (Failed)
I have created a transformation set for jabber as an initial effort to incorporate otr4j in SIP Communicator. I've chosen jabber because it is an open standard with server implementation, such as OpenFire, freely available.
I did not proceed into creating transformation sets for the rest of the protocols because there is an issue that the DSA signature (generated with standard JCE) does not verify in Pidgin/libotr, this action is taken in the OTR Protocol Draft, High Level Overview, Authenticated Key Exchange, Step 9. I tried to sign using BouncyCastle Lightweight API instead of the Standard JCE, but that failed too.
To make sure the signature I use is correct, I created a set of test cases to verify signatures created with bouncycastle using the Sun JCE provider and visa versa, but that failed too.
I posted a question about this issue today in several places (CodeRanch, Sun Forums, SIP Communicator dev-list), but I have received no answer yet, so I need to further investigate this issue.
Sunday, July 5, 2009
OSGi + BouncyCastle Round 3
Problem A is this exception [java] java.net.MalformedURLException: invalid url: reference:file:sc-bundles/protocol-msn.jar!/ (java.net.MalformedURLException: Unknown protocol: reference) during AES128-CTR encryption.
The solution to this problem was found by Werner Dittmann in this email. Briefly, I needed to install the "unlimited strength crypto policies" from Sun which are available here in the Other Downloads section. This is not an acceptable solution off course, so we will have to find an alternative (which is pretty obvious, drop the alternative JCE provider and use BouncyCastle Lightweight API).
Problem B is that running SIP Communicator from within Eclipse, and only from within Eclipse, the bundle-plugin-otr fails to generate a D-H key pair using BouncyCastle as alternate provider with class "org.bouncycastle.crypto.CipherParameters"'s signer information does not match signer information of other classes in the same package.
This email in the BouncyCastle developers mailing list mentions that the cause for this exception most likely is an incorrect installation of BouncyCastle, which in my case I guess that means a class path problem.
This guess makes sense, because when Eclipse launches SIP Communicator sets the classpath to whatever the buildpath is. The buildpath in my case contained both bouncycastle and zrtp4j which both export org.bouncycastle.crypto.*. Apparently there is a conflict there.
In this case we could have a bouncycastle bundle that both otr4j and zrtp4j will use or remove zrtp4j from the classpath (we could also update the "How to configure Eclipse to compile and debug SIP Communicator" to contain only the most required libs, like felix, in the classpath).
Friday, July 3, 2009
OSGi + BouncyCastle, Round 2
What I've tried is:
A) Import every single package of BouncyCastle (I found those packages using this snippet) in org.osgi.framework.system.packages.extra + any other packages required (discover them through ClassDefNotFound exceptions + this snippet) in felix.client.run.properties file.
B) Import all of those packages in bundle-plugin-otr in build.xml.
So with this setup...
Running SIP Communicator using "ant run" seems to be partially working. We can generate D-H key pair using BouncyCastle as alternate provider, but I get (Problem A) [java] java.net.MalformedURLException: invalid url: reference:file:sc-bundles/protocol-msn.jar!/ (java.net.MalformedURLException: Unknown protocol: reference), like in this SIP Communicator issue. So let's try to debug this problem!
Running SIP Communicator using Eclipse, fails to generate a D-H key pair using BouncyCastle as alternate provider (Problem B) with class "org.bouncycastle.crypto.CipherParameters"'s signer information does not match signer information of other classes in the same package, so I cannot debug the above problem... So let's try to debug this problem!
The BouncyCastle signed jar does not have debug information, so attaching the BouncyCastle source code and installing a breakpoint in org.bouncycastle.jce.provider.JDKKeyPairGenerator$DH constructor gives me Unable to install breakpoint due to missing line numbers (Problem C), so I cannot debug the above problem, and this problem can only be resolved if we recompile the BouncyCastle lib, and it won't be a signed jar anymore.To the bottom line, even if I didn't care about the first problem, the most important problem is that I cannot debug properly (Problem B). To the very bottom line, this probably means refactoring otr4j so as to use the BouncyCastle lightweight API instead of the BouncyCastle JCE provider. This would solve Problem C, and hopefully Problem B as well.
The setup I've used is r5496 of my branch.. I checked it in for reference.
UPDATE: There are solutions to these problems, and I discuss them in OSGi + BouncyCastle Round 3.
Tuesday, June 30, 2009
OSGi Bundle of BouncyCastle / Alternate JCE Provider
So, if you try to OSGi bundle BouncyCastle the resulting jar won't be signed anymore, and JCE won't be able to authenticate the BouncyCastle provider.
This is the reason we see problems like this: ZRTP integration (possible) OSGi bundle related problem and this: bouncy castle exception with osgi. Two workarounds would be to...
- OSGi bundle BouncyCastle, but loose it's ability to be an alternate JCE provider
- Add it in the org.osgi.framework.system.packages.extra list in the felix.client.run.properties and make sure it's in the class path as it is mentioned here.
java.lang.NullPointerException
at java.util.jar.Manifest$FastInputStream.fill(Unknown Source)
at java.util.jar.Manifest$FastInputStream.readLine(Unknown Source)
at java.util.jar.Manifest$FastInputStream.readLine(Unknown Source)
at java.util.jar.Attributes.read(Unknown Source)
at java.util.jar.Manifest.read(Unknown Source)
at java.util.jar.Manifest.(Unknown Source)
at org.apache.felix.framework.searchpolicy.ContentLoaderImpl.calculateContentPath(ContentLoaderImpl.java:344)
at org.apache.felix.framework.searchpolicy.ContentLoaderImpl.initializeContentPath(ContentLoaderImpl.java:315)
at org.apache.felix.framework.searchpolicy.ContentLoaderImpl.getClassPath(ContentLoaderImpl.java:90)
at org.apache.felix.framework.searchpolicy.ContentClassLoader.findClass(ContentClassLoader.java:154)
at org.apache.felix.framework.searchpolicy.ContentClassLoader.loadClassFromModule(ContentClassLoader.java:94)
at org.apache.felix.framework.searchpolicy.ContentLoaderImpl.getClass(ContentLoaderImpl.java:166)
at org.apache.felix.framework.searchpolicy.R4Wire.getClass(R4Wire.java:105)
at org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.searchImports(R4SearchPolicyCore.java:505)
at org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.findClassOrResource(R4SearchPolicyCore.java:466)
at org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.findClass(R4SearchPolicyCore.java:185)
at org.apache.felix.framework.searchpolicy.R4SearchPolicy.findClass(R4SearchPolicy.java:45)
at org.apache.felix.moduleloader.ModuleImpl.getClass(ModuleImpl.java:216)
at org.apache.felix.framework.Felix.createBundleActivator(Felix.java:3468)
at org.apache.felix.framework.Felix._startBundle(Felix.java:1649)
at org.apache.felix.framework.Felix.startBundle(Felix.java:1578)
at org.apache.felix.framework.Felix.setFrameworkStartLevel(Felix.java:1172)
at org.apache.felix.framework.StartLevelImpl.run(StartLevelImpl.java:265)
at java.lang.Thread.run(Unknown Source)
java.lang.NullPointerException
at org.apache.felix.framework.searchpolicy.ContentClassLoader.findClass(ContentClassLoader.java:154)
at org.apache.felix.framework.searchpolicy.ContentClassLoader.loadClassFromModule(ContentClassLoader.java:94)
at org.apache.felix.framework.searchpolicy.ContentLoaderImpl.getClass(ContentLoaderImpl.java:166)
at org.apache.felix.framework.searchpolicy.R4Wire.getClass(R4Wire.java:105)
at org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.searchImports(R4SearchPolicyCore.java:505)
at org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.findClassOrResource(R4SearchPolicyCore.java:466)
at org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.findClass(R4SearchPolicyCore.java:185)
at org.apache.felix.framework.searchpolicy.R4SearchPolicy.findClass(R4SearchPolicy.java:45)
at org.apache.felix.moduleloader.ModuleImpl.getClass(ModuleImpl.java:216)
at org.apache.felix.framework.Felix.createBundleActivator(Felix.java:3468)
at org.apache.felix.framework.Felix._startBundle(Felix.java:1649)
at org.apache.felix.framework.Felix.startBundle(Felix.java:1578)
at org.apache.felix.framework.Felix.setFrameworkStartLevel(Felix.java:1172)
at org.apache.felix.framework.StartLevelImpl.run(StartLevelImpl.java:265)
at java.lang.Thread.run(Unknown Source)
Subversion, SourceGear's Diffmerge and Cygwin
It turns out to be a little trickier with SVN firstly because SVN is not that versatile as Mercurial and second because I use SVN under Cygwin which results in paths being delivered in diffmerge Cygwinized.
To enable a 3d party diff tool you need add something like this in your ~/.subversion/config file (c:\cygwin\home\your_user\.subversion\config):
diff-cmd = diffwrapper.sh
With the help of Eric's post Living with Subversion and Pete's post Subversion, KDiff3, and Cygwin I've built diffwrapper.sh to look like this:
#!/bin/sh
LEFT=`cygpath -d ${6}`
RIGHT=`cygpath -d ${7}`
# thanks to jtr for the sed regex
LEFT_NAME=`echo ${3} | sed 's/.*\/\([^/]*\)/\1/'`
RIGHT_NAME=`echo ${5} | sed 's/.*\/\([^/]*\)/\1/'` #src/net/java/sip/communicator/impl/protocol/jabber/OperationSetInstantMessageTransformJabberImpl.java (revision 0)
/cygdrive/c/Program\ Files/SourceGear/Vault\ Client/sgdm.exe /title1:"$LEFT_NAME" "$LEFT" /title2:"$RIGHT_NAME" "$RIGHT"
Now you need to make sure that diffwrapper.sh script is somewhere in your PATH. I've added in ~/bin, and did
echo export PATH="\$PATH:$HOME/bin" >> ~/.bashrc
Update: Friday, 24 July, 2009
Here's a mergewrapper.sh script
#!/bin/sh
local=`cygpath -d ${3}`
remote=`cygpath -d ${2}`
base=`cygpath -d ${1}`
merged=`cygpath -d ${4}`
/cygdrive/c/Program\ Files/SourceGear/Vault\ Client/sgdm.exe /result:"$merged" /title1:"Local" /title2:"Merged" /title3:"Remote" "$local" "$merged" "$remote"
Saturday, June 27, 2009
Publishing your java.net SVN commits using Yahoo! Pipes
Working with your SVN branch - Merge trunk changes to your branch

Now that the java otr library otr4j is functional, I wanted to merge any trunk changes back to my SIP Communicator branch, prior tto getting to work with SIP Communicator. I decided to post this because I always find my self googling for the answer..
this actually involves 4 commands:
- svn update, you run svn update to sync your working copy so svn info will show you updated information.
- svn info, running svn info will reveal the current HEAD revision (r2) as well as the revision of the last change of your branch (r1).
- svn merge, having these two pieces of information you can run svn merge -r r1:r2 trunk_location
- svn ci -m "Merged trunk changes r1:r2 into my branch"
If you have time I would recommend reading at least Subversion in Action and Branching and Merging from the book Version Control with Subversion.
The procedure described above is not correct. It is simpler in >= 1.5 setups and, occasionally, more complicated in < 1.5 setups.
MiniMax and stsp on #svn channel on Freenode kindly answered my questions regarding some issues I had. I have to incorporate the outcome of the discussion here but until then here's the log.
Friday, June 26, 2009
OTR4j Authenticated Key Eexchange Log in Chainsaw V2

Screen capture of Chainsaw V2 visualizing otr4j running the Off-the-Record (OTR) Authenticated Key Exchange.
Sunday, June 21, 2009
Progress by June 25
I have been working on it during the past 14 days, and I am pretty happy to announce that with the latest changes just a few minutes ago, goal "June 25" has been reached. That is, as of revision 068510f52f otr4j can successfully run an Authenticated Key Exchange, and exchange encrypted data.
Tomorrow I will write new tests and improve existing ones to make sure the implementation is fully functional.
After that I will dive into SIP Communicator and will start working for goal July 05.
Thursday, June 11, 2009
Progress by June 11
Simplified how messages are assembled/disassembled. Now one can disassemble a message by calling the appropriate constructor, and can assemble messages by calling the toString() method of a message instance.
Implemented state transition handling and message reply dispatching mechanism when receiving
- Plain text messages (with or without whitespace)
- Query messages
- Error messages
- D-H Commit messages
- D-H key messages
The project now uses Mercurial. Get a local copy of the repository with this command:
hg clone https://otr4j.googlecode.com/hg/ otr4j
Tuesday, June 9, 2009
Arsenal selection
A promising plugin, unfortunately not officially supported, for integrating Mercurial with Eclipse exists, and I installed it. IMHO the plugin is very nice and clean (I downloaded the source) BUT -as it usually happens..- I did some wrong clicks here and there and I messed up my source tree..
Then (in a bright moment I guess..) I thought I'd better switch to the command line (, I am aware of TortoiseHg, but I want my terminal back!) where I can have full control of what I’m doing (step by step..). So there I was, back at the beginning, using Eclipse and the command line :D and as I had already lost quite some time clicking around the various windows, I got back to work.
Finally (and thankfully..), I completed my changes and I wanted a tool to compare the diffs. I wanted a tool that would do folder diffing/directory diffing/folder compare/”call it what you like”, because I had done many changes and I wanted an overview picture of them.
I stumbled upon this stackoverflow post which led me to use WinMerge, because it is free, and even better it’s open source! I had to download the setup executable to get it to work because WinMergeU.exe depends on MFC7.1 and I could not find the the Microsoft VC++ 2003 Redistributable Package. The tool works fine, in fact it works great and I liked a lot.
If anyone wants to use WinMerge add this to the Mercurial.ini:
[extensions]
hgext.extdiff =
[extdiff]
cmd.wmdiff = C:\Program Files\WinMerge\WinMergeU.exe
opts.wmdiff = /r /e /x /ub
and then run hg wmdiff
But, (in yet another bright moment I guess..) I thought I’d try SourceGear’s DiffMerge which am used to it’s coloring conventions. This tool has folder diffing/directory diffing/folder compare/”call it what you like” and most importantly, it seemed to be a little faster than WinMerge.
If anyone want to use Sourcegear’s DiffMerge tool add this to the Mercurial.ini:
[extensions]
hgext.extdiff =
[extdiff]
cmd.sgdm = C:\Program Files\SourceGear\Vault Client\sgdm.exe
and run then hg sgdm
That’s all with my arsenal selection. If you ask me, it was a little boring to do all this stuff, but one has to do changes to his development toolset from time to time :-)
Sunday, June 7, 2009
Have you checked out some cool features of NetBeans?
Initially, I checked what's the Eclipse way of doing this. It seems although there are tools for modeling in Eclipse, they don't support reverse engineering source code into UML diagrams, so I thought "this must be something Eclipse developers do with some 3rd party -not very expensive- application..".
I browsed the web for a while, but found nothing standard except from ArgoUML maybe (one should define standard off course..). I eventually settled with NetBeans.
I was aware of the fact that NetBeans has support for reverse engineering Java Applications but didn't consider using it from the beginning because I wanted to build up my existing Eclipse skills.
The good stuff about NetBeans don't end here, it even has Mercurial support by default, which made me want to use Mercurial and let me be productive at the same time. Apparently I was very wrong about NetBeans..
I got so excited that I just made a question in the post where Mercurial support for Google Code has been announced, asking when it will go public. Now that Mercurial is working for me, I want to push my change sets!