<?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:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
 <title>mikereedell.com</title>
 
 <link href="http://mikereedell.com/" />
 <updated>2012-08-21T14:14:32-04:00</updated>
 <id>http://mikereedell.com/</id>
 <author>
   <name>Mike Reedell</name>
   <email>mike@reedell.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/mikereedell" /><feedburner:info uri="mikereedell" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Back to Basics</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/ZGdgKUzMac8/Back-to-Basics.html" />
   <updated>2012-08-21T00:00:00-04:00</updated>
   <id>http://mikereedell.com/2012/08/21/Back-to-Basics</id>
   <content type="html">&lt;h1 id='back_to_basics'&gt;Back to Basics&lt;/h1&gt;
&lt;p class='postdate'&gt;21 August 2012&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve spent entirely too long being an &amp;#8220;enterprise&amp;#8221; developer. Too much time putting a UI on a database with a dash of proprietary &amp;#8216;secret-sauce&amp;#8217; to justify 6- and 7- figure per annum license agreements. Too much time stringing together an ever-growing collection of frameworks, containers and libraries to build these applications in the name of &amp;#8216;enterprise Java&amp;#8217;.&lt;/p&gt;

&lt;p&gt;These are precisely the reasons why I&amp;#8217;m going back to basics and learning low-level programming. What do I intend to do with such knowledge? Who knows. Maybe a job building development tools, data-stores, web-servers, platforms, etc. or maybe not. Either way I&amp;#8217;ll be learning something new and thinking about concepts that I don&amp;#8217;t get to think about in my professional setting.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t know about you, but when I hear &amp;#8216;low-level programming&amp;#8217;, I think of good, &amp;#8216;ol-fashioned &lt;a href='http://en.wikipedia.org/wiki/C_(programming_language'&gt;C&lt;/a&gt;. So that&amp;#8217;s where I&amp;#8217;m starting, getting back into the land of structs, pointers, header files and other things that give most Java developers nightmares. From C, I intend to re-kindle my brief affair with &lt;a href='http://golang.org/'&gt;Go&lt;/a&gt; and possibly &lt;a href='http://www.rust-lang.org/'&gt;Rust&lt;/a&gt;, learning lower-level programming in a language built for modern multi-core machines.&lt;/p&gt;

&lt;p&gt;So far, I&amp;#8217;ve dusted off my old copy of &lt;a href='http://www.amazon.com/gp/product/1565923065/ref=as_li_tf_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=1565923065&amp;amp;linkCode=as2&amp;amp;tag=mikereed-20'&gt;Practical C&lt;/a&gt; and have been burning through the early chapters. From there I&amp;#8217;ll go through &lt;a href='http://c.learncodethehardway.org'&gt;Learn C The Hard Way&lt;/a&gt; since I had a wonderful time picking up the essentials of Python with &lt;a href='http://learnpythonthehardway.org/'&gt;Learn Python the Hard Way&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Any useful tips for getting into lower-level/system programming?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/ZGdgKUzMac8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2012/08/21/Back-to-Basics.html</feedburner:origLink></entry>
 
 <entry>
   <title>Conditionally Ignoring Test Cases With JUnit Rules</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/QSfTcA--_JM/JUnit-Conditional-Ignore-Using-Rules.html" />
   <updated>2011-12-15T00:00:00-05:00</updated>
   <id>http://mikereedell.com/2011/12/15/JUnit-Conditional-Ignore-Using-Rules</id>
   <content type="html">&lt;h1 id='conditionally_ignoring_test_cases_with_junit_rules'&gt;Conditionally Ignoring Test Cases With JUnit Rules&lt;/h1&gt;
&lt;p class='postdate'&gt;15 December 2011&lt;/p&gt;
&lt;p&gt;With JUnit 4.x, the developers introduced the concept of annotating tests with @Ignore so developers could mark tests that the test runner should ignore. What wasn&amp;#8217;t added was the ability to specify conditions for which the test should be ignored, for instance:&lt;/p&gt;

&lt;p&gt;Ignore this test when running locally:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='nd'&gt;@IgnoreWhen&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;env&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;LOCAL&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='kd'&gt;public&lt;/span&gt; &lt;span class='kt'&gt;void&lt;/span&gt; &lt;span class='nf'&gt;testSomethingReallyCPUIntensive&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
	&lt;span class='o'&gt;...&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;A bit of google&amp;#8217;ing will yield &lt;a href='http://stackoverflow.com/questions/6096061/is-there-any-conditional-annotation-in-junit-to-mark-few-test-cases-to-be-skippe'&gt;a lot&lt;/a&gt; &lt;a href='http://stackoverflow.com/questions/1689242/conditionally-ignoring-tests-in-junit-4'&gt;of pages&lt;/a&gt; &lt;a href='http://programmaticallyspeaking.blogspot.com/2008/10/run-time-equivalent-to-junits-ignore.html'&gt;that&lt;/a&gt; &lt;a href='http://garygregory.wordpress.com/2011/03/12/conditionally-ignoring-tests-in-junit/'&gt;purport&lt;/a&gt; to have the solution to this problem or discuss ways to work around it.&lt;/p&gt;

&lt;p&gt;While there&amp;#8217;s nothing wrong with any of these solutions technically, I didn&amp;#8217;t want to write a custom JUnit test runner nor have code that executed after the class- and method-level setup&amp;#8217;s were run. In other words, I wanted a conditional short-circuit that would exit the test as soon as possible without running any code the test-to-be-ignored depends on.&lt;/p&gt;

