<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;C0IDQH8zfSp7ImA9WhRWFEU.&quot;"><id>tag:blogger.com,1999:blog-14512504</id><updated>2012-01-02T10:49:31.185+05:30</updated><category term="Netbeans" /><category term="Firefox" /><category term="TDD" /><category term="jivox" /><category term="Git" /><category term="Javascript" /><category term="Maven" /><category term="player" /><category term="Linux" /><category term="Technology Musings" /><category term="Hadoop" /><category term="video" /><category term="Spring" /><category term="Java" /><category term="Unit Testing" /><category term="bee" /><category term="Open Source" /><title>Tech Talks for Newbies from a Newbie</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.tuxychandru.com/" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/tuxychandru" /><feedburner:info uri="tuxychandru" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;D0UGQH0zeCp7ImA9WhdRFU4.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-2293523916802732797</id><published>2011-08-04T19:02:00.013+05:30</published><updated>2011-08-05T14:37:01.380+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-05T14:37:01.380+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="video" /><category scheme="http://www.blogger.com/atom/ns#" term="bee" /><category scheme="http://www.blogger.com/atom/ns#" term="jivox" /><category scheme="http://www.blogger.com/atom/ns#" term="player" /><title>Jivox Launches Bee</title><content type="html">&lt;a href="http://www.jivox.com"&gt;Jivox&lt;/a&gt; has launched &lt;a href="http://bee.jivox.com"&gt;Bee&lt;/a&gt;, a free content player to embed self-hosted videos in web pages. We will soon provide a way to monetize your content using our &lt;a href="http://www.jivox.co.in/publishers"&gt;interactive video advertising platform&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Here is a screencast showing it in action.&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://bee.jivox.com/player/contentPlayer.php?siteId=94e390151d7430&amp;contentURL=http://cdn-in.jivox.com/bee/bee-web.m4v&amp;autoPlay=false&amp;rtmpServer=&amp;rtmpStream=&amp;vastURL=&amp;previewMode=false&amp;width=438&amp;height=246" width="438" height="246" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Note: Bee is under beta testing. Try it and give your feedback in comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-2293523916802732797?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/7zvQ5CUdHHs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/2293523916802732797/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=2293523916802732797" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2293523916802732797?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2293523916802732797?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/7zvQ5CUdHHs/jivox-launches-bee.html" title="Jivox Launches Bee" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2011/08/jivox-launches-bee.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkANR38_fSp7ImA9WhZaE0s.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-8508260396958569637</id><published>2011-06-29T22:31:00.002+05:30</published><updated>2011-06-29T23:03:16.145+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-29T23:03:16.145+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><category scheme="http://www.blogger.com/atom/ns#" term="Hadoop" /><title>Hadoop's POM Conflicts with Distribution</title><content type="html">My current project uses Hadoop to do some data munching. I hit a snag when trying to upload a file to S3 from a hadoop job using the &lt;a href="http://jets3t.s3.amazonaws.com/index.html"&gt;jets3t&lt;/a&gt; api. We use maven to handle all the dependencies of our project including hadoop. When I deployed the job to our test cluster, I received a "java.lang.VerifyError". I couldn't find the solution on the internet so decided to blog it myself.&lt;br /&gt;&lt;br /&gt;Turns out that the POM of hadoop-core 0.20.2 has a dependency on jets3t-0.7.1, but the hadoop distribution ships with jets3t-0.6.1 (which is incompatible with 0.7.1). Since our JAR was compiled with 0.7.1, byte code verification failed.&lt;br /&gt;&lt;br /&gt;To fix this I had to exclude jetst3t from hadop-core dependency list,&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1054316.js?file=pom_exclusion"&gt;&lt;/script&gt;&lt;br /&gt;And add an explicit dependency on jets3t 0.6.1 in our project.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1054316.js?file=explicit_dependency"&gt;&lt;/script&gt;&lt;br /&gt;That fixes it. Hope this post helps someone affected by this bug in hadoop's POM.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-8508260396958569637?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/PMAvlKW1wCU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/8508260396958569637/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=8508260396958569637" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/8508260396958569637?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/8508260396958569637?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/PMAvlKW1wCU/hadoops-pom-conflicts-with-distribution.html" title="Hadoop's POM Conflicts with Distribution" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2011/06/hadoops-pom-conflicts-with-distribution.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4ARXc7eSp7ImA9WxBXFE8.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-3073645027591603283</id><published>2010-01-22T18:49:00.008+05:30</published><updated>2010-01-25T19:29:04.901+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-25T19:29:04.901+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Git" /><title>How Git shines above Subversion at Merging</title><content type="html">I've recently started getting my head around Git having been a Subversion (sadly even CVS) user all along.  While I liked the fact that it was distributed and way faster than Subversion at most operations, I couldn't understand why many claimed it was better at merging than Subversion (1.5 and above).  Even the "Branch Handling" section in &lt;a href="http://git.wiki.kernel.org/index.php/GitSvnComparsion"&gt;Git's wiki&lt;/a&gt; talks only about better history tracking but not about how Git is better at merging the content themselves.&lt;br /&gt;&lt;br /&gt;While correct history tracking is important, merging without breaking the code is an absolute must.  So I wanted to see if there was a place where Subversion would silently break the code during a merge but Git would not.  This might not be new to long time Git users but I hope this would help many Subversion users take another look at Git.  Without further ado, lets see how Git manages merges better.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;The Workflow&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You initially start off with a file named Test.java in both SVN and Git repositories with initial content as below.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/283800.js?file=initial_Test.java"&gt;&lt;/script&gt;&lt;br /&gt;You then create a branch named "refactor" and within this branch rename the class to NicerName (and consequently rename the file too) and commit to the branch.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/283800.js?file=branch_NicerName.java"&gt;&lt;/script&gt;&lt;br /&gt;You switch back to the main branch (trunk/master) and fix a bug.  In this case we change the message being printed to "Correct Message" and commit to the main branch.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/283800.js?file=fixed_Test.java"&gt;&lt;/script&gt;&lt;br /&gt;Finally, we merge the changes from the refactor branch into the main branch.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;The commands&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;SVN would do it with the following commands.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/283800.js?file=svn_commands"&gt;&lt;/script&gt;&lt;br /&gt;Git would do the same with these commands.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/283800.js?file=git_commands"&gt;&lt;/script&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;The Result&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Neither SVN nor Git complain about conflicts which is fine.  However, after the merge, SVN leaves two files in the main branch.  NicerName.java has the new name but doesn't have the fix while Test.java has the fix but not the new name.  Here is how it looks in SVN.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/283800.js?file=svn_NicerName.java"&gt;&lt;/script&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/283800.js?file=svn_Test.java"&gt;&lt;/script&gt;&lt;br /&gt;Essentially your code is broken silently by SVN during the merge.  On the other hand Git handles this very cleanly.  It leaves only NicerName.java back including the fix to the message and removes Test.java, exactly as you'd expect.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/283800.js?file=git_NicerName.java"&gt;&lt;/script&gt;&lt;br /&gt;Over all the branching and merging commands looked cleaner with Git too. This kind of excellent support for branching, refactoring and merging back alone should make everyone give Git a serious consideration.  Even if Git is used in a centralized workflow just like Subversion, it can still provide huge benefits over Subversion.  If you utilize its distribution features too, it just gets better!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-3073645027591603283?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/aws_IZlpskg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/3073645027591603283/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=3073645027591603283" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/3073645027591603283?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/3073645027591603283?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/aws_IZlpskg/how-git-shines-above-subversion-at.html" title="How Git shines above Subversion at Merging" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2010/01/how-git-shines-above-subversion-at.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkECSH44cSp7ImA9WhRSE0s.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-3412248329071485917</id><published>2009-12-13T00:55:00.008+05:30</published><updated>2011-11-15T19:14:29.039+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-15T19:14:29.039+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Spring" /><title>Simple Layouts with JSP in Spring MVC</title><content type="html">Every web application has elements common to all its pages which are good candidates for re-use.  While Spring MVC provides integration with Tiles, it can be an overkill for simple applications and needs using Spring's client side JS library for AJAX (correct me if I'm wrong).&lt;br /&gt;&lt;br /&gt;For most applications, standard JSPs can serve as good layout engine.  This post shows how Spring's handler interceptor can be used to specify a normal JSP file as the layout for a Spring MVC web application.&lt;br /&gt;&lt;br /&gt;This interceptor allows you to specify a JSP file containing the layout for the application into which the actual views get plugged.  The interceptor takes the actual model and view and replaces the actual view with the layout view's name and puts the actual view name into the model map to be used by the layout file.  If you do not want to include the layout for certain requests (AJAX requests) you can prefix the view name with "noLayout:".&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Interceptor&lt;/b&gt;&lt;pre class="code"&gt;public class LayoutInterceptor extends HandlerInterceptorAdapter {&lt;br /&gt;   private static final String NO_LAYOUT = "noLayout:";&lt;br /&gt;&lt;br /&gt;   private String layoutView;&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {&lt;br /&gt;       super.postHandle(request, response, handler, modelAndView);&lt;br /&gt;&lt;br /&gt;       String originalView = modelAndView.getViewName();&lt;br /&gt;      &lt;br /&gt;       if (originalView != null &amp;&amp; !originalView.startsWith("redirect:")) {&lt;br /&gt;           includeLayout(modelAndView, originalView);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void includeLayout(ModelAndView modelAndView, String originalView) {&lt;br /&gt;       boolean noLayout = originalView.startsWith(NO_LAYOUT);&lt;br /&gt;&lt;br /&gt;       String realViewName = (noLayout) ? originalView.substring(NO_LAYOUT.length()) : originalView;&lt;br /&gt;&lt;br /&gt;       if (noLayout) {&lt;br /&gt;           modelAndView.setViewName(realViewName);&lt;br /&gt;       } else {&lt;br /&gt;           modelAndView.addObject("view", realViewName);&lt;br /&gt;           modelAndView.setViewName(layoutView);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void setLayoutView(String layoutView) {&lt;br /&gt;       this.layoutView = layoutView;&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Sample Usage&lt;/b&gt;&lt;/div&gt;&lt;pre class="code"&gt;&amp;lt;bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"&amp;gt;&lt;br /&gt;   &amp;lt;property name="interceptors"&amp;gt;&lt;br /&gt;       &amp;lt;list&amp;gt;&lt;br /&gt;           &amp;lt;bean id="layoutInterceptor" class="LayoutInterceptor"&amp;gt;&lt;br /&gt;               &amp;lt;property name="layoutView" value="layout"&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;           &amp;lt;/bean&amp;gt;&lt;br /&gt;       &amp;lt;/list&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&amp;gt;&lt;br /&gt;   &amp;lt;property name="viewClass" value="org.springframework.web.servlet.view.JstlView"&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name="prefix" value="/WEB-INF/jsp/"&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name="suffix" value=".jsp"&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;/pre&gt;With that all the views returned by controllers can be included within the layout JSP by including the following line in &lt;i&gt;WEB-INF/jsp/layout.jsp&lt;/i&gt;.&lt;pre class="code"&gt;&amp;lt;jsp:include page="/WEB-INF/jsp/${view}.jsp"&amp;gt;&amp;lt;/jsp:include&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-3412248329071485917?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/ayKLomkN9fw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/3412248329071485917/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=3412248329071485917" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/3412248329071485917?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/3412248329071485917?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/ayKLomkN9fw/simple-layouts-with-jsp-in-spring-mvc.html" title="Simple Layouts with JSP in Spring MVC" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2009/12/simple-layouts-with-jsp-in-spring-mvc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMBRXg-eip7ImA9WxNUFE0.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-2734830813978137461</id><published>2009-11-01T23:34:00.013+05:30</published><updated>2009-11-05T13:04:14.652+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-05T13:04:14.652+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>Mocking Math.random() using PowerMock</title><content type="html">Let's consider the below Game class in a guessing game where a random target is chosen by the system and the user guesses the target.  The system returns an appropriate message based on whether the guess was higher, lower or equal to the random target.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;package org.game;&lt;br /&gt;&lt;br /&gt;public class Game {&lt;br /&gt; private int target = (int) (Math.random() * 100);&lt;br /&gt;&lt;br /&gt; public int guess(int guess) {&lt;br /&gt;  return target - guess;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No magic there.  Now let's look at the unit test for this class.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;package org.game;&lt;br /&gt;&lt;br /&gt;// imports hidden;&lt;br /&gt;&lt;br /&gt;public class GameTest {&lt;br /&gt; private Game game;&lt;br /&gt;&lt;br /&gt; @Before&lt;br /&gt; public void setUp() {&lt;br /&gt;  game = new Game();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; public void testHigherGuess() {&lt;br /&gt;  int result = game.guess(55);&lt;br /&gt;  Assert.assertTrue(result &lt; 0);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; public void testLowerGuess() {&lt;br /&gt;  int result = game.guess(35);&lt;br /&gt;  Assert.assertTrue(result &gt; 0);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; public void testCorrectGuess() {&lt;br /&gt;  int result = game.guess(50);&lt;br /&gt;  Assert.assertTrue(result == 0);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you might have guessed by now this wouldn't work as the target is randomly generated.  Now we have three options to handle this.&lt;br /&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Add a constructor taking the target value as argument and set the target using that. This would make passing a non-random value for testing simple.  However, this would change the interface of the class unnecessarily.&lt;/li&gt;&lt;li&gt;Access "target" using reflection and set its value after object creation.  However, this would make the unit test fragile as it knows too much about the internals of the class under test.&lt;/li&gt;&lt;li&gt;We can make Math.random() to return a constant value within our test case.  This is the approach demonstrated in this post.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;a href="http://code.google.com/p/powermock/"&gt;PowerMock&lt;/a&gt; is a mocking framework which extends several popular frameworks to allow mocking of static methods and more.  In this post we'll use PowerMocks' extension for &lt;a href="http://easymock.org/"&gt;EasyMock&lt;/a&gt;.  The general technique to mock static methods using PowerMock is outlined &lt;a href="http://code.google.com/p/powermock/wiki/MockStatic"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This wouldn't work for system classes like Math.  To workaround this, we can prepare the class using the static method for test rather than the class containing the static method.  Which means we'd be using @PrepareForTest(Game.class) instead of @PrepareForTest(Math.class) in our case.  The completed unit test would look like this.&lt;/div&gt;&lt;br /&gt;&lt;pre class="code"&gt;package org.game;&lt;br /&gt;&lt;br /&gt;// imports hidden&lt;br /&gt;&lt;br /&gt;@RunWith(PowerMockRunner.class)&lt;br /&gt;@PrepareForTest(Game.class) // Preparing class under test.&lt;br /&gt;public class GameTest {&lt;br /&gt; private Game game;&lt;br /&gt;&lt;br /&gt; @Before&lt;br /&gt; public void setUp() {&lt;br /&gt;  // Mocking Math.random()&lt;br /&gt;  PowerMock.mockStatic(Math.class);&lt;br /&gt;  EasyMock.expect(Math.random()).andReturn(0.50).anyTimes();&lt;br /&gt;  PowerMock.replay(Math.class);&lt;br /&gt;&lt;br /&gt;  game = new Game();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; public void testHigherGuess() {&lt;br /&gt;  int result = game.guess(55);&lt;br /&gt;  Assert.assertTrue(result &lt; 0);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; public void testLowerGuess() {&lt;br /&gt;  int result = game.guess(35);&lt;br /&gt;  Assert.assertTrue(result &gt; 0);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; public void testCorrectGuess() {&lt;br /&gt;  int result = game.guess(50);&lt;br /&gt;  Assert.assertTrue(result == 0);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Now PowerMock ensures that any call to Math.random() would always return a constant value within the Game class when used for testing.  Hence we can test the guess() method just as how any client code using the Game class would.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-2734830813978137461?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/pxFFJjlbPwU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/2734830813978137461/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=2734830813978137461" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2734830813978137461?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2734830813978137461?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/pxFFJjlbPwU/mocking-mathrandom-using-powermock.html" title="Mocking Math.random() using PowerMock" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2009/11/mocking-mathrandom-using-powermock.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMCSHwzfSp7ImA9WxNQFEo.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-2619772203313528305</id><published>2009-08-29T10:17:00.029+05:30</published><updated>2009-09-20T23:44:29.285+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-20T23:44:29.285+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>Using Javascript as DI Container in Java</title><content type="html">Javascript is almost as dynamic as any programming language can get.  However, it is mostly used only within the browser and many developers (including dynamic language fans) don't know of many of the cool language features of Javascript.  When these features are used effectively, it lets us write highly expressive code which even many dynamic languages can't match.&lt;br /&gt;&lt;br /&gt;Most Java developers turn to Spring for their DI and AOP requirements.  However the configuration of Spring is quite verbose and is mostly XML.  Plain JDK can handle AOP using dynamic proxies and as this post demonstrates Javascript can be used to handle the dependency injections.&lt;br /&gt;&lt;br /&gt;Starting with Java 6, Java applications can invoke scripting languages within their JVM instance and communicate with them seamlessly using the &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html"&gt;Scripting API&lt;/a&gt;.  Sun's JRE also ships with a built-in engine for handling Javasript through this API.  We can utilize Javascript's power and expressiveness to perform cool stuffs on top of the JVM.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What are we Building?&lt;br /&gt;&lt;/span&gt;&lt;ol&gt;&lt;li&gt;Two DAOs and their mock implementations.&lt;/li&gt;&lt;li&gt;A sample service utilizing these DAOs.&lt;/li&gt;&lt;li&gt;JS script wiring them up together.&lt;/li&gt;&lt;li&gt;A simple interceptor to log invocations of service methods.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-weight: bold;"&gt;DAOs&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;package dao;&lt;br /&gt;&lt;br /&gt;public interface BooksDAO {&lt;br /&gt;    public int count();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;pre class="code"&gt;package dao;&lt;br /&gt;&lt;br /&gt;public interface MembersDAO {&lt;br /&gt;    public int count();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;pre class="code"&gt;package dao;&lt;br /&gt;&lt;br /&gt;public class MockBooksDAO implements BooksDAO {&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public int count() {&lt;br /&gt;        return 500;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;pre class="code"&gt;package dao;&lt;br /&gt;&lt;br /&gt;public class MockMembersDAO implements MembersDAO {&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public int count() {&lt;br /&gt;        return 100;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Service&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;package service;&lt;br /&gt;&lt;br /&gt;public interface LibraryService {&lt;br /&gt;&lt;br /&gt;    public abstract int countBooks();&lt;br /&gt;&lt;br /&gt;    public abstract int countMembers();&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;pre class="code"&gt;package service;&lt;br /&gt;&lt;br /&gt;import dao.BooksDAO;&lt;br /&gt;import dao.MembersDAO;&lt;br /&gt;&lt;br /&gt;public class MockLibraryService implements LibraryService {&lt;br /&gt;    private BooksDAO booksDAO;&lt;br /&gt;    private MembersDAO membersDAO;&lt;br /&gt;&lt;br /&gt;    public MockLibraryService(BooksDAO booksDAO, MembersDAO membersDAO) {&lt;br /&gt;        this.booksDAO = booksDAO;&lt;br /&gt;        this.membersDAO = membersDAO;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int countBooks() {&lt;br /&gt;        System.out.println("In countBooks()");&lt;br /&gt;        return booksDAO.count();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int countMembers() {&lt;br /&gt;        System.out.println("In countMembers()");&lt;br /&gt;        return membersDAO.count();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;DI Script&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We utilize Javascript's &lt;a href="http://www.dyn-web.com/tutorials/obj_lit.php"&gt;Object literals&lt;/a&gt; to define and group our DAOs and services.  These can then looked up from our applications to obtain the actual implementations.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;src/objects.js&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;importPackage(Packages.dao)&lt;br /&gt;importPackage(Packages.service)&lt;br /&gt;importPackage(Packages.interceptor)&lt;br /&gt;&lt;br /&gt;daos = {&lt;br /&gt; booksDAO : new MockBooksDAO(),&lt;br /&gt; membersDAO : new MockMembersDAO()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;services = {&lt;br /&gt; libraryService : LoggingInterceptor.getProxy(new MockLibraryService(daos.booksDAO, daos.membersDAO))&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Application Code&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We use the ScriptEngineBuilder introduced in a &lt;a href="http://tuxychandru.blogspot.com/2009/08/scriptenginebuilder-for-java.html"&gt;previous post&lt;/a&gt; to evaluate our Javacript and then obtain the service instance from it.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;package app;&lt;br /&gt;&lt;br /&gt;import javax.script.ScriptEngine;&lt;br /&gt;import javax.script.ScriptException;&lt;br /&gt;&lt;br /&gt;import service.LibraryService;&lt;br /&gt;import util.ScriptEngineBuilder;&lt;br /&gt;&lt;br /&gt;public class Main {&lt;br /&gt;    public static void main(String[] args) throws ScriptException {&lt;br /&gt;        ScriptEngine engine = new ScriptEngineBuilder("js").add("/objects.js").build();&lt;br /&gt;&lt;br /&gt;        LibraryService service = (LibraryService) engine.eval("services.libraryService");&lt;br /&gt;&lt;br /&gt;        System.out.println("Found " + service.countMembers() + " Members!");&lt;br /&gt;        System.out.println("Found " + service.countBooks() + " Members!");&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Adding AOP to the Mix&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let's create a JDK dynamic proxy to log all method invocations.&lt;br /&gt;&lt;pre class="code"&gt;package interceptor;&lt;br /&gt;&lt;br /&gt;import java.lang.reflect.InvocationHandler;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;import java.lang.reflect.Proxy;&lt;br /&gt;&lt;br /&gt;public class LoggingInterceptor implements InvocationHandler {&lt;br /&gt;    private Object target;&lt;br /&gt;&lt;br /&gt;    public static Object getProxy(Object target) {&lt;br /&gt;        ClassLoader loader = LoggingInterceptor.class.getClassLoader();&lt;br /&gt;        Class&lt;?&gt;[] interfaces = target.getClass().getInterfaces();&lt;br /&gt;        InvocationHandler handler = new LoggingInterceptor(target);&lt;br /&gt;        &lt;br /&gt;        return Proxy.newProxyInstance(loader, interfaces, handler);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private LoggingInterceptor(Object target) {&lt;br /&gt;        this.target = target;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Object invoke(Object proxy, Method method, Object[] args)&lt;br /&gt;            throws Throwable {&lt;br /&gt;        try {&lt;br /&gt;            System.out.println("Entered Method: " + method.getName());&lt;br /&gt;            Object val = method.invoke(target, args);&lt;br /&gt;            System.out.println("Completed Method: " + method.getName());&lt;br /&gt;            return val;&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            System.out.println("Exception in Method: " + method.getName());&lt;br /&gt;            throw e;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Let's now modify our service creation in DI script as below to utilize the proxy.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;libraryService : LoggingInterceptor.getProxy(new MockLibraryService(daos.booksDAO, daos.membersDAO))&lt;/pre&gt;&lt;br /&gt;So there we have a nice and clean DI configuration including AOP without needing anything outside of Java SE.  An important thing to note here is that we are still maintaining the DI and AOP config entirely outside our application code unlike when using annotations.  Spring would have needed a  truck load of XML to achieve the same!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-2619772203313528305?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/zQoZxYHvcz4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/2619772203313528305/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=2619772203313528305" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2619772203313528305?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2619772203313528305?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/zQoZxYHvcz4/using-javascript-as-di-container-in.html" title="Using Javascript as DI Container in Java" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2009/08/using-javascript-as-di-container-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEMQ3s9cSp7ImA9WxNSFUo.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-3759278848682682151</id><published>2009-08-28T23:43:00.005+05:30</published><updated>2009-08-30T00:01:22.569+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-30T00:01:22.569+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>ScriptEngineBuilder for Java</title><content type="html">Java 6 allows you to execute and communicate with scripts written in any scripting language, using the &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html"&gt;Scripting API&lt;/a&gt;.  However, the code needed to create a &lt;a href="http://java.sun.com/javase/6/docs/api/javax/script/ScriptEngine.html"&gt;ScriptEngine&lt;/a&gt; and evaluate a set of script files within it, is quite verbose and throws several checked exceptions.&lt;br /&gt;&lt;br /&gt;I decided to create a simple fluent Builder which can be used to create a ScriptEngine and execute a set of script files inside it.  It also allows you to add Java Objects into the engine before executing the script files.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;ScriptEngineBuilder&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;import java.io.InputStreamReader;&lt;br /&gt;import java.net.URL;&lt;br /&gt;&lt;br /&gt;import javax.script.ScriptEngine;&lt;br /&gt;import javax.script.ScriptEngineManager;&lt;br /&gt;&lt;br /&gt;public class ScriptEngineBuilder {&lt;br /&gt;    private ScriptEngine engine;&lt;br /&gt;&lt;br /&gt;    public ScriptEngineBuilder(String shortName) {&lt;br /&gt;        this.engine = new ScriptEngineManager().getEngineByName(shortName);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ScriptEngineBuilder add(String scriptResource) {&lt;br /&gt;        try {&lt;br /&gt;            URL scriptURL = getClass().getResource(scriptResource);&lt;br /&gt;            InputStreamReader scriptReader = new InputStreamReader(scriptURL.openStream());&lt;br /&gt;            engine.eval(scriptReader);&lt;br /&gt;&lt;br /&gt;            return this;&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            throw new RuntimeException(e);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ScriptEngineBuilder put(String key, Object value) {&lt;br /&gt;        engine.put(key, value);&lt;br /&gt;        return this;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ScriptEngine build() {&lt;br /&gt;        return engine;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Applications can create an instance of ScriptEngineBuilder by passing the shortName of the engine to the constructor.  Then they can invoke add() method for the script files to be evaluated (as classpath resource name).  They can finally invoke build() to get the ScriptEngine instance.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sample Invocation&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;ScriptEngine engine = new ScriptEngineBuilder("js").add("/script1.js").put("myObj", obj).add("/script2.js").build();&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-3759278848682682151?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/O9i0nGr75vc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/3759278848682682151/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=3759278848682682151" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/3759278848682682151?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/3759278848682682151?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/O9i0nGr75vc/scriptenginebuilder-for-java.html" title="ScriptEngineBuilder for Java" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2009/08/scriptenginebuilder-for-java.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UFQXg_fyp7ImA9WxVaFEo.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-2436031067605712966</id><published>2009-04-11T23:52:00.000+05:30</published><updated>2009-04-12T01:16:50.647+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-12T01:16:50.647+05:30</app:edited><title>DevCamp Bangalore 2</title><content type="html">I had attended &lt;a href="http://devcamp.in/wiki/Main_Page"&gt;DevCamp Bangalore 2&lt;/a&gt; on Saturday.  There were several &lt;a href="http://devcamp.in/wiki/DevCamp_Bangalore_2_Sessions"&gt;sessions planned&lt;/a&gt; and many happened simultaneously.  So I could attend only a handful of them though many others were interesting too.  I had quite a nice experience in most of the sessions except for those where either I was not interested or didn't understand anything.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sahi&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://sahi.co.in/w/"&gt;Sahi&lt;/a&gt; is an automation and testing tool for web applications, with the facility to record and playback scripts. Sahi runs on any modern browser which supports javascript.&lt;span&gt;  The founder of Sahi, &lt;/span&gt;Narayan Raman,&lt;span&gt; gave a nice descriptive demo of how Sahi works and was answering the various interesting questions fired at him by audience.  He als&lt;/span&gt;&lt;span&gt;o mentioned&lt;/span&gt;&lt;span&gt; the limitations which Sahi had in its current state.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;Visualization of Code Metrics&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nealford.com/"&gt;Neal Ford&lt;/a&gt; gave a nice presentation on the various tools which provide visual presentation of various code metrics like Cyclomatic Complexity, LOC, Methods per Class, etc.  It was a nice learning for me about various standards and thresholds the industry follows regarding code quality.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Augmented Reality&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Mrinal Wadhwa's session on this one didn't really interest me and I just moved out.  Not that the session was bad just that it did not align with my interests.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Productive Programmer Mechanics&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is was one of the more interesting sessions.  Neal Ford talked about different ways to improve the productivity of programmers.  While it was nothing revolutionary, some of the tips on using IDEs better were Aha! moments.&lt;br /&gt;&lt;br /&gt;When he mentioned but Window's behavior affected programmers' productivity, I felt it was indeed so true.  Though, I myself have never realized it though I'm sick of Windows.  This indeed has been disturbing me at work daily but I just never realized it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Erlang &amp;amp; Distribution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Bhasker V Kode's session on Erlang was very interesting.  Especially his biological analogies were helping in explaining it a lot better.  However, since I have absolutely no familiarity with Erlang and have very little understanding of FP, it really was greek and hebrew to me.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ruby for the Curious Hacker&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This was a session I was waiting for given my recent in &lt;a href="http://rubyonrails.org/"&gt;RoR&lt;/a&gt;.  &lt;a href="http://blog.sidu.in/"&gt;Sidu&lt;/a&gt; had a very simple presentation but the Q&amp;amp;A discussion took up the session's time and even exceeded it a bit.&lt;br /&gt;&lt;br /&gt;There were several people criticizing the syntax of Ruby and its monkey patching capabilities.  Sidu also expressed some of his gripes about Ruby and to some extent Rails.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;DSLs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Neal Fords, session on how normal languages can be used as DSLs was the last session I attended.  It was very interesting as he demonstrated how playing around with languages' syntax can turn them into DSLs.  He also mentioned various ways of building DSLs out of common languages.&lt;br /&gt;&lt;br /&gt;Over all it was a very nice experience, interacting and learning from fellow geeks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-2436031067605712966?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/e-0GHUi6pNc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/2436031067605712966/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=2436031067605712966" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2436031067605712966?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2436031067605712966?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/e-0GHUi6pNc/devcamp-bangalore-2.html" title="DevCamp Bangalore 2" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>3</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2009/04/devcamp-bangalore-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEACR3Y_fip7ImA9WxVTEk0.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-8308004824066461022</id><published>2008-12-25T00:49:00.000+05:30</published><updated>2008-12-25T16:29:26.846+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-25T16:29:26.846+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Netbeans" /><category scheme="http://www.blogger.com/atom/ns#" term="Firefox" /><title>Netbeans Firefox Hack</title><content type="html">Most Ubuntu (any distro specific Firefox package for that matter) users who also happen to use Netbeans, would have come across &lt;a href="http://www.netbeans.org/issues/show_bug.cgi?id=76970"&gt;this annoying issue&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Even if the Arguments setting for Firefox was changed to juts "{URL}" in Netbeans options, it displays an error when the project is run multiple times and then Firefox is closed.  But at least it doesn't display for each run.  Still getting the error is annoying even though it is only when Firefox is closed after multiple runs.&lt;br /&gt;&lt;br /&gt;I felt Netbeans was somehow waiting for Firefox to close before next run (I really have no clue what exactly is wrong).  So I thought starting Firefox in background and returning immediately to Netbeans will help.&lt;br /&gt;&lt;br /&gt;So I created a shell script with the following content.  And made it executable.&lt;br /&gt;&lt;pre class="code"&gt;#!/bin/bash&lt;br /&gt;firefox "$1" &amp;&lt;/pre&gt;&lt;br /&gt;Then I selected the shell script as the command for starting Firefox in Netbeans.  Final settings in Netbeans, look like this.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_g5hM85MTy7c/SVKPT6ZWxcI/AAAAAAAAASg/mQXpho8ldW0/s1600-h/nb_firefox.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 214px;" src="http://2.bp.blogspot.com/_g5hM85MTy7c/SVKPT6ZWxcI/AAAAAAAAASg/mQXpho8ldW0/s320/nb_firefox.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5283442885114906050" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;While I never understood how this fixed it, it did.  No more annoying error messages.  :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-8308004824066461022?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/qio6ZEPSRBM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/8308004824066461022/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=8308004824066461022" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/8308004824066461022?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/8308004824066461022?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/qio6ZEPSRBM/netbeans-firefox-hack.html" title="Netbeans Firefox Hack" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_g5hM85MTy7c/SVKPT6ZWxcI/AAAAAAAAASg/mQXpho8ldW0/s72-c/nb_firefox.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2008/12/netbeans-firefox-hack.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEHRHs_eSp7ImA9WxRaFUw.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-2126585242487515053</id><published>2008-12-01T22:59:00.000+05:30</published><updated>2008-12-17T18:27:15.541+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-17T18:27:15.541+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><title>Making openAL use PulseAudio in Ubuntu Intrepid</title><content type="html">With the release if Ubuntu Intrepid, everything was supercool except for one pain point.  Sound system would crash leaving a noise which would not stop until a system reboot whenever I play and exit from torcs.&lt;br /&gt;&lt;br /&gt;For a system wide fix for this problem, edit /etc/openal/alsoft.conf and change the device value in the section titled [alsa] as below.&lt;br /&gt;&lt;pre class="code"&gt;device = alsa&lt;/pre&gt;Ubuntu rocks again.  :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-2126585242487515053?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/WApIX9Ejb2o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/2126585242487515053/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=2126585242487515053" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2126585242487515053?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2126585242487515053?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/WApIX9Ejb2o/making-openal-use-pulseaudio-in-ubuntu.html" title="Making openAL use PulseAudio in Ubuntu Intrepid" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2008/12/making-openal-use-pulseaudio-in-ubuntu.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUMR3c8fip7ImA9WxJVEUo.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-604795631340678086</id><published>2008-10-06T00:38:00.001+05:30</published><updated>2009-06-28T13:01:26.976+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-28T13:01:26.976+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>Shortcuts in JSF web applications using AJAX4JSF</title><content type="html">AJAX4JSF is library of JSF components which can be used to easily add AJAX capabilities to JSF web applications.  AJAX4JSF is available as part of the &lt;a href="http://www.jboss.org/jbossrichfaces/"&gt;Richfaces&lt;/a&gt; component library.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Goal&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For this example, let us consider a simple goal of listing a set of products or services based on the category chosen by the user.  A combo box is presented to the user, where he can choose between "Products" and "Services".  Based on his choice a list of products or services is retrieved from the server and displayed.&lt;br /&gt;&lt;br /&gt;The user can also hit "Ctrl + 1" to list all products and "Ctrl + 2" to list all services, instead of choosing from the combo box.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Compromises&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;While in real world scenarios, the list of products/services will have to retrieved from a DB, to keep the example simple, we just swap between 2 predefined lists of Strings.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;How does it work?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;a4j:support&amp;gt; tag is used to send an AJAX request to the server whenever the combo box selection changes.&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;a4j:support event="onchange" action="#{dataLoader.updateCurrentData}"&lt;br /&gt;rerender="currentItemsTable"&amp;gt;&lt;br /&gt;&amp;lt;/a4j:support&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Providing shortcut keys involves two steps.&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Using &amp;lt;a4j:jsFunction&amp;gt; tag to define a Javascript function which takes the category as parameter.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Writing Javascript code to check for keystrokes and invoke the JS function define in step-1 with appropriate parameters.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The &amp;lt;a4j:jsFunction&amp;gt; tag&lt;/span&gt;&lt;br /&gt;This tag simplifies the client side process of initiating AJAX request from Javascript.  The value specified for its name attribute is used as the name of the Javascript function generated.  It also takes the JSF action to be invoked and the region of page to be re-rendered after the AJAX request as attributes.&lt;br /&gt;&lt;br /&gt;&amp;lt;a4j:actionparam&amp;gt; tag can be used to define the parameters to be accepted by the generated JS frunction and the managed bean property to which they are to be assigned.  In our case the key pressed is passed as parameter to the generated JS function, "updateData()".&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;a4j:jsFunction name="updateData"&lt;br /&gt;action="#{dataLoader.updateCurrentData}"&lt;br /&gt;reRender="currentItemsTable"&amp;gt;&lt;br /&gt;&amp;lt;a4j:actionparam name="choice"&lt;br /&gt;assignTo="#{dataLoader.currentChoice}" /&amp;gt;&lt;br /&gt;&amp;lt;/a4j:jsFunction&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Javascript code&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This fragment of Javascript is used to check for keystrokes and invoke the generated JS function with appropriate parameter.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var ctrlPressed;&lt;br /&gt;&lt;br /&gt;document.onkeydown = function(e) {&lt;br /&gt;var keyCode;&lt;br /&gt;&lt;br /&gt;if (window.event)&lt;br /&gt;keyCode = window.event.keyCode;&lt;br /&gt;else if (e.which)&lt;br /&gt;keyCode = e.which;&lt;br /&gt;&lt;br /&gt;if (keyCode == 17)&lt;br /&gt;ctrlPressed = true;&lt;br /&gt;&lt;br /&gt;if (ctrlPressed) {&lt;br /&gt;switch (keyCode) {&lt;br /&gt;case 49:&lt;br /&gt; updateData(1);&lt;br /&gt; break;&lt;br /&gt;case 50:&lt;br /&gt; updateData(2);&lt;br /&gt; break;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;document.onkeyup = function(e) {&lt;br /&gt;var keyCode;&lt;br /&gt;&lt;br /&gt;if (window.event)&lt;br /&gt;keyCode = window.event.keyCode;&lt;br /&gt;else if (e.which)&lt;br /&gt;keyCode = e.which;&lt;br /&gt;&lt;br /&gt;if (keyCode == 17)&lt;br /&gt;ctrlPressed = false;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For further details of implementation, look into the complete source code archive provided below.  This archive does not include the JSF and Richfaces libraries.  You'll have to download them separately before being able to successfully execute this code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-604795631340678086?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/hZHfM2RWoBA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/604795631340678086/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=604795631340678086" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/604795631340678086?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/604795631340678086?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/hZHfM2RWoBA/shortcuts-in-jsf-web-applications-using.html" title="Shortcuts in JSF web applications using AJAX4JSF" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2008/10/shortcuts-in-jsf-web-applications-using.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIEQ386fyp7ImA9WxRbFUU.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-2492844829488190965</id><published>2008-09-14T19:21:00.000+05:30</published><updated>2008-12-07T00:05:02.117+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-07T00:05:02.117+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>Python's String Translations for Java</title><content type="html">Just as I started poking my nose into Python, I came across two really interesting functions in its string module.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;maketrans()&lt;/li&gt;&lt;li&gt;translate()&lt;/li&gt;&lt;/ol&gt;These two methods when used together, can be used for string transformations based on a mapping between characters.&lt;br /&gt;&lt;br /&gt;Java's API didn't seem to provide any equivalent for this.  So I decided to write one just for kicks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Note:&lt;/span&gt; This is not a RegEx based approach for replacing parts of a String.  It uses a mapping table of characters to perform the transformation.&lt;br /&gt;&lt;br /&gt;Here is a simple Java code to achieve what maketrans() and translate() achieve together in Python.&lt;br /&gt;&lt;pre class="code"&gt;package translator;&lt;br /&gt;&lt;br /&gt;import java.util.HashMap;&lt;br /&gt;import java.util.Map;&lt;br /&gt;&lt;br /&gt;public class StringTranslator {&lt;br /&gt; private Map&amp;lt;Character, Character&amp;gt; translationMap;&lt;br /&gt;&lt;br /&gt; public StringTranslator(String from, String to) {&lt;br /&gt;  translationMap = new HashMap&amp;lt;Character, Character&amp;gt;();&lt;br /&gt;&lt;br /&gt;  if (from.length() != to.length())&lt;br /&gt;   throw new IllegalArgumentException(&lt;br /&gt;     "The from and to strings must be of the same length");&lt;br /&gt;&lt;br /&gt;  for (int i = 0; i &amp;lt; from.length(); i++)&lt;br /&gt;   translationMap.put(from.charAt(i), to.charAt(i));&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String translate(String str) {&lt;br /&gt;  StringBuilder buffer = new StringBuilder(str);&lt;br /&gt;&lt;br /&gt;  for (int i = 0; i &amp;lt; buffer.length(); i++) {&lt;br /&gt;   Character ch = buffer.charAt(i);&lt;br /&gt;   Character replacement = translationMap.get(ch);&lt;br /&gt;   if (replacement != null)&lt;br /&gt;    buffer.replace(i, i + 1, "" + replacement);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return buffer.toString();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String translate(String str, String deleteChars) {&lt;br /&gt;  StringBuilder buffer = new StringBuilder(str);&lt;br /&gt;  char[] deletions = deleteChars.toCharArray();&lt;br /&gt;  for (char ch : deletions) {&lt;br /&gt;   int index;&lt;br /&gt;   if ((index = buffer.indexOf("" + ch)) != -1)&lt;br /&gt;    buffer.deleteCharAt(index);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return translate(buffer.toString());&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once the above code is in place, here are the equivalent Python and Java code to achieve the same result.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Python Code:&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;"He!!0 W0r!d".translate(maketrans("!0", "lo"))&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Java Code:&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;new StringTranslator("!0", "lo").translate("He!!0 W0r!d");&lt;/pre&gt;&lt;br /&gt;The constructor of the StringTranslator class takes the from and to strings for mapping like maketrans() of Python.  The overloaded translate() methods take the String to be transformed and optionally another String containing the characters to be deleted (like translate() of Python).  The translation table need not be passed as an argument in this case as the StringTranslator instance will already hold it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-2492844829488190965?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/gpyJ3dOL6p8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/2492844829488190965/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=2492844829488190965" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2492844829488190965?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2492844829488190965?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/gpyJ3dOL6p8/pythons-string-translations-for-java.html" title="Python's String Translations for Java" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2008/09/pythons-string-translations-for-java.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ABQXY4eCp7ImA9WxdbEkg.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-1930037092981548455</id><published>2007-10-18T23:55:00.000+05:30</published><updated>2008-08-09T08:45:50.830+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-09T08:45:50.830+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Technology Musings" /><title>Tata Indicom: The worst private broadband service provider in India</title><content type="html">I recently moved to Bangalore after getting a job here.  As many sites (even clean ones like the blogs at Sun) are blocked in Indian IT companies, I decided it would be a good idea to get a new Internet connection at home.  My mind was fixed on BSNL's Dataone.  But upon enquiry I came to know that there are people waiting for almost an year to get the connection.  Since I had planned to pursue my higher education through distance learning along with my job, I needed a connection soon.&lt;br /&gt;&lt;br /&gt;I tried Airtel as the second option.  Unfortunately, as no one nearby has taken an Airtel broadband connection, they were not ready to provide the connection.&lt;br /&gt;&lt;br /&gt;Finally I paid in advance for four months (there was an offer by which I could get zero installation charges) and  applied for Tata Indicom broadband, which the sales representative promised will be provided the very next day.  But after 7 days it was provided on 8 August 2007.  The connection worked fine till 28 September, 2007.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;First Downtime&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;On the morning of 29 September, 2007 , when I tried to connect to the Internet, it failed.  I launched a complaint with the customer care on the same day at 09:21 am and the customer care executive promised that the problem will be solved within 24 hours.  However, nothing happened as the next day was Sunday.  When I called the customer care again, they gave Sunday as the reason.  Though the delay is acceptable I was disappointed because in the first place the customer care guy had promised that it will be fixed withinin 24 hours.  Also, weekends are the only time I can get solid time for my higher education which is the primary reason I took the connection in the first place.&lt;br /&gt;&lt;br /&gt;I was promised that money will be refunded to me for any downtime automatically in the current billing cycle without me having to run around.  I was very happy to see that though I lost a weekend, things were reasonable and fair.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Second Downtime&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The week went without any problem after the fix.  Then comes 6 October, 2007, a Saturday.  In the afternoon the connection failed.  I launched a complaint with the customer care and was given the same funny promise of fix in 24 hours.  I told about how my previous week's complaint was not fixed in 24 hours due to Sunday.  He promised that it will not repeat this time.  So when the problem was not solved the next day too, I called and spoke to a customer care supervisor.  She promised that the problem will be attended to at 10 am on Monday.  I have lost another weekend but I was patient.  This was the downtime which got on my nerves.&lt;br /&gt;&lt;br /&gt;From the time I launched the complaint, till Friday (13 October, 2007) it was not fixed though I made several calls and spoke to several customer care executives and supervisors.  Everyday when I call they'd promise me that it will be fixed by the end of the day or as the first thing next day.  When I called at the night of Wednesday and spoke to a person of escalation bay, he said they are looking into it seriously from that morning.  Does that mean they did not look into it seriously till then?  Then when I called back on Friday, they said they need 3 more days.  I was shocked.  It means a third weekend is going to be lost due to this thrid rate broadband service and problem resolution.  But without any other option as they would not refund from my advance payment I kept quiet.&lt;br /&gt;&lt;br /&gt;On the whole due to the two downtimes, I have lost one weekend (29th and 30th September) in the first case and more than a week along with two more weekends in the second case (6th October to 18th October).&lt;br /&gt;&lt;br /&gt;The reason given for the downtime is that permission to use BESCOM poles for broadband cables has expired and hence BESCOM has cut down the cables.  I don't understand whose responsibility it is to renew the permission.  If not Tata Indicom should have made alternative arrangements for its broadband customers.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Downtime Credit Issue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;My billing cycle is from the 11th of each month to the 10th of the next.  So the downtime credit of the first downtime and a part of the credit for the second downtime should have been credited in the bill for 11th September - 10th October.  To confirm this I called up the customer care on Saturday (14 October, 2007).  Another shock awaited.  The credit for neither of the downtimes has been given.  I had to lodge a complaint regarding this too.  And since the second downtime is yet to be solved, it seems it will come up in the next bill.&lt;br /&gt;&lt;br /&gt;When I called back on Monday (15 October, 2007), they had closed the complaint without my confirmation.  I was told that I had used the internet during the complaint period and hence credit cannot be given.  This is in regard to the first downtime.  As mentioned before I had complained on 29th September and was able to use the internet by 12:30 pm on 1st October.  I had immediately called the customer care and told that connection was restored.  But for some reason the complaint has been closed on 4th October, thus usage before closure of complaint is shown as the reason.&lt;br /&gt;&lt;br /&gt;In the second case, the field engineers on 17th October, tried loading a page.  Due to some loose connection in the cables the page loaded once and the net went down again.  This has been calculated as a usage.  Also, the complaint was closed on 18th October at 12:33 pm while the connection started working only at 05:45 pm.  I was told that the downtime credit will be given only till the first usage (the one done by the field engineers), which was a whole day before the problem was actually solved.&lt;br /&gt;&lt;br /&gt;This is atrocious.  I should have been given the downtime credit for the period, 09:21 am on 29th September to 12:30 pm on 1st October, which is 51 hours.  It must also be given for the one whole day after the test usage in the second downtime.  I strongly feel that Tata Indicom is trying to cheat me. I place a request before readers.  If any of you can enlighten me on the legal means by which I can ensure that I get back the downtime credit along with any expense incurred for the legal proceedings as per &lt;span style="font-weight: bold;"&gt;Indian law&lt;/span&gt;, I'd be grateful.  Please take into account that I don't have too many thousands to spend on this and this is also going to be against one of the top business houses in India.  The amount money and power on their side is huge.  But consumers must get their share of justice.  I'm not even asking refund for the large number of long calls to customer care.  There is no toll free number even for Tata Indicom walky customers.  Also, the amount of agony suffered by me cannot be given a monetary value.&lt;br /&gt;&lt;br /&gt;After all this, I warn anyone considering Tata Indicom's broadband.  Do not go for it unless you have no other option.  Even if you go for it, do not pay in advance and get locked in like me.  At this stage I feel extremely sorry for taking up this connection.  But I understand it is not just the public internet service providers who provide poor service, private service providers like Tata Indicom are no better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-1930037092981548455?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/U19Yt8hs_N4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/1930037092981548455/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=1930037092981548455" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/1930037092981548455?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/1930037092981548455?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/U19Yt8hs_N4/tata-indicom.html" title="Tata Indicom: The worst private broadband service provider in India" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>4</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2007/10/tata-indicom.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IMSXs9fyp7ImA9WxdbEkg.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-2147939312882021723</id><published>2007-06-02T15:34:00.000+05:30</published><updated>2008-08-09T08:43:08.567+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-09T08:43:08.567+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><title>Katapult: The cool launcher</title><content type="html">KDE has some very cool and useful applications. After Konqueror (the file manager) and Amarok (the music player) , Katapult (the launcher) has also joined the list.&lt;br /&gt;&lt;br /&gt;Katapult provides a very intuitive way of launching applications. All you need to do is press (Alt + Space) and type the name of the application as it appears on the K-Menu. The application's icon is show along with its full name. If the correct app is not show after typing few characters, continue typing till proper icons keep appearing, at some point the right app would be show. If no app matches your characters, an unknown icon will be displayed. If so, check the spelling you typed.&lt;br /&gt;&lt;br /&gt;Here is a screenshot of my own activities to open ksnapshot,&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5071407885246216290" alt="" src="http://1.bp.blogspot.com/_g5hM85MTy7c/RmFCmic3OGI/AAAAAAAAAAw/_-VSFk7eG_0/s320/katapult.png" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;If you need a new item to be shown in katapult (which is not already available), all you need to do is add it to your K-Menu and relogin into KDE. Your new app will be shown this time around.&lt;br /&gt;&lt;br /&gt;Mmmmm.... who said Linux lacks desktop innovations?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-2147939312882021723?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/0to8J_V_WVY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/2147939312882021723/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=2147939312882021723" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2147939312882021723?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/2147939312882021723?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/0to8J_V_WVY/katapult-cool-launcher.html" title="Katapult: The cool launcher" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_g5hM85MTy7c/RmFCmic3OGI/AAAAAAAAAAw/_-VSFk7eG_0/s72-c/katapult.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2007/06/katapult-cool-launcher.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08CR3oyfCp7ImA9WxdbEkg.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-3092973692268602420</id><published>2007-02-22T14:50:00.000+05:30</published><updated>2008-08-09T08:47:46.494+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-09T08:47:46.494+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><title>Contributing to OSS projects</title><content type="html">The most important criteria which can ensure the sustainability of various OSS projects is the contribution from its community.  IMO, the primary reason why people don't contribute sufficiently is their misconception that the only contribution that can be made to OSS projects is the code.  OSS projects need a lot more than just code.&lt;br /&gt;&lt;br /&gt;Here are a few things that any OSS project of significant size would need.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Cash (Not a surprise, after all programmers need food).&lt;/li&gt;&lt;li&gt;Bug reporters.&lt;/li&gt;&lt;li&gt;Artists.&lt;/li&gt;&lt;li&gt;Spreading the word.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;If you are well-to-do, try to donate some amount to those software which you use.  This would allow the programmers to concentrate on the development and also increase their enthusiasm.&lt;br /&gt;&lt;br /&gt;If you neither know programming nor have enough cash, download the latest version of the software and report any problems you come across, to its developers.  This would speed up the development process and improve the quality of your favorite software.  When you report your bug findings, try to include as much detail as possible.  This would allow the developers to iron out the problems quickly.&lt;br /&gt;&lt;br /&gt;Lastly, if you have good artistic skills, try creating icon sets, wallpapers and color schemes for your favorite free software.&lt;br /&gt;&lt;br /&gt;There are thousands of great developers working on innovative free software projects.  What such projects really lack is good marketing.  You can take this up and spread the word about the software across your friends.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-3092973692268602420?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/42mhvr7lhls" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/3092973692268602420/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=3092973692268602420" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/3092973692268602420?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/3092973692268602420?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/42mhvr7lhls/contributing-to-oss-projects.html" title="Contributing to OSS projects" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>3</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2007/02/contributing-to-oss-projects.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EARHY8fSp7ImA9WxdbEkg.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-4208746457145776136</id><published>2007-02-15T12:28:00.000+05:30</published><updated>2008-08-09T08:44:05.875+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-09T08:44:05.875+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><title>Kubuntu Customization Tips</title><content type="html">While I like the KDE desktop of Kubuntu, I'm not very happy with its software selection and default settings. So, here is what I did to make it suit my tastes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Tips for Kubuntu 6.10 (Edgy Eft)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Managing Repositories&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Visit &lt;a href="https://help.ubuntu.com/6.10/kubuntu/desktopguide/C/extra-repositories.html"&gt;this page&lt;/a&gt;&lt;a href="https://help.ubuntu.com/6.10/kubuntu/desktopguide/C/extra-repositories.html"&gt;&lt;/a&gt; for explanation of what repositories are and how you can manage them.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Installing new Packages&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Many of my customizations tips, require you to install certain packages. So here are the steps you need to follow whenever you need to install packages.&lt;br /&gt;&lt;br /&gt;1. Open KMenu -&gt; System -&gt; Adept Package Manager.&lt;br /&gt;2. Click on "Fetch Updates" in the toolbar.&lt;br /&gt;3. Search for the package and mark it for installation.&lt;br /&gt;4. Click on "Apply Changes" and you are done.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Installing multimedia-codecs&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you are from The Windows world, you might be wondering why you are not able to play your MP3 music and video clips on Kubuntu. These are formats restricted by patents and hence do not fit into Kubuntu which tries to stick to free software and formats. There are equivalent formats in the free world like OGG. But, that's not going to make you convert all your MP3s into OGGs. So, here is how you can play these non-free formats on Kubuntu. All you need to do is install a few codecs. Here is how you go about it.&lt;br /&gt;&lt;br /&gt;Install the package "libxine-extracodecs", to enable support for most of the proprietary formats. If you need to play Windows Media and Real Player Files you need to install the package, "w32codecs" which is available here. Installing "w32codecs" might be illegal. So, you must install it at you own risk.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Changing the login screen theme&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you want to change the theme of your login theme, install the package "kdmtheme". Unfortunately, this does not create any entry in K-Menu or in the "System Settings" area. So, create an entry in "K-Menu" for the command "kcmshell kdmtheme". To do this, right click on "K-Menu" button and select "Menu Editor". From here you should be able to get going on your own.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Small workaround for applications requiring admin privileges&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Sometimes when I tried to start applications requiring admin privileges, they did not start.  This is a bug and I have reported it to Kubuntu bug database (&lt;a href="https://launchpad.net/ubuntu/+source/kdebase/+bug/72545"&gt;see it here&lt;/a&gt;).  To avoid this, I had to edit the "/etc/sudoers" file.  To do the same, do the following from "konsole".&lt;br /&gt;&lt;ol&gt;&lt;li&gt;sudo visudo&lt;/li&gt;&lt;li&gt;Add the line "Defaults timestamp_timeout=0" at the end of the file.&lt;/li&gt;&lt;li&gt;Save the file by pressing "Ctrl+O".  Ensure that you save it as "/etc/sudoers".  Allow it to be overwritten.&lt;/li&gt;&lt;li&gt;Quit the editor by pressing "Ctrl+X".&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Installing and Configuring your nVIDIA Graphics Card&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To enable complete hardware 3D acceleration support of your nVIDIA graphics card, you need to install the package, "nvidia-glx".  If you have a very old card, you may have to install "nvidia-glx-legacy" instead.&lt;br /&gt;&lt;br /&gt;Once you have installed the driver, you need to configure your display to use your drivers.  To get this done, issue the following commands from "konsole", which is the terminal program.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;sudo rm -f /etc/X11/xorg.conf&lt;/li&gt;&lt;li&gt;sudo nvidia-xconfig&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;On my graphics card (nVIDIA GeForce MX 4000), I experienced random system freezes when running OpenGL (the counter-part for DirectX) applications.  If you experience the same, you can issue the following commands to fix it.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;sudo rm -f /etc/X11/xorg.conf&lt;/li&gt;&lt;li&gt;sudo nvidia-xconfig --nvagp=0&lt;/li&gt;&lt;/ol&gt;If you have a wide screen monitor, make a note of the automatically detected resolution and issue the following commands instead.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;sudo rm -f /etc/X11/xorg.conf&lt;/li&gt;&lt;li&gt;sudo nvidia-xconfig --mode=&amp;lt;noted_resolution&amp;gt; --nvagp=0&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;That's it for now!! I'd fill in more tips as and when needed. Feel free to contact me at chandru.in@gmail.com for further details.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-4208746457145776136?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/QsfO47HQeOE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/4208746457145776136/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=4208746457145776136" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/4208746457145776136?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/4208746457145776136?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/QsfO47HQeOE/initial-customizations-on-kubuntu.html" title="Kubuntu Customization Tips" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2007/02/initial-customizations-on-kubuntu.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08CR3oyfCp7ImA9WxdbEkg.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-982218183535166158</id><published>2007-02-14T18:00:00.000+05:30</published><updated>2008-08-09T08:47:46.494+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-09T08:47:46.494+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><title>Nvu: The buggy wonder</title><content type="html">I was looking for a free, cross-platform HTML editor for a project.  That definitely rules out Dreamweaver, Coffee Cup and Frontpage.  I was left with two option:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Nvu&lt;/li&gt;&lt;li&gt;Quanta&lt;/li&gt;&lt;/ol&gt;But, Quanta was not available for MS Windows which I had to use at college.  So I was left with Nvu.  It was a very good WYSIWYG HTML editor and did all my works but with some hacks.  The GUI has several glitches and it also lacks certain features.  Here are some:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;While it allows insertion of PHP code, it doesn't open files with ".php" extension.&lt;/li&gt;&lt;li&gt;The CSS Editor lacks several features like changing the cursor.&lt;/li&gt;&lt;li&gt;Designing forms using it also required several workarroud.&lt;/li&gt;&lt;li&gt;The list continues.....&lt;/li&gt;&lt;/ol&gt;However, looking at its version (1.0), I understand that it is still a young project but has a promising future.  It is the best free web-authoring tool out there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-982218183535166158?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/AzrBw5-qFiE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/982218183535166158/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=982218183535166158" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/982218183535166158?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/982218183535166158?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/AzrBw5-qFiE/nvu-buggy-wonder.html" title="Nvu: The buggy wonder" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>3</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2007/02/nvu-buggy-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08MQ3k5cSp7ImA9WxdbEkg.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-8248161789420658975</id><published>2007-02-09T12:12:00.001+05:30</published><updated>2008-08-09T08:48:02.729+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-09T08:48:02.729+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><title>Creating local repository</title><content type="html">I have long been wanting to make a local directory, which contains all my Debian packages, as a repository to be added in, /etc/apt/sources.list. Finally, I did it. This is what I did,&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Install the package "dpkg-dev".  It is available on the installation disk.&lt;/li&gt;&lt;li&gt;Download necessary packages along with the dependencies to a directory on your local fileystsem. You may organize the packages into sub directories.&lt;/li&gt;&lt;li&gt;Let us call the directory into which the files have been copied as &lt;dest_dir&gt;.&lt;/dest_dir&gt;&lt;/li&gt;&lt;li&gt;From konsole or any other terminal of your choice, issue following commands.&lt;/li&gt;&lt;ol&gt;&lt;li&gt;cd &lt;dest_dir&gt;&lt;/dest_dir&gt;&lt;/li&gt;&lt;li&gt;dpkg-scanpackages . /dev/null &gt;Packages&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;Open /etc/apt/source.list in your favorite editor and add the line "deb file://&lt;dest_dir&gt; ./"&lt;/dest_dir&gt;&lt;/li&gt;&lt;li&gt;Your new repository is ready.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-8248161789420658975?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/9lilT48SdfU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/8248161789420658975/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=8248161789420658975" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/8248161789420658975?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/8248161789420658975?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/9lilT48SdfU/making-local-repository.html" title="Creating local repository" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2007/02/making-local-repository.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAGQ3c6eCp7ImA9WhZUFE4.&quot;"><id>tag:blogger.com,1999:blog-14512504.post-112479639989217387</id><published>2005-08-23T16:48:00.001+05:30</published><updated>2011-06-07T14:55:22.910+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-07T14:55:22.910+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><title>Easy way to create Slack Packages</title><content type="html">I came across this interesting utility which allows cretion of slack packages easily.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;checkinstall&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It allows you to create slack packages from source archives.  Issuing these three commands would do it,&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;./configure&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;make&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;checkinstall&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It would ask you for few details like description of the package.  Do what it says and your work is done.&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14512504-112479639989217387?l=blog.tuxychandru.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tuxychandru/~4/AnG3ow7U-So" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.tuxychandru.com/feeds/112479639989217387/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14512504&amp;postID=112479639989217387" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/112479639989217387?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14512504/posts/default/112479639989217387?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tuxychandru/~3/AnG3ow7U-So/easy-way-to-create-slack-packages.html" title="Easy way to create Slack Packages" /><author><name>Chandru</name><uri>http://www.blogger.com/profile/06766185414588126442</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="23" src="http://2.bp.blogspot.com/-923RMquqZtA/TjuZ2YsDjgI/AAAAAAAAAxc/cU5DmoySE-c/s220/pengtypes.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.tuxychandru.com/2005/08/easy-way-to-create-slack-packages.html</feedburner:origLink></entry></feed>

