Posts tagged technology

Reminder: ThoughtWorks Master Class Series 2007 – Registrations closing… and fast

Sidu has written a good post on why you ought to be attending the ThoughtWorks Master Class Series 2007.

Registrations for the Bangalore event have already come to a close down. We’re already sending invites for the Pune event. There’s still some invites left for the Pune event, and you can just about make it if you register quick.

Composite Logger for Ant

When doing long builds in CruiseControl, ant build logs are generally logged using the XmlLogger.

In certain cases, say for example when the build is taking longer than usual, and needs to be killed/stopped, the XmlLogger does not flush contents to disk.

It would be nice if there is some sort of a composite logger than can chain any logger along with the XmlLogger.

I just happened to write one sometime today. This is the source code for a CompositeLogger that logs to a default logger, and the XmlLogger. This needs the environment variable ANT_LOG_PREFIX to be set (there’s no better way I can think of)

package com.thoughtworks.ant.logger;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildLogger;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.XmlLogger;

/**
 * @author Ketan Padegaonkar
 */
public class CompositeAntLogger implements BuildLogger {

        private ArrayList       loggers;
        private String          logPrefix;
        private PrintStream     out;

        public CompositeAntLogger() {
                checkLogPrefix();
                createLoggers();
        }

        public void setEmacsMode(boolean emacsMode) {
                for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
                        BuildLogger logger = (BuildLogger) iterator.next();
                        logger.setEmacsMode(emacsMode);
                }
        }

        public void buildFinished(BuildEvent event) {
                for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
                        BuildLogger logger = (BuildLogger) iterator.next();
                        logger.buildFinished(event);
                }
        }

        public void buildStarted(BuildEvent event) {
                for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
                        BuildLogger logger = (BuildLogger) iterator.next();
                        logger.buildStarted(event);
                }
        }

        public void messageLogged(BuildEvent event) {
                for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
                        BuildLogger logger = (BuildLogger) iterator.next();
                        logger.messageLogged(event);
                }

        }

        public void targetFinished(BuildEvent event) {
                for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
                        BuildLogger logger = (BuildLogger) iterator.next();
                        logger.targetFinished(event);
                }
        }

        public void targetStarted(BuildEvent event) {
                for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
                        BuildLogger logger = (BuildLogger) iterator.next();
                        logger.targetStarted(event);
                }
        }

        public void taskFinished(BuildEvent event) {
                for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
                        BuildLogger logger = (BuildLogger) iterator.next();
                        logger.taskFinished(event);
                }
        }

        public void taskStarted(BuildEvent event) {
                for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
                        BuildLogger logger = (BuildLogger) iterator.next();
                        logger.taskStarted(event);
                }
        }

        public void setMessageOutputLevel(int level) {
                for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
                        BuildLogger logger = (BuildLogger) iterator.next();
                        logger.setMessageOutputLevel(level);
                }
        }

        public void setOutputPrintStream(PrintStream output) {
                // do nothing
        }

        public void setErrorPrintStream(PrintStream err) {
                // do nothing
        }

        private void createLoggers() {
                loggers = new ArrayList();
                try {
                        loggers.add(createDefaultLogger());
                        loggers.add(createXmlLogger());
                } catch (FileNotFoundException e) {
                        throw new BuildException("The loggers could not open the file", e);
                }
        }

        private void checkLogPrefix() {
                logPrefix = System.getenv("ANT_LOG_PREFIX");
                if (logPrefix == null || logPrefix.trim().length() == 0)
                        throw new BuildException("You need to set the environment variable ANT_LOG_PREFIX.");
        }

        private DefaultLogger createDefaultLogger() throws FileNotFoundException {
                DefaultLogger logger = new DefaultLogger();
                out = new PrintStream(new FileOutputStream(logPrefix + ".txt"));
                logger.setOutputPrintStream(out);
                logger.setErrorPrintStream(out);
                return logger;
        }

        private XmlLogger createXmlLogger() throws FileNotFoundException {
                XmlLogger logger = new XmlLogger();
                out = new PrintStream(new FileOutputStream(logPrefix + ".xml"));
                logger.setOutputPrintStream(out);
                logger.setErrorPrintStream(out);
                return logger;
        }
}

CruiseControl.rb is out

ThoughtWorks today announced a Continuous Integration tool, CruiseControl.rb. CruiseControl.rb is the Ruby version of CruiseControl, called CruiseControl.rb