&lt;p&gt;That leads us to using JUnit&amp;#8217;s &lt;a href='http://www.junit.org/node/580'&gt;@Rule&lt;/a&gt; feature. By using Rules, we can introduce just the type of short-circuit mechanism mentioned above by creating a rule that applies to all test cases that will determine whether the test case should execute or not.&lt;/p&gt;

&lt;p&gt;The case we had to solve was specifying the test data sets that certain tests could run against. If one test had test data available in data set QA01 but not in QA02, we didn&amp;#8217;t want that test to run, and fail, when the suite was run against QA02.&lt;/p&gt;

&lt;p&gt;To solve this, we created a method-level annotation called DataSets:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='nd'&gt;@Retention&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;RetentionPolicy&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;RUNTIME&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='nd'&gt;@Target&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;ElementType&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;METHOD&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='kd'&gt;public&lt;/span&gt; &lt;span class='nd'&gt;@interface&lt;/span&gt; &lt;span class='n'&gt;DataSets&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
	&lt;span class='n'&gt;String&lt;/span&gt;&lt;span class='o'&gt;[]&lt;/span&gt; &lt;span class='nf'&gt;value&lt;/span&gt;&lt;span class='o'&gt;();&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;which we then used to annotate our test cases with the data sets that they should be executed on:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='nd'&gt;@DataSets&lt;/span&gt;&lt;span class='o'&gt;({&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;QA01&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;})&lt;/span&gt;
&lt;span class='nd'&gt;@Test&lt;/span&gt;
&lt;span class='kd'&gt;public&lt;/span&gt; &lt;span class='kt'&gt;void&lt;/span&gt; &lt;span class='nf'&gt;someDataIntensiveTest&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
	&lt;span class='n'&gt;assertTrue&lt;/span&gt;&lt;span class='o'&gt;(....);&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;To &amp;#8216;enforce&amp;#8217; the DataSets annotation, we created a JUnit Rule that would inspect the annotation along with the JVM argument &amp;#8216;dataset&amp;#8217; to see if the test should be executed.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='kd'&gt;public&lt;/span&gt; &lt;span class='kd'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;DataSetRule&lt;/span&gt; &lt;span class='kd'&gt;implements&lt;/span&gt; &lt;span class='n'&gt;TestRule&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;

	&lt;span class='nd'&gt;@Override&lt;/span&gt;
	&lt;span class='kd'&gt;public&lt;/span&gt; &lt;span class='n'&gt;Statement&lt;/span&gt; &lt;span class='nf'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Statement&lt;/span&gt; &lt;span class='n'&gt;statement&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;Description&lt;/span&gt; &lt;span class='n'&gt;description&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
		&lt;span class='n'&gt;DataSets&lt;/span&gt; &lt;span class='n'&gt;annotation&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;description&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;getAnnotation&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;DataSets&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;class&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
		&lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;annotation&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
			&lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;statement&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
		&lt;span class='o'&gt;}&lt;/span&gt;
		&lt;span class='n'&gt;String&lt;/span&gt; &lt;span class='n'&gt;testDataSet&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;System&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;getProperty&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;dataset&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;

		&lt;span class='n'&gt;List&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;String&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;allowedDataSets&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Arrays&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;asList&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;annotation&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;value&lt;/span&gt;&lt;span class='o'&gt;());&lt;/span&gt;
		&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;allowedDataSets&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;contains&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;testDataSet&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
			&lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;statement&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
		&lt;span class='o'&gt;}&lt;/span&gt;

		&lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nf'&gt;Statement&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;

			&lt;span class='nd'&gt;@Override&lt;/span&gt;
			&lt;span class='kd'&gt;public&lt;/span&gt; &lt;span class='kt'&gt;void&lt;/span&gt; &lt;span class='nf'&gt;evaluate&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='kd'&gt;throws&lt;/span&gt; &lt;span class='n'&gt;Throwable&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
				&lt;span class='c1'&gt;// Return an empty Statement object for those tests &lt;/span&gt;
				&lt;span class='c1'&gt;// that shouldn&amp;#39;t run on the specified dataset.&lt;/span&gt;
			&lt;span class='o'&gt;}&lt;/span&gt;
		&lt;span class='o'&gt;};&lt;/span&gt;
	&lt;span class='o'&gt;}&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This rule checks the value of the annotation, and if the &amp;#8216;dataset&amp;#8217; JVM argument is contained in the list of allowed data sets (or the annotation isn&amp;#8217;t present at all), passes the test (Statement object) unaltered to the next step in the execution sequence. If the &amp;#8216;dataset&amp;#8217; JVM argument is not in the list of allowed data sets, the rule creates a new, empty Statement object which then gets executed in place of the actual test case.&lt;/p&gt;

&lt;p&gt;To put the DataSetRule into effect, we need to decorate our test classes with one more annotation:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='nd'&gt;@Rule&lt;/span&gt;
&lt;span class='kd'&gt;public&lt;/span&gt; &lt;span class='n'&gt;TestRule&lt;/span&gt; &lt;span class='n'&gt;dataSetRule&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;DataSetRule&lt;/span&gt;&lt;span class='o'&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;This snippet lets JUnit know that there&amp;#8217;s a rule that needs to be executed before each test case gets run. There&amp;#8217;s also a ClassRule interface that can be implemented to create JUnit rules that are executed before any @BeforeClass methods are run.&lt;/p&gt;

