<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Niklas blog</title>
	<atom:link href="http://therning.org/niklas/feed/" rel="self" type="application/rss+xml" />
	<link>http://therning.org/niklas</link>
	<description>Just another WordPress weblog</description>
	<pubDate>Sun, 26 Oct 2008 20:30:37 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>Ubuntu — now also in liquid form</title>
		<link>http://therning.org/niklas/2008/10/ubuntu-now-also-in-liquid-form/</link>
		<comments>http://therning.org/niklas/2008/10/ubuntu-now-also-in-liquid-form/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 20:28:02 +0000</pubDate>
		<dc:creator>niklas</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://therning.org/niklas/?p=77</guid>
		<description><![CDATA[
Just had my first one and it tastes great! Didn&#8217;t know that there was such a thing until I happened to see a bunch of them at Coop Konsum Avenyn in Gothenburg. I bought the last three they had!  
BTW, It&#8217;s got nothing to do with my favorite linux distribution expect for the name [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ubuntu-trading.com"><img class="alignright size-full wp-image-76" style="float: right; border: none;" title="Ubuntu Cola" src="http://therning.org/niklas/wp-content/uploads/2008/10/ubuntu-cola.jpg" alt="" width="350" height="412" /></a></p>
<p>Just had my first one and it tastes great! Didn&#8217;t know that there was such a thing until I happened to see a bunch of them at Coop Konsum Avenyn in Gothenburg. I bought the last three they had! <img src='http://therning.org/niklas/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>BTW, It&#8217;s got nothing to do with my favorite linux distribution expect for the name and the fact that, just like the guys doing Ubuntu Linux, the people behind Ubuntu Cola is trying to make the world a better place.</p>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2008/10/ubuntu-now-also-in-liquid-form/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getting the mic working on a Dell Dimension 5000 running Ubuntu 8.04</title>
		<link>http://therning.org/niklas/2008/10/getting-the-mic-working-on-a-dell-dimension-5000-running-ubuntu-804/</link>
		<comments>http://therning.org/niklas/2008/10/getting-the-mic-working-on-a-dell-dimension-5000-running-ubuntu-804/#comments</comments>
		<pubDate>Sun, 19 Oct 2008 19:57:25 +0000</pubDate>
		<dc:creator>niklas</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://therning.org/niklas/?p=73</guid>
		<description><![CDATA[I&#8217;ve been trying hard to get the microphone working on my wife Jenny&#8217;s old Dell Dimension 5000 running Ubuntu 8.04. Google wasn&#8217;t much help I&#8217;m afraid. I finally figured out, after lots of trial and error, that I had to set the option Surround Jack Mode in the Gnome Mixer to the value Independent to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been trying hard to get the microphone working on my wife Jenny&#8217;s old Dell Dimension 5000 running Ubuntu 8.04. Google wasn&#8217;t much help I&#8217;m afraid. I finally figured out, after lots of trial and error, that I had to set the option <em>Surround Jack Mode</em> in the Gnome Mixer to the value <em>Independent</em> to get the mic working. Skype seems to be working fine now. Next challenge will be to find a web cam that works&#8230;</p>
<p>For your reference, here&#8217;s the full output I get when running <code>amixer</code>:<span id="more-73"></span></p>
<pre>Simple mixer control 'Master',0
  Capabilities: pvolume pswitch
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Mono:
  Front Left: Playback 31 [100%] [0.00dB] [on]
  Front Right: Playback 31 [100%] [0.00dB] [on]
Simple mixer control 'Master Mono',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback 0 - 31
  Mono: Playback 31 [100%] [0.00dB] [on]
Simple mixer control 'Headphone',0
  Capabilities: pvolume pswitch
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Mono:
  Front Left: Playback 31 [100%] [0.00dB] [on]
  Front Right: Playback 31 [100%] [0.00dB] [on]
Simple mixer control 'Headphone Jack Sense',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'PCM',0
  Capabilities: pvolume pswitch
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Mono:
  Front Left: Playback 31 [100%] [12.00dB] [on]
  Front Right: Playback 31 [100%] [12.00dB] [on]
Simple mixer control 'Surround',0
  Capabilities: pvolume pswitch
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Mono:
  Front Left: Playback 0 [0%] [-46.50dB] [off]
  Front Right: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Surround Jack Mode',0
  Capabilities: enum
  Items: 'Shared' 'Independent'
  Item0: 'Independent'
Simple mixer control 'Center',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback 0 - 31
  Mono: Playback 31 [100%] [0.00dB] [off]
Simple mixer control 'LFE',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback 0 - 31
  Mono: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Line',0
  Capabilities: pvolume pswitch cswitch cswitch-exclusive
  Capture exclusive group: 0
  Playback channels: Front Left - Front Right
  Capture channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
  Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Line Jack Sense',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'CD',0
  Capabilities: pvolume pswitch cswitch cswitch-exclusive
  Capture exclusive group: 0
  Playback channels: Front Left - Front Right
  Capture channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Front Left: Playback 31 [100%] [12.00dB] [on] Capture [off]
  Front Right: Playback 31 [100%] [12.00dB] [on] Capture [off]
Simple mixer control 'Mic',0
  Capabilities: pvolume pswitch cswitch cswitch-exclusive
  Capture exclusive group: 0
  Playback channels: Front Left - Front Right
  Capture channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [on]
  Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [on]
Simple mixer control 'Mic Boost (+20dB)',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'Mic Select',0
  Capabilities: enum
  Items: 'Mic1' 'Mic2'
  Item0: 'Mic2'
Simple mixer control 'Video',0
  Capabilities: cswitch cswitch-exclusive
  Capture exclusive group: 0
  Capture channels: Front Left - Front Right
  Front Left: Capture [off]
  Front Right: Capture [off]
Simple mixer control 'Phone',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined cswitch cswitch-exclusive
  Capture exclusive group: 0
  Playback channels: Mono
  Capture channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Mono: Playback 0 [0%] [-34.50dB] [off]
  Front Left: Capture [off]
  Front Right: Capture [off]
Simple mixer control 'PC Speaker',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback 0 - 15
  Mono: Playback 0 [0%] [-45.00dB] [off]
Simple mixer control 'Aux',0
  Capabilities: pvolume pswitch cswitch cswitch-exclusive
  Capture exclusive group: 0
  Playback channels: Front Left - Front Right
  Capture channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Front Left: Playback 31 [100%] [12.00dB] [on] Capture [off]
  Front Right: Playback 31 [100%] [12.00dB] [on] Capture [off]
Simple mixer control 'Mono Output Select',0
  Capabilities: enum
  Items: 'Mix' 'Mic'
  Item0: 'Mix'
Simple mixer control 'Capture',0
  Capabilities: cvolume cswitch
  Capture channels: Front Left - Front Right
  Limits: Capture 0 - 15
  Front Left: Capture 13 [87%] [19.50dB] [on]
  Front Right: Capture 13 [87%] [19.50dB] [on]
Simple mixer control 'Mix',0
  Capabilities: cswitch cswitch-exclusive
  Capture exclusive group: 0
  Capture channels: Front Left - Front Right
  Front Left: Capture [off]
  Front Right: Capture [off]
Simple mixer control 'Mix Mono',0
  Capabilities: cswitch cswitch-exclusive
  Capture exclusive group: 0
  Capture channels: Front Left - Front Right
  Front Left: Capture [off]
  Front Right: Capture [off]
Simple mixer control 'Channel Mode',0
  Capabilities: enum
  Items: '2ch' '4ch' '6ch'
  Item0: '2ch'
Simple mixer control 'Downmix',0
  Capabilities: enum
  Items: 'Off' '6 -&gt; 4' '6 -&gt; 2'
  Item0: 'Off'
Simple mixer control 'Exchange Center/LFE',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'Exchange Front/Surround',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'Exchange Mic/Line In',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'External Amplifier',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'Spread Front to Surround and Center/LFE',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'Stereo Mic',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'V_REFOUT',0
  Capabilities: enum
  Items: 'High-Z' '3.7 V' '2.25 V' '0 V'
  Item0: 'High-Z'</pre>
<p>And <code>lspci</code> says:</p>
<pre>00:00.0 Host bridge: Intel Corporation 82915G/P/GV/GL/PL/910GL Memory Controller Hub (rev 04)
00:01.0 PCI bridge: Intel Corporation 82915G/P/GV/GL/PL/910GL PCI Express Root Port (rev 04)
00:02.0 VGA compatible controller: Intel Corporation 82915G/GV/910GL Integrated Graphics Controller (rev 04)
00:02.1 Display controller: Intel Corporation 82915G Integrated Graphics Controller (rev 04)
00:1c.0 PCI bridge: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (rev 03)
00:1c.1 PCI bridge: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (rev 03)
00:1d.0 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (rev 03)
00:1d.1 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (rev 03)
00:1d.2 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (rev 03)
00:1d.3 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (rev 03)
00:1d.7 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (rev 03)
00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev d3)
00:1e.2 Multimedia audio controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (rev 03)
00:1f.0 ISA bridge: Intel Corporation 82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (rev 03)
00:1f.1 IDE interface: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (rev 03)
00:1f.2 IDE interface: Intel Corporation 82801FB/FW (ICH6/ICH6W) SATA Controller (rev 03)
00:1f.3 SMBus: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (rev 03)
04:03.0 Ethernet controller: Broadcom Corporation BCM4401 100Base-T (rev 01)</pre>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2008/10/getting-the-mic-working-on-a-dell-dimension-5000-running-ubuntu-804/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rotating video clips shot in &#34;portrait&#34; mode (revisited)</title>
		<link>http://therning.org/niklas/2007/12/rotating-video-clips-shot-in-portrait-mode-revisited/</link>
		<comments>http://therning.org/niklas/2007/12/rotating-video-clips-shot-in-portrait-mode-revisited/#comments</comments>
		<pubDate>Mon, 31 Dec 2007 17:56:31 +0000</pubDate>
		<dc:creator>niklas</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">172 at http://therning.org/niklas</guid>
		<description><![CDATA[Some time ago I write about how to use mencoder to rotate videos. After playing around with mencoder some more today I found a better way of doing it, all in one go.
mencoder -ovc lavc -lavcopts vcodec=mpeg4 -vf-add rotate=1,expand=432:324,scale=640:480 -oac mp3lame -lameopts br=64:mode=3 -srate 22050 input.avi -o output.avi
This will run the video through three filters. [...]]]></description>
			<content:encoded><![CDATA[<p>Some time ago I write about <a href="/niklas/2006/07/rotating-video-clips-shot-in-portrait-mode/">how to use <code>mencoder</code> to rotate videos</a>. After playing around with <code>mencoder</code> some more today I found a better way of doing it, all in one go.<span id="more-4"></span></p>
<p><code>mencoder -ovc lavc -lavcopts vcodec=mpeg4 -vf-add rotate=1,expand=432:324,scale=640:480 -oac mp3lame -lameopts br=64:mode=3 -srate 22050 input.avi -o output.avi</code></p>
<p>This will run the video through three filters. The first one rotates, the second one expands and the third one scales. This time I&#8217;m expanding to 432&#215;324 which is exactly 4:3.</p>
<p>The reason I&#8217;m scaling to 640&#215;480 at the end is that I&#8217;m now using <a href="http://www.smugmug.com">SmugMug</a> for all my photos and videos.  SmugMug scales the video automatically to 320&#215;240 and 640&#215;480. If the video I upload is smaller than 640&#215;480 it won&#8217;t upscale it to 640&#215;480 but will only keep a 320&#215;240 version. The original is always discarded.</p>
<p>The <code>mencoder</code> command line also converts to mpeg4 for the video and mp3 for the audio. This way I don&#8217;t have to run the video through <code>ffmpeg</code> to make it work in Windows Media Player. I discovered that that last step seriously lowered the quality of the output.</p>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2007/12/rotating-video-clips-shot-in-portrait-mode-revisited/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Preprocessing JSP files to automatically escape EL expressions</title>
		<link>http://therning.org/niklas/2007/09/preprocessing-jsp-files-to-automatically-escape-el-expressions/</link>
		<comments>http://therning.org/niklas/2007/09/preprocessing-jsp-files-to-automatically-escape-el-expressions/#comments</comments>
		<pubDate>Thu, 20 Sep 2007 15:25:44 +0000</pubDate>
		<dc:creator>niklas</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">171 at http://therning.org/niklas</guid>
		<description><![CDATA[In his post, Proposed Tomcat Enhancement: Add flag to escape JSP&#8217;s EL by default, Matt Raible suggests that Tomcat should add an option to escape the output of EL expressions by default. At Trillian we&#8217;ve also run into the problem he&#8217;s describing since we needed the output of our JSPs to be valid XML at [...]]]></description>
			<content:encoded><![CDATA[<p>In his post, <a href="http://raibledesigns.com/rd/entry/proposed_tomcat_enhancement_add_flag">Proposed Tomcat Enhancement: Add flag to escape JSP&#8217;s EL by default</a>, Matt Raible suggests that Tomcat should add an option to escape the output of EL expressions by default. At Trillian we&#8217;ve also run into the problem he&#8217;s describing since we needed the output of our JSPs to be valid XML at all times.<span id="more-5"></span></p>
<p>We ended up using a servlet filter which preprocesses all JSP files the first time they are executed. The filter uses an XSL which replaces all <code>${foo}</code> occurrences with <code>${fn:escapeXml(foo)}</code>. Obviously, the JSPs have to be written using the JSP XML syntax otherwise the XSL won&#8217;t to be able to process them.</p>
<p>Matt asked if I was willing to share this filter and I would be more than happy to do so. You will find the files attached.</p>
<p>Please note that I had to strip out some stuff from the files. Particularly the caching of the compiled XSL file since that involved lots of other code which I couldn&#8217;t strip down to a manageable size. It shouldn&#8217;t be too hard to implement this using your preferred caching library. I&#8217;m not 100% sure the Java files will compile but that shouldn&#8217;t be too hard to work out. Also, there&#8217;s lots of dependencies (commons-io, commons-logging, dom4j, spring, etc, all open source) that you might want to get rid of.</p>
<p>The <code>JspPreprocessFilter</code> will intercept any request for a JSP file. If that JSP hasn&#8217;t already been preprocessed it will rename the original file to .jsp.bak and then run it through the XSL producing the preprocessed .jsp file. The filter uses the modification time of the files to determine if a file has been changed and needs to be preprocessed again.</p>
<p>I&#8217;m using Spring to configure this filter which is why it takes its dependencies in the constructor and not isn&#8217;t configured using the <code>init()</code> method. I&#8217;m using <code>org.apache.xalan.xsltc.trax.SmartTransformerFactoryImpl</code> as <code>SAXTransformerFactory</code> implementation.</p>
<p>The XSL will match on all HTML attributes and text nodes and run their contents through the <code>XalanUtil.escape()</code> helper method. This method will find any EL expressions in the contents and change them as described above.</p>
<p>I hope this code will be of some use. (Ab)use it as you see fit. <img class="smiley" title="Eye-wink" src="/niklas/modules/smileys/examples/wink.png" alt="Eye-wink" /> The only thing I&#8217;m asking is that you let me know if you spot some stupid mistake I&#8217;ve done or find a bug. Thanks!</p>
<p><a href="/niklas/wp-content/uploads/2007/09/JspPreprocessFilter.java">JspPreprocessFilter.java</a><br />
<a href="/niklas/wp-content/uploads/2007/09/preprocess.xsl">preprocess.xsl</a><br />
<a href="/niklas/wp-content/uploads/2007/09/XalanUtil.java">XalanUtil.java</a></p>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2007/09/preprocessing-jsp-files-to-automatically-escape-el-expressions/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Xbox Media Center Linux port in the works</title>
		<link>http://therning.org/niklas/2007/07/xbox-media-center-linux-port-in-the-works/</link>
		<comments>http://therning.org/niklas/2007/07/xbox-media-center-linux-port-in-the-works/#comments</comments>
		<pubDate>Mon, 02 Jul 2007 20:06:31 +0000</pubDate>
		<dc:creator>niklas</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">170 at http://therning.org/niklas</guid>
		<description><![CDATA[Seems like the Xbox Media Center team are working on a Linux port! Apparently they have only been working on it for a couple of months now but it&#8217;s already beyond just being a tool for skinners and plugin developers. Remote control support using LIRC is in there and it already plays most audio and [...]]]></description>
			<content:encoded><![CDATA[<p>Seems like the Xbox Media Center team are working on a Linux port! Apparently they have only been working on it for a couple of months now but it&#8217;s already beyond just being a tool for skinners and plugin developers. Remote control support using LIRC is in there and it already plays most audio and video files. Even DVD ISO&#8217;s over Samba!<span id="more-6"></span></p>
<p><a href="http://therning.org/niklas/wp-content/uploads/2008/10/xbmc2.png"><img class="alignnone size-medium wp-image-42" title="XBMC Screenshot" src="http://therning.org/niklas/wp-content/uploads/2008/10/xbmc2-300x225.png" alt="" /></a><a href="http://therning.org/niklas/wp-content/uploads/2008/10/xbmc1_1.png"><img class="size-medium wp-image-40 alignnone" title="XBMC Screenshot" src="http://therning.org/niklas/wp-content/uploads/2008/10/xbmc1_1-300x225.png" alt="" /></a><a href="http://therning.org/niklas/files/images/XBMC2.png" target="_blank"><br />
</a></p>
<p>Ever since I bought my HTPC about six months ago I hoped this would happen. After using the HTPC in the living room for a couple of months I realized that the Xbox wouldn&#8217;t give up without a fight! When compared to the alternatives XBMC is by far the best media center software out there. I&#8217;ve tried the alternatives: MythTV, Media Portal, Freevo. None of them provide the same level of user experience as XBMC.</p>
<p>Obviously, XBMC doesn&#8217;t do TV like the alternatives when running on the Xbox, but hopefully it will in Linux once this port matures. That would be awesome!</p>
<p>The <a href="http://www.xboxmediacenter.com/wiki/index.php?title=Linux_port_project">Linux Port Project pages on the XBMC wiki</a> has build instructions and more info for developers.</p>
<p>There&#8217;s a <a href="http://www.xboxmediacenter.com/forum/forumdisplay.php?f=41">sub-forum dedicated to discussing the Linux port</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2007/07/xbox-media-center-linux-port-in-the-works/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Useful link: SEO checklist for Drupal websites</title>
		<link>http://therning.org/niklas/2007/04/useful-link-seo-checklist-for-drupal-websites/</link>
		<comments>http://therning.org/niklas/2007/04/useful-link-seo-checklist-for-drupal-websites/#comments</comments>
		<pubDate>Mon, 23 Apr 2007 20:25:52 +0000</pubDate>
		<dc:creator></dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">167 at http://therning.org/niklas</guid>
		<description><![CDATA[tela has posted a SEO checklist for Drupal websites. If I&#039;ve managed to configure drupal correctly this post should get a nice URL alias automatically from the title. I&#039;m using drupal&#039;s pathauto module.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://tela-web.com/">tela</a> has posted a <a href="http://tela-web.com/website-marketing/seo-checklist-for-drupal-websites/">SEO checklist for Drupal websites</a>. If I&#039;ve managed to configure drupal correctly this post should get a nice URL alias automatically from the title. I&#039;m using drupal&#039;s <a href="http://drupal.org/project/pathauto">pathauto module</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2007/04/useful-link-seo-checklist-for-drupal-websites/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Ant + Log4j</title>
		<link>http://therning.org/niklas/2007/03/ant-log4j/</link>
		<comments>http://therning.org/niklas/2007/03/ant-log4j/#comments</comments>
		<pubDate>Thu, 15 Mar 2007 14:05:32 +0000</pubDate>
		<dc:creator>niklas</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">166 at http://therning.org/niklas</guid>
		<description><![CDATA[Hibernate&#8217;s SchemaExportTask ant task always gives very informative error messages (not! ). Here&#8217;s an example:
BUILD FAILED
build.xml:267: Schema text failed: Could not parse mapping document from file SomeClass.hbm.xml
To get some useful info on what went wrong we need to specify a log4j configuration file:
niklas@niklas:~$ ANT_OPTS=-Dlog4j.configuration=file:///path/to/log4j.properties ant some-task
Don&#8217;t forget file://!
Here&#8217;s a simple log4j.properties file you could use:
log4j.rootLogger=DEBUG, [...]]]></description>
			<content:encoded><![CDATA[<p>Hibernate&#8217;s SchemaExportTask ant task always gives very informative error messages (not! <img class="smiley" title="Smiling" src="/niklas/modules/smileys/examples/smile.png" alt="Smiling" />). Here&#8217;s an example:</p>
<pre>BUILD FAILED
build.xml:267: Schema text failed: Could not parse mapping document from file SomeClass.hbm.xml</pre>
<p>To get some useful info on what went wrong we need to specify a log4j configuration file:</p>
<pre>niklas@niklas:~$ ANT_OPTS=-Dlog4j.configuration=file:///path/to/log4j.properties ant some-task</pre>
<p><strong>Don&#8217;t forget file://!</strong></p>
<p>Here&#8217;s a simple log4j.properties file you could use:</p>
<pre>log4j.rootLogger=DEBUG, consoleAppender
log4j.appender.consoleAppender=org.apache.log4j.ConsoleAppender
log4j.appender.consoleAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.consoleAppender.layout.ConversionPattern=%d [%t] %-5p %c %x - %m%n</pre>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2007/03/ant-log4j/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Spring and named constructor arguments (cont.)</title>
		<link>http://therning.org/niklas/2006/09/spring-and-named-constructor-arguments-cont/</link>
		<comments>http://therning.org/niklas/2006/09/spring-and-named-constructor-arguments-cont/#comments</comments>
		<pubDate>Tue, 05 Sep 2006 19:53:32 +0000</pubDate>
		<dc:creator>niklas</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">165 at http://therning.org/niklas</guid>
		<description><![CDATA[I&#8217;ve just uploaded the patch I was talking about in my previous post to Spring&#8217;s issue tracker. I just hope they won&#8217;t be too hard on me. 
The page is right here: http://opensource.atlassian.com/projects/spring/browse/SPR-2539.
It&#8217;s going to be very interesting to hear what they think about it.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just uploaded the patch I was talking about in my <a href="/niklas/2006/09/spring-and-named-constructor-arguments/">previous post</a> to Spring&#8217;s issue tracker. I just hope they won&#8217;t be too hard on me. <img class="smiley" title="Smiling" src="/niklas/modules/smileys/examples/smile.png" alt="Smiling" /></p>
<p>The page is right here: <a href="http://opensource.atlassian.com/projects/spring/browse/SPR-2539">http://opensource.atlassian.com/projects/spring/browse/SPR-2539</a>.</p>
<p>It&#8217;s going to be very interesting to hear what they think about it.</p>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2006/09/spring-and-named-constructor-arguments-cont/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Spring and named constructor arguments</title>
		<link>http://therning.org/niklas/2006/09/spring-and-named-constructor-arguments/</link>
		<comments>http://therning.org/niklas/2006/09/spring-and-named-constructor-arguments/#comments</comments>
		<pubDate>Mon, 04 Sep 2006 19:10:15 +0000</pubDate>
		<dc:creator>niklas</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">164 at http://therning.org/niklas</guid>
		<description><![CDATA[I&#8217;m a big fan of Spring and I&#8217;ve been using various parts of it now for the last two and a half years. Using the Spring dependency injection container has indeed made my life (as a programmer, of course ) a lot easier. In this post I will demonstrate a technique which could be incorporated [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a big fan of <a href="http://www.springframework.org/">Spring</a> and I&#8217;ve been using various parts of it now for the last two and a half years. Using the Spring dependency injection container has indeed made my life (as a programmer, of course <img class="smiley" title="Eye-wink" src="/niklas/modules/smileys/examples/wink.png" alt="Eye-wink" />) a lot easier. In this post I will demonstrate a technique which could be incorporated into Spring to add support for constructor injection using named parameters. The same technique could also be useful for scripting languages like <a href="http://www.jython.org/Project/index.html">Jython</a> and <a href="http://groovy.codehaus.org/">Groovy</a> to add support for calling Java methods using named parameters. <span id="more-10"></span></p>
<h3>The problem</h3>
<p>With Spring I have the option of using either constructor injection or setter injection. I prefer constructor injection over setter injection because I won&#8217;t have to break basic OO principles like encapsulation (by providing a setter for a required dependency) and I don&#8217;t have to tie my code to Spring (by implementing <code>InitializingBean</code>) just to be able to check if all dependencies have been set up properly.</p>
<p>Many times however I fall back to setter injection just because it makes my Spring configuration files much more readable. Consider the following Spring configuration file snippets:</p>
<div class="code">
<pre><strong><span style="color: #a020f0;">&lt;!-- Set up ConnectionPoolImpl instance using constructor injection --&gt;</span></strong>
<strong><span style="color: #a020f0;">&lt;bean id=</span></strong><strong><span style="color: #bc8f8f;">"connectionPool"</span></strong><strong><span style="color: #a020f0;"> class=</span></strong><strong><span style="color: #bc8f8f;">"ConnectionPoolImpl"</span></strong><strong><span style="color: #a020f0;">&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;constructor-arg index=</span></strong><strong><span style="color: #bc8f8f;">"0"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"gbg5"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;constructor-arg index=</span></strong><strong><span style="color: #bc8f8f;">"1"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"3066"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;constructor-arg index=</span></strong><strong><span style="color: #bc8f8f;">"2"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"bob"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;constructor-arg index=</span></strong><strong><span style="color: #bc8f8f;">"3"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"Ns7Ysh"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"minConnections"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"1"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"maxConnections"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"10"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"maxIdleTime"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"10000"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
<strong><span style="color: #a020f0;">&lt;/bean&gt;</span></strong>

<strong><span style="color: #a020f0;">&lt;!-- And now using setter injection --&gt;</span></strong>
<strong><span style="color: #a020f0;">&lt;bean id=</span></strong><strong><span style="color: #bc8f8f;">"connectionPool"</span></strong><strong><span style="color: #a020f0;"> class=</span></strong><strong><span style="color: #bc8f8f;">"ConnectionPoolImpl"</span></strong><strong><span style="color: #a020f0;">&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"host"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"gbg5"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"port"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"3066"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"username"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"bob"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"password"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"Ns7Ysh"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"minConnections"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"1"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"maxConnections"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"10"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"maxIdleTime"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"10000"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
<strong><span style="color: #a020f0;">&lt;/bean&gt;</span></strong></pre>
</div>
<p>The second one is clearly much more readable. I could of course have added comments to the first one to make it more readable but comments will have to be maintained and neither Spring nor any other tool I know of would be able to warn me when the comments have to be updated. Also note that sometimes there are sensible defaults for some properties and in those cases there&#8217;s nothing wrong with setter injection (that&#8217;s why I use setter injection for the last three integer values).</p>
<p>In the above example there are no sensible defaults for host, port, username and password and all of them are required. If I would go with the second alternative my <code>ConnectionPoolImpl</code> class would have to implement Spring&#8217;s <code>InitializingBean</code> to be able to enforce that these properties get set. This clearly ties my code to Spring. Not only in the sense that the <code>InitializingBean</code> interface must be available at runtime regardless of whether Spring is used to construct the <code>ConnectionPoolImpl</code> instance or not. But also when not using Spring one would have to make sure to call <code>afterPropertiesSet()</code> on <code>ConnectionPoolImpl</code> to determine whether the object has been set up properly.</p>
<h3>The solution</h3>
<p>So, what would the solution be? Well, I&#8217;d like to be able to do the following in Spring:</p>
<div class="code">
<pre><strong><span style="color: #a020f0;">&lt;!-- Set up ConnectionPoolImpl instance using constructor injection --&gt;</span></strong>
<strong><span style="color: #a020f0;">&lt;bean id=</span></strong><strong><span style="color: #bc8f8f;">"connectionPool"</span></strong><strong><span style="color: #a020f0;"> class=</span></strong><strong><span style="color: #bc8f8f;">"ConnectionPoolImpl"</span></strong><strong><span style="color: #a020f0;">&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;constructor-arg name=</span></strong><strong><span style="color: #bc8f8f;">"host"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"gbg5"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;constructor-arg name=</span></strong><strong><span style="color: #bc8f8f;">"port"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"3066"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;constructor-arg name=</span></strong><strong><span style="color: #bc8f8f;">"username"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"bob"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;constructor-arg name=</span></strong><strong><span style="color: #bc8f8f;">"password"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"Ns7Ysh"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"minConnections"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"1"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"maxConnections"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"10"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
  <strong><span style="color: #a020f0;">&lt;property name=</span></strong><strong><span style="color: #bc8f8f;">"maxIdleTime"</span></strong><strong><span style="color: #a020f0;"> value=</span></strong><strong><span style="color: #bc8f8f;">"10000"</span></strong><strong><span style="color: #a020f0;">/&gt;</span></strong>
<strong><span style="color: #a020f0;">&lt;/bean&gt;</span></strong></pre>
</div>
<p>Here I&#8217;m assuming that the <code>ConnectionPoolImpl</code> class has a constructor with the signature:</p>
<p><code>ConnectionPoolImpl(String host, String port, String username, String password)</code></p>
<p>Using the <code>name</code> attribute with the <code>constructor-arg</code> element would let me match an argument with a named parameter in the constructor&#8217;s signature instead of using the index. Note that the order of the <code>constructor-arg</code> elements should be insignificant. Even if I change the constructor signature to</p>
<p><code>ConnectionPoolImpl(String username, String password, String host, String port)</code></p>
<p>the above Spring configuration file snippet should still do the right thing.</p>
<p>Now you might think that there&#8217;s no way to do this in Java. After all, it&#8217;s simple enough to obtain the parameter types from a Java <code>Constructor</code> object, but there&#8217;s no way to get the list of parameter names. That may be true, but it&#8217;s also true that if you compile your Java classes with local variable debugging information (i.e. using <code>javac -g</code> or <code>javac -g:vars</code>) all the information about constructor (and method) parameter names will be readily available inside the resulting <code>.class</code> file. All we need is a way of obtaining that piece of debug info.</p>
<p>It turns out that <a href="http://asm.objectweb.org/">ASM</a> makes this very easy. The following code dumps out the constructor and method signatures including parameter names (if available) of a class you specify on the command line:</p>
<div class="codebox">
<pre><strong><span style="color: #a020f0;">import</span></strong> java.io.InputStream;
<strong><span style="color: #a020f0;">import</span></strong> java.util.ArrayList;

<strong><span style="color: #a020f0;">import</span></strong> org.objectweb.asm.ClassReader;
<strong><span style="color: #a020f0;">import</span></strong> org.objectweb.asm.Label;
<strong><span style="color: #a020f0;">import</span></strong> org.objectweb.asm.MethodVisitor;
<strong><span style="color: #a020f0;">import</span></strong> org.objectweb.asm.Opcodes;
<strong><span style="color: #a020f0;">import</span></strong> org.objectweb.asm.Type;
<strong><span style="color: #a020f0;">import</span></strong> org.objectweb.asm.commons.EmptyVisitor;

<strong><span style="color: #a020f0;">public</span></strong> <strong><span style="color: #a020f0;">class</span></strong> ParameterNamesTest {

    <strong><span style="color: #a020f0;">public</span></strong> ParameterNamesTest(String a, Object[] b) {
    }

    <strong><span style="color: #a020f0;">public</span></strong> ParameterNamesTest(<strong><span style="color: #a020f0;">long</span></strong> x, <strong><span style="color: #a020f0;">double</span></strong> y, <strong><span style="color: #a020f0;">int</span></strong> z) {
    }

    <strong><span style="color: #a020f0;">public</span></strong> <strong><span style="color: #a020f0;">void</span></strong> doSomething(<strong><span style="color: #a020f0;">byte</span></strong> a, <strong><span style="color: #a020f0;">short</span></strong> b, String c) {
    }

    <strong><span style="color: #a020f0;">public</span></strong> <strong><span style="color: #a020f0;">static</span></strong> <strong><span style="color: #a020f0;">void</span></strong> main(String[] args) <strong><span style="color: #a020f0;">throws</span></strong> Exception {

        Class clazz = ParameterNamesTest.<strong><span style="color: #a020f0;">class</span></strong>;
        <strong><span style="color: #a020f0;">if</span></strong> (args.length &gt; 0) {
            clazz = Class.forName(args[0]);
        }

        <em><span style="color: #b22222;">/*
         * Load the .class file from the class path.
         */</span></em>
        String clazzName = clazz.getName();
        <strong><span style="color: #a020f0;">int</span></strong> lastDot = clazzName.lastIndexOf(<strong><span style="color: #bc8f8f;">'.'</span></strong>);
        clazzName = clazzName.substring(lastDot + 1);
        InputStream is = clazz.getResourceAsStream(clazzName
                                                + <strong><span style="color: #bc8f8f;">".class"</span></strong>);

        <em><span style="color: #b22222;">/*
         * Now use ASM to extract the method and constructor
         * parameter names from the class file.
         */</span></em>
        ClassReader cr = <strong><span style="color: #a020f0;">new</span></strong> ClassReader(is);
        cr.accept(<strong><span style="color: #a020f0;">new</span></strong> MyClassVisitor(), <strong><span style="color: #a020f0;">false</span></strong>);
        is.close();
    }

    <strong><span style="color: #a020f0;">private</span></strong> <strong><span style="color: #a020f0;">static</span></strong> <strong><span style="color: #a020f0;">class</span></strong> MyClassVisitor <strong><span style="color: #a020f0;">extends</span></strong> EmptyVisitor {
        <strong><span style="color: #a020f0;">public</span></strong> MethodVisitor visitMethod(<strong><span style="color: #a020f0;">int</span></strong> access, String name,
                String desc, String signature, String[] exceptions) {
            <em><span style="color: #b22222;">/*
             * This is called by ASM for every method and
             * constructor in the class file. Create a new
             * MyMethodVisitor which will receive callbacks when ASM
             * reads local variable debug info in the class file.
             */</span></em>
            <strong><span style="color: #a020f0;">boolean</span></strong> ztatic = (access &amp; Opcodes.ACC_STATIC) &gt; 0;
            <strong><span style="color: #a020f0;">return</span></strong> <strong><span style="color: #a020f0;">new</span></strong> MyMethodVisitor(ztatic, name, desc);
        }
    }

    <strong><span style="color: #a020f0;">private</span></strong> <strong><span style="color: #a020f0;">static</span></strong> <strong><span style="color: #a020f0;">class</span></strong> MyMethodVisitor <strong><span style="color: #a020f0;">extends</span></strong> EmptyVisitor {
        <strong><span style="color: #a020f0;">private</span></strong> String methodName;
        <strong><span style="color: #a020f0;">private</span></strong> Type[] paramTypes;
        <strong><span style="color: #a020f0;">private</span></strong> ArrayList paramNames;
        <strong><span style="color: #a020f0;">private</span></strong> <strong><span style="color: #a020f0;">boolean</span></strong> ztatic;

        <strong><span style="color: #a020f0;">public</span></strong> MyMethodVisitor(<strong><span style="color: #a020f0;">boolean</span></strong> ztatic, String methodName,
                               String desc) {

            <strong><span style="color: #a020f0;">this</span></strong>.methodName = methodName;
            <strong><span style="color: #a020f0;">this</span></strong>.ztatic = ztatic;
            <em><span style="color: #b22222;">/*
             * Determine the parameter types of the visited method
             * or constructor.
             */</span></em>
            paramTypes = Type.getArgumentTypes(desc);
            <em><span style="color: #b22222;">/*
             * paramNames will be used to collect the actual
             * parameter names.
             */</span></em>
            paramNames = <strong><span style="color: #a020f0;">new</span></strong> ArrayList(paramTypes.length);
        }

        <strong><span style="color: #a020f0;">public</span></strong> <strong><span style="color: #a020f0;">void</span></strong> visitLocalVariable(String variableName,
                String desc, String sig, Label start,
                Label end, <strong><span style="color: #a020f0;">int</span></strong> index) {

            <strong><span style="color: #a020f0;">if</span></strong> (!ztatic) {
                <em><span style="color: #b22222;">/*
                 * For non static methods the first local variable is
                 * always 'this'.
                 */</span></em>
                index--;
            }
            <strong><span style="color: #a020f0;">if</span></strong> (index &gt;= 0 &amp;&amp; paramNames.size() &lt; paramTypes.length) {
                <em><span style="color: #b22222;">/*
                 * The first paramTypes.length local variables are
                 * always the local variables which hold the method
                 * arguments.
                 */</span></em>
                paramNames.add(variableName);
            }
        }

        <strong><span style="color: #a020f0;">public</span></strong> <strong><span style="color: #a020f0;">void</span></strong> visitEnd() {
            <em><span style="color: #b22222;">/*
             * Now paramNames contains the parameter names (if the
             * class was compiled with local variable debug info).
             * Dump the method or constructor signature including
             * the parameter names to System.out.
             */</span></em>
            <strong><span style="color: #a020f0;">if</span></strong> (ztatic) {
                System.out.print(<strong><span style="color: #bc8f8f;">"static "</span></strong>);
            }
            System.out.print(methodName + <strong><span style="color: #bc8f8f;">"("</span></strong>);
            <strong><span style="color: #a020f0;">for</span></strong> (<strong><span style="color: #a020f0;">int</span></strong> i = 0; i &lt; paramTypes.length; i++) {
                String paramName = paramNames.isEmpty() ? <strong><span style="color: #bc8f8f;">"?"</span></strong>
                                 : (String) paramNames.get(i);
                System.out.print(paramTypes[i].getClassName());
                System.out.print(<strong><span style="color: #bc8f8f;">" "</span></strong> + paramName);
                <strong><span style="color: #a020f0;">if</span></strong> (i &lt; paramTypes.length - 1) {
                    System.out.print(<strong><span style="color: #bc8f8f;">", "</span></strong>);
                }
            }
            System.out.println(<strong><span style="color: #bc8f8f;">")"</span></strong>);
        }

    }
}</pre>
</div>
<p><code>asm-2.2.2.jar</code> and <code>asm-commons-2.2.2.jar</code> are needed<br />
to compile and run this example. You will find them on the<br />
<a href="http://asm.objectweb.org/">ASM web site</a>.</p>
<h3>Limitations</h3>
<p>It&#8217;s important to note that this technique has a few limitations:</p>
<ul>
<li> As I&#8217;ve already mentioned the <code>.class</code> files must be compiled with local<br />
variable debugging information. This is a problem if you&#8217;re using third party<br />
classes which haven&#8217;t been compiled with the required debug info. E.g. Sun&#8217;s<br />
classes included in the JRE (like <code>java.lang.String</code>) won&#8217;t work with this<br />
technique.</li>
<li> If you&#8217;re using an obfuscator to protect your classes from reverse engineering<br />
the obfuscator will most probably remove any debugging information from the class<br />
files.</li>
<li> The <code>.class</code> files must be available for reading. There may be<br />
security restrictions in the environment your code is running in<br />
which limits the access to the actual <code>.class</code> files, e.g. when<br />
running in an application server. Also, the technique will most likely not<br />
work for dynamically generated classes (generated using<br />
<a href="http://cglib.sourceforge.net/">CGLIB</a> or similar).</li>
</ul>
<p>Neither of these are big issues for me.  I&#8217;d use the technique mainly with my<br />
own classes which I have full control over and the projects I work on don&#8217;t<br />
require the use of an obfuscator. I&#8217;ve also verified that this technique will<br />
work in plain Tomcat which is the environment I deploy to most of the time.</p>
<p>I must admit that it&#8217;s unfortunate that this won&#8217;t work with Sun&#8217;s classes.<br />
But the good news is that it will work with a lot of open source projects out<br />
there, even if you don&#8217;t want to recompile from source. Out of the 60000 classes<br />
currently in my local Maven repository, about 40000 have local variable<br />
debugging information.</p>
<h3>Conclusions</h3>
<p>It is my belief that adding this feature to Spring would make the decision<br />
whether to use setter or constructor injection a lot easier. I would get<br />
nicer looking and more self documenting Spring configuration files without<br />
having to sacrifice anything in the design of my classes.</p>
<p>Of course, the Java code presented above was only a very simple example to<br />
demonstrate the technique. Currently, I&#8217;m working on a patch for Spring which<br />
adds the <code>name</code> attribute to the <code>constructor-arg</code> element<br />
in the Spring configuration XML schema. Hopefully I will have it ready and<br />
uploaded to the Spring issue tracker in a few days. Then it will, of course, be<br />
up to the Spring people to decide whether this should be added to Spring or not.<br />
Keep your fingers crossed!</p>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2006/09/spring-and-named-constructor-arguments/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Downloading YouTube movie clips to your local hard drive</title>
		<link>http://therning.org/niklas/2006/08/downloading-youtube-movie-clips-to-your-local-hard-drive/</link>
		<comments>http://therning.org/niklas/2006/08/downloading-youtube-movie-clips-to-your-local-hard-drive/#comments</comments>
		<pubDate>Thu, 10 Aug 2006 20:22:00 +0000</pubDate>
		<dc:creator>niklas</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">163 at http://therning.org/niklas</guid>
		<description><![CDATA[I tried to watch this YouTube clip the other day but found that my flash player had a hard time synching the audio and video. Very annoying! And as far as I can see YouTube doesn&#8217;t provide a download link to let me download the movie and play it directly from my hard drive. I [...]]]></description>
			<content:encoded><![CDATA[<p>I tried to watch <a href="http://www.youtube.com/watch?v=3CiW838wNiM">this YouTube clip</a> the other day but found that my flash player had a hard time synching the audio and video. Very annoying! And as far as I can see YouTube doesn&#8217;t provide a download link to let me download the movie and play it directly from my hard drive. I really wanted to see this clip but couldn&#8217;t stand the audio lagging behind. I figured there must be a way to hack that flash thing they are using to play the movie. It turned out to be quite easy!<span id="more-11"></span></p>
<p>First I downloaded the flash animation embedded in the page. You&#8217;ll find the URL of the SWF file in the text field labelled <strong>Embed</strong> to the right of the movie or you could have a look at the page&#8217;s HTML code. Then I used <code>wget</code> to download this URL:</p>
<p><code>wget 'http://www.youtube.com/v/3CiW838wNiM'</code></p>
<p>Watching the output from <code>wget</code> one can see that this URL actually does a redirect to another URL:</p>
<p><code>Location: /p.swf?video_id=3CiW838wNiM&amp;eurl=&amp;iurl=http%3A//sjl-static5.sjl.youtube.com/vi/3CiW838wNiM/2.jpg<br />
&amp;t=OEgsToPDskJAsFn4X26z0PYTiD7rKU DG</code></p>
<p>After <code>wget</code> downloaded the <code>p.swf</code> file (this is a flash animation file) I used <a href="http://www.nowrap.de/flare.html">flare</a> to decompile it and had a look at the ActionScript code. The code had a number of URL strings and after reading <a href="http://livedocs.macromedia.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&amp;file=00001589.html">Macromedia&#8217;s docs on the NetStream class</a> I knew I had found the URL I was looking for. Here&#8217;s how I downloaded the movie above which I wanted to watch:</p>
<p><code>wget  'http://www.youtube.com/get_video?video_id=3CiW838wNiM&amp;t=OEgsToPDskKC-YjD-y9Yr3q63ZzBUd1A'</code></p>
<p>The <code>t</code> parameter comes from the redirect URL we got as a response to the first <code>wget</code>. This appears to be some kind of ticket or something and seems to change over time.</p>
<p>After executing this <code>wget</code> command I had an FLV movie file on my hard drive which I could watch using mplayer without any audio problems!</p>
]]></content:encoded>
			<wfw:commentRss>http://therning.org/niklas/2006/08/downloading-youtube-movie-clips-to-your-local-hard-drive/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