The motto of CC.rb reads:

easy to install, pleasant to use and simple to hack

What kind of good stuff does that mean?

  • download and get building in 5-10 minutes (maybe 15 if you stop to read the manual)
  • little to no configuration (seriously, just tell it your svn url)
  • works for ruby, java, dotnet … anything that you can invoke from the command line
  • aesthetic beauty (not bad for a build tool)

SVNAnt: Using ant with SVN

While working on some ant build scripts today. A lot of custom batch files that were being exec’ed from within ant builds; batch files that would perform svn updates, reverts and commits, among other svn actions.

A good alternative would be to use SVNAnt (some snippets follow):

<svn>
  <delete>
    <fileset dir="workingcopy/deleteTest">
      <include name="**/*.del"/>
    </fileset>
  </delete>
  <commit message="commit deleted files"
       dir="workingcopy/deleteTest"/>
</svn>
<svn>
  <update dir="dir/to/update/" recurse="true" />
</svn>

Overriding equals and hashCode in Eclipse

Most colleagues use IntelliJ Idea as their favorite Java IDE. I’m an Eclipse plugin developer, and Eclipse happens to be my favorite Development platform of choice.

A lot more that just once, I’ve seen peers curse Eclipse for the lack of keyboard support, lack of refactoring, lack of functionality, lack of blah, blah, blah…

Let me address some of these issues:
Read the rest of this entry »

How would you clean this up ?

This was an interesting piece of code from a long time mentor and friend. He’s just started to learn Java some time ago, and has written this program to demonstrate how to draw an Ellipse.

He’s about 60 years of age. Has been a long time Turbo C-2.0 programmer. Mostly he develops small graphics programs to demonstrate some engineering drawing and mechanics concepts.

import java.awt.*; // Requisite files od JAVA
import java.awt.event.*;
//import java.awt.geom.*;
import javax.swing.*;
//import java.math.*;
//import java.util.*;
  //Projest name and the following class name should be same
public class leenaTrial1 extends JFrame {
        JFrame frame = new JFrame("Applet");
        JPanel drawingArea = new JPanel(); // Drawing Area is named
        JButton b1; // Defines action Button
        int mouse_i = 1;  // Counter for action