&lt;p&gt;While this solution isn&amp;#8217;t perfect: it still shows the tests as being run and passing, albeit with an execution time approaching zero, it does allow JUnit tests to be decorated with custom annotations that control the execution of the test&lt;/p&gt;

&lt;p&gt;For more information on JUit rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://cwd.dhemery.com/2011/01/what-junit-rules-are-good-for/'&gt;http://cwd.dhemery.com/2011/01/what-junit-rules-are-good-for/&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://cwd.dhemery.com/2010/12/junit-rules/'&gt;http://cwd.dhemery.com/2010/12/junit-rules/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/QSfTcA--_JM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2011/12/15/JUnit-Conditional-Ignore-Using-Rules.html</feedburner:origLink></entry>
 
 <entry>
   <title>Using MyBatis to Insert Collections Into MySQL</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/gJpZJAe7szU/Using-MyBatis-Foreach-to-Insert-Collections.html" />
   <updated>2011-03-21T00:00:00-04:00</updated>
   <id>http://mikereedell.com/2011/03/21/Using-MyBatis-Foreach-to-Insert-Collections</id>
   <content type="html">&lt;h1 id='using_mybatis_to_insert_collections_into_mysql'&gt;Using MyBatis to Insert Collections Into MySQL&lt;/h1&gt;
&lt;p class='postdate'&gt;21 March 2011&lt;/p&gt;
&lt;p&gt;I recently updated one of my Java projects from and old iBatis version to the latest and greatest MyBatis 3.0.4. The conversion part was fairly straightforward so I decided to see what the new library could do to help with performance.&lt;/p&gt;

&lt;p&gt;Since the application I&amp;#8217;m writing is an ant task that process XML documents into list data that needs to be saved to MySQL, I wanted to see if MyBatis could help out with inserting Collections.&lt;/p&gt;

&lt;p&gt;If you google around for &amp;#8216;mybatis insert list&amp;#8217; you&amp;#8217;ll end up on &lt;a href='http://groups.google.com/group/mybatis-user/browse_thread/thread/b81c654041037384/22c448fca4b1c860?pli=1'&gt;this page&lt;/a&gt; which shows the following (incorrect) XML snippet:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='xml'&gt;INSERT INTO tbl_name (A,B,C) VALUES 
&lt;span class='nt'&gt;&amp;lt;foreach&lt;/span&gt; &lt;span class='na'&gt;collection=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;_parameter&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;item=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;parm&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;open=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;(&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;close=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;)&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;separator=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;,&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
	#{parm.val1},#{parm.val2},#{parm.val3}
&lt;span class='nt'&gt;&amp;lt;/foreach&amp;gt;&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Which will generate SQL:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='sql'&gt;&lt;span class='k'&gt;INSERT&lt;/span&gt; &lt;span class='k'&gt;INTO&lt;/span&gt; &lt;span class='n'&gt;tbl_name&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;A&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;C&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;VALUES&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After downloading the source, finding the unit test that covered this scenario and adding an additional test for the case I was seeing I discovered that this is the snippet that generates correct MySQL SQL for inserting a list into a table:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='xml'&gt;&lt;span class='nt'&gt;&amp;lt;insert&lt;/span&gt; &lt;span class='na'&gt;id=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;insertList&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;useGeneratedKeys=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;parameterType=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;java.util.List&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
	INSERT INTO tbl_name (A,B,C) VALUES (
	&lt;span class='nt'&gt;&amp;lt;foreach&lt;/span&gt; &lt;span class='na'&gt;collection=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;_parameter&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;item=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;parm&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;open=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;close=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;separator=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;),()&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
		#{parm.val1},#{parm.val2},#{parm.val3}
	&lt;span class='nt'&gt;&amp;lt;/foreach&amp;gt;&lt;/span&gt;
&lt;span class='nt'&gt;&amp;lt;/insert&amp;gt;&lt;/span&gt;
)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Which will output SQL like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='sql'&gt;&lt;span class='k'&gt;INSERT&lt;/span&gt; &lt;span class='k'&gt;INTO&lt;/span&gt; &lt;span class='n'&gt;tbl_name&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;A&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;C&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;VALUES&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='p'&gt;.....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/gJpZJAe7szU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2011/03/21/Using-MyBatis-Foreach-to-Insert-Collections.html</feedburner:origLink></entry>
 
 <entry>
   <title>POST'ing Form Data to CSRF-protected Forms With Cocoa</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/9T8F9cRyYyY/POST-Form-Data-to-CSRF-Protected-Forms-With-Cocoa.html" />
   <updated>2010-12-12T00:00:00-05:00</updated>
   <id>http://mikereedell.com/2010/12/12/POST-Form-Data-to-CSRF-Protected-Forms-With-Cocoa</id>
   <content type="html">&lt;h1 id='posting_form_data_to_csrfprotected_forms_with_cocoa'&gt;POST&amp;#8217;ing Form Data to CSRF-protected Forms With Cocoa&lt;/h1&gt;
&lt;p class='postdate'&gt;21 December 2010&lt;/p&gt;
&lt;p&gt;While writing &lt;a href='http://luckycatlabs.com/macgist.html'&gt;MacGist&lt;/a&gt;, I had to engineer my way around &lt;a href='http://github.com'&gt;GitHub&amp;#8217;s&lt;/a&gt; lack of API support for gists. The &lt;a href='http://develop.github.com/p/gist.html'&gt;gist API&lt;/a&gt; doesn&amp;#8217;t allow for much, just simple GET&amp;#8217;s around the gists metadata and content, for public gists only. The only way around these limitations that I saw was to programmatically access the web interface of &lt;a href='http://gist.github.com'&gt;gist.github.com&lt;/a&gt; and POST the data in the HTTP headers.&lt;/p&gt;

