Ketan's Musings

Where he blogs about his eclipse musings

Archive for the ‘technology’ tag

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

without comments

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.

Written by Ketan

May 18th, 2007 at 2:44 pm

Composite Logger for Ant

with 3 comments

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;
        }
}

Written by Ketan

April 4th, 2007 at 7:24 pm

CruiseControl.rb is out

without comments

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)

Written by Ketan

March 13th, 2007 at 8:33 pm

SVNAnt: Using ant with SVN

without comments

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>

Written by Ketan

March 13th, 2007 at 8:10 pm

Overriding equals and hashCode in Eclipse

with 2 comments

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 »

Written by Ketan

March 1st, 2007 at 7:45 pm