        public void run() {
                frame.setSize(1000, 500); // Frame size is defined
                final Container content = getContentPane();
                content.setBackground(Color.lightGray);
                // color of frame or container is defined
                content.setLayout(new FlowLayout());

                drawingArea.setPreferredSize(new Dimension(750, 700));
                // Size of draw area is defined & color in the next line

                drawingArea.setBackground(Color.black);
                content.add(drawingArea);
                b1 = new JButton("Next Step"); // b1 is button for the next step
                content.add(b1);

                b1.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent event) {
                        Graphics g = drawingArea.getGraphics();
                        Font font20 =new Font("TimesRoman",Font.PLAIN,20);
                        Font f0nt14=new Font("TimesRoman",Font.PLAIN,14);
                        g.setFont(font20);
                        int r1 = 250, r2 = 150, x0 = 375, y0 = 415;
                        // r1, r2 semi-major & semi-minor axex, x0,y0 center of circles
                        double inc = 0.005; // increment 
                        int x1, y1, x2, y2; // Two ends of a line

                        // inner circle in 
                        if(mouse_i == 1) {
                                g.setColor(Color.white);
                                //g.drawOval(w, w, x, y);           // top, left, width, height
                                g.drawString("Step 1: Draw inner circle with the radius equal to semi-minor axis of the ellipse.", 20, 20);
                                ovalByPixels(x0,y0,r2,r2,1,Color.blue);
                     }

                        // outer circle
                         if(mouse_i == 2) {
                                g.setColor(Color.white);
                                g.drawString("Step 2: Draw outer circle with the radius equal to semi-major axis of the ellipse.", 20, 35);
                                ovalByPixels(x0,y0,r1,r1,1,Color.red); // Color spesified by name
                        }

                        // twelve lines
                         if(mouse_i == 3) {
                                g.setColor(Color.white);
                                g.drawString("Step 3: Divide the circles in twelve parts.", 20, 50);
                                for(int k = 0; k < 6; k++) {
                                        double cos = Math.cos(k*2*Math.PI/12);
                                        double sin = Math.sin(k*2*Math.PI/12);
                                        double f1 = 1.06 ; // numbers are printed out side of larger circle
                                        double f2 = 0.9 ; // numbers are printed in side of smaller circle
                                        x1 = x0 + (int)(r1*cos); // x1,y1 are on outer circle on one end of diameter
                                        y1 = y0 - (int)(r1*sin);
                                        x2 = x0 - (int)(r1*cos); // x2,y2 are on outer circle at other end of diameter
                                        y2 = y0 + (int)(r1*sin);
                                        lineByPixels(x1, y1, x2, y2,5,new Color(255,100,100)); // 5 is delay value
                                        // Color spesified by values of three colors
                                        g.drawString("a" + Integer.toString(k+1),  x0-10+ (int)(f1*r1*cos), y0+10 - (int)(f1*r1*sin));
                                        g.drawString("a" + Integer.toString(k+7),  x0-10 - (int)(f1*r1*cos), y0+10 + (int)(f1*r1*sin));
                                        g.drawString("b" + Integer.toString(k+1),  x0 -10+ (int)(f2*r2*cos), y0+10 - (int)(f2*r2*sin));
                                        g.drawString("b" + Integer.toString(k+7),  x0 -10- (int)(f2*r2*cos), y0+10 + (int)(f2*r2*sin));
                                        delay(500);        // call delay function         
                                }
                        }

                         if(mouse_i == 4) { // Step 4     * * * * * * * * * * *
                                g.setColor(Color.white);
                                g.drawString("Step 4: From inner circle points, draw horizontal lines and from corresponding points ", 20, 70);
                                g.drawString("         on the outer circle, draw vertical lines. Cutting points are points on Ellipse.", 20, 85);
                                Color cr = new Color(255,200,100);
                                for(int k = 0; k <= 11; k++) {
                                        //int x1,x2,y1,y2;
                                        x1 = x0 + (int)(r1*Math.cos((2*Math.PI/12)*k)); // point on outer circle
                                        y1 = y0 - (int)(r1*Math.sin((2*Math.PI/12)*k));
                                        x2 = x0 + (int)(r2*Math.cos((2*Math.PI/12)*k)); //points on inner circle
                                        y2 = y0 - (int)(r2*Math.sin((2*Math.PI/12)*k));
                                        int x1L = x0 + (int)(1.2*r1*Math.cos((2*Math.PI/12)*k)); // point on outer circle
                                        int y2L = y0 - (int)(0.9*r2*Math.sin((2*Math.PI/12)*k));
                                        g.setColor(Color.green);
                                        if(k==3 || k==9){
                                                lineByPixels(x0-20, y2, x0+20, y2,5,cr );}// 5 is delay value
                           //g.drawLine( x0-20, y2, x0+20, y2);}
                                        else{
                                                lineByPixels(x2, y2, x1L, y2,5,new Color(255,100,200));}
                                                //g.drawLine(x2, y2, x1L, y2);} // horizontal line
                                        g.setColor(Color.yellow);
                                        if(k==0 || k==6){
                                                lineByPixels(x1, y0-20, x1,  y0+20,5,new Color(100,100,200));}
                                                //g.drawLine(x1, y0-20, x1,  y0+20);}// Vertical line
                                        else {
                                                lineByPixels(x1, y1, x1, y2L,5,new Color(100,255,100));}
                                                //g.drawLine(x1, y1, x1, y2L);}// vertical line
                                        delay(500); // call delay function         
                                        g.setColor(Color.white);
                                        g.drawOval(x1-3, y2-3, 6, 6); // Box (top, left, width, height
                    delay(500);
                                }
                        }

                        if(mouse_i == 5) {
                                g.setColor(Color.white);
                                g.drawString("Step 5: Draw a smooth curve connecting the twelve cutting points.", 20, 100);
                                g.setColor(Color.RED);
                                for(double i = 0; i < 2*(3.1415926); i=i+inc) {
                                        g.drawLine((int)(x0+r1*Math.cos(i)), (int)(y0-r2*Math.sin(i)), (int)(x0+(r1+1)*Math.cos(i)), (int)(y0-(r2+1)*Math.sin(i)));
                                        delay(1); // calls delay function

                                } // Ellipse drawing is complete

                                g.drawString("Ellipse by Concentric Circles, by Dr. Vasant D. Barve", 20, 680);
                                g.drawString("DONE!", 670, 350);
                        }
                        mouse_i++;
                 }
                });

                pack();
                setVisible(true);
        }
    // This is delay procedure  
        public void delay(int dt1)
        {
                try {
                        Thread.sleep(dt1);
                }
                catch (InterruptedException e) {
                }
        } // Delay procedure ends

    // This is Oval (circle or ellipse) by pixel procedure   * * * * * * * * * * * * * * *      
        public void ovalByPixels(float x0, float y0, float r1, float r2, int dt, Color objColor)
        {   // Center of circle at x0,y0 Radius r dt delay after each pixel counterclckwise
                Graphics g = drawingArea.getGraphics();
                double rm = Math.max(r1, r2); // Greater of the two picked up
                for(double i = 0; i < 2*(3.1415926); i=i+1/rm) {
                        double x1 = x0+ r1*Math.cos(i);
                        double y1 = y0+r2*Math.sin(i);
                        double x2 = x0+(r1+1)*Math.cos(i);
                        double y2 = y0+(r2+1)*Math.sin(i);
                        g.setColor(objColor);
                        g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
                        delay(dt); // call delay function    
                }
        } // OvalByPixels procedure Ends