&lt;p&gt;Sounds easy enough.&lt;/p&gt;

&lt;p&gt;And it was, but my lovingly crafted HTTP POST&amp;#8217;s didn&amp;#8217;t actually do anything. Some quick Firebug&amp;#8217;ing uncovered that Github uses &lt;a href='http://en.wikipedia.org/wiki/CSRF'&gt;CSRF&lt;/a&gt; form fields to protect themselves from, well, CSRF attacks. Without this uniquely generated key present in the POST data, the requests weren&amp;#8217;t going to do anything.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s the solution I came up with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Login to github using standard username/password authentication (BASIC auth over https).&lt;/li&gt;

&lt;li&gt;Construct the URL of the form you want to POST to, in my case the URL has the form https://gist.github.com/gists/$GIST_ID/edit.&lt;/li&gt;

&lt;li&gt;GET the form URL.&lt;/li&gt;

&lt;li&gt;Get the &amp;#8220;authenticity_token&amp;#8221; hidden form field from the HTML content.&lt;/li&gt;

&lt;li&gt;Use the value of the &amp;#8220;authenticity_token&amp;#8221; in the POST data.&lt;/li&gt;

&lt;li&gt;POST the form.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Getting the authenticity_token from the HTML form data is pretty straight-forward:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nl'&gt;getAuthenticityTokenForUrl:&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='n'&gt;url&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='n'&gt;ASIHTTPRequest&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;request&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;ASIHTTPRequest&lt;/span&gt; &lt;span class='nl'&gt;requestWithURL:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;NSURL&lt;/span&gt; &lt;span class='nl'&gt;URLWithString:&lt;/span&gt;&lt;span class='n'&gt;url&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
    &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;request&lt;/span&gt; &lt;span class='n'&gt;startSynchronous&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

    &lt;span class='n'&gt;NSError&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;error&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;request&lt;/span&gt; &lt;span class='n'&gt;error&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;error&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;NSLog&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Error getting authenticity_token from github for url: %@ with error: %@&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
            &lt;span class='n'&gt;url&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;error&lt;/span&gt; &lt;span class='n'&gt;localizedDescription&lt;/span&gt;&lt;span class='p'&gt;]);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;

    &lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;textData&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;request&lt;/span&gt; &lt;span class='n'&gt;responseString&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
    &lt;span class='n'&gt;NSRange&lt;/span&gt; &lt;span class='n'&gt;location&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;textData&lt;/span&gt; &lt;span class='nl'&gt;rangeOfString:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;authenticity_token&amp;quot;&lt;/span&gt; &lt;span class='nl'&gt;options:&lt;/span&gt;&lt;span class='n'&gt;NSLiteralSearch&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

    &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;location&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;location&lt;/span&gt; &lt;span class='o'&gt;!=&lt;/span&gt; &lt;span class='n'&gt;NSNotFound&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;location&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;location&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;location&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;location&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;41&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='n'&gt;location&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;length&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;40&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;formData&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;textData&lt;/span&gt; &lt;span class='nl'&gt;substringWithRange:&lt;/span&gt;&lt;span class='n'&gt;location&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;formData&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nb'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this solution, we&amp;#8217;re essentially grep&amp;#8217;ing the HTML for the string &amp;#8220;authenticity_token&amp;#8221; then returning the next 40 characters. There&amp;#8217;s more than one hammer for this nail: &lt;a href='http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSScanner_Class/Reference/Reference.html'&gt;NSScanner&lt;/a&gt;, regular expressions, parsing the XHTML and walking the DOM, but for something quick and easy, this one works just as well.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/9T8F9cRyYyY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2010/12/12/POST-Form-Data-to-CSRF-Protected-Forms-With-Cocoa.html</feedburner:origLink></entry>
 
 <entry>
   <title>Sunrise-WS - A Super Simple Sinatra Wrapper for RubySunrise</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/gD3wfPab7w8/Sunrise-WS-A-Super-Simple-Sinatra-Wrapper-for-RubySunrise.html" />
   <updated>2010-08-11T00:00:00-04:00</updated>
   <id>http://mikereedell.com/2010/08/11/Sunrise-WS-A-Super-Simple-Sinatra-Wrapper-for-RubySunrise</id>
   <content type="html">&lt;h1 id='sunrisews__a_super_simple_sinatra_wrapper_for_rubysunrise'&gt;Sunrise-WS - A Super Simple Sinatra Wrapper for RubySunrise&lt;/h1&gt;
&lt;p class='postdate'&gt;11 August 2010&lt;/p&gt;
&lt;p&gt;Just did a push to github of &lt;a href='http://github.com/mikereedell/Sunrise-WS'&gt;sunrise-ws&lt;/a&gt;, a super simple &lt;a href='http://www.sinatrarb.com/'&gt;Sinatra&lt;/a&gt; wrapper for the RubySunrise gem. The concept is simple: call a web-service to get the sunrise/sunset data for a given location in a given timezone. Since the requirements were so simple and there is no database or security, it made sense to use Sinatra instead of rails. First off, Sinatra is easy. I know I&amp;#8217;m not breaking new ground here, but as a 10-year professional java developer, getting ANYTHING done in that little code is next to impossible. I certainly appreciated the ease of setup of the Sinatra app and how easy it was to test it using RSpec.&lt;/p&gt;

&lt;p&gt;Like the title says, this app is SIMPLE. It only exposes three web-services: get the sunrise/sunset data for today, a specified date, or for the entire year. That&amp;#8217;s it. And instead of using XML as the response, everything is in JSON.&lt;/p&gt;

&lt;p&gt;For more information on how to use it, go to the project&amp;#8217;s &lt;a href='http://github.com/mikereedell/Sunrise-WS/blob/master/README.md'&gt;README&lt;/a&gt; on github.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;d like to try it out without having to run it locally, it&amp;#8217;s been deployed to &lt;a href='http://heroku.com'&gt;Heroku&lt;/a&gt;. Hit the following links to try it out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://fierce-fire-51.heroku.com/sunrise/today/39.9537/-75.8301537/America/New_York'&gt;http://fierce-fire-51.heroku.com/sunrise/today/39.9537/-75.8301537/America/New_York&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://fierce-fire-51.heroku.com/sunrise/2004-01-31/39.9537/-75.8301537/America/New_York'&gt;http://fierce-fire-51.heroku.com/sunrise/2004-01-31/39.9537/-75.8301537/America/New_York&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://fierce-fire-51.heroku.com/sunrise/year/39.9537/-75.8301537/America/New_York'&gt;http://fierce-fire-51.heroku.com/sunrise/year/39.9537/-75.8301537/America/New_York&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To get a better visualization of the JSON output, install the JSON bundle for TextMate or use this &lt;a href='http://chris.photobooks.com/json/default.htm'&gt;JSON Visualization&lt;/a&gt; page.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/gD3wfPab7w8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2010/08/11/Sunrise-WS-A-Super-Simple-Sinatra-Wrapper-for-RubySunrise.html</feedburner:origLink></entry>
 
 <entry>
   <title>RubySunrise Gem</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/yv2JGht5T-Q/RubySunrise-Gem.html" />
   <updated>2010-03-15T00:00:00-04:00</updated>
   <id>http://mikereedell.com/2010/03/15/RubySunrise-Gem</id>
   <content type="html">&lt;h1 id='rubysunrise_gem'&gt;RubySunrise Gem&lt;/h1&gt;
&lt;p class='postdate'&gt;15 March 2010&lt;/p&gt;
&lt;p&gt;As a follow-up to the Java sunrise/sunset calculator I released early last year, I&amp;#8217;m releasing a ruby gem that does essentially the same thing. Just in A LOT less code, but with the same attention to test goodness.&lt;/p&gt;

&lt;p&gt;To install and use the RubySunrise gem just:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;$ &lt;/span&gt;gem install RubySunrise
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or download from &lt;a href='http://rubygems.org/gems/RubySunrise'&gt;RubyGems&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The current version as of today is 0.2, which requires the &lt;a href='http://tzinfo.rubyforge.org/'&gt;tzinfo&lt;/a&gt; gem to perform the timezone offset lookups.&lt;/p&gt;

&lt;p&gt;If you want/need the lastest, just grab it from the github repo:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;$ &lt;/span&gt;git clone git://github.com/mikereedell/sunrisesunset-ruby
&lt;span class='nv'&gt;$ &lt;/span&gt;gem build RubySunrise
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;At this time the RubySunrise gem covers astronomical, nautical, civil, and official sunrise/sunset calculations for every location that experiences a sunrise and sunset every day (Sorry Alaska!). I&amp;#8217;m currently working on the strangeness that is causing my Alaskan test suite to fail with known-good data.&lt;/p&gt;

&lt;p&gt;Example time:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;solareventcalculator&amp;#39;&lt;/span&gt;

&lt;span class='n'&gt;date&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Date&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;parse&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;2008-11-01&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;calc&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;SolarEventCalculator&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;date&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='no'&gt;BigDecimal&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;39.9537&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='no'&gt;BigDecimal&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-75.7850&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='n'&gt;utcOfficialSunrise&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;calc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;compute_utc_official_sunrise&lt;/span&gt;
&lt;span class='n'&gt;localOfficialSunrise&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;calc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;compute_official_sunrise&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;America/New_York&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;utcOfficialSunrise &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;utcOfficialSunrise&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;localOfficialSunrise &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;localOfficialSunrise&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Which yields:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;utcOfficialSunrise 2008-11-01T11:33:00+00:00
localOfficialSunrise 2008-11-01T07:33:00-04:00
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The source is available under the Apache License, Version 2.0 at &lt;a href='http://github.com/mikereedell/sunrisesunset-ruby'&gt;Github&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/yv2JGht5T-Q" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2010/03/15/RubySunrise-Gem.html</feedburner:origLink></entry>
 
 <entry>
   <title>Maven with Ruby Part II</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/r30lxUpx54U/Maven-with-Ruby-Part-II.html" />
   <updated>2009-03-20T00:00:00-04:00</updated>
   <id>http://mikereedell.com/2009/03/20/Maven-with-Ruby-Part-II</id>
   <content type="html">&lt;h1 id='maven_with_ruby_part_ii'&gt;Maven with Ruby Part II&lt;/h1&gt;