//       lineByPixels Procedure starts              * * * * * *  * * * * *
        public void lineByPixels(int x1, int y1, int x2, int y2, int dt,Color objCol ) {
                // Line starts at (x1,y1) & ends at (x2,y2) each point is drawn as short line of one pixel length
                Graphics g = drawingArea.getGraphics();
                //g.setColor(Color.white); 
                g.setColor(objCol);

                int L= (int) Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));
            // length of line is found
                double th=Math.atan2(y2-y1,x2-x1); // inclination of line with x axis
               for(int i=0; i<=L-1; i=i+1)
            { g.drawLine((int) (x1+i*Math.cos(th)), (int) (y1+i*Math.sin(th)),(int) (x1+(i+1)*Math.cos(th)), (int) (y1+(i+1)*Math.sin(th)));
          delay(dt);    //delay introduced to see line being drawn    
            }
        } // lineByPixels Procedure Ends

        // Paint graphics starts                     * * * * * * * * *
        public void paint(Graphics g) {
                super.paint(g);
        } // Paint graphics Ends

        public static void main(String[] args) {
                leenaTrial1 ecc = new leenaTrial1(); // here the function is called
                ecc.run();
        }
}

SWTBot is coming

I’d used Sahi by Narayan Raman a while ago, and heard of frankenstein by Vivek Prahlad.

Sahi helped save quite a lot of time testing the web application that I was developing. Reproducing bugs was also very easy ;)

I’m currently working on developing Eclipse plug-ins and RCP applications. Testing the daily builds that Nirav makes is quite a pain. Hence a record and playback tool for SWT applications.

I’ve registered a project on sourceforge. You should see it at swtbot.sourceforge.net sometime in the next couple of days.

A headless build using ant has been put in place. A little bit of work has already been done. Code coverage is above 95%, for now. And I hope to keep it above 80% during the course of development of the application.

Eclipse RCP HOWTO — An Insurance Application in 2 hours

Here is a HOWTO on developing Eclipse RCP applications. We’d demonstrated this application at GNUnify07, held at SICSR, Pune.

This application is based on the chapter AHA, in “The Design Patterns Smalltalk Companion.”

Table of Contents:

Read the rest of this entry »

GNUnify 07 — an amazing event

GNUnify 07 at Symbiosis was a great event.

Sriram and me spoke on eclipse plug-in development on behalf of The Pune Eclipse Developers’ Group

The talk by A. Sundararajan from Sun on opensourcing the Java implementation (OpenJDK) from Sun was very interesting.

Moinak Ghosh from Sun gave a demo on some of the advanced features of OpenSolaris.

Also got an opportunity to meet Narayan Raman and Vivek Prahlad who’d developed Sahi and frankenstein.

Of Women, Technology and Open-Source

With all love and respect to my sisters in product management, marketing, sales, finance, HR, 50 years of IT history strongly suggests that technology companies will ever continue to be founded by entrepreneurs from engineering backgrounds; and if women never become engineers in sufficient numbers, they will disproportionately fail to experience the upper end of the range of IT outcomes.

Read the rest of this entry »