&lt;p class='postdate'&gt;20 March 2009&lt;/p&gt;
&lt;p&gt;Want to add something to your projects Maven builds (like code coverage&amp;#8230;) but don&amp;#8217;t want to CTL-C/CTL-V your way to boredom? Use the below script to lend a hand. Substitute the XML in the SNIPPET variable to the artifact/plugin/dependency to be injected (leave the &amp;#8216;inject&amp;#8217; tag in place) and use the command:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;$&amp;gt;&lt;/span&gt;ruby mavenInjector.rb /xpath/to/element
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here&amp;#8217;s the code. Check the &lt;a href='http://github.com/mikereedell/scripts/tree/master'&gt;git repository&lt;/a&gt; for the latest.&lt;/p&gt;

&lt;p&gt;In the beginning of the &amp;#8216;for&amp;#8217; loop in the inject method I remove the read-only bit from the file. This is for those of us afflicted with ClearCase and can be removed for those fortunate enough to use a sane SCM.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='c1'&gt;#/usr/bin/env ruby&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;rexml/document.rb&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;fileutils.rb&amp;#39;&lt;/span&gt;

&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;MavenInjector&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;inject&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='kp'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Must provide the root path of the node to inject under.&amp;#39;&lt;/span&gt;
      &lt;span class='nb'&gt;exit&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='n'&gt;poms&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pwd&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/**/pom.xml&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;

    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;pom&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='n'&gt;poms&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
      &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;writable?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pom&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
        &lt;span class='no'&gt;FileUtils&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chmod&lt;/span&gt; &lt;span class='mo'&gt;0644&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;pom&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='n'&gt;pomXML&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;REXML&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Document&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pom&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
      &lt;span class='n'&gt;element&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;pomXML&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_elements&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;

      &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;element&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='kp'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;parentElement&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;pomXML&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_elements&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/project/build&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
        &lt;span class='n'&gt;element&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;REXML&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Element&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;plugins&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;parentElement&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;plugin&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='n'&gt;getElementsToInject&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
        &lt;span class='n'&gt;element&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add_element&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;plugin&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='n'&gt;formatter&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;REXML&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Formatters&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Default&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='n'&gt;formatter&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;write&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pomXML&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pom&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;w+&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;getElementsToInject&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
    &lt;span class='n'&gt;elementXML&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;REXML&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Document&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;SNIPPET&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;elementXML&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_elements&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/inject/plugin&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='no'&gt;SNIPPET&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='no'&gt;head&lt;/span&gt;
&lt;span class='err'&gt;&amp;lt;inject&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;  &amp;lt;plugin&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;    &amp;lt;artifactId&amp;gt;cobertura-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;    &amp;lt;configuration&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;        &amp;lt;formats&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;          &amp;lt;format&amp;gt;html&amp;lt;/format&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;        &amp;lt;/formats&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;    &amp;lt;/configuration&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;  &amp;lt;/plugin&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;&amp;lt;/inject&amp;gt;&lt;/span&gt;
&lt;span class='err'&gt;HEAD&lt;/span&gt;

&lt;span class='err'&gt;MavenInjector.new.inject(ARGV[0])&lt;/span&gt;
&lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;inject&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;
  &lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;plugin&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;
    &lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;groupId&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;org&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;codehaus&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;mojo&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='sr'&gt;/groupId&amp;gt;&lt;/span&gt;
&lt;span class='sr'&gt;    &amp;lt;artifactId&amp;gt;cobertura-maven-plugin&amp;lt;/&lt;/span&gt;&lt;span class='n'&gt;artifactId&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;
    &lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;configuration&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;
        &lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;formats&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;
          &lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;html&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='sr'&gt;/format&amp;gt;&lt;/span&gt;
&lt;span class='sr'&gt;        &amp;lt;/&lt;/span&gt;&lt;span class='n'&gt;formats&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;
    &lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='sr'&gt;/configuration&amp;gt;&lt;/span&gt;
&lt;span class='sr'&gt;  &amp;lt;/&lt;/span&gt;&lt;span class='n'&gt;plugin&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;
&lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='sr'&gt;/inject&amp;gt;&lt;/span&gt;
&lt;span class='sr'&gt;HEAD&lt;/span&gt;

&lt;span class='sr'&gt;MavenInjector.new.inject(ARGV[0])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Any questions/problems/enhancements are welcome in the comments.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/r30lxUpx54U" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2009/03/20/Maven-with-Ruby-Part-II.html</feedburner:origLink></entry>
 
 <entry>
   <title>Using Ruby to Help Maven</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/93nJHGJnLqs/Using-Ruby-to-Help-Maven.html" />
   <updated>2009-03-13T00:00:00-04:00</updated>
   <id>http://mikereedell.com/2009/03/13/Using-Ruby-to-Help-Maven</id>
   <content type="html">&lt;h1 id='using_ruby_to_help_maven'&gt;Using Ruby to Help Maven&lt;/h1&gt;
&lt;p class='postdate'&gt;13 March 2009&lt;/p&gt;
&lt;p&gt;Maven projects can become a wasteland of neglected, old dependencies: huge, unmanageable .pom files and a local repository that&amp;#8217;s catalog of every Apache project in the past 10 years. Who knows if your project still requires that old version of Xerces?&lt;/p&gt;

&lt;p&gt;This script takes the name of a dependency and removes it from every pom.xml in any sub-directory from where it&amp;#8217;s called, removing the dependency element for the given jar file from each one. The script also saves the dependency tree in the file $artifactname.xml in case you need to put it back.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='c1'&gt;#/usr/bin/env ruby&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;rexml/document.rb&amp;#39;&lt;/span&gt;

&lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;ARGV&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='kp'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Must provide the name of the artifact to remove.&amp;#39;&lt;/span&gt;
  &lt;span class='nb'&gt;exit&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='n'&gt;artifact&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;ARGV&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;chomp&lt;/span&gt;
&lt;span class='n'&gt;poms&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pwd&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/**/pom.xml&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;

&lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;pom&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='n'&gt;poms&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;pomXML&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;REXML&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Document&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pom&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='n'&gt;element&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;pomXML&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_elements&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;//dependency[artifactId=&amp;#39;&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='n'&gt;artifact&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;#39;]&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;

  &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;element&lt;/span&gt; &lt;span class='o'&gt;!=&lt;/span&gt; &lt;span class='kp'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;temp&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;artifact&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;.xml&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;w+&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;formatter&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;REXML&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Formatters&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Default&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
    &lt;span class='n'&gt;formatter&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;write&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;element&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;temp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Removing the dependency: &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='n'&gt;artifact&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s2'&gt;from &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='n'&gt;pom&lt;/span&gt;
    &lt;span class='n'&gt;element&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;parent&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;delete&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;element&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;pomXML&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;write&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pom&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;w+&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='k'&gt;else&lt;/span&gt;
    &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;No artifacts with the name:&amp;#39;&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='n'&gt;artifact&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;#39; were found.&amp;quot;&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/93nJHGJnLqs" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2009/03/13/Using-Ruby-to-Help-Maven.html</feedburner:origLink></entry>
 
 <entry>
   <title>Licensing Your Code the Ruby Way</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/_w5cEdOynb0/Licensing-Your-Code-the-Ruby-Way.html" />
   <updated>2009-01-31T00:00:00-05:00</updated>
   <id>http://mikereedell.com/2009/01/31/Licensing-Your-Code-the-Ruby-Way</id>
   <content type="html">&lt;h1 id='licensing_your_code_the_ruby_way'&gt;Licensing Your Code the Ruby Way&lt;/h1&gt;
&lt;p class='postdate'&gt;31 January 2009&lt;/p&gt;
&lt;p&gt;Do you have an existing project you want to open-source? Does the thought of manually adding the license comment block to EVERY. SINGLE. SOURCE. FILE. sound not-so-exciting? Here&amp;#8217;s some help, ruby style:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Licenser&lt;/span&gt;

    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;licenseFiles&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
          &lt;span class='n'&gt;filenames&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Dir&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chop&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;**/*.java&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
	  &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;filename&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='n'&gt;filenames&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
              &lt;span class='n'&gt;contents&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;
              &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;open&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;filename&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;contents&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;read&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
              &lt;span class='n'&gt;contents&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;HEADER&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='n'&gt;contents&lt;/span&gt;
              &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;open&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;filename&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;write&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;contents&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
          &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='no'&gt;HEADER&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;lt&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;&lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;lt&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;&lt;span class='no'&gt;HEAD&lt;/span&gt;&lt;span class='sr' /&gt;
&lt;span class='sr'&gt;/*&lt;/span&gt;
&lt;span class='sr'&gt; * Copyright 2008-2009 Mike Reedell /&lt;/span&gt; &lt;span class='no'&gt;LuckyCatLabs&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='no'&gt;Licensed&lt;/span&gt; &lt;span class='n'&gt;under&lt;/span&gt; &lt;span class='n'&gt;the&lt;/span&gt; &lt;span class='no'&gt;Apache&lt;/span&gt; &lt;span class='no'&gt;License&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='no'&gt;Version&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;the&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;License&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;you&lt;/span&gt; &lt;span class='n'&gt;may&lt;/span&gt; &lt;span class='ow'&gt;not&lt;/span&gt; &lt;span class='n'&gt;use&lt;/span&gt; &lt;span class='n'&gt;this&lt;/span&gt; &lt;span class='n'&gt;file&lt;/span&gt; &lt;span class='n'&gt;except&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='n'&gt;compliance&lt;/span&gt; &lt;span class='n'&gt;with&lt;/span&gt; &lt;span class='n'&gt;the&lt;/span&gt; &lt;span class='no'&gt;License&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='no'&gt;You&lt;/span&gt; &lt;span class='n'&gt;may&lt;/span&gt; &lt;span class='n'&gt;obtain&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;copy&lt;/span&gt; &lt;span class='n'&gt;of&lt;/span&gt; &lt;span class='n'&gt;the&lt;/span&gt; &lt;span class='no'&gt;License&lt;/span&gt; &lt;span class='n'&gt;at&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt;      &lt;span class='n'&gt;http&lt;/span&gt;&lt;span class='ss'&gt;:/&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='n'&gt;www&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;apache&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;org&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='n'&gt;licenses&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='no'&gt;LICENSE&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='no'&gt;Unless&lt;/span&gt; &lt;span class='n'&gt;required&lt;/span&gt; &lt;span class='n'&gt;by&lt;/span&gt; &lt;span class='n'&gt;applicable&lt;/span&gt; &lt;span class='n'&gt;law&lt;/span&gt; &lt;span class='ow'&gt;or&lt;/span&gt; &lt;span class='n'&gt;agreed&lt;/span&gt; &lt;span class='n'&gt;to&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='n'&gt;writing&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;software&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;distributed&lt;/span&gt; &lt;span class='n'&gt;under&lt;/span&gt; &lt;span class='n'&gt;the&lt;/span&gt; &lt;span class='no'&gt;License&lt;/span&gt; &lt;span class='n'&gt;is&lt;/span&gt; &lt;span class='n'&gt;distributed&lt;/span&gt; &lt;span class='n'&gt;on&lt;/span&gt; &lt;span class='n'&gt;an&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;AS IS&amp;quot;&lt;/span&gt; &lt;span class='no'&gt;BASIS&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='no'&gt;WITHOUT&lt;/span&gt; &lt;span class='no'&gt;WARRANTIES&lt;/span&gt; &lt;span class='no'&gt;OR&lt;/span&gt; &lt;span class='no'&gt;CONDITIONS&lt;/span&gt; &lt;span class='no'&gt;OF&lt;/span&gt; &lt;span class='no'&gt;ANY&lt;/span&gt; &lt;span class='no'&gt;KIND&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;either&lt;/span&gt; &lt;span class='n'&gt;express&lt;/span&gt; &lt;span class='ow'&gt;or&lt;/span&gt; &lt;span class='n'&gt;implied&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='no'&gt;See&lt;/span&gt; &lt;span class='n'&gt;the&lt;/span&gt; &lt;span class='no'&gt;License&lt;/span&gt; &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;the&lt;/span&gt; &lt;span class='n'&gt;specific&lt;/span&gt; &lt;span class='n'&gt;language&lt;/span&gt; &lt;span class='n'&gt;governing&lt;/span&gt; &lt;span class='n'&gt;permissions&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt;
 &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;limitations&lt;/span&gt; &lt;span class='n'&gt;under&lt;/span&gt; &lt;span class='n'&gt;the&lt;/span&gt; &lt;span class='no'&gt;License&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;
 &lt;span class='o'&gt;*/&lt;/span&gt;

&lt;span class='no'&gt;HEAD&lt;/span&gt;

&lt;span class='no'&gt;Licenser&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;licenseFiles&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;ARGV&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This script was inspired by the the &lt;a href='http://svn.apache.org/viewvc/incubator/ode/trunk/tasks/check_license_headers.rb?revision=524802&amp;amp;view=markup&amp;amp;pathrev=524802'&gt;check_license_headers.rb&lt;/a&gt; script in the Apache SVN repo. Couldn&amp;#8217;t get it to work on my setup, so I rewrote the parts I needed.&lt;/p&gt;

&lt;p&gt;This can be found in the &lt;a href='http://github.com/mikereedell/scripts/tree/master'&gt;GitHub scripts project&lt;/a&gt;. Look for updates to handle more source types and to check for existing license headers.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/_w5cEdOynb0" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2009/01/31/Licensing-Your-Code-the-Ruby-Way.html</feedburner:origLink></entry>
 
 <entry>
   <title>Sunrise/Sunset Java Library</title>
   <link href="http://feedproxy.google.com/~r/mikereedell/~3/OYzmLS_LQ8Y/Sunrise-Sunset-Java-Library.html" />
   <updated>2009-01-27T00:00:00-05:00</updated>
   <id>http://mikereedell.com/2009/01/27/Sunrise-Sunset-Java-Library</id>
   <content type="html">&lt;h1 id='sunrisesunset_java_library'&gt;Sunrise/Sunset Java Library&lt;/h1&gt;
&lt;p class='postdate'&gt;27 January 2009&lt;/p&gt;
&lt;p&gt;I just wrote a Java library that computes the sunrise / sunset using GPS coordinates and a date. To use, simply download the tar or zip file from the &lt;a href='http://mikereedell.github.com/sunrisesunsetlib-java/'&gt;GitHub page&lt;/a&gt;, or use git to pull the source:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;$&amp;gt;&lt;/span&gt;git clone git://github.com/mikereedell/sunrisesunsetlib-java
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Once you have the source, use the command:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;$ &lt;/span&gt;ant all
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To compile the source, build the bin, src, and test jars, execute the unit tests and generate the JavaDoc for the library.&lt;/p&gt;

&lt;p&gt;This code snippet illustrates the main usage pattern:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='c1'&gt;// Location of sunrise/set, as latitude/longitude.&lt;/span&gt;
&lt;span class='n'&gt;Location&lt;/span&gt; &lt;span class='n'&gt;location&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;Location&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;39.9937&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;-75.7850&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;

&lt;span class='c1'&gt;// Create calculator object with the location and time zone identifier.&lt;/span&gt;
&lt;span class='n'&gt;SunriseSunsetCalculator&lt;/span&gt; &lt;span class='n'&gt;calculator&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;SunriseSunsetCalculator&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;location&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;America/New_York&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;

&lt;span class='n'&gt;Calendar&lt;/span&gt; &lt;span class='n'&gt;date&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;Calendar&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;getInstance&lt;/span&gt;&lt;span class='o'&gt;();&lt;/span&gt;
&lt;span class='n'&gt;String&lt;/span&gt; &lt;span class='n'&gt;dawn&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;calculator&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;getCivilSunriseForDate&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;date&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
&lt;span class='n'&gt;String&lt;/span&gt; &lt;span class='n'&gt;dusk&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;calculator&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;getCivilSunsetForDate&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;date&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The list of supported time zone identifiers is given by:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='c1'&gt;//Returns String[] of supported tz identifiers.&lt;/span&gt;
&lt;span class='n'&gt;TimeZone&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;getAvailableIDs&lt;/span&gt;&lt;span class='o'&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Any feedback? Comments? Features? Bugs? Comment below.&lt;/p&gt;

&lt;p&gt;Released under the &lt;a href='http://www.apache.org/licenses/LICENSE-2.0'&gt;Apache License 2.0&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/mikereedell/~4/OYzmLS_LQ8Y" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://mikereedell.com/2009/01/27/Sunrise-Sunset-Java-Library.html</feedburner:origLink></entry>
 
 
</feed